Previous | Table of Contents | Next

LISTING 25.1 L25-1.ASM

    ; Program to illustrate operation of data rotate and bit mask
    ;  features of Graphics Controller. Draws 8×8 character at
    ;  specified location, using VGA’s 8×8 ROM font. Designed
    ;  for use with modes 0Dh, 0Eh, 0Fh, 10h, and 12h.
    ; By Michael Abrash.
    ;
    stack   segment para stack ‘STACK’
            db      512 dup(?)
    stack   ends
    ;
    VGA_VIDEO_SEGMENT       equ     0a000h  ;VGA display memory segment
    SCREEN_WIDTH_IN_BYTES   equ     044ah   ;offset of BIOS variable
    FONT_CHARACTER_SIZE     equ     8       ;# bytes in each font char
    ;
    ; VGA register equates.
    ;
    GC_INDEX        equ     3ceh    ;GC index register
    GC_ROTATE       equ     3       ;GC data rotate/logical function
                                    ; register index
    GC_BIT_MASK     equ     8       ;GC bit mask register index
    ;
    dseg    segment para common ‘DATA’
    TEST_TEXT_ROW   equ     69      ;row to display test text at
    TEST_TEXT_COL   equ     17      ;column to display test text at
    TEST_TEXT_WIDTH equ     8       ;width of a character in pixels

    TestString      label   byte
            db      ‘Hello, world!’,0       ;test string to print.
    FontPointer     dd      ?               ;font offset
    dseg    ends
    ;
    ; Macro to set indexed register INDEX of GC chip to SETTING.
    ;
    SETGC   macro   INDEX, SETTING
            mov     dx,GC_INDEX
            mov     ax,(SETTING SHL 8) OR INDEX
            out     dx,ax
            endm
    ;
    cseg    segment para public ‘CODE’
            assume  cs:cseg, ds:dseg
    start   proc    near
            mov     ax,dseg
            mov     ds,ax
    ;
    ; Select 640×480 graphics mode.
    ;
            mov     ax,012h
            int     10h
    ;
    ; Set driver to use the 8×8 font.
    ;
             mov     ah,11h  ;VGA BIOS character generator function,
             mov     al,30h  ; return info subfunction
             mov     bh,3;get 8×8 font pointer
             int     10h
             call    SelectFont
    ;
    ; Print the test string.
    ;
            mov     si,offset TestString
            mov     bx,TEST_TEXT_ROW
            mov     cx,TEST_TEXT_COL
    StringOutLoop:
            lodsb
            and     al,al
            jz      StringOutDone
            call    DrawChar
            add     cx,TEST_TEXT_WIDTH
            jmp     StringOutLoop
    StringOutDone:
    ;
    ; Reset the data rotate and bit mask registers.
    ;
            SETGC   GC_ROTATE, 0
            SETGC   GC_BIT_MASK, 0ffh
    ;
    ; Wait for a keystroke.
    ;
            mov     ah,1
            int     21h
    ;
    ; Return to text mode.
    ;
            mov     ax,03h
            int     10h
    ;
    ; Exit to DOS.
    ;
            mov     ah,4ch
            int     21h
    Start   endp
    ;
    ; Subroutine to draw a text character in a linear graphics mode
    ;  (0Dh, 0Eh, 0Fh, 010h, 012h).
    ; Font used should be pointed to by FontPointer.
    ;
    ; Input:
    ;  AL = character to draw
    ;  BX = row to draw text character at
    ;  CX = column to draw text character at
    ;
    ;  Forces ALU function to “move”.
    ;
    DrawChar        proc    near
            push    ax
            push    bx
            push    cx
            push    dx
            push    si
            push    di
            push    bp
            push    ds
    ;
    ; Set DS:SI to point to font and ES to point to display memory.
    ;
            lds     si,[FontPointer]        ;point to font
            mov     dx,VGA_VIDEO_SEGMENT
            mov     es,dx                   ;point to display memory
    ;
    ; Calculate screen address of byte character starts in.
    ;
            push    ds      ;point to BIOS data segment
            sub     dx,dx
            mov     ds,dx
            xchg    ax,bx
            mov     di,ds:[SCREEN_WIDTH_IN_BYTES]   ;retrieve BIOS
                                                    ; screen width
            pop     ds
            mul     di      ;calculate offset of start of row
            push    di      ;set aside screen width
            mov     di,cx    ;set aside the column
            and     cl,0111b    ;keep only the column in-byte address
            shr     di,1
            shr     di,1
            shr     di,1       ;divide column by 8 to make a byte address
            add     di,ax    ;and point to byte
    ;
    ; Calculate font address of character.
    ;
            sub     bh,bh
            shl     bx,1    ;assumes 8 bytes per character; use
            shl     bx,1    ; a multiply otherwise
            shl     bx,1    ;offset in font of character
            add     si,bx    ;offset in font segment of character
    ;
    ; Set up the GC rotation.
    ;
            mov     dx,GC_INDEX
            mov     al,GC_ROTATE
            mov     ah,cl
            out     dx,ax
    ;
    ; Set up BH as bit mask for left half,
    ; BL as rotation for right half.
    ;
            mov     bx,0ffffh
            shr     bh,cl
            neg     cl
            add     cl,8
            shl     bl,cl
    ;
    ; Draw the character, left half first, then right half in the
    ; succeeding byte, using the data rotation to position the character
    ; across the byte boundary and then using the bit mask to get the
    ; proper portion of the character into each byte.
    ; Does not check for case where character is byte-aligned and
    ; no rotation and only one write is required.
    ;
            mov     bp,FONT_CHARACTER_SIZE
            mov     dx,GC_INDEX
            pop     cx      ;get back screen width
            dec     cx
            dec     cx      ; -2 because do two bytes for each char
    CharacterLoop:
    ;
    ; Set the bit mask for the left half of the character.
    ;
            mov     al,GC_BIT_MASK
            mov     ah,bh
            out     dx,ax
    ;
    ; Get the next character byte & write it to display memory.
    ; (Left half of character.)
    ;
            mov     al,[si]         ;get character byte
            mov     ah,es:[di]      ;load latches
            stosb                   ;write character byte
    ;
    ; Set the bit mask for the right half of the character.
    ;
            mov     al,GC_BIT_MASK
            mov     ah,bl
            out     dx,ax
    ;
    ; Get the character byte again & write it to display memory.
    ; (Right half of character.)
    ;
            lodsb                   ;get character byte
            mov     ah,es:[di]      ;load latches
            stosb                   ;write character byte
    ;
    ; Point to next line of character in display memory.
    ;
            add     di,cx
    ;
            dec     bp
            jnz     CharacterLoop
    ;
            pop     ds
            pop     bp
            pop     di
            pop     si
            pop     dx
            pop     cx
            pop     bx
            pop     ax
            ret
    DrawChar        endp
    ;
    ; Set the pointer to the font to draw from to ES:BP.
    ;
    SelectFont      proc    near
            mov     word ptr [FontPointer],bp       ;save pointer
            mov     word ptr [FontPointer+2],es
            ret
    SelectFont      endp
    ;
    cseg    ends
            end     start

The bit mask can be used for much more than bit-aligned fonts. For example, the bit mask is useful for fast pixel drawing, such as that performed when drawing lines, as we’ll see in Chapter 35. It’s also useful for drawing the edges of primitives, such as filled polygons, that potentially involve modifying some but not all of the pixels controlled by a single byte of display memory.

Basically, the bit mask is handy whenever only some of the eight pixels in a byte of display memory need to be changed, because it allows full use of the VGA’s four-way parallel processing capabilities for the pixels that are to be drawn, without interfering with the pixels that are to be left unchanged. The alternative would be plane-by-plane processing, which from a performance perspective would be undesirable indeed.

Previous | Table of Contents | Next

Graphics Programming Black Book © 2001 Michael Abrash