Previous | Table of Contents | Next

Another interesting point about flipping from graphics to text and back is that the standard mode 3 character/attribute map doesn’t actually take up every byte of the first 4000 bytes of planes 0 and 1. The standard mode 3 character/attribute map actually only takes up every even byte of the first 4000 in each plane; the odd bytes are left untouched. This means that only about 12K bytes actually have to be saved when going to text mode. The code in Listing 27.3 flips from graphics mode to text mode and back, saving only those 12K bytes that actually have to be saved. This code saves and restores the first 8K of plane 2 (the font area) while in graphics mode, but performs the save and restore of the 4000 bytes used for the character/attribute map while in text mode, because the characters and attributes, which are actually stored in the even bytes of planes 0 and 1, respectively, appear to be contiguous bytes in memory in text mode and so are easily saved as a single block.

Explaining why only every other byte of planes 0 and 1 is used in text mode and why characters and attributes appear to be contiguous bytes when they are actually in different planes is a large part of the explanation I’m not going to go into now. One bit of fallout from this, however, is that if you flip to text mode and preserve the graphics bitmap using the mechanism illustrated in Listing 27.3, you shouldn’t write to any text page other than page 0 (that is, don’t write to any offset in display memory above 3999 in text mode) or alter the Page Select bit in the Miscellaneous Output register (3C2H) while in text mode. In order to allow completely unfettered access to text pages, it would be necessary to save every byte in the first 32K of each of planes 0 and 1. (On the other hand, this would allow up to 16 text screens to be stored simultaneously, with any one displayable instantly.) Moreover, if any fonts other than the default font are loaded, the portions of plane 2 that those particular fonts are loaded into would have to be saved, up to a maximum of all 64K of plane 2. In the worst case, a full 128K would have to be saved in order to preserve all the memory potentially used by text mode.

As I said, Phil Coleman’s question is an interesting one, and I’ve only touched on the intriguing possibilities arising from the various configurations of display memory in VGA graphics and text modes. Right now, though, we’ve still got the basics of the remarkably complex (but rewarding!) VGA to cover.

LISTING 27.3 L27-3.ASM

    ; Program to illustrate flipping from bit-mapped graphics mode to
    ; text mode and back without losing any of the graphics bit-map.
    ;
    ; Assemble with MASM or TASM
    ;
    ; By Michael Abrash
    ;
    Stack   segment para stack ‘STACK’
            db      512 dup(0)
    Stack   ends

    GRAPHICS_SEGMENT equ     0a000h  ;mode 10 bit-map segment
    TEXT_SEGMENT    equ     0b800h  ;mode 3 bit-map segment
    SC_INDEX        equ     3c4h    ;Sequence Controller Index register
    MAP_MASK        equ     2       ;index of Map Mask register
    GC_INDEX        equ     3ceh    ;Graphics Controller Index register
    READ_MAP        equ     4       ;index of Read Map register

    Data    segment para common ‘DATA’

    GStrikeAnyKeyMsg0       label   byte
            db      0dh, 0ah, ‘Graphics mode’, 0dh, 0ah
            db      ‘Strike any key to continue...’, 0dh, 0ah, ‘$’

    GStrikeAnyKeyMsg1       label   byte
            db      0dh, 0ah, ‘Graphics mode again’, 0dh, 0ah
            db      ‘Strike any key to continue...’, 0dh, 0ah, ‘$’

    TStrikeAnyKeyMsg        label   byte
            db      0dh, 0ah, ‘Text mode’, 0dh, 0ah
            db      ‘Strike any key to continue...’, 0dh, 0ah, ‘$’

    Plane2Save      db      2000h dup (?)   ;save area for plane 2 data
                                            ; where font gets loaded
    CharAttSave     db      4000 dup (?)    ;save area for memory wiped
                                            ; out by character/attribute
                                            ; data in text mode
    Data    ends

    Code    segment para public ‘CODE’
            assume  cs:Code, ds:Data
    Start   proc    near
            mov     ax,10h
            int     10h             ;select video mode 10h (640×350)
    ;
    ; Fill the graphics bit-map with a colored pattern.
    ;
            cld
            mov     ax,GRAPHICS_SEGMENT
            mov     es,ax
            mov     ah,3            ;initial fill pattern
            mov     cx,4            ;four planes to fill
            mov     dx,SC_INDEX
            mov     al,MAP_MASK
            out     dx,al           ;leave the SC Index pointing to the
            inc     dx              ; Map Mask register

    FillBitMap:
            mov     al,10h
            shr     al,cl           ;generate map mask for this plane
            out     dx,al           ;set map mask for this plane
            sub     di,di           ;start at offset 0
            mov     al,ah           ;get the fill pattern
            push    cx              ;preserve plane count
            mov     cx,8000h        ;fill 32K words
            rep stosw               ;do fill for this plane
            pop     cx              ;get back plane count
            shl     ah,1
            shl     ah,1
            loop    FillBitMap
    ;
    ; Put up “strike any key” message.
    ;
            mov     ax,Data
            mov     ds,ax
            mov     dx,offset GStrikeAnyKeyMsg0
            mov     ah,9
            int     21h
    ;
    ; Wait for a key.
    ;
            mov     ah,01h
            int     21h
    ;
    ; Save the 8K of plane 2 that will be used by the font.
    ;
            mov     dx,GC_INDEX
            mov     al,READ_MAP
            out     dx,al
            inc     dx
            mov     al,2
            out     dx,al           ;set up to read from plane 2
            mov     ax,Data
            mov     es,ax
            mov     ax,GRAPHICS_SEGMENT
            mov     ds,ax
            sub     si,si
            mov     di,offset Plane2Save
            mov     cx,2000h/2      ;save 8K (length of default font)
            rep movsw
    ;
    ; Go to text mode without clearing display memory.
    ;
            mov     ax,083h
            int     10h
    ;
    ; Save the text mode bit-map.
    ;
            mov     ax,Data
            mov     es,ax
            mov     ax,TEXT_SEGMENT
            mov     ds,ax
            sub     si,si
            mov     di,offset CharAttSave
            mov     cx,4000/2       ;length of one text screen in words
            rep movsw
    ;
    ; Fill the text mode screen with dots and put up “strike any key”
    ; message.
    ;
            mov     ax,TEXT_SEGMENT
            mov     es,ax
            sub     di,di
            mov     al,‘.’          ;fill character
            mov     ah,7            ;fill attribute
            mov     cx,4000/2       ;length of one text screen in words
            rep stosw
            mov     ax,Data
            mov     ds,ax
            mov     dx,offset TStrikeAnyKeyMsg
            mov     ah,9
            int     21h
    ;
    ; Wait for a key.
    ;
            mov     ah,01h
            int     21h
    ;
    ; Restore the text mode screen to the state it was in on entering
    ; text mode.
    ;
            mov     ax,Data
            mov     ds,ax
            mov     ax,TEXT_SEGMENT
            mov     es,ax
            mov     si,offset CharAttSave
            sub     di,di
            mov     cx,4000/2       ;length of one text screen in words
            rep movsw
    ;
    ; Return to mode 10h without clearing display memory.
    ;
            mov     ax,90h
            int     10h
    ;
    ; Restore the portion of plane 2 that was wiped out by the font.
    ;
            mov     dx,SC_INDEX
            mov     al,MAP_MASK
            out     dx,al
            inc     dx
            mov     al,4
            out     dx,al           ;set up to write to plane 2
            mov     ax,Data
            mov     ds,ax
            mov     ax,GRAPHICS_SEGMENT
            mov     es,ax
            mov     si,offset Plane2Save
            sub     di,di
            mov     cx,2000h/2      ;restore 8K (length of default font)
            rep movsw
    ;
    ; Put up “strike any key” message.
    ;
            mov     ax,Data
            mov     ds,ax
            mov     dx,offset GStrikeAnyKeyMsg1
            mov     ah,9
            int     21h
    ;
    ; Wait for a key before returning to text mode and ending.
    ;
            mov     ah,01h
            int     21h
            mov     ax,03h
            int     10h
            mov     ah,4ch
            int     21h
    Start   endp
    Code    ends
            end     Start

Previous | Table of Contents | Next

Graphics Programming Black Book © 2001 Michael Abrash