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

170 lines
8.4 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](50-02.html) [Table of Contents](index.html) [Next](50-04.html)
------------------------ --------------------------------- --------------------
**LISTING 50.1 L50-1.ASM**
; Draws all pixels in the list of horizontal lines passed in, in
; Mode X, the VGA’s undocumented 320x240 256-color mode. Clips to
; the rectangle specified by (ClipMinX,ClipMinY),(ClipMaxX,ClipMaxY).
; Draws to the page specified by CurrentPageBase.
; C near-callable as:
;
; void DrawHorizontalLineList(struct HLineList * HLineListPtr,
; int Color);
;
; All assembly code tested with TASM and MASM
SCREEN_WIDTH equ 320
SCREEN_SEGMENT equ 0a000h
SC_INDEX equ 03c4h ;Sequence Controller Index
MAP_MASK equ 2 ;Map Mask register index in SC
HLine struc
XStart dw ? ;X coordinate of leftmost pixel in line
XEnd dw ? ;X coordinate of rightmost pixel in line
HLine ends
HLineList struc
Lngth dw ? ;# of horizontal lines
YStart dw ? ;Y coordinate of topmost line
HLinePtr dw ? ;pointer to list of horz lines
HLineList ends
Parms struc
dw 2 dup(?) ;return address & pushed BP
HLineListPtr dw ? ;pointer to HLineList structure
Color dw ? ;color with which to fill
Parms ends
.model small
.data
extrn _CurrentPageBase:word,_ClipMinX:word
extrn _ClipMinY:word,_ClipMaxX:word,_ClipMaxY:word
; Plane masks for clipping left and right edges of rectangle.
LeftClipPlaneMask db 00fh,00eh,00ch,008h
RightClipPlaneMask db 001h,003h,007h,00fh
.code
align 2
ToFillDone:
jmp FillDone
public _DrawHorizontalLineList
align 2
_DrawHorizontalLineList proc
push bp ;preserve caller’s stack frame
mov bp,sp ;point to our stack frame
push si ;preserve caller’s register variables
push di
cld ;make string instructions inc pointers
mov dx,SC_INDEX
mov al,MAP_MASK
out dx,al ;point SC Index to the Map Mask
mov ax,SCREEN_SEGMENT
mov es,ax ;point ES to display memory for REP STOS
mov si,[bp+HLineListPtr] ;point to the line list
mov bx,[si+HLinePtr] ;point to the XStart/XEnd descriptor
; for the first (top) horizontal line
mov cx,[si+YStart] ;first scan line to draw
mov si,[si+Lngth] ;# of scan lines to draw
cmp si,0 ;are there any lines to draw?
jle ToFillDone ;no, so we’re done
cmp cx,[_ClipMinY] ;clipped at top?
jge MinYNotClipped ;no
neg cx ;yes, discard however many lines are
add cx,[_ClipMinY] ; clipped
sub si,cx ;that many fewer lines to draw
jle ToFillDone ;no lines left to draw
shl cx,1 ;lines to skip*2
shl cx,1 ;lines to skip*4
add bx,cx ;advance through the line list
mov cx,[_ClipMinY] ;start at the top clip line
MinYNotClipped:
mov dx,si
add dx,cx ;bottom row to draw + 1
cmp dx,[_ClipMaxY] ;clipped at bottom?
jle MaxYNotClipped ;no
sub dx,[_ClipMaxY] ;# of lines to clip off the bottom
sub si,dx ;# of lines left to draw
jle ToFillDone ;all lines are clipped
MaxYNotClipped:
mov ax,SCREEN_WIDTH/4 ;point to the start of the first
mul cx ; scan line on which to draw
add ax,[_CurrentPageBase] ;offset of first line
mov dx,ax ;ES:DX points to first scan line to draw
mov ah,byte ptr [bp+Color] ;color with which to fill
FillLoop:
push bx ;remember line list location
push dx ;remember offset of start of line
push si ;remember # of lines to draw
mov di,[bx+XStart] ;left edge of fill on this line
cmp di,[_ClipMinX] ;clipped to left edge?
jge MinXNotClipped ;no
mov di,[_ClipMinX] ;yes, clip to the left edge
MinXNotClipped:
mov si,di
mov cx,[bx+XEnd] ;right edge of fill
cmp cx,[_ClipMaxX] ;clipped to right edge?
jl MaxXNotClipped ;no
mov cx,[_ClipMaxX] ;yes, clip to the right edge
dec cx
MaxXNotClipped:
cmp cx,di
jl LineFillDone ;skip if negative width
shr di,1 ;X/4 = offset of first rect pixel in scan
shr di,1 ; line
add di,dx ;offset of first rect pixel in display mem
mov dx,si ;XStart
and si,0003h ;look up left-edge plane mask
mov bh,LeftClipPlaneMask[si] ; to clip & put in BH
mov si,cx
and si,0003h ;look up right-edge plane
mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL
and dx,not 011b ;calculate # of addresses across rect
sub cx,dx
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 dx,SC_INDEX+1 ;already points to the Map Mask reg
FillRowsLoop:
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:
LineFillDone:
pop si ;retrieve # of lines to draw
pop dx ;retrieve offset of start of line
pop bx ;retrieve line list location
add dx,SCREEN_WIDTH/4 ;point to start of next line
add bx,size HLine ;point to the next line descriptor
dec si ;count down lines
jnz FillLoop
FillDone:
pop di ;restore caller’s register variables
pop si
pop bp ;restore caller’s stack frame
ret
_DrawHorizontalLineList endp
end
------------------------ --------------------------------- --------------------
[Previous](50-02.html) [Table of Contents](index.html) [Next](50-04.html)
------------------------ --------------------------------- --------------------
* * * * *
Graphics Programming Black Book © 2001 Michael Abrash