142 lines
5.3 KiB
Markdown
142 lines
5.3 KiB
Markdown
Listing 28.3 illustrates an efficient use of write mode 3 in conjunction
|
|
with read mode 1 and a Color Don't Care register setting of 0. The mask
|
|
in AL is passed directly to the VGA's bit mask (that's how write mode 3
|
|
works—see Chapter 4 for details). Because the VGA always returns 0FFH,
|
|
the single **AND** instruction loads the latches, and writes the value
|
|
in AL, unmodified, to the VGA, where it is used to generate the bit
|
|
mask. This is more compact and register-efficient than using separate
|
|
instructions to read and write, although it is not necessarily faster by
|
|
cycle count, because on a 486 or a Pentium **MOV** is a 1-cycle
|
|
instruction, but **AND** with memory is a 3-cycle instruction. However,
|
|
given display memory wait states, it is often the case that the two
|
|
approaches run at the same speed, and the register that the above
|
|
approach frees up can frequently be used to save one or more cycles in
|
|
any case.
|
|
|
|
By the way, Listing 28.3 illustrates how write mode 3 can make for
|
|
excellent pixel- and line-drawing code.
|
|
|
|
**LISTING 28.3 L28-3.ASM**
|
|
|
|
; Program that draws a diagonal line to illustrate the use of a
|
|
; Color Don't Care register setting of 0FFH to support fast
|
|
; read-modify-write operations to VGA memory in write mode 3 by
|
|
; drawing a diagonal line.
|
|
;
|
|
; Note: Works on VGAs only.
|
|
;
|
|
; By Michael Abrash
|
|
;
|
|
stack segment word stack 'STACK'
|
|
db 512 dup (?)
|
|
stackends
|
|
;
|
|
VGA_SEGMENT EQU 0a000h
|
|
SCREEN_WIDTH EQU 80 ;in bytes
|
|
GC_INDEX EQU 3ceh ;Graphics Controller Index register
|
|
SET_RESET EQU 0 ;Set/Reset register index in GC
|
|
ENABLE_SET_RESET EQU 1 ;Enable Set/Reset register index in GC
|
|
GRAPHICS_MODE EQU 5 ;Graphics Mode register index in GC
|
|
COLOR_DONT_CARE EQU 7 ;Color Don't Care register index in GC
|
|
;
|
|
code segment word 'CODE'
|
|
assume cs:code
|
|
Startprocnear
|
|
;
|
|
; Select graphics mode 12h.
|
|
;
|
|
mov ax,12h
|
|
int 10h
|
|
;
|
|
; Select write mode 3 and read mode 1.
|
|
;
|
|
mov dx,GC_INDEX
|
|
mov al,GRAPHICS_MODE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx ;VGA registers are readable, bless them!
|
|
or al,00001011b ;bit 3=1 selects read mode 1, and
|
|
; bits 1 & 0=11 selects write mode 3
|
|
jmp $+2 ;delay between IN and OUT to same port
|
|
out dx,al
|
|
dec dx
|
|
;
|
|
; Set up set/reset to always draw in white.
|
|
;
|
|
mov al,SET_RESET
|
|
out dx,al
|
|
inc dx
|
|
mov al,0fh
|
|
out dx,al
|
|
dec dx
|
|
mov al,ENABLE_SET_RESET
|
|
out dx,al
|
|
inc dx
|
|
mov al,0fh
|
|
out dx,al
|
|
dec dx
|
|
;
|
|
; Set Color Don't Care to 0, so reads of VGA memory always return 0FFH.
|
|
;
|
|
mov al,COLOR_DONT_CARE
|
|
out dx,al
|
|
inc dx
|
|
sub al,al
|
|
out dx,al
|
|
;
|
|
; Set up the initial memory pointer and pixel mask.
|
|
;
|
|
mov ax,VGA_SEGMENT
|
|
mov ds,ax
|
|
sub bx,bx
|
|
mov al,80h
|
|
;
|
|
; Draw 400 points on a diagonal line sloping down and to the right.
|
|
;
|
|
mov cx,400
|
|
DrawDiagonalLoop:
|
|
and [bx],al ;reads display memory, loading the latches,
|
|
; then writes AL to the VGA. AL becomes the
|
|
; bit mask, and set/reset provides the
|
|
; actual data written
|
|
add bx,SCREEN_WIDTH
|
|
; point to the next scan line
|
|
ror al,1 ;move the pixel mask one pixel to the right
|
|
adc bx,0 ;advance to the next byte if the pixel mask wrapped
|
|
loopDrawDiagonalLoop
|
|
;
|
|
; Wait for a key to be pressed to end, then return to text mode and
|
|
; return to DOS.
|
|
;
|
|
WaitKeyLoop:
|
|
mov ah,1
|
|
int 16h
|
|
jz WaitKeyLoop
|
|
sub ah,ah
|
|
int 16h ;clear the key
|
|
mov ax,3
|
|
int 10h ;return to text mode
|
|
mov ah,4ch
|
|
int 21h ;done
|
|
Startendp
|
|
code ends
|
|
end Start
|
|
|
|
I hope I've given you a good feel for what color compare mode is and
|
|
what it might be used for. Color compare mode isn't particularly easy to
|
|
understand, but it's not that complicated in actual operation, and it's
|
|
certainly useful at times; take some time to study the sample code and
|
|
perform a few experiments of your own, and you may well find useful
|
|
applications for color compare mode in your graphics code.
|
|
|
|
A final note: The Read Map register has no effect in read mode 1, and
|
|
the Color Compare and Color Don't Care registers have no effect either
|
|
in read mode 0 or when writing to VGA memory. And with that, by gosh,
|
|
we're actually done with the basics of accessing VGA memory!
|
|
|
|
Not to worry—that still leaves us a slew of interesting VGA topics,
|
|
including smooth panning and scrolling, the split screen, color
|
|
selection, page flipping, and Mode X. And that's not to mention actual
|
|
uses to which the VGA's hardware can be put, including lines, circles,
|
|
polygons, and my personal favorite, animation. We've covered a lot of
|
|
challenging and rewarding ground—and we've only just begun.
|