[Back to CURSOR SWAG index] [Back to Main SWAG index] [Original]

    { Author:  Chad Moore

      I have been writing my own multipurpose units for projects for quite some
      time now, and I noticed how all of the cursor routines in the SWAG used
      BIOS calls, well, I just happened to be writing an extended display unit
      for use with my display unit, and I figured you all could enjoy my
      routines.  They may not be as optomized as they could be, but they work.
      So, in other words, rip it, steal it, use it, distribute it, etc.

      Some of them may screw up while using the Crt unit, because it keeps track
      of cursor movement itself...  (remember, I have my OWN display unit...I
      hate the Crt one)  Anyway, they all DO work, but I am not responsible for
      any damages caused by these routines.  Oh, and the routines are all based
      on 0 through whatever - 1, rather than 1 through whatever.  (the way the
      computer would do it)

      If you would like to get information on the CRTC registers (the ones I
      used for this), Mode-X, sound, XMS/EMS/conventional memory, 3-D graphics,
      and much more, I recomend this book:

      PC Underground Unconventional Programming Topics
      from Abacus...

    }

    { Extended alphanumeric display unit }
    unit XDisplay;
    {$G+} { Enable 286 instructions }

    interface

    procedure CursorOn;
      { turns the cursor ON }
    procedure CursorOff;
      { turns the cursor OFF }
    function CursorState : Boolean;
      { returns TRUE if the cursor is ON }
    procedure CursorShape( StartScan, EndScan : Byte );
      { defines the cursor shape }
    function GetCursorShape : Word;
      { high 8 bits = startscan, low 8 bits = endscan }
    procedure CursorPosition( Column, Row : Byte );
      { positions the cursor }
    function CursorColumn : Byte;
      { returns the cursor column }
    function CursorRow : Byte;
      { returns the cursor row }

    implementation

    procedure CursorOn; assembler;
    asm
      MOV   DX,03D4H        { CRTC index register }
      MOV   AL,0AH          { select register 0Ah }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get status }
      AND   AL,0DFH         { bit 5 = 0 (Cursor on) }
      OUT   DX,AL
    end;

    procedure CursorOff; assembler;
    asm
      MOV   DX,03D4H        { CRTC index register }
      MOV   AL,0AH          { select register 0Ah }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get status }
      OR    AL,20H          { bit 5 = 1 (Cursor off) }
      OUT   DX,AL
    end;

    function CursorState : Boolean; assembler;
    asm
      MOV   DX,03D4H        { CRTC index register }
      MOV   AL,0AH          { select register 0Ah }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get status }
      AND   AL,20H          { if bit 5 = 1, cursor is off }
      CMP   AL,20H          { is bit 5 on? }
      JE    @@cursoroff
      MOV   AL,TRUE         { no, cursor is on }
      JMP   @@done          { return }
    @@cursoroff:
      MOV   AL,FALSE        { yes, cursor is off }
    @@done:
    end;

    procedure CursorShape( StartScan, EndScan : Byte ); assembler;
    asm
      MOV   DX,03D4H        { CRTC index register }
      MOV   AL,0AH          { select register 0Ah }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get status }
      MOV   AH,StartScan
      AND   AL,0E0H         { clear bits 0-4 }
      OR    AL,AH           { bits 0-4 = StartScan, save bits 5-7 }
      OUT   DX,AL
      DEC   DX              { CRTC index register }
      MOV   AL,0BH          { select register 0Bh }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get status }
      MOV   AH,EndScan
      AND   AL,0E0H         { clear bits 0-4 }
      OR    AL,AH           { bits 0-4 = EndScan, save bits 5-7 }
      OUT   DX,AL
    end;

    function GetCursorShape : Word; assembler;
    asm
      MOV   DX,03D4H        { CRTC index register }
      MOV   AL,0AH          { select register 0Ah }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get status }
      AND   AL,1FH          { clear bits 5-7 }
      MOV   AH,AL           { AH = startscan }
      DEC   DX              { CRTC index register }
      MOV   AL,0BH          { select register 0Bh }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get status }
      AND   AL,1FH          { clear bits 5-7 }
    end;

    procedure CursorPosition( Column, Row : Byte ); assembler;
    asm
      { get cursor offset into BX }
      MOV   DX,03D4H        { CRTC index register }
      MOV   AL,13H          { select register 13H }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX
      MOV   AH,AL           { store row offset in AH }
      DEC   DX              { CRTC index register }
      MOV   AL,14H          { select register 14H }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX
      SHL   AH,01H          { multiply by 2 }
      AND   AL,40H          { check bit 5 for doubleword addressing }
      CMP   AL,00H          { doubleword? }
      JE    @@continue      { no, continue }
      SHL   AH,01H          { yes, multiply by 2 *more* }
    @@continue:
                            { AH = row length }
      SHR   AX,08H          { AX = row length }
      MUL   Row             { row length * Row }
      MOV   BL,Column
      XOR   BH,BH
      ADD   AX,BX           { + Column }
      MOV   BX,AX           { BX = cursor offset }
      { send BX to CRTC }
      DEC   DX              { CRTC index register }
      MOV   AL,0EH          { select register 0EH (cursor offset HIGH) }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      MOV   AL,BH           { get HIGH to send }
      OUT   DX,AL
      DEC   DX              { CRTC index register }
      MOV   AL,0FH          { select register 0FH (cursor offset LOW) }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      MOV   AL,BL           { get LOW to send }
      OUT   DX,AL
    end;

    function CursorColumn : Byte; assembler;
    asm
      { get cursor offset }
      MOV   DX,03D4H        { CRTC index register }
      MOV   AL,0EH          { select register 0Eh }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX
      SHL   AX,08H          { AH = high bits }
      DEC   DX              { CRTC index register }
      MOV   AL,0FH          { select register 0Fh }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { AL = low bits }
      MOV   CX,AX           { save cursor offset }
      { get chars per line }
      DEC   DX              { CRTC index register }
      MOV   AL,14H          { select register 14h }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { doubleword addressing? }
      MOV   BL,AL           { save in BL }
      DEC   DX              { CRTC index register }
      MOV   AL,13H          { select register 13h }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get offset between 2 lines (line width) }
      SHL   AL,01H          { multiply by 2 }
      AND   BL,40H          { check bit 5 for doubleword addressing }
      CMP   BL,00H          { doubleword? }
      JE    @@continue      { no, continue }
      SHL   AL,01H          { multiply by 2 *more* }
    @@continue:             { AL = chars per line }
      { calculate }
      XOR   AH,AH           { clear upper AX }
      MOV   BX,AX           { get chars per line in BX }
      XOR   DX,DX           { DX:AX gets ready for div }
      MOV   AX,CX           { get cursor offset }
      DIV   BX              { div DX = remainder, AX = answer }
      MOV   AX,DX           { get remainder }
    end;

    function CursorRow : Byte; assembler;
    asm
      { get cursor offset }
      MOV   DX,03D4H        { CRTC index register }
      MOV   AL,0EH          { select register 0Eh }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX
      SHL   AX,08H          { AH = high bits }
      DEC   DX              { CRTC index register }
      MOV   AL,0FH          { select register 0Fh }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { AL = low bits }
      MOV   CX,AX           { save cursor offset }
      { get chars per line }
      DEC   DX              { CRTC index register }
      MOV   AL,14H          { select register 14h }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { doubleword addressing? }
      MOV   BL,AL           { save in BL }
      DEC   DX              { CRTC index register }
      MOV   AL,13H          { select register 13h }
      OUT   DX,AL
      INC   DX              { CRTC data register }
      IN    AL,DX           { get offset between 2 lines (line width) }
      SHL   AL,01H          { multiply by 2 }
      AND   BL,40H          { check bit 5 for doubleword addressing }
      CMP   BL,00H          { doubleword? }
      JE    @@continue      { no, continue }
      SHL   AL,01H          { multiply by 2 *more* }
    @@continue:             { AL = chars per line }
      { calculate }
      XOR   AH,AH           { clear upper AX }
      MOV   BX,AX           { get chars per line in BX }
      XOR   DX,DX           { DX:AX gets ready for div }
      MOV   AX,CX           { get cursor offset }
      DIV   BX              { div DX = remainder, AX = answer }
                            { returns AL }
    end;

    end.

[Back to CURSOR SWAG index] [Back to Main SWAG index] [Original]