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


procedure qwrite(x, y: byte; s: string; f, b: byte);

{ Does a direct video write -- extremely fast. }

begin
  asm
    mov dh, y         { move X and Y into DL and DH }
    mov dl, x
    xor al, al
    mov ah, b         { load background into AH }
    mov cl, 4         { shift background over to next nibble }
    shl ax, cl
    add ah, f         { add foreground }
    push ax           { PUSH color combo onto the stack }
    mov bx, 0040h     { look at 0040h:0049h to get video mode }
    mov es, bx
    mov bx, 0049h
    mov al, es:[bx]
    cmp al, 7         { see if mode = 7 (i.e., monochrome) }
    je @mono_segment
    mov ax, 0b800h    { it's color: use segment B800h }
    jmp @got_segment
    @mono_segment:
    mov ax, 0b000h    { it's mono: use segment B000h }
    @got_segment:
    push ax           { PUSH video segment onto stack }
    mov bx, 004ah     { check 0040h:0049h to get number of screen columns }
    xor ch, ch
    mov cl, es:[bx]
    xor ah, ah        { move Y into AL; decrement to convert Pascal coords }
    mov al, dh
    dec al
    xor bh, bh        { shift X over into BL; decrement again }
    mov bl, dl
    dec bl
    cmp cl, $50       { see if we're in 80-column mode }
    je @eighty_column
    mul cx            { multiply Y by the number of columns }
    jmp @multiplied
    @eighty_column:   { 80-column mode: it may be faster to perform the }
    mov cl, 4         {   multiplication via shifts and adds: remember  }
    shl ax, cl        {   that 80d = 1010000b , so one can SHL 4, copy  }
    mov dx, ax        {   the result to DX, SHL 2, and add DX in.       }
    mov cl, 2
    shl ax, cl
    add ax, dx
    @multiplied:
    add ax, bx        { add X in }
    shl ax, 1         { multiply by 2 to get offset into video segment }
    mov di, ax        { video pointer is in DI }
    lea si, s         { string pointer is in SI }
    SEGSS lodsb
    cmp al, 00h       { if zero-length string, jump to end }
    je @done
    mov cl, al
    xor ch, ch        { string length is in CX }
    pop es            { get video segment back from stack; put in ES }
    pop ax            { get color back from stack; put in AX (AH = color) }
    @write_loop:
    SEGSS lodsb       { get character to write }
    mov es:[di], ax   { write AX to video memory }
    inc di            { increment video pointer }
    inc di
    loop @write_loop  { if CX > 0, go back to top of loop }
    @done:            { end }
    end;
  end;

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