![]() |
|
![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
|
![]() |
![]() |
When to Use Write Mode 2 and when to Use Set/ResetAs indicated above, write mode 2 and set/reset are functionally interchangeable. Write mode 2 lends itself to more efficient implementations when the drawing color changes frequently, as in Listing 5.2. Set/reset tends to be superior when many pixels in succession are drawn in the same color, since with set/reset enabled for all planes the Set/Reset register provides the color data and as a result the CPU is free to draw whatever byte value it wishes. For example, the CPU can execute an OR instruction to display memory when set/reset is enabled for all planes, thus both loading the latches and writing the color value with a single instruction, secure in the knowledge that the value it writes is ignored in favor of the set/reset color. Set/reset is also the mode of choice whenever it is necessary to force the value written to some planes to a fixed value while allowing the CPU byte to modify other planes. This is the mode of operation when set/reset is enabled for some but not all planes. Mode 13H320×200 with 256 ColorsIm going to take a minuteand I do mean a minuteto discuss the programming model for mode 13H, the VGAs 320×200 256-color mode. Frankly, theres just not much to it, especially compared to the convoluted 16-color model that weve explored over the last five chapters. Mode 13H offers the simplest programming model in the history of PC graphics: A linear bitmap starting at A000:0000, consisting of 64,000 bytes, each controlling one pixel. The byte at offset 0 controls the upper left pixel on the screen, the byte at offset 319 controls the upper right pixel on the screen, the byte at offset 320 controls the second pixel down at the left of the screen, and the byte at offset 63,999 controls the lower right pixel on the screen. Thats all there is to it; its so simple that Im not going to spend any time on a demo program, especially given that some of the listings later in this book, such as the antialiasing code in Chapter 25, use mode 13H. Flipping Pages from Text to Graphics and BackA while back, I got an interesting letter from Phil Coleman, of La Jolla, who wrote: Suppose I have the EGA in mode 10H (640×350 16-color graphics). I would like to preserve some or all of the image while I temporarily switch to text mode 3 to give my user a Help screen. Naturally memory is scarce so Id rather not make a copy of the video buffer at A000H to remember the image while I digress to the Help text. The EGA BIOS says that the screen memory will not be cleared on a mode set if bit 7 of AL is set. Yet if I try that, it is clear that writing text into the B800H buffer trashes much more than the 4K bytes of a text page; when I switch back to mode 10H, ghosts appear in the form of bands of colored dots. (When in text mode, I do make a copy of the 4K buffer at B800H before showing the help; and I restore the 4K before switching back to mode 10H.) Is there a way to preserve the graphics image while I switch to text mode? A corollary to this question is: Where does the 64/128/256K of EGA memory hide when the EGA is in text mode? Some I guess is used to store character sets, but what happens to the rest? Or rather, how can I protect it? Those are good questions. Alas, answering them in full would require extensive explanation that would have little general application, so Im not going to do that. However, the issue of how to go to text mode and back without losing the graphics image certainly rates a short discussion, complete with some working code. Thats especially true given that both the discussion and the code apply just as well to the VGA as to the EGA (with a few differences in mode 12H, the VGAs high-resolution mode, as noted below). Phil is indeed correct in his observation that setting bit 7 of AL instructs the BIOS not to clear display memory on mode sets, and he is also correct in surmising that a font is loaded when going to text mode. The normal mode 10H bitmap occupies the first 28,000 bytes of each of the VGAs four planes. (The mode 12H bitmap takes up the first 38,400 bytes of each plane.) The normal mode 3 character/attribute memory map resides in the first 4000 bytes of planes 0 and 1 (the blue and green planes in mode 10H). The standard font in mode 3 is stored in the first 8K of plane 2 (the red plane in mode 10H). Neither mode 3 nor any other text mode makes use of plane 3 (the intensity plane in mode 10H); if necessary, plane 3 could be used as scratch memory in text mode. Consequently, you can get away with saving a total of just under 16K bytesthe first 4000 bytes of planes 0 and 1 and the first 8K bytes of plane 2when going from mode 10H or mode 12H to mode 3, to be restored on returning to graphics mode. Thats hardly all there is to the matter of going from text to graphics and back without bitmap corruption, though. One interesting point is that the mode 10H bitmap can be relocated to A000:8000 simply by doing a mode set to mode 10H and setting the start address (programmed at CRT Controller registers 0CH and 0DH) to 8000H. You can then access display memory starting at A800:8000 instead of the normal A000:0000, with the resultant display exactly like that of normal mode 10H. There are BIOS issues, since the BIOS doesnt automatically access display memory at the new start address, but if your program does all its drawing directly without the help of the BIOS, thats no problem. The mode 12H bitmap cant start at A000:8000, because its so long that it would run off the end of display memory. However, the mode 12H bitmap can be relocated to, say, A000:6000, where it would fit without conflicting with the default font or the normal text mode memory map, although it would overlap two of the upper pages available for use (but rarely used) by text-mode programs. At any rate, once the graphics mode bitmap is relocated, flipping to text mode and back becomes painless. The memory used by mode 3 doesnt overlap the relocated mode 10H bitmap at all (unless additional portions of font memory are loaded), so all you need do is set bit 7 of AL on mode sets in order to flip back and forth between the two modes. Another interesting point about flipping from graphics to text and back is that the standard mode 3 character/attribute map doesnt 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 5.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. LISTING 5.3 L5-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 (640x350) ; ; 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 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 Im 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 5.3, you shouldnt write to any text page other than page 0 (that is, dont 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 Colemans question is an interesting one, and Ive only touched on the intriguing possibilities arising from the various configurations of display memory in VGA graphics and text modes. Right now, though, weve still got the basics of the remarkably complex (but rewarding!) VGA to cover.
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
|