EarthWeb   
   datamation.com Brought to you by EarthWeb

HomeSubscribeSearchFAQSitemapContact Us
     

   

  Search Tips
  Advanced Search
   
  

  
Go to ITKnowledge Enterprise

Zen of Graphics Programming, 2nd Edition Zen of Graphics Programming, 2nd Edition
by Michael Abrash
Coriolis, The Coriolis Group
ISBN: 1883577896   Pub Date: 04/01/96

Search this book:
 
Previous Table of Contents Next


Chapter 7
Saving Screens and Other VGA Mysteries

Useful Nuggets from the VGA Zen File

There are a number of VGA graphics topics that aren’t quite involved enough to warrant their own chapters, yet still cause a fair amount of programmer headscratching—and thus deserve treatment somewhere in this book. This is the place, and during the course of this chapter we’ll touch on saving and restoring 16-color EGA and VGA screens, the 16-out-of-64 colors issue, and techniques involved in reading and writing VGA control registers.

That’s a lot of ground to cover, so let’s get started!

Saving and Restoring EGA and VGA Screens

The memory architectures of EGAs and VGAs are similar enough to treat both together in this regard. The basic principle for saving EGA and VGA 16-color graphics screens is astonishingly simple: Write each plane to disk separately. Let’s take a look at how this works in the EGA’s hi-res mode 10H, which provides 16 colors at 640×350.

All we need do is enable reads from plane 0 and write the 28,000 bytes of plane 0 that are displayed in mode 10H to disk, then enable reads from plane 1 and write the displayed portion of that plane to disk, and so on for planes 2 and 3. The result is a file that’s 112,000 (28,000 * 4) bytes long, with the planes stored as four distinct 28,000-byte blocks, as shown in Figure 7.1.


Figure 7.1  Saving EGA/VGA Display Memory

The program shown later on in Listing 7.1 does just what I’ve described above, putting the screen into mode 10H, putting up some bit- mapped text so there’s something to save, and creating the 112K file SNAPSHOT.SCR, which contains the visible portion of the mode 10H frame buffer.

The only part of Listing 7.1 that’s even remotely tricky is the use of the Read Map register (Graphics Controller register 4) to make each of the four planes of display memory readable in turn. The same code is used to write 28,000 bytes of display memory to disk four times, and 28,000 bytes of memory starting at A000:0000 are written to disk each time; however, a different plane is read each time, thanks to the changing setting of the Read Map register. (If this is unclear, refer back to Figure 7.1; you may also want to reread Chapter 6 to brush up on the operation of the Read Map register in particular and reading EGA and VGA memory in general.)

Of course, we’ll want the ability to restore what we’ve saved, and Listing 7.2 does this. Listing 7.2 reverses the action of Listing 7.1, selecting mode 10H and then loading 28,000 bytes from SNAPSHOT.SCR into each plane of display memory. The Map Mask register (Sequence Controller register 2) is used to select the plane to be written to. If your computer is slow enough, you can see the colors of the text change as each plane is loaded when Listing 7.2 runs. Note that Listing 7.2 does not itself draw any text, but rather simply loads the bit map saved by Listing 7.1 back into the mode 10H frame buffer.

LISTING 7.1 L7-1.ASM

; Program to put up a mode 10h EGA graphics screen, then save it
; to the file SNAPSHOT.SCR.
;
VGA_SEGMENT                equ   0a000h
GC_INDEX                   equ   3ceh      ;Graphics Controller Index
                                            register
READ_MAP                   equ   4         ;Read Map register index in GC
DISPLAYED_SCREEN_SIZE      equ (640/8)*350 ;# of displayed bytes per plane
                                            in a
                                           ; hi-res graphics screen
;
stack   segment para stack 'STACK'
        db      512 dup (?)
stack   ends
;
Data    segment word 'DATA'
SampleText   db    'This is bit-mapped text, drawn in hi-res '
             db    'EGA graphics mode 10h.', 0dh, 0ah, 0ah
             db    'Saving the screen (including this text)…'
             db    0dh, 0ah, '$'
Filename     db    'SNAPSHOT.SCR',0     ;name of file we're saving to
ErrMsg1      db    '*** Couldn''t open SNAPSHOT.SCR ***',0dh,0ah,'$'
ErrMsg2      db    '*** Error writing to SNAPSHOT.SCR ***',0dh,0ah,'$'
WaitKeyMsg   db    0dh, 0ah, 'Done. Press any key to end…',0dh,0ah,'$'
Handle       dw    ?                    ;handle of file we're saving to
Plane        db    ?                    ;plane being read
Data ends
;
Code    segment
        assume cs:Code, ds:Data
Start   proc   near
        mov    ax,Data
        mov    ds,ax
;
; Go to hi-res graphics mode.
;
        mov     ax,10h       ;AH = 0 means mode set, AL =
                              10h selects
                             ; hi-res graphics mode
        int     10h          ;BIOS video interrupt
;
; Put up some text, so the screen isn't empty.
;
        mov     ah,9         ;DOS print string function
        mov     dx,offset SampleText
        int     21h
;
; Delete SNAPSHOT.SCR if it exists.
;
        mov     ah,41h       ;DOS unlink file function
        mov     dx,offset Filename
        int     21h
;
; Create the file SNAPSHOT.SCR.
;
        mov     ah,3ch       ;DOS create file function
        mov     dx,offset Filename
        sub     cx,cx        ;make it a normal file
        int     21h
        mov     [Handle],ax  ;save the handle
        jnc     SaveTheScreen;we're ready to save if no error
        mov     ah,9         ;DOS print string function
        mov     dx,offset ErrMsg1
        int     21h          ;notify of the error
        jmp     short Done   ;and done
;
; Loop through the 4 planes, making each readable in turn and
; writing it to disk. Note that all 4 planes are readable at
; A000:0000; the Read Map register selects which plane is readable
; at any one time.
;
SaveTheScreen:
        mov     [Plane],0    ;start with plane 0
SaveLoop:
        mov     dx,GC_INDEX
        mov     al,READ_MAP  ;set GC Index to Read Map register
        out     dx,al
        inc     dx
        mov     al,[Plane]   ;get the # of the plane we want
                             ; to save
        out     dx,al        ;set to read from the desired plane
        mov     ah,40h       ;DOS write to file function
        mov     bx,[Handle]
        mov     cx,DISPLAYED_SCREEN_SIZE ;# of bytes to save
        sub     dx,dx         ;write all displayed bytes at A000:0000
        push    ds
        mov     si,VGA_SEGMENT
        mov     ds,si
        int     21h          ;write the displayed portion of this plane
        pop     ds
        cmp     ax,DISPLAYED_SCREEN_SIZE ;did all bytes get written?
        jz         SaveLoopBottom
        mov     ah,9         ;DOS print string function
        mov     dx,offset ErrMsg2
        int     21h          ;notify about the error
        jmp     short DoClose;and done
SaveLoopBottom:
        mov     al,[Plane]
        inc     ax           ;point to the next plane
        mov     [Plane],al
        cmp     al,3         ;have we done all planes?
        jbe     SaveLoop     ;no, so do the next plane
;
; Close SNAPSHOT.SCR.
;
DoClose:
        mov     ah,3eh       ;DOS close file function
        mov     bx,[Handle]
        int     21h
;
; Wait for a keypress.
;
        mov     ah,9         ;DOS print string function
        mov     dx,offset WaitKeyMsg
        int     21h          ;prompt
        mov     ah,8         ;DOS input without echo function
        int     21h
;
; Restore text mode.
;
        mov     ax,3
        int     10h
;
; Done.
;
Done:
        mov     ah,4ch       ;DOS terminate function
        int     21h
Start   endp
Code    ends
        end     Start

LISTING 7.2 L7-2.ASM

; Program to restore a mode 10h EGA graphics screen from
; the file SNAPSHOT.SCR.
;
VGA_SEGMENT               equ  0a000h
SC_INDEX                  equ  3c4h       ;Sequence Controller Index
                                           register
MAP_MASK                  equ  2          ;Map Mask register index
                                          in SC
DISPLAYED_SCREEN_SIZE     equ (640/8)*350 ;# of displayed bytes per
                                           plane in a
                                          ; hi-res graphics screen
;
stack   segment para stack 'STACK'
        db      512 dup (?)
stack   ends
;
Data    segment word 'DATA'
Filename     db    'SNAPSHOT.SCR',0       ;name of file we're
                                           restoring from
ErrMsg1      db    '*** Couldn''t open SNAPSHOT.SCR ***',0dh,0ah,'$'
ErrMsg2      db    '*** Error reading from SNAPSHOT.SCR ***',0dh,0ah,'$'
WaitKeyMsg   db    0dh, 0ah, 'Done. Press any key to end…',0dh,0ah,'$'
Handle       dw    ?                      ;handle of file we're restoring
                                           from
Plane        db    ?                      ;plane being written
Data    ends
;
Code    segment
        assume  cs:Code, ds:Data
Start   proc    near
        mov     ax,Data
        mov     ds,ax
;
; Go to hi-res graphics mode.
;
        mov     ax,10h               ;AH = 0 means mode set, AL = 10h
                                      selects
                                     ; hi-res graphics mode
        int     10h                  ;BIOS video interrupt
;
; Open SNAPSHOT.SCR.
;
        mov     ah,3dh               ;DOS open file function
        mov     dx,offset Filename
        sub     al,al                ;open for reading
        int     21h
        mov     [Handle],ax          ;save the handle
        jnc     RestoreTheScreen     ;we're ready to restore if no error
        mov     ah,9                 ;DOS print string function
        mov     dx,offset ErrMsg1
        int     21h                  ;notify of the error
        jmp     short Done ;and done
;
; Loop through the 4 planes, making each writable in turn and
; reading it from disk. Note that all 4 planes are writable at
; A000:0000; the Map Mask register selects which planes are readable
; at any one time. We only make one plane readable at a time.
;
RestoreTheScreen:
        mov     [Plane],0                   ;start with plane 0
RestoreLoop:
        mov     dx,SC_INDEX
        mov     al,MAP_MASK                 ;set SC Index to Map Mask
                                            register
        out     dx,al
        inc     dx
        mov     cl,[Plane]                  ;get the # of the plane we want
                                            ; to restore
        mov     al,1
        shl     al,cl                       ;set the bit enabling writes to
                                            ; only the one desired plane
        out     dx,al                       ;set to read from desired plane
        mov     ah,3fh                      ;DOS read from file function
        mov     bx,[Handle]
        mov     cx,DISPLAYED_SCREEN_SIZE    ;# of bytes to read
        sub     dx,dx                       ;start loading bytes at
                                             A000:0000
        push    ds
        mov     si,VGA_SEGMENT
        mov     ds,si
        int     21h                  ;read the displayed portion of this
                                      plane
        pop     ds
        jc      ReadError
        cmp     ax,DISPLAYED_SCREEN_SIZE     ;did all bytes get read?
        jz      RestoreLoopBottom
ReadError:
        mov     ah,9                         ;DOS print string function
        mov     dx,offset ErrMsg2
        int     21h                          ;notify about the error
        jmp     short DoClose                ;and done
RestoreLoopBottom:
        mov     al,[Plane]
        inc     ax                           ;point to the next plane
        mov     [Plane],al
        cmp     al,3                         ;have we done all planes?
        jbe     RestoreLoop                  ;no, so do the next plane
;
; Close SNAPSHOT.SCR.
;
DoClose:
        mov     ah,3eh                       ;DOS close file function
        mov     bx,[Handle]
        int     21h
;
; Wait for a keypress.
;
        mov     ah,8                         ;DOS input without echo
                                              function
        int     21h
;
; Restore text mode.
;
        mov     ax,3
        int     10h
;
; Done.
;
Done:
        mov     ah,4ch                       ;DOS terminate function
        int     21h
Start   endp
Code    ends
        end     Start


Previous Table of Contents Next

homesubscribesearchfaqsitemapcontactus
Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.