mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 01:49:19 +00:00
1165 lines
43 KiB
Plaintext
1165 lines
43 KiB
Plaintext
;
|
||
; File: QuickPolys.a
|
||
;
|
||
; Copyright: © 1981-1990, 1992-1993 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM3> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
|
||
; so they can conditionalized out of the build.
|
||
; <SM2> 6/11/92 stb <sm 6/9/92>stb Synch with QDciPatchROM.a; added comments to
|
||
; PaintVector, SKIPSETUP, DrawPoly.
|
||
; <6> 11/26/90 SMC Fixed L-shaped polygon getting optimized out as a rectangle.
|
||
; With BAL.
|
||
; <5> 7/20/90 gbm Change some identifiers so there aren't any more conflicts
|
||
; <4> 7/11/90 gbm get rid of some assembly warnings
|
||
; <3> 4/6/90 KON Fix PaintVector so if VCount=0 it aborts.
|
||
; <2> 2/13/90 BAL Calculate initial bit offset as a long not a word to support
|
||
; large rowbytes.
|
||
; <1.5> 11/15/89 KON Changed " to ' so new UNLINK macro in colorEqu.a works properly
|
||
; <1.4> 11/2/89 BAL Changed bsr to DrawRect to be a bsr.l for the ROM link.
|
||
; <•1.3> 7/14/89 BAL For Aurora: Final CQD
|
||
; <1.2> 6/30/89 BAL DrawPoly now returns an error code in qdErr before aborting
|
||
; <•1.1> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
|
||
; <1.0> 4/12/89 BAL Blasting in 32-Bit QuickDraw 1.0B1
|
||
; 1/22/89 BAL Made patVPos a long.
|
||
; 10/3/88 BAL Added references to DstRow.
|
||
; 9/22/88 BAL Moved initialization of region state records into GetSeek.
|
||
; 9/19/88 BAL Altered to get CRSRFLAG value from _BitsToPix
|
||
; 9/19/88 BAL Altered to use common stack frame file 'Drawing Vars.a'
|
||
; 12/2/87 AWC Macintosh II rom patch installed this date
|
||
;
|
||
;_______________________________________________________________________________________
|
||
; This code replaces StdPoly with a version that has two important features. It does
|
||
; not use QuickDraw regions, and so does not blow up. In addition, for screen sized
|
||
; polygons it performs about 4 times faster than QuickDraw polygons.
|
||
;_______________________________________________________________________________________
|
||
;
|
||
; modification history
|
||
;
|
||
; <02Dec87> AWC Macintosh II rom patch installed this date
|
||
; <24Mar88> PMAB440 AWC Fixed sorting problem to make QuickPolys match Classic QuickDraw;
|
||
; included QuickPolysEqu.a in QuickPolysPatch.a
|
||
; <26Mar88> PMAB444 AWC Fixed nil NewHandle bug in QuickPolys; refixed save A0 across _FixRatio
|
||
; <31Mar88> PMAB451 AWC Fixed a bug in PMAB440 above and saved registers across FixRatio
|
||
; <19Sep88> BAL Altered to get CRSRFLAG value from _BitsToPix
|
||
; <19Sep88> BAL Altered to use common stack frame file 'Drawing Vars.a'
|
||
; <22Sep88> BAL Moved initialization of region state records into GetSeek.
|
||
; <03Oct88> BAL Added references to DstRow.
|
||
; <22Jan89> BAL Made patVPos a long.
|
||
;
|
||
|
||
XDrawPoly PROC EXPORT ; make sure data structures are at the global level
|
||
ENDPROC
|
||
|
||
;-------------------------------------------------------------
|
||
;
|
||
; Definition of the VectorRec structure
|
||
;
|
||
|
||
YVector Equ 0
|
||
XVector Equ 2
|
||
YDelta Equ 4
|
||
XDelta Equ 6
|
||
VectorSize Equ 8
|
||
|
||
;-------------------------------------------------------------
|
||
;
|
||
; Definition of the EdgeRec structure
|
||
;
|
||
|
||
NextEdge Equ 0 ; pointer to next edge
|
||
PrevEdge Equ NextEdge+4 ; pointer to previous edge
|
||
XValue Equ PrevEdge+4 ; current x position (Fixed)
|
||
XSlope Equ XValue+4 ; slope of the line (Fixed)
|
||
LastY Equ XSlope+4 ; end of the edge
|
||
Sign Equ LastY+2 ; sign of the vector (+1 or -1)
|
||
EdgeRecSize Equ Sign+2 ; size of the EdgeRec structure (20)
|
||
|
||
;-------------------------------------------------------------
|
||
;
|
||
; PROCEDURE SortVectors(Vectors: Ptr; VCount: integer);
|
||
;
|
||
; SortVectors performs a non-recursive QuickSort on an array of
|
||
; vectors (y,x,dy,dx). The vectors are sorted first on y and second
|
||
; on x. The differential values are not examined. This code is
|
||
; a modified version of SortPoints, found in the QuickDraw ROM.
|
||
; The vectors are placed in increasing Y.X order. See the source
|
||
; reference "Algorithms + Data Structures = Programs, p. 80"
|
||
|
||
SortVectors PROC EXPORT
|
||
|
||
ParamSize Equ 6
|
||
Vectors Equ ParamSize+8-4
|
||
VCount Equ Vectors-2
|
||
|
||
VarSize Equ 0
|
||
|
||
Link A6,#VarSize ; no local variables
|
||
MoveM.L D3-D4/A2-A4,-(SP) ; save registers
|
||
Move.L Vectors(A6),A3 ; LeftPtr := start of point array
|
||
Move A3,D3 ; set up low bits for sort
|
||
And #7,D3 ; AWC - #3 => #7
|
||
MoveQ #0,D0 ; clear high word
|
||
Move VCount(A6),D0 ; get VCount
|
||
Ble.S GoHome ; do nothing if no vectors
|
||
Lsl.L #3,D0 ; AWC - #2 => #3; LineCount * 8 for bytes
|
||
Move.L A3,A4
|
||
Add.L D0,A4 ; add to DstStart
|
||
SubQ.L #8,A4 ; AWC - #4 => #8; RightPtr := DstEnd - 8
|
||
Move.L SP,D4 ; remember stack marker
|
||
MoveM.L A3/A4,-(SP) ; push LeftPtr and RightPtr
|
||
RePartition MoveM.L (SP)+,A3/A4 ; pop LeftPtr and RightPtr
|
||
Split Move.L A3,A1 ; IPtr := LeftPtr
|
||
Move.L A4,A2 ; JPtr := RightPtr
|
||
|
||
; Calculate MidPtr and MidPt
|
||
|
||
Move.L A3,D0 ; D0 := LeftPtr + RightPtr
|
||
Add.L A4,D0
|
||
RoxR.L #1,D0 ; divide by 2 for MidPtr
|
||
And #$FFF8,D0 ; AWC - #$FFFC => #$FFF8; truncate to multiple of 8 bytes
|
||
Or D3,D0 ; OR in low bits for vector boundary
|
||
Move.L D0,A0 ; put MidPtr into A0
|
||
Move XVector(A0),D1 ; D1 := MidPt.X
|
||
Move YVector(A0),D2 ; D2 := MidPt.Y
|
||
Bra.S IScan
|
||
|
||
; while IPtr^ < MidPt do IPtr := IPtr + 8
|
||
|
||
NextIPtr AddQ.L #8,A1 ; AWC - #4 => #8; bump IPtr to "right"
|
||
IScan Cmp YVector(A1),D2 ; is MidPt.Y > IPtr^.Y?
|
||
Bgt.S NextIPtr ; yes => continue bumping
|
||
Blt.S JScan ; MidPt.Y < IPtr^.Y? yes => done with IPtr
|
||
Cmp XVector(A1),D1 ; sort on X - is MidPt.X > IPtr^.X?
|
||
Bgt.S NextIPtr ; yes => continue bumping
|
||
Bra.S JScan ; go to loop start
|
||
|
||
; while JPtr^ > MidPt do JPtr := JPtr - 8
|
||
|
||
NextJPtr SubQ.L #8,A2 ; AWC - #4 => #8; decrement JPtr
|
||
JScan Cmp YVector(A2),D2 ; is JPtr^.Y > MidPt.Y?
|
||
Blt.S NextJPtr ; yes => look at the next JPtr
|
||
Bgt.S EndScan ; is JPtr^.Y < MidPt.Y? yes => this partition is done
|
||
Cmp XVector(A2),D1 ; is JPtr^.X > MidPt.X?
|
||
Blt.S NextJPtr ; yes => look at the next JPtr
|
||
|
||
; if IPtr <= JPtr then swap IPtr^ and JPtr^, and bump both pointers
|
||
|
||
EndScan Cmp.L A2,A1 ; is IPtr > JPtr?
|
||
Bgt.S NoSwap ; yes => all done
|
||
Move.L (A1),D0 ; D0 := IPtr^
|
||
Move.L (A2),(A1) ; IPtr^ := JPtr^
|
||
Move.L D0,(A2) ; JPtr^ := D0
|
||
Move.L 4(A1),D0 ; D0 := IPtr^.dy
|
||
Move.L 4(A2),4(A1) ; IPtr^.dy := JPtr^.dy
|
||
Move.L D0,4(A2) ; JPtr^.dy := D0
|
||
AddQ.L #8,A1 ; IPtr := IPtr + 8
|
||
SubQ.L #8,A2 ; JPtr := JPtr - 8
|
||
|
||
; repeat until this partitioning is complete, IPtr > JPtr
|
||
|
||
NoSwap CmpA.L A2,A1 ; is IPtr > JPtr
|
||
Bls.S IScan ; no => loop again
|
||
|
||
; if IPtr < RightPtr then stack request to sort right partition
|
||
|
||
CmpA.L A4,A1 ; is IPtr < RightPtr?
|
||
Bhs.S RightOkay ; yes => continue
|
||
MoveM.L A1/A4,-(SP) ; no => PushPartition(IPtr,RightPtr)
|
||
|
||
RightOkay Move.L A2,A4 ; RightPtr := JPtr
|
||
CmpA.L A4,A3 ; is LeftPtr >= RightPtr?
|
||
Blo.S Split ; no => partition again
|
||
CmpA.L D4,SP ; is stack empty yet?
|
||
Bne.S RePartition ; no => loop for more
|
||
|
||
GoHome MoveM.L (SP)+,D3-D4/A2-A4 ; restore registers
|
||
Unlk A6
|
||
Rtd #ParamSize
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE PaintVector(Vector:VectorArray; VCount:integer; EoFill:boolean;
|
||
; VectRect:Rect; Mode:integer; Pat:Pattern);
|
||
;
|
||
|
||
PaintVector PROC EXPORT
|
||
|
||
ParamSize Equ 18
|
||
Vector Equ ParamSize+8-4
|
||
VCount Equ Vector-2
|
||
EoFill Equ VCount-2
|
||
VectRect Equ EoFill-4
|
||
Mode Equ VectRect-2
|
||
Pat Equ Mode-4
|
||
|
||
IMPORT RSect,ShieldCursor,ShowCursor,TrimRect
|
||
IMPORT PatExpand,ColorMap
|
||
IMPORT XorSlab,DrawSlab,SlabMode,FastSlabMode
|
||
IMPORT GetSeek,BitsToPix
|
||
|
||
;-------------------------------------------------
|
||
;
|
||
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
|
||
;
|
||
; STACK FRAME VARS USED BY SEEKMASK (CALLED BY STRETCHBITS, RGNBLT, DRAWARC, DRAWLINE)
|
||
;
|
||
&CurFile SETC 'DRAWPOLY'
|
||
|
||
INCLUDE 'DrawingVars.a'
|
||
|
||
|
||
;-------------------------------------------------
|
||
|
||
IF &TYPE('Nil') = 'UNDEFINED' THEN
|
||
Nil: Equ 0
|
||
ENDIF
|
||
|
||
; A2 Edge
|
||
; A3 Vector
|
||
; A4 NextActive
|
||
;
|
||
; D3 VCount
|
||
; D4 CurrentY
|
||
; D5 LineFlag/WrapCount
|
||
; D6 LineMove/WrapMove
|
||
|
||
Link A6,#VarSize ; no local variables
|
||
|
||
; from QDciPatchROM.a at BitsToPix come-from patch to abort when there are no edges <sm 6/9/92>stb
|
||
tst.w VCount(A6) ; is number of edges 0? <5Apr90 KON>
|
||
beq abort ; <5Apr90 KON>
|
||
|
||
MoveM.L D3-D7/A2-A4,-(SP) ; save registers
|
||
Move.L SP,OldStacker(A6) ; save the stack pointer
|
||
|
||
|
||
;;;;; Sicko code from DrawArc
|
||
|
||
CLR.L DSTMASKBUF(A6) ;ASSUME NO MASK
|
||
|
||
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
|
||
MOVE.L THEPORT(A0),A4 ;GET CURRENT GRAFPORT
|
||
TST PNVIS(A4) ;IS PNVIS NEG ?
|
||
BLT GOHOME ;YES, QUIT
|
||
|
||
MOVE.W MODE(A6),D1 ;get pen mode Start of <6>
|
||
_GetStreamMode ;strip off alpha bits
|
||
BSET #3,D1 ;set the pattern bit in case the user forgot to
|
||
MOVEQ #$10,D0 ;1 past normal mode range
|
||
BTST #5,D1 ;arithmetic mode?
|
||
BEQ.S @noRith
|
||
CMP #$3A,D1 ;hilite?
|
||
BEQ.S @ok
|
||
MOVEQ #$30,D0 ;1 past arithmetic mode range
|
||
@noRith CMP D0,D1 ;greater than defined range?
|
||
BGT GOHOME
|
||
@ok MOVE D1,LOCMODE(A6) ;copy mode for colormap End of <6>
|
||
|
||
LEA EXPAT(A6),A0 ;DUMMY PATTERN USED IN ONESLAB
|
||
MOVE.L A0,(A0) ;POINT IT AT ITSELF
|
||
CLR.l PATVPOS(A6) ;INITIALIZE IN CASE NO PATTERN <BAL 22Jan89>
|
||
CLR PATVMASK(A6) ;INITIALIZE IN CASE NO PATTERN
|
||
MOVE #1,PATROW(A6) ;INITIALIZE IN CASE NO PATTERN
|
||
|
||
;----------------------------------------------------------------
|
||
;
|
||
; MAKE SURE THE STACK IS ON A LONGWORD BOUNDARY (FOR FAST BUFFERS)
|
||
;
|
||
MOVE.L SP,D1 ;GET THE STACK POINTER
|
||
AND.B #$FC,D1 ;FORCE LONG ALIGNMENT
|
||
MOVE.L D1,SP ;USE IT
|
||
|
||
|
||
;----------------------------------------------------
|
||
;
|
||
; CONVERT PORTBITS TO A PIXMAP
|
||
; (A5 must contain global ptr)
|
||
;
|
||
LEA PORTBITS(A4),A1 ;PUSH POINTER TO PORTBITS
|
||
LEA DSTPIX(A6),A2 ;AND COPY INTO DSTPIX
|
||
_BitsToPix ;CONVERT BITMAP
|
||
;FromPaintVector ;(as seen in QDciPatchROM.a)
|
||
MOVE.L D1,REALBOUNDS(A6) ;SAVE REAL DST BOUNDS.TOPLEFT
|
||
MOVE.B D2,CRSRFLAG(A6) ;REMEMBER IF DST IS SCREEN <BAL 18Sep88>
|
||
|
||
|
||
;----------------------------------------------------
|
||
;
|
||
; CONVERT PIXEL DEPTH TO SHIFT AMOUNT TO AVOID MULTIPLIES
|
||
;
|
||
LEA SHFTTBL,A0 ;POINT TO SHIFT TABLE
|
||
MOVE DSTPIX+PIXELSIZE(A6),D0 ;GET DST PIXEL SIZE
|
||
MOVEQ #0,D1 ;DEFAULT SHIFT = 0
|
||
MOVE.B 0(A0,D0),D1 ;GET SRC SHIFT
|
||
MOVE D1,DSTSHIFT(A6) ;AND SAVE DST SHIFT AMOUNT
|
||
|
||
|
||
;----------------------------------------------------------------
|
||
;
|
||
; SET UP NEWPATTERN TO INDICATE OLD OR NEW STYLE PATTERN
|
||
; ALSO SET UP LOCAL PATTERN POINTER, LOCPAT(A6)
|
||
;
|
||
MOVE.L PAT(A6),LOCPAT(A6) ;COPY PATTERN POINTER
|
||
TST PORTBITS+ROWBYTES(A4) ;IS THE DST OLD OR NEW?
|
||
SMI NEWPATTERN(A6) ;FLAG = TRUE IF NEW PATTERN
|
||
|
||
|
||
;----------------------------------------------------------------
|
||
;
|
||
; ADJUST MODE AND PATTERN IF COLOR FILTERING.
|
||
; (A5 must contain global ptr)
|
||
;
|
||
CLR.B multiColor(A6) ;use fg/bg color
|
||
_COLORMAP ;ALTER BY THECOLOR, THEFILTER
|
||
|
||
|
||
;---------------------------------------------------------
|
||
;
|
||
; GET CLIPRGN AND VISRGN HANDLES AND DE-REFERENCE THEM
|
||
;
|
||
MOVE.L CLIPRGN(A4),A2 ;GET CLIPRGN HANDLE
|
||
MOVE.L (A2),A2 ;GET CLIPRGN POINTER
|
||
MOVE.L VISRGN(A4),A3 ;GET VISRGN HANDLE
|
||
MOVE.L (A3),A3 ;GET VISRGN POINTER
|
||
|
||
|
||
;-----------------------------------------------------------------------
|
||
;
|
||
; CALC MINRECT, THE INTERSECTION OF DSTRECT, BITMAP BOUNDS,
|
||
; CLIPRGN BBOX, AND VISRGN BBOX. QUIT IF NO INTERSECTION.
|
||
;
|
||
MOVE.L VectRect(A6),-(SP) ;PUSH VectRect
|
||
PEA DSTPIX+BOUNDS(A6) ;PUSH BITMAP BOUNDS
|
||
PEA RGNBBOX(A2) ;PUSH CLIPRGN BBOX
|
||
PEA RGNBBOX(A3) ;PUSH VISRGN BBOX
|
||
MOVE #4,-(SP) ;PUSH NRECTS=4
|
||
PEA MINRECT(A6) ;PUSH DST ADDR
|
||
_RSECT ;CALC INTERSECTION
|
||
BEQ GOHOME ;QUIT IF NO INTERSECT
|
||
|
||
|
||
;--------------------------------------------------
|
||
;
|
||
; CHECK FOR BOTH VISRGN AND CLIPRGN RECTANGULAR
|
||
;
|
||
CLR.B FASTFLAG(A6) ;FASTFLAG := FALSE
|
||
CMP #10,RGNSIZE(A2) ;IS CLIPRGN RECTANGULAR ?
|
||
BNE.S FLAGOK ;NO, CONTINUE
|
||
CMP #10,RGNSIZE(A3) ;IS VISRGN RECTANGULAR ?
|
||
BEQ.S CKPAT ;YES, CONTINUE
|
||
|
||
|
||
;--------------------------------------------------
|
||
;
|
||
; If only visRgn is non-rectangular, then check if
|
||
; its intersection with minrect would be rectangular.
|
||
; IF TrimRect(visRgn,minRect) then treat as rectangular.
|
||
;
|
||
MOVE.L visRgn(A4),-(SP) ;push rgnHandle
|
||
PEA minRect(A6) ;push addr of minRect
|
||
MOVE.W #-1,-(SP) ;pass Trim = True
|
||
_TrimRect ;call trimRect
|
||
BLT GOHOME ;quit if intersection empty
|
||
BGT.S FLAGOK ;continue if non-rectangular
|
||
|
||
|
||
;--------------------------------------------------
|
||
;
|
||
; CHECK FOR BLACK OR WHITE PATTERN
|
||
;
|
||
CKPAT BTST #5,LocMode+1(A6) ;an arithmetic mode?
|
||
BNE.S FlagOK ;skip fast case if so
|
||
|
||
MOVE.L LOCPAT(A6),A0 ;POINT TO PATTERN
|
||
TST.B NEWPATTERN(A6) ;is it a new pattern? <C945 20Mar89 BAL>
|
||
BEQ.S @oldPat ;=>yes, skip pixpat fields <C945 20Mar89 BAL>
|
||
|
||
MOVE.L (a0),a0 ;get the pixpat handle <C945 20Mar89 BAL>
|
||
MOVE.L (a0),a0 ;get the pixpat pointer <C945 20Mar89 BAL>
|
||
TST PATTYPE(A0) ;is it an old-style pattern? <C945 20Mar89 BAL>
|
||
BNE.S FLAGOK ;=>no, skip fast case <C945 20Mar89 BAL>
|
||
|
||
MOVE.L patData(a0),a0 ;get handle to pattern data <C945 20Mar89 BAL>
|
||
MOVE.L (a0),a0 ;get pattern ptr <C945 20Mar89 BAL>
|
||
|
||
@oldPat MOVE.L (A0)+,D0 ;GET 1ST HALF OF PATTERN
|
||
CMP.L (A0)+,D0 ;IS IT SAME AS 2ND HALF ?
|
||
BNE.S FLAGOK ;NO, CONTINUE
|
||
NOT.L D0 ;IS PATTERN BLACK ?
|
||
BEQ.S YESFLAG ;YES, WE MADE IT
|
||
NOT.L D0 ;IS PATTERN WHITE ?
|
||
BNE.S FLAGOK ;NO, CONTINUE
|
||
EOR #4,LOCMODE(A6) ;YES, ALTER MODE AS IF BLACK
|
||
YESFLAG ST FASTFLAG(A6) ;REMEMBER RECT CLIPPED AND BLACK
|
||
|
||
|
||
;--------------------------------------------------
|
||
;
|
||
; fast case: map mode into black,xor,white, or do-nothing
|
||
;
|
||
MOVEQ #7,D0 ;GET 3 BIT MASK
|
||
AND LOCMODE(A6),D0 ;GET 3 BITS OF MODE
|
||
MOVE.B MODEMAP(D0),D0 ;MAP TO BLACK,XOR,WHITE,NOP
|
||
BMI GOHOME ;QUIT IF DO-NOTHING MODE
|
||
MOVE D0,LOCMODE(A6) ;UPDATE MODE
|
||
BRA.S FLAGOK ;AND CONTINUE
|
||
|
||
MODEMAP DC.B 0,0,1,2,2,255,255,255
|
||
FLAGOK
|
||
|
||
;----------------------------------------------------------------
|
||
;
|
||
; HIDE CURSOR IF CURSOR INTERSECTS MINRECT AND DST IS SCREEN.
|
||
;
|
||
TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? <BAL 19Sep88>
|
||
BEQ.S NOTSCREEN ;=>NO
|
||
PEA MINRECT(A6) ;PUSH SHIELDRECT PARAMETER
|
||
MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL
|
||
_SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
|
||
|
||
NOTSCREEN
|
||
;------------------------------------
|
||
;
|
||
; CALC BUFLEFT
|
||
;
|
||
MOVE DSTSHIFT(A6),D5 ;GET SHIFT FOR PIXEL DEPTH
|
||
MOVE MINRECT+LEFT(A6),D2 ;GET MINRECT LEFT
|
||
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT TO GLOBAL COORDS
|
||
EXT.L D2 ;MAKE IT A LONG
|
||
LSL.L D5,D2 ;CONVERT PIXELS TO BITS
|
||
AND.l #~$1f,D2 ;TRUNC TO MULT OF 32 BITS
|
||
MOVE.L D2,D0 ;GET FOR PATHPOS CALC
|
||
LSR.L #3,D0 ;CONVERT TO BYTES
|
||
MOVE D0,PATHPOS(A6) ;SAVE FOR BIG PATTERNS
|
||
LSR.L D5,D2 ;CONVERT BITS TO PIXELS
|
||
ADD DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BACK TO GLOBAL
|
||
MOVE D2,BUFLEFT(A6) ;SAVE AS BUFLEFT
|
||
;
|
||
; IF FASTFLAG, THEN SKIP REGION SETUP
|
||
;
|
||
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
|
||
BNE SKIPSETUP ;YES, DON'T WASTE TIME WITH SETUP
|
||
;
|
||
; CALC expansion buffer = [ (minRect.right-minRect.left) div 32 + 1 ] * pixelsize - 1
|
||
; CALC bufSize = [ (minRect.right-minRect.left) * pixelsize - 1 ] div 32 <C954> 20Mar89 BAL
|
||
;
|
||
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
|
||
SUB D2,D0 ;CALC MAXH-BUFLEFT
|
||
move d0,d1 ;save for expansion scanline buffer <C954>
|
||
|
||
ext.l d1 ;clear out high word <C954>
|
||
lsl.l d5,d1 ;convert to bits <C954>
|
||
subq.l #1,d1 ;force downward round <C954>
|
||
LSR.l #5,D1 ;GET NUMBER OF LONGS IN SCANBUF - 1 <C954>
|
||
MOVE D1,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 <C954>
|
||
|
||
LSR #5,D0 ;get (pixels in scanbuf)/32 <C954>
|
||
ADDQ #1,D0 ;MAKE IT ONE BASED
|
||
LSL D5,D0 ;CONVERT PIXELS TO BITS
|
||
SUBQ #1,D0 ;MAKE 0 BASED AGAIN
|
||
|
||
;-------------------------------------------------------------------------
|
||
;
|
||
; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK
|
||
;
|
||
CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR ONE LONG
|
||
DBRA D0,CLRMASK ;LOOP TILL DONE
|
||
MOVE.L SP,RGNBUFFER(A6) ;REMEMBER WHERE RGNBUFFER IS
|
||
|
||
|
||
;--------------------------------------------------------------------
|
||
;
|
||
; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION
|
||
; GET SEEK ROUTINE INTO SEEKMASK(A6)
|
||
; GET EXPAND ROUTINE INTO EXRTN(A6) FOR SEEK ROUTINE
|
||
; Clobbers: A0-A3, D0-D4
|
||
;
|
||
lea Show,a0 ;get go home routine
|
||
move.l a0,goShow(a6) ;pass to getSeek <BAL 21Mar89>
|
||
move.l maskbc,StackFree(a6) ;pretend lots of stack <BAL 21Mar89>
|
||
|
||
clr.l DstRow(a6) ;flag as seeking down
|
||
clr.l runBuf(a6) ;don't use run clipping <1.2> BAL
|
||
MOVE.L VISRGN(A4),-(SP) ;PUSH THEPORT^.VISRGN
|
||
MOVE.L CLIPRGN(A4),-(SP) ;PUSH THEPORT^.CLIPRGN
|
||
MOVE.L #1,-(SP) ;PUSH HANDLE COUNT - 1
|
||
_GETSEEK ;GET EXPAND ROUTINE INTO EXRTN(A6)
|
||
;AND SEEK ROUTINE INTO SEEKMASK(A6)
|
||
|
||
SKIPSETUP
|
||
;------------------------------------
|
||
;
|
||
; CALC STARTING DSTLEFT
|
||
;
|
||
; from patches to FastSlabMode and GetSeek in QDciPatchROM.a <sm 6/9/92>stb
|
||
|
||
MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP
|
||
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT TO GLOBAL COORDS
|
||
MOVE DSTPIX+ROWBYTES(A6),D0 ;GET DST ROWBYTES
|
||
AND #nuRBMask,D0 ;CLEAR FLAG BITS
|
||
EXT.L D0 ;MAKE IT LONG
|
||
MOVE.L D0,DSTROW(A6) ;SAVE FOR LATER
|
||
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
|
||
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
|
||
|
||
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
|
||
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
|
||
ext.l d2 ;clear out high end <BAL 13Feb90>
|
||
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
|
||
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
|
||
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
|
||
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
|
||
ADD.L D2,D1 ;ADD HORIZ BYTE OFFSET
|
||
MOVE.L D1,DSTLEFT(A6) ;SAVE AS DSTLEFT
|
||
|
||
|
||
;----------------------------------------------------
|
||
;
|
||
; MAKE ALL HORIZONTAL COORDINATES RELATIVE TO BUFFER
|
||
;
|
||
MOVE BUFLEFT(A6),D1 ;GET LEFT OF BUFFER
|
||
SUB D1,MINRECT+LEFT(A6)
|
||
SUB D1,MINRECT+RIGHT(A6)
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; SET UP CASE JUMP BASED ON MODE AND FASTFLAG
|
||
;
|
||
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
|
||
TST.B FastFlag(A6) ;Rect clipped and black ?
|
||
BEQ.S @1 ;no, use slow drawslab loop
|
||
_FastSlabMode ;yes, get fast modeCase in A4
|
||
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
|
||
BRA.S GOFORIT ;SKIP PATTERN STUFF
|
||
|
||
@1
|
||
;------------------------------------------------------------------
|
||
;
|
||
; ALLOCATE EXPANDED PATTERN BUFFER.
|
||
; EXPAND BYTE PATTERN TO PROPER DEPTH AND INIT PATTERN SELECTOR
|
||
;
|
||
CLR.L D7 ;SAY NOT INVERTED
|
||
MOVE LOCMODE(A6),D2 ;GET MODE
|
||
BTST #5,D2 ;a new arithmetic mode? <BAL 17Jan89>
|
||
BNE.S NOTINV ;if so, no invert bit to test <BAL 17Jan89>
|
||
BCLR #2,D2 ;TEST AND CLR INVERT BIT
|
||
BEQ.S NOTINV ;SKIP IF NOT INVERTED
|
||
NOT.L D7 ;INVERTED; D7 GETS ALL 1'S
|
||
|
||
NOTINV _PATEXPAND ;EXPAND 8 BYTE PATTERN TO 16 LONGS
|
||
;SET UP PATROW,PATHMASK,PATVMASK
|
||
MOVE PATROW(A6),D1 ;BIG PATTERN USED?
|
||
BNE.S DONEW ;=>YES, GO USE IT
|
||
|
||
MOVEQ #$F,D0 ;ELSE 16 ROWS OF PATTERN
|
||
MOVEQ #4,D1 ;GET PATTERN ROWBYTES
|
||
MOVE D1,PATROW(A6) ;SET PATTERN ROWBYTES
|
||
MOVE #3,PATHMASK(A6) ;HORIZONTAL MASK FOR PATTERN
|
||
MOVE #$3F,PATVMASK(A6) ;VERTICAL MASK FOR PATTERN
|
||
BRA.S DOOLD ;=>GO GET VERTICAL OFFSET
|
||
|
||
; NEW PATTERN. SET STARTING VERT POSITION, SET FLAG.
|
||
|
||
DONEW MOVEQ #0,D0 ;CLEAR HIGH WORD
|
||
MOVE PATVMASK(A6),D0 ;GET VERTICAL MASK
|
||
ADDQ #1,D0 ;CONVERT TO COUNT
|
||
DIVU PATROW(A6),D0 ;DIVIDE BY ROWSIZE
|
||
SUBQ #1,D0 ;CONVERT TO ROW MASK
|
||
|
||
DOOLD AND MINRECT+TOP(A6),D0 ;GET TOP VERT LOCAL COORD
|
||
MULU D1,D0 ;CALC OFFSET INTO PATTERN
|
||
MOVE.l D0,PATVPOS(A6) ;SAVE AS PATVPOS <BAL 22Jan89>
|
||
|
||
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
|
||
_SlabMode ;GET SLOW MODECASE IN A4
|
||
;RELIES ON PATROW(A6)
|
||
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
|
||
|
||
|
||
GOFORIT
|
||
;-----------------------------------------------------------
|
||
;
|
||
; Switch to 32 bit addressing mode
|
||
;
|
||
moveq #true32b,d0 ;switch to 32 bit addressing
|
||
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
|
||
move.b d0,MMUsave(a6) ;save previous state for later
|
||
|
||
;;;;; End of sicko code from DrawArc
|
||
|
||
Clr.L FreeList(A6) ; FreeList := nil;
|
||
Clr.L ActiveList(A6) ; ActiveList := nil;
|
||
_StackSpace ; how much stack is available
|
||
Move.L SP,D1 ; grab current stack
|
||
Sub.L D0,D1 ; calculate the maximum stack limit
|
||
Add.L #qdStackXtra,D1 ; give us some spare room <1.2> BAL
|
||
Move.L D1,StackLimit(A6) ; save it
|
||
Move.L Vector(A6),D0 ; get pointer to VectorArray
|
||
_rTranslate24To32 ; <BAL/DJW 20Mar89>
|
||
move.l d0,a3 ; get 32 bit clean ptr <BAL/DJW 20Mar89>
|
||
Move (A3),D4 ; get CurrentY
|
||
Move D4,Vert(A6) ; set up for SeekMask
|
||
Move VCount(A6),D3 ; get number of edges
|
||
ActiveLoop MoveQ #Nil,A0 ; NewEdges := nil
|
||
MoveQ #Nil,A1 ; CurrentEdge := nil
|
||
|
||
; while (Vector < VCount) & (CurrentY = Vectors[Vector+1].YVector) do begin
|
||
|
||
Tst D3 ; any new edges left?
|
||
Beq NoNewEdges ; no => don't add any new
|
||
NewEdgeLoop Cmp (A3),D4 ; does CurrentY = NextY?
|
||
Bne NoNewEdges ; no => don't add any at the moment
|
||
Move.L FreeList(A6),A2 ; grab the FreeList
|
||
Move.L A2,D0 ; CmpA #Nil,A2; can we get an edge from the free list?
|
||
Bne.S FreeAndEasy ; yes => good enough
|
||
SubA.L #EdgeRecSize,SP ; make room for daddy
|
||
Move.L SP,A2 ; and create a new edge on the stack (gross)
|
||
CmpA.L StackLimit(A6),A2 ; have we bombed
|
||
Bge.S StackEdge ; no => keep trucking
|
||
move.w #-144,qdErr ; return aborted poly error code <1.2> BAL
|
||
Bra NoMorePoly ; yes => get out of here
|
||
|
||
FreeAndEasy Move.L (A2),FreeList(A6) ; FreeList := FreeList^.NextEdge
|
||
StackEdge MoveM.L A0-A1,-(SP) ; save registers across the FixRatio AWC.PMAB451
|
||
Clr.L -(SP) ; FixRatio result
|
||
Move.L YDelta(A3),-(SP) ; push numerator and denominator for FixRatio
|
||
_FixRatio ; calculate it
|
||
|
||
; The following few lines are excerpted from the PutLine code of Quickdraw so we can match
|
||
; the old polygon code precisely in terms of pixels rendered.
|
||
|
||
Move.L (SP)+,D2 ; D2 := slope
|
||
MoveM.L (SP)+,A0-A1 ; restore registers AWC.PMAB451
|
||
Move XVector(A3),D1 ; HiWord(D1) := XVector
|
||
Sub BufLeft(A6),D1 ; adjust to global coordinates
|
||
Swap D1 ; put the coordinate in the high word
|
||
Move #$8000,D1 ; LoWord(XVector) := 1/2
|
||
Move.L D2,D0 ; D0 := slope
|
||
Asr.L #1,D0 ; D0 := slope/2
|
||
Add.L D0,D1 ; XValue := XValue + Slope/2
|
||
Move.L #$10000,D0 ; D0 := 1.0000 fixed
|
||
Tst.L D2 ; is slope negative?
|
||
Bmi.S NegSlope ; yes => continue
|
||
Cmp.L D0,D2 ; is slope < 1.0000?
|
||
Bge.S SlopeOkay ; no => continue
|
||
Add.L D2,D1 ; XValue := XValue + Slope
|
||
Bra.S SlopeOkay ; continue
|
||
|
||
NegSlope Cmp.L #$FFFF0000,D2 ; is slope > -1.0000?
|
||
Bge.S SlopeOkay ; yes => continue
|
||
Add.L D0,D1 ; XValue := XValue + 1.0000
|
||
|
||
SlopeOkay Move.L D1,XValue(A2) ; XValue := D1
|
||
Move.L D2,XSlope(A2) ; XSlope := FixRatio(XVector,YVector)
|
||
MoveQ #1,D1 ; Sign := 1
|
||
Move YDelta(A3),D0 ; D0 := abs(YDelta)
|
||
Bpl.S SignOkay ; don't negate it
|
||
Neg D0 ; abs(YDelta)
|
||
Neg D1 ; Sign := -1
|
||
SignOkay Add D4,D0 ; D0 := CurrentY + abs(YDelta)
|
||
Move D0,LastY(A2) ; Edge^.LastY := CurrentY + abs(YDelta)
|
||
Tst.B EoFill(A6) ; are we EoFill'ing?
|
||
Beq.S Winder ; no => leave sign alone
|
||
MoveQ #0,D1 ; Sign := 0
|
||
Winder Move D1,Sign(A2) ; save Sign
|
||
|
||
Move.L A0,D0 ; CmpA.L #Nil,A0; is NewEdges nil? AWC.PMAB440
|
||
Bne.S InsertMid ; no => insert this new edge in the list AWC.PMAB440
|
||
Move.L A2,A0 ; NewEdges := Edge AWC.PMAB440
|
||
Move.L A2,A1 ; CurrentEdge := Edge AWC.PMAB440
|
||
Clr.L NextEdge(A2) ; end of list AWC.PMAB440
|
||
Clr.L PrevEdge(A2) ; beginning of list, too AWC.PMAB440
|
||
Bra.S InsertDone ; continue AWC.PMAB440
|
||
|
||
InsertMid Move.L A1,A4 ; InsertPt := CurrentEdge AWC.PMAB440
|
||
Move.L XValue(A2),D0 ; grab our compare value AWC.PMAB440
|
||
InsertNext Cmp.L XValue(A4),D0 ; D0 - InsertPt^.XValue AWC.PMAB440
|
||
Bge.S InsertIt ; if greater or equal, insert it AWC.PMAB440
|
||
Move.L PrevEdge(A4),A4 ; InsertPt := InsertPt^.NextEdge AWC.PMAB440
|
||
Move.L A4,D1 ; is the next edge nil? AWC.PMAB440
|
||
Bne.S InsertNext ; no => keep looking AWC.PMAB440
|
||
Move.L A0,NextEdge(A2) ; Edge^.NextEdge := NewEdges AWC.PMAB440
|
||
Move.L A2,PrevEdge(A0) ; NewEdges^.PrevEdge := Edge AWC.PMAB440
|
||
Clr.L PrevEdge(A2) ; Edge^.PrevEdge := nil AWC.PMAB440
|
||
Move.L A2,A0 ; NewEdges := Edge AWC.PMAB440
|
||
Bra.S InsertDone ; continue AWC.PMAB440
|
||
|
||
InsertIt CmpA.L A1,A4 ; at the end of the list? AWC.PMAB440
|
||
Beq.S InsertEnd ; yes => insert this edge at the end of list AWC.PMAB440
|
||
Move.L A4,PrevEdge(A2) ; Edge^.PrevEdge := InsertPt AWC.PMAB440
|
||
Move.L NextEdge(A4),D0 ; save InsertPt^.NextEdge AWC.PMAB440
|
||
Move.L A2,NextEdge(A4) ; InsertPt^.NextEdge := Edge AWC.PMAB451
|
||
Move.L D0,NextEdge(A2) ; Edge^.NextEdge := InsertPt^.NextEdge AWC.PMAB440
|
||
Move.L D0,A4 ; InsertPt := InsertPt^.NextEdge AWC.PMAB440
|
||
Move.L A2,PrevEdge(A4) ; InsertPt^.NextEdge^.PrevEdge := Edge AWC.PMAB440
|
||
Bra.S InsertDone ; continue AWC.PMAB440
|
||
|
||
InsertEnd Move.L A2,NextEdge(A1) ; CurrentEdge^.NextEdge := Edge AWC.PMAB440
|
||
Move.L A1,PrevEdge(A2) ; Edge^.PrevEdge := CurrentEdge AWC.PMAB440
|
||
Clr.L NextEdge(A2) ; Edge^.NextEdge := nil AWC.PMAB440
|
||
Move.L A2,A1 ; CurrentEdge := Edge AWC.PMAB440
|
||
InsertDone AddA.L #VectorSize,A3 ; bump A3 to the next vector AWC.PMAB440
|
||
SubQ #1,D3 ; VCount := VCount - 1
|
||
Bgt NewEdgeLoop ; check for more edges
|
||
|
||
; Merge the NewEdges with the ActiveList
|
||
|
||
NoNewEdges Move.L #Nil,A1 ; CurrentEdge := nil
|
||
Move.L ActiveList(A6),A4 ; NextActive := ActiveList
|
||
MergeLoop Move.L A4,D0 ; CmpA.L #Nil,A4; is NextActive nil?
|
||
Bne.S NextOrMerge ; no => merge edges
|
||
Move.L A0,D0 ; CmpA.L #Nil,A0; is NewEdges nil?
|
||
Beq.S Merged ; yes => don't merge edges
|
||
|
||
; NextActive = nil; NewEdges <> nil
|
||
|
||
Move.L A1,PrevEdge(A0) ; NewEdges^.PrevEdge := CurrentEdge; is CurrentEdge nil?
|
||
Bne.S C1 ; no => fix up CurrentEdge^.NextEdge
|
||
Move.L A0,ActiveList(A6) ; ActiveList := NewEdges
|
||
Bra.S Merged ; continue
|
||
|
||
C1 Move.L A0,NextEdge(A1) ; CurrentEdge^.NextEdge := NewEdges
|
||
Bra.S Merged ; continue
|
||
|
||
; else if NewEdges = nil { and therefore NextActive <> nil } then begin
|
||
|
||
NextOrMerge Move.L A0,D0 ; CmpA.L #Nil,A0; is NewEdges nil?
|
||
Bne.S MergeEdges ; no => merge edges
|
||
Move.L A1,PrevEdge(A4) ; NextActive^.PrevEdge := CurrentEdge; is CurrentEdge nil?
|
||
Bne.S C2 ; no => append NextActive to the list
|
||
Move.L A4,ActiveList(A6) ; ActiveList := NextActive
|
||
Bra.S Merged ; continue
|
||
|
||
C2 Move.L A4,NextEdge(A1) ; CurrentEdge^.NextEdge := NextActive
|
||
Bra.S Merged ; continue
|
||
|
||
; else { both are still active so } begin
|
||
|
||
MergeEdges Move.L XValue(A4),D0 ; get NextActive^.XValue
|
||
Cmp.L XValue(A0),D0 ; is NextActive^.XValue > NewEdges^.XValue?
|
||
Ble.S C3 ; no => select NextActive
|
||
Move.L A0,A2 ; Edge := NewEdges
|
||
Move.L NextEdge(A2),A0 ; NewEdges := Edge^.NextEdge
|
||
Bra.S C4 ; continue
|
||
|
||
C3 Move.L A4,A2 ; Edge := NextActive
|
||
Move.L NextEdge(A2),A4 ; NextActive := Edge^.NextEdge
|
||
C4 Move.L A1,PrevEdge(A2) ; Edge^.PrevEdge := CurrentEdge; is CurrentEdge nil?
|
||
Bne.S C5 ; no => patch CurrentEdge
|
||
Move.L A2,ActiveList(A6) ; ActiveList := Edge
|
||
Bra.S C6 ; continue
|
||
|
||
C5 Move.L A2,NextEdge(A1) ; CurrentEdge^.NextEdge := Edge
|
||
C6 Clr.L NextEdge(A2) ; Edge^.NextEdge := nil
|
||
Move.L A2,A1 ; CurrentEdge := Edge
|
||
Bra.S MergeLoop ; continue
|
||
|
||
Merged
|
||
|
||
;;;;; More DrawArc craziness
|
||
|
||
CMP MINRECT+TOP(A6),D4 ;IS CURRENT VERT < MINV ?
|
||
BLT.S NoMask ;YES, DON'T DRAW
|
||
|
||
; SEEK MASK TO THE CURRENT VERTICAL
|
||
|
||
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
|
||
BNE.S NOMASK ;YES, DON'T BOTHER WITH MASK
|
||
Move D4,Vert(A6) ; SeekMask seems to want this...
|
||
JSR ([SEEKMASK,A6]) ;MAKE RGNBUFFER CURRENT
|
||
|
||
NoMask Move.L ActiveList(A6),A4 ; NextActive := ActiveList
|
||
MoveQ #0,D5 ; LineFlag := false or WrapCount := 0
|
||
SlabLoop Move.L A4,A1 ; CurrentEdge := NextActive
|
||
Move.L NextEdge(A1),A4 ; NextActive := CurrentEdge^.NextEdge
|
||
Cmp LastY(A1),D4 ; is LastY <= CurrentY?
|
||
Bge RemoveEdge ; yes => go remove the edge
|
||
Move Sign(A1),D0 ; grab the sign
|
||
Beq.S Toggle ; if zero then EoFill, toggle the flag
|
||
Tst D5 ; is current wrapcount 0?
|
||
Bne.S NoWrapMove ; no => don't establish WrapMove
|
||
Move XValue(A1),D6 ; save wrapmove
|
||
NoWrapMove Add D0,D5 ; WrapCount += Sign; is it 0?
|
||
Bne.S BumpX ; no => don't draw a line
|
||
NoLineMove Move XValue(A1),D0 ; grab current value
|
||
Cmp D6,D0 ; is line XValue.HiWord > move XValue.HiWord?
|
||
Bgt.S DrawLine ; yes => draw a line
|
||
Bra.S BumpX ; continue
|
||
|
||
Toggle Eor #1,D5 ; toggle D5
|
||
Beq.S NoLineMove ; yes => go draw the line
|
||
Move XValue(A1),D6 ; save line mvoe
|
||
Bra.S BumpX ; continue
|
||
|
||
DrawLine
|
||
CMP MINRECT+TOP(A6),D4 ;IS CURRENT VERT < MINV ?
|
||
Blt.S BumpX ;YES, DON'T DRAW
|
||
|
||
Move D6,D1 ; get start of slab
|
||
Move D0,D2 ; get end of slab
|
||
MoveM.L D3-D6/A1-A4,-(SP) ; save everything
|
||
|
||
MOVE.l PATVPOS(A6),D6 ;GET VERT POS IN PATTERN <BAL 22Jan89>
|
||
LEA ([EXPAT,A6],D6.l),A0 ;GET pointer to THIS ROW'S PATTERN
|
||
MOVE.L (A0),D6 ;set up the pattern
|
||
MOVE.L DSTLEFT(A6),A1 ;INIT DSTPTR TO LEFT
|
||
MOVE.L RGNBUFFER(A6),A2 ;INIT MASKPTR TO LEFT
|
||
LEA MINRECT(A6),A3 ;POINT TO MINRECT
|
||
MOVE.L MODECASE(A6),A4 ;GET MODE CASE JUMP
|
||
MOVE DSTSHIFT(A6),D0 ;GET PIXEL TO BIT SHIFT AMOUNT
|
||
MOVE.L FCOLOR(A6),D4 ;PASS FCOLOR
|
||
MOVE.L BCOLOR(A6),D5 ;AND BACKCOLOR
|
||
_DrawSlab
|
||
MOVE.L a4,MODECASE(A6) ;save it for later <BAL 22Jan89>
|
||
|
||
MoveM.L (SP)+,D3-D6/A1-A4 ; restore everything
|
||
|
||
BumpX Move.L XValue(A1),D0 ; grab current XValue
|
||
Add.L XSlope(A1),D0 ; bump it to the next value
|
||
Move.L D0,XValue(A1) ; XValue := XValue + XSlope
|
||
Move.L PrevEdge(A1),A2 ; Edge := CurrentEdge^.PrevEdge
|
||
Move.L A2,D1 ; CmpA.L #Nil,A2; is Edge = nil?
|
||
Beq.S CheckEdge ; yes => sorting order is okay
|
||
Cmp.L XValue(A2),D0 ; is PrevEdge^.XValue <= CurrentEdge^.XValue?
|
||
Bge.S CheckEdge ; yes => sorting order is okay
|
||
Move.L NextEdge(A1),NextEdge(A2) ; PrevEdge^.NextEdge := CurrentEdge^.NextEdge; nil?
|
||
Beq.S NextIsNil ; yes => don't bother setting backlink
|
||
Move.L NextEdge(A1),A0 ; grab the next edge
|
||
Move.L A2,PrevEdge(A0) ; NextEdge^.PrevEdge := CurrentEdge^.PrevEdge
|
||
|
||
NextIsNil Move.L PrevEdge(A2),A2 ; Edge := Edge^.PrevEdge
|
||
Move.L A2,D1 ; CmpA.L #Nil,A2; is it nil?
|
||
Bne.S CheckCross ; no => check for crossing
|
||
Move.L ActiveList(A6),A2 ; get NextEdge
|
||
Move.L A2,NextEdge(A1) ; CurrentEdge^.NextEdge := ActiveList
|
||
Clr.L PrevEdge(A1) ; PrevEdge := nil
|
||
Move.L A1,PrevEdge(A2) ; NextEdge^.PrevEdge := CurrentEdge
|
||
Move.L A1,ActiveList(A6) ; ActiveList := CurrentEdge
|
||
Bra.S CheckEdge ; continue
|
||
|
||
CheckCross Cmp.L XValue(A2),D0 ; is Edge^.XValue <=CurrentEdge^.XValue?
|
||
Blt.S NextIsNil ; no => continue searching
|
||
Move.L NextEdge(A2),A0 ; grab NextEdge
|
||
Move.L A0,NextEdge(A1) ; CurrentEdge^.NextEdge := Edge^.NextEdge
|
||
Move.L A2,PrevEdge(A1) ; CurrentEdge^.PrevEdge := Edge
|
||
Move.L A1,PrevEdge(A0) ; CurrentEdge^.NextEdge^.PrevEdge := CurrentEdge
|
||
Move.L A1,NextEdge(A2) ; Edge^.NextEdge := CurrentEdge
|
||
Bra.S CheckEdge ; continue
|
||
|
||
RemoveEdge Move.L PrevEdge(A1),A0 ; grab PrevEdge
|
||
Move.L A0,D0 ; CmpA.L #Nil,A0; is PrevEdge nil?
|
||
Bne.S PrevNotNil ; no => remove from middle
|
||
Move.L NextEdge(A1),ActiveList(A6) ; ActiveList := CurrentEdge^.NextEdge
|
||
Bra.S PrevWasNil ; continue
|
||
|
||
PrevNotNil Move.L NextEdge(A1),NextEdge(A0) ; PrevEdge^.NextEdge := CurrentEdge^.NextEdge
|
||
PrevWasNil Beq.S NextWasNil ; if NextEdge is nil, don't patch back pointer
|
||
Move.L NextEdge(A1),A2 ; grab NextEdge
|
||
Move.L A0,PrevEdge(A2) ; NextEdge^.PrevEdge := CurrentEdge^.PrevEdge
|
||
NextWasNil Move.L FreeList(A6),NextEdge(A1) ; CurrentEdge^.NextEdge := FreeList
|
||
Move.L A1,FreeList(A6) ; FreeList := CurrentEdge
|
||
Move.L A0,A1 ; CurrentEdge := CurrentEdge^.PrevEdge
|
||
|
||
CheckEdge Move.L A4,D0 ; CmpA.L #Nil,A4; is NextActive nil?
|
||
Bne SlabLoop ; no => do another edge
|
||
|
||
CMP MINRECT+TOP(A6),D4 ;IS CURRENT VERT < MINV ?
|
||
Blt.S BumpY ;YES, DON'T DRAW
|
||
;-------------------------------------------------------------------
|
||
;
|
||
; BUMP DESTINATION VERTICALLY AND LOOP FOR ALL SCAN LINES
|
||
;
|
||
NEXTPAT MOVE.l PATVPOS(A6),D0 ;GET PATVPOS <BAL 22Jan89>
|
||
ADD PATROW(A6),D0 ;BUMP TO NEXT SCAN
|
||
AND PATVMASK(A6),D0 ;WRAP AT END OF PATTERN
|
||
MOVE.l D0,PATVPOS(A6) ;SAVE PATVPOS <BAL 22Jan89>
|
||
MOVE.L DSTROW(A6),D0 ;GET DST ROWBYTES
|
||
ADD.L D0,DSTLEFT(A6) ;BUMP DST TO NEXT ROW
|
||
|
||
BumpY AddQ #1,D4 ; CurrentY += 1
|
||
Move D4,Vert(A6) ; update param for SeekMask (twice?)
|
||
Cmp MinRect+Bottom(A6),D4 ; have we reached the bottom?
|
||
Bge.S NoMorePoly ; yes => shut down ahead of schedule
|
||
|
||
Tst.L ActiveList(A6) ; does the ActiveList contain edges?
|
||
Bne ActiveLoop ; yes => loop
|
||
Tst D3 ; any new edges left?
|
||
Bne ActiveLoop ; yes => loop
|
||
|
||
NoMorePoly move.b MMUsave(a6),d0 ;get previous MMU state in d0
|
||
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
|
||
Show Tst.B CrsrFlag(A6) ; is screen Dst?
|
||
Beq.S GoHome ; no => don't show cursor
|
||
_ShowCursor ; restore cursor
|
||
GoHome BSet #HiliteBit,HiliteMode ; reset hilite override, in case colormap was skipped
|
||
Move.L OldStacker(A6),SP ; clean up the free list and strip buffer
|
||
MoveM.L (SP)+,D3-D7/A2-A4 ; restore registers
|
||
Abort ;<5Apr90 KON>
|
||
Unlink Paramsize,'DrawPoly' ; clean up and return
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE DrawPoly(poly: PolyHandle; mode: integer; VAR pat: Pattern);
|
||
;
|
||
; from QDciPatchROM.a <sm 6/9/92>stb
|
||
|
||
DrawPoly PROC EXPORT
|
||
|
||
ParamSize Equ 10
|
||
Poly Equ ParamSize+8-4
|
||
Mode Equ Poly-2
|
||
Pat Equ Mode-4
|
||
|
||
PolyRect Equ -8
|
||
VarSize Equ PolyRect
|
||
|
||
; <11Jul88> PMAB543 BAL/JDB Implemented fast case for rectangular filled polys.
|
||
|
||
Link A6,#VarSize ; local variables
|
||
move.l ([poly,a6]),a0 ; pick up polyptr <Begin PMAB543 BAL/JDB>
|
||
move (a0)+,d0 ; pick up byte count
|
||
cmp #4*5+10,d0 ; quadrilateral?
|
||
bne.s @chk4pt ; no, take general case
|
||
move.l 8+4*4(a0),d1 ; pick up last pnt
|
||
cmp.l 8(a0),d1 ; cmpare with first pnt
|
||
bne.s @notRect ;
|
||
bra.s @4Pnts
|
||
|
||
@chk4pt cmp #4*4+10,d0 ; quadrilateral?
|
||
bne.s @notRect ; no, take general case
|
||
@4Pnts moveq #2,d0 ; force to 4 points
|
||
addq #8,a0 ; bump past rect
|
||
lea 4(a0),a1 ; point to next point
|
||
@nxtPnt SWAP D0 ; swap equality flags into low word <6>
|
||
cmp (a0)+,(a1)+ ; cmp h's
|
||
seq d1 ; remember equality
|
||
ADD.B D0,D0 ; shift left to make room for new flag bit <6>
|
||
SUB.B D1,D0 ; if same, set low bit, if not, clear it <6>
|
||
cmp (a0)+,(a1)+ ; cmp v's
|
||
seq d2 ; remember equality
|
||
or.b d2,d1 ; compute h1=h2 | v1=v2
|
||
beq.s @notRect ; no, not rect
|
||
ADD.B D0,D0 ; shift left to make room for new flag bit <6>
|
||
SUB.B D2,D0 ; if same, set low bit, if not, clear it <6>
|
||
SWAP D0 ; put counter back in low word <6>
|
||
dbra d0,@nxtPnt
|
||
|
||
SWAP D0 ; swap equality flags into low word <6>
|
||
lea -12(a0),a1 ; point to first point
|
||
cmp (a0)+,(a1)+ ; cmp h's
|
||
seq d1 ; remember equality
|
||
ADD.B D0,D0 ; shift left to make room for new flag bit <6>
|
||
SUB.B D1,D0 ;if same, set low bit, if not, clear it <6>
|
||
cmp (a0)+,(a1)+ ; cmp v's
|
||
seq d2 ; remember equality
|
||
or.b d2,d1 ; compute h1=h2 | v1=v2
|
||
beq.s @notRect ; no, not rect
|
||
ADD.B D0,D0 ; shift left to make room for new flag bit <6>
|
||
SUB.B D2,D0 ; if same, set low bit, if not, clear it <6>
|
||
CMP.B #$99,D0 ; do the equality flags match that of type 1 rectangle ?<6>
|
||
BEQ.S @isRect ; yes, use fast case <6>
|
||
CMP.B #$66,D0 ; do they match that of a type 2 rectangle ? <6>
|
||
BNE.S @notRect ; no, use slow case <6>
|
||
@isRect lea polyRect(a6),a0 ; point to rect
|
||
move.l a0,-(sp) ;
|
||
move.l -12(a1),(a0)+ ; save top left
|
||
move.l -8(a1),(a0) ; save bot rght
|
||
move.w mode(a6),-(sp) ; push mode
|
||
move.l pat(a6),-(sp) ; push pat
|
||
bsr.l DrawRect ; go sooo fast <End PMAB543 BAL/JDB>
|
||
bra goHome2
|
||
|
||
@notRect MoveM.L D3-D5/A2,-(SP) ; save registers
|
||
Move.L GrafGlobals(A5),A0 ; point to QuickDraw globals
|
||
Move.L ThePort(A0),A0 ; get current port
|
||
Tst PnVis(A0) ; is PnVis neg ?
|
||
Bmi GoHome ; yes, quit AWC.PMAB444
|
||
Move.L Poly(A6),A0 ; get the poly handle
|
||
Move.L A0,D0 ; CmpA.L #Nil,A0; is it real?
|
||
Beq GoHome ; no => punt AWC.PMAB444
|
||
_HLock ; lock it down
|
||
Move.L (A0),A0 ; dereference poly
|
||
Move.L 2(A0),PolyRect(A6) ; move Top.Left
|
||
Move.L 6(A0),PolyRect+4(A6) ; move Bottom.Right
|
||
Move (A0),D4 ; get the length of the data
|
||
Sub #10,D4 ; remove the length word and the bounding box rect
|
||
Lsr #2,D4 ; D4 is temporarily the point count
|
||
MoveQ #0,D0 ; clear the high word
|
||
Move D4,D0 ; copy the number of points
|
||
AddQ.L #1,D0 ; bump it for the closing edge, maybe
|
||
Asl.L #3,D0 ; multiply by 8 bytes per edge
|
||
_NewHandle ; get a new handle
|
||
Tst D0 ; was there an error? AWC.PMAB444
|
||
Bne TempError ; yes => cleanup and get out of here AWC.PMAB444
|
||
Move.L A0,A2 ; copy it
|
||
_HLock ; lock it down
|
||
MoveQ #0,D3 ; clear VCount
|
||
Move.L Poly(A6),A1 ; get the handle again
|
||
Move.L (A1),A1 ; redereference it
|
||
AddA.L #polyPoints,A1 ; bump A1 to the first point
|
||
Move.L (A1)+,D5 ; get h and v for "old" position
|
||
Move D4,D2 ; copy loop counter to D2
|
||
SubQ.L #1,D2 ; remove the first point
|
||
Move.L (A2),A0 ; dereference the sorted edge list
|
||
Bra.S PolyEnd ; jump into the loop
|
||
|
||
PolyLoop Move.L D5,D4 ; copy current to old
|
||
Move.L (A1)+,D5 ; get next point
|
||
Move.L D4,D0 ; get the old point
|
||
Move.L D5,D1 ; copy the new point
|
||
Sub D0,D1 ; calculate XDelta
|
||
Swap D0 ; y1 is in D0.Low
|
||
Swap D1 ; y2 is in D1.Low
|
||
Sub D0,D1 ; calculate YDelta; does dy = 0?
|
||
Beq.S PolyEnd ; yes => ignore horizontal vectors
|
||
Bmi.S Upwards ; negative => save the new point
|
||
Move.L D4,(A0)+ ; save the old point
|
||
Bra.S IncVCount ; and continue
|
||
|
||
Upwards Move.L D5,(A0)+ ; save the new point
|
||
IncVCount AddQ #1,D3 ; bump VCount (D3)
|
||
Swap D1 ; XDelta:YDelta => YDelta:XDelta
|
||
Move.L D1,(A0)+ ; save YDelta:XDelta
|
||
PolyEnd DBra D2,PolyLoop ; loop for another poly point
|
||
|
||
Move.L D5,D4 ; save the new point to old
|
||
Move.L Poly(A6),A1 ; get poly handle again
|
||
Move.L (A1),A1 ; dereference it again
|
||
Move.L polyPoints(A1),D5 ; grab the first point again
|
||
Cmp.L D4,D5 ; did we end where we began?
|
||
Beq.S PolyDone ; yes => don't close it
|
||
|
||
Move.L D4,D0 ; get the old point
|
||
Move.L D5,D1 ; copy the new point
|
||
Sub D0,D1 ; calculate XDelta
|
||
Swap D0 ; y1 is in D0.Low
|
||
Swap D1 ; y2 is in D1.Low
|
||
Sub D0,D1 ; calculate YDelta; does dy = 0?
|
||
Beq.S PolyDone ; yes => ignore horizontal vectors
|
||
Bmi.S Upwards2 ; positive => use the old point
|
||
Move.L D4,(A0)+ ; save the old point
|
||
Bra.S IncVCount2 ; and continue
|
||
|
||
Upwards2 Move.L D5,(A0)+ ; save the new point
|
||
IncVCount2 AddQ #1,D3 ; bump VCount (D4)
|
||
Swap D1 ; XDelta:YDelta => YDelta:XDelta
|
||
Move.L D1,(A0)+ ; save deltas
|
||
PolyDone Move.L Poly(A6),A0 ; grab poly handle
|
||
_HUnlock ; unlock it
|
||
Move.L (A2),-(SP) ; push vectors pointer
|
||
Move D3,-(SP) ; push VCount
|
||
Jsr SortVectors ; sort them vectors
|
||
Move.L (A2),-(SP) ; push vectors pointer
|
||
Move D3,-(SP) ; push VCount
|
||
; Tst.B WnFill(A6) ; are we winding-number filling?
|
||
; Seq -(SP) ; push (not WnFill)
|
||
St -(SP) ; push EoFill
|
||
Pea PolyRect(A6) ; push rect
|
||
Move Mode(A6),-(SP) ; repush mode
|
||
Move.L Pat(A6),-(SP) ; repush pat
|
||
Jsr PaintVector ; go paint it
|
||
Move.L A2,A0 ; grab vectors handle
|
||
_HUnlock ; unlock it
|
||
Move.L A2,A0 ; grab it again
|
||
_DisposHandle ; dump it
|
||
MoveQ #0,D0 ; no error
|
||
Bra.S GoHome ; continue AWC.PMAB444
|
||
|
||
TempError Move.L Poly(A6),A0 ; grab poly handle AWC.PMAB444
|
||
_HUnlock ; unlock it AWC.PMAB444
|
||
GoHome MoveM.L (SP)+,D3-D5/A2 ; restore registers AWC.PMAB444
|
||
GoHome2 Unlink Paramsize,'DrawArt' ; clean up <15Nov89 KON> changed " to '
|
||
|
||
|
||
if 0 then ; This stuff is only for the system file patch
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE StdPoly(verb: GrafVerb; poly: PolyHandle);
|
||
;
|
||
|
||
myStdPoly PROC EXPORT
|
||
IMPORT PushVerb,RSect,DrawPoly
|
||
|
||
CheckPic EQU $20EF2 ; <PB302>
|
||
PutPicVerb EQU $20904 ; <PB302>
|
||
DPutPicOp EQU $20884 ; <PB302>
|
||
PutPicRgn Equ $208B8
|
||
GetRect Equ $213B2
|
||
FrPoly Equ $21594
|
||
|
||
|
||
PARAMSIZE EQU 6
|
||
VERB EQU PARAMSIZE+8-2 ;GRAFVERB
|
||
POLY EQU VERB-4 ;LONG, PolyHandle
|
||
|
||
MINRECT EQU -8 ;RECT
|
||
VARSIZE EQU MINRECT ;TOTAL BYTES OF LOCALS
|
||
|
||
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
|
||
MOVEM.L D5-D7/A2-A4,-(SP) ;SAVE REGS
|
||
MOVEQ #0,D7 ; clear lo word of reg for add later <PB279/DAF>
|
||
MOVE.B VERB(A6),D7 ;GET VERB
|
||
|
||
;need to change this to use vector:
|
||
|
||
JSRROM CheckPic ;SET UP A4,A3 AND CHECK PICSAVE
|
||
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
|
||
|
||
MOVE.B D7,-(SP)
|
||
JSRROM PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
|
||
MOVEQ #$70,D0 ;PUT POLYNOUN IN HI NIBBLE
|
||
ADD D7,D0 ;PUT VERB IN LO NIBBLE
|
||
JSRROM DPutPicOp ;PUT OPCODE TO THEPIC
|
||
|
||
MOVE.L POLY(A6),-(SP) ;PUSH POLYHANDLE
|
||
JSRROM PutPicRgn ;TREAT SAME AS A REGION
|
||
|
||
; CALL STANDARD LOOP TO DRAW TO ALL DEVICES
|
||
|
||
NOTPIC PEA StdDraw ;PUSH ADDRESS OF DRAW ROUTINE
|
||
PEAROM GetRect ;PUSH ADDRESS OF RECT ROUTINE
|
||
_StdDevLoop ;DRAW TO ALL DEVICES
|
||
|
||
GOHOME MOVEM.L (SP)+,D5-D7/A2-A4 ;RESTORE REGS
|
||
UNLINK PARAMSIZE,'STDPOLY '
|
||
|
||
|
||
;---------------------------------------------------------------
|
||
;
|
||
; PROCEDURE StdDraw;
|
||
;
|
||
; DRAW THE OBJECT
|
||
;
|
||
StdDraw MOVE.L POLY(A6),A2 ;GET POLYHANDLE
|
||
TST.B D7 ;IS VERB FRAME ?
|
||
BNE.S NOTFR ;NO, CONTINUE
|
||
MOVE.L A2,-(SP) ;PUSH POLYHANDLE
|
||
JSRROM FrPoly ;FrPoly(poly);
|
||
BRA.S DONE ;AND QUIT
|
||
|
||
NOTFR MOVE.L (A2),A0 ;DE-REFERENCE POLYHANDLE
|
||
PEA POLYBBOX(A0) ;PUSH POLYBBOX
|
||
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
|
||
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
|
||
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
|
||
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
|
||
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
|
||
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
|
||
MOVE #3,-(SP) ;PUSH NRECTS = 3
|
||
PEA MINRECT(A6) ;PUT RESULT IN MINRECT
|
||
_RSECT ;CALC INTERSECTION
|
||
BEQ.S DONE ;QUIT IF NO INTERSECT
|
||
|
||
MOVE.L A2,-(SP) ;PUSH POLYHANDLE
|
||
_PushVerb ;PUSH MODE AND PATTERN
|
||
JSR DrawPoly ;DrawPoly(poly,mode,pat);
|
||
DONE RTS
|
||
|
||
|
||
endif
|
||
|