|Previous||Table of Contents||Next|
Given the tremendous advantages of Mode X over the documented mode 13H, Id very much like to get it into the hands of as many developers as possible, so Im going to spend the next few chapters exploring this odd but worthy mode. Ill provide mode set code, delineate the bitmap organization, and show how the basic write pixel and read pixel operations work. Then, Ill move on to the magic stuff: rectangle fills, screen clears, scrolls, image copies, pixel inversion, and, yes, polygon fills (just a different driver for the polygon code), all blurry fast; hardware raster ops; and page flipping. In the end, Ill build a working animation program that shows many of the features of Mode X in action.
The mode set code is the logical place to begin.
We could, if we wished, write our own mode set code for Mode X from scratchbut why bother? Instead, well let the BIOS do most of the work by having it set up mode 13H, which well then turn into Mode X by changing a few registers. Listing 47.1 does exactly that.
The code in Listing 47.1 has been around for some time, and the very first version had a bug that serves up an interesting lesson. The original DDJ version made images roll on IBMs fixed-frequency VGA monitors, a problem that didnt come to my attention until the code was in print and shipped to 100,000 readers.
The bug came about this way: The code I modified to make the Mode X mode set code used the VGAs 28-MHz clock. Mode X should have used the 25-MHz clock, a simple matter of setting bit 2 of the Miscellaneous Output register (3C2H) to 0 instead of 1.
Alas, I neglected to change that single bit, so frames were drawn at a faster rate than they should have been; however, both of my monitors are multifrequency types, and they automatically compensated for the faster frame rate. Consequently, my clock-selection bug was invisible and innocuousuntil it was distributed broadly and everybody started banging on it.
IBM makes only fixed-frequency VGA monitors, which require very specific frame rates; if they dont get what youve told them to expect, the image rolls. The corrected version is the one shown here as Listing 47.1; it does select the 25-MHz clock, and works just fine on fixed-frequency monitors.
Why didnt I catch this bug? Neither I nor a single one of my testers had a fixed-frequency monitor! This nicely illustrates how difficult it is these days to test code in all the PC-compatible environments in which it might run. The problem is particularly severe for small developers, who cant afford to buy every model of every hardware component from every manufacturer; just imagine trying to test network-aware software in all possible configurations!
When people ask why software isnt bulletproof; why it crashes or doesnt coexist with certain programs; why PC clones arent always compatible; why, in short, the myriad irritations of using a PC existthis is a big part of the reason. I guess thats just the price we pay for the unfettered creativity and vast choice of the PC market.
LISTING 47.1 L47-1.ASM
; Mode X (320x240, 256 colors) mode set routine. Works on all VGAs. ; **************************************************************** ; * Revised 6/19/91 to select correct clock; fixes vertical roll * ; * problems on fixed-frequency (IBM 851X-type) monitors. * ; **************************************************************** ; C near-callable as: ; void Set320x240Mode(void); ; Tested with TASM ; Modified from public-domain mode set code by John Bridges. SC_INDEX equ 03c4h ;Sequence Controller Index CRTC_INDEX equ 03d4h ;CRT Controller Index MISC_OUTPUT equ 03c2h ;Miscellaneous Output register SCREEN_SEG equ 0a000h ;segment of display memory in mode X .model small .data ; Index/data pairs for CRT Controller registers that differ between ; mode 13h and mode X. CRTParms label word dw 00d06h ;vertical total dw 03e07h ;overflow (bit 8 of vertical counts) dw 04109h ;cell height (2 to double-scan) dw 0ea10h ;v sync start dw 0ac11h ;v sync end and protect cr0-cr7 dw 0df12h ;vertical displayed dw 00014h ;turn off dword mode dw 0e715h ;v blank start dw 00616h ;v blank end dw 0e317h ;turn on byte mode CRT_PARM_LENGTH equ (($-CRTParms)/2) .code public _Set320x240Mode _Set320x240Mode proc near push bp ;preserve callers stack frame push si ;preserve C register vars push di ; (dont count on BIOS preserving anything) mov ax,13h ;let the BIOS set standard 256-color int 10h ; mode (320x200 linear) mov dx,SC_INDEX mov ax,0604h out dx,ax ;disable chain4 mode mov ax,0100h out dx,ax ;synchronous reset while setting Misc Output ; for safety, even though clock unchanged mov dx,MISC_OUTPUT mov al,0e3h out dx,al ;select 25 MHz dot clock & 60 Hz scanning rate mov dx,SC_INDEX mov ax,0300h out dx,ax ;undo reset (restart sequencer) mov dx,CRTC_INDEX ;reprogram the CRT Controller mov al,11h ;VSync End reg contains register write out dx,al ; protect bit inc dx ;CRT Controller Data register in al,dx ;get current VSync End register setting and al,7fh ;remove write protect on various out dx,al ; CRTC registers dec dx ;CRT Controller Index cld mov si,offset CRTParms ;point to CRT parameter table mov cx,CRT_PARM_LENGTH ;# of table entries SetCRTParmsLoop: lodsw ;get the next CRT Index/Data pair out dx,ax ;set the next CRT Index/Data pair loop SetCRTParmsLoop mov dx,SC_INDEX mov ax,0f02h out dx,ax ;enable writes to all four planes mov ax,SCREEN_SEG ;now clear all display memory, 8 pixels mov es,ax ; at a time sub di,di ;point ES:DI to display memory sub ax,ax ;clear to zero-value pixels mov cx,8000h ;# of words in display memory rep stosw ;clear all of display memory pop di ;restore C register vars pop si pop bp ;restore callers stack frame ret _Set320x240Mode endp end
|Previous||Table of Contents||Next|