abrash-black-book/47-07.md
2013-12-30 17:51:31 +11:00

163 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

------------------------ --------------------------------- --------------------
[Previous](47-06.html) [Table of Contents](index.html) [Next](48-01.html)
------------------------ --------------------------------- --------------------
**LISTING 47.6 L47-6.ASM**
; Mode X (320x240, 256 colors) rectangle fill routine. Works on all
; VGAs. Uses fast approach that fans data out to up to four planes at
; once to draw up to four pixels at once. Fills up to but not
; including the column at EndX and the row at EndY. No clipping is
; performed.
; C near-callable as:
; void FillRectangleX(int StartX, int StartY, int EndX, int EndY,
; unsigned int PageBase, int Color);
SC_INDEX equ 03c4h ;Sequence Controller Index
MAP_MASK equ 02h ;index in SC of Map Mask register
SCREEN_SEG equ 0a000h ;segment of display memory in mode X
SCREEN_WIDTH equ 80 ;width of screen in bytes from one scan line
; to the next
parms struc
dw 2 dup (?) ;pushed BP and return address
StartX dw ? ;X coordinate of upper left corner of rect
StartY dw ? ;Y coordinate of upper left corner of rect
EndX dw ? ;X coordinate of lower right corner of rect
; (the row at EndX is not filled)
EndY dw ? ;Y coordinate of lower right corner of rect
; (the column at EndY is not filled)
PageBase dw ? ;base offset in display memory of page in
; which to fill rectangle
Color dw ? ;color in which to draw pixel
parms ends
.model small
.data
; Plane masks for clipping left and right edges of rectangle.
LeftClipPlaneMask db 00fh,00eh,00ch,008h
RightClipPlaneMask db 00fh,001h,003h,007h
.code
public _FillRectangleX
_FillRectangleX proc near
push bp ;preserve caller’s stack frame
mov bp,sp ;point to local stack frame
push si ;preserve caller’s register variables
push di
cld
mov ax,SCREEN_WIDTH
mul [bp+StartY] ;offset in page of top rectangle scan line
mov di,[bp+StartX]
shr di,1 ;X/4 = offset of first rectangle pixel in scan
shr di,1 ; line
add di,ax ;offset of first rectangle pixel in page
add di,[bp+PageBase] ;offset of first rectangle pixel in
; display memory
mov ax,SCREEN_SEG ;point ES:DI to the first rectangle
mov es,ax ; pixel’s address
mov dx,SC_INDEX ;set the Sequence Controller Index to
mov al,MAP_MASK ; point to the Map Mask register
out dx,al
inc dx ;point DX to the SC Data register
mov si,[bp+StartX]
and si,0003h ;look up left edge plane mask
mov bh,LeftClipPlaneMask[si]; to clip & put in BH
mov si,[bp+EndX]
and si,0003h ;look up right edge plane
mov bl,RightClipPlaneMask[si]; mask to clip & put in BL
mov cx,[bp+EndX] ;calculate # of addresses across rect
mov si,[bp+StartX]
cmp cx,si
jle FillDone ;skip if 0 or negative width
dec cx
and si,not 011b
sub cx,si
shr cx,1
shr cx,1 ;# of addresses across rectangle to fill - 1
jnz MasksSet ;there’s more than one byte to draw
and bh,bl ;there’s only one byte, so combine the left-
; and right-edge clip masks
MasksSet:
mov si,[bp+EndY]
sub si,[bp+StartY] ;BX = height of rectangle
jle FillDone ;skip if 0 or negative height
mov ah,byte ptr [bp+Color] ;color with which to fill
mov bp,SCREEN_WIDTH ;stack frame isn’t needed any more
sub bp,cx ;distance from end of one scan line to start
dec bp ; of next
FillRowsLoop:
push cx ;remember width in addresses - 1
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the left edge
dec cx ;count off left edge byte
js FillLoopBottom ;that’s the only byte
jz DoRightEdge ;there are only two bytes
mov al,00fh ;middle addresses are drawn 4 pixels at a pop
out dx,al ;set the middle pixel mask to no clip
mov al,ah ;put color in AL
rep stosb ;draw the middle addresses four pixels apiece
DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the right edge
FillLoopBottom:
add di,bp ;point to the start of the next scan line of
; the rectangle
pop cx ;retrieve width in addresses - 1
dec si ;count down scan lines
jnz FillRowsLoop
FillDone:
pop di ;restore caller’s register variables
pop si
pop bp ;restore caller’s stack frame
ret
_FillRectangleX endp
end
Just so you can see Mode X in action, Listing 47.7 is a sample program
that selects Mode X and draws a number of rectangles. Listing 47.7 links
to any of the rectangle fill routines I’ve presented.
And now, I hope, you’re beginning to see why I’m so fond of Mode X. In
the next chapter, we’ll continue with Mode X by exploring the wonders
that the latches and parallel plane hardware can work on scrolls,
copies, blits, and pattern fills.
**LISTING 47.7 L47-7.C**
/* Program to demonstrate mode X (320x240, 256-colors) rectangle
fill by drawing adjacent 20x20 rectangles in successive colors from
0 on up across and down the screen */
#include <conio.h>
#include <dos.h>
void Set320x240Mode(void);
void FillRectangleX(int, int, int, int, unsigned int, int);
void main() {
int i,j;
union REGS regset;
Set320x240Mode();
FillRectangleX(0,0,320,240,0,0); /* clear the screen to black */
for (j = 1; j < 220; j += 21) {
for (i = 1; i < 300; i += 21) {
FillRectangleX(i, j, i+20, j+20, 0, ((j/21*15)+i/21) & 0xFF);
}
}
getch();
regset.x.ax = 0x0003; /* switch back to text mode and done */
int86(0x10, &regset, &regset);
}
------------------------ --------------------------------- --------------------
[Previous](47-06.html) [Table of Contents](index.html) [Next](48-01.html)
------------------------ --------------------------------- --------------------
* * * * *
Graphics Programming Black Book © 2001 Michael Abrash