170 lines
8.4 KiB
Markdown
170 lines
8.4 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[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
|