154 lines
5.8 KiB
Markdown
154 lines
5.8 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](28-04.html) [Table of Contents](index.html) [Next](29-01.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
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.
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](28-04.html) [Table of Contents](index.html) [Next](29-01.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|