abrash-black-book/50-03.html
2013-12-30 12:21:49 +11:00

225 lines
9.2 KiB
HTML

<HTML>
<HEAD>
<META name=vsisbn content="1576101746">
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
<META name=vsauthor content="Michael Abrash">
<META name=vspublisher content="The Coriolis Group">
<META name=vspubdate content="07/01/97">
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Adding a Dimension</TITLE>
<!-- HEADER -->
<!-- Empty Reference Subhead -->
<!--ISBN=1576101746//-->
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
<!--AUTHOR=Michael Abrash//-->
<!--PUBLISHER=The Coriolis Group, Inc.//-->
<!--CHAPTER=50//-->
<!--PAGES=940-943//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="50-02.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="50-04.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<P><B>LISTING 50.1 L50-1.ASM</B></P>
<!-- CODE //-->
<PRE>
; Draws all pixels in the list of horizontal lines passed in, in
; Mode X, the VGA&#146;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 &amp 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&#146;s stack frame
mov bp,sp ;point to our stack frame
push si ;preserve caller&#146;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&#43;HLineListPtr] ;point to the line list
mov bx,[si&#43;HLinePtr] ;point to the XStart/XEnd descriptor
; for the first (top) horizontal line
mov cx,[si&#43;YStart] ;first scan line to draw
mov si,[si&#43;Lngth] ;# of scan lines to draw
cmp si,0 ;are there any lines to draw?
jle ToFillDone ;no, so we&#146;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 &#43; 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&#43;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&#43;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&#43;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 &amp put in BH
mov si,cx
and si,0003h ;look up right-edge plane
mov bl,RightClipPlaneMask[si] ; mask to clip &amp 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&#146;s more than one byte to draw
and bh,bl ;there&#146;s only one byte, so combine the left
; and right edge clip masks
MasksSet:
mov dx,SC_INDEX&#43;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&#146;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&#146;s register variables
pop si
pop bp ;restore caller&#146;s stack frame
ret
_DrawHorizontalLineList endp
end
</PRE>
<!-- END CODE //-->
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="50-02.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="50-04.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<hr width="90%" size="1" noshade>
<div align="center">
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book &copy; 2001 Michael Abrash</font>
</div>
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
<!-- reference_subfoot = footer -->
<!-- reference_footer = subfoot -->
<!-- BEGIN SUB FOOTER -->
</BODY>
</HTML>
<!-- END FOOTER -->