boot3/QuickDraw/Patches/QuickPolysClassicPatch.a
Elliot Nunn 5b0f0cc134 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 10:02:57 +08:00

1054 lines
38 KiB
Plaintext

;
; File: QuickPolysClassicPatch.a
;
; Contains: xxx put contents here (or delete the whole line) xxx
;
; Written by: xxx put name of writer here (or delete the whole line) xxx
;
; Copyright: © 1981-1990 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <4> 9/21/90 KON Removed equate for CheckPic since all machines should call the
; new version in AllB&Wpatch.a.
; <3> 7/16/90 gbm Die, warnings, Die!
; <2> 7/11/90 gbm get rid of some assembly warnings
; <1.2> 4/17/89 CCH Unconditionalized fixed from 6.0.3.
; <1.1> 1/16/89 CCH Merged 6.0.3 final sources into 7.0.
; <1.0> 11/16/88 CCH Added to EASE.
; 1/18/88 AWC MacPlus/SE rom patch installed this date
;
; To Do:
;
;EASE$$$ READ ONLY COPY of file ÒQuickPolysClassicPatch.aÓ
; 1.2 CCH 04/17/1989 Unconditionalized fixed from 6.0.3.
; 1.1 CCH 01/16/1989 Merged 6.0.3 final sources into 7.0.
; 1.0 CCH 11/16/1988 Added to EASE.
; END EASE MODIFICATION HISTORY
; File QuickPolysClassicPatch.a
;
; Copyright Apple Computer, Inc. 1981-1988
;
; All Rights Reserved
;_______________________________________________________________________________________
; 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
;
; <18Jan88> AWC MacPlus/SE rom patch installed this date
; <24Mar88> PMAB440 AWC Fixed sorting problem to make QuickPolys match Classic QuickDraw
; <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
; <25Jul88> PMAB543 BAL/JDB Implemented fast case for rectangular filled polys.
;
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)
IF &TYPE('Nil') = 'UNDEFINED' THEN
Nil: Equ 0
ENDIF
;-------------------------------------------------------------
;
; ROM entry points
;
if 0 then
if OnMacPP then
ShowCursor Equ $412A2E
ShieldCursor Equ $412A34
MaskTab Equ $412B6E
PatExpand Equ $412BCE
ColorMap Equ $412C96
XorSlab Equ $412D78
DrawSlab Equ $412DBC
SlabMode Equ $412E4C
FastSlabMode Equ $412EA6
PushVerb Equ $414650
RSect Equ $414880
SeekMask Equ $415DC4
FrPoly Equ $4162D0
TrimRect Equ $41692A
InitRgn Equ $416A36
DPutPicByte Equ $418A30
PutPicVerb Equ $418AD6
PutPicRgn Equ $418AB8
;CheckPic Equ $418BD4 <17Sept90 KON>
ROMDrawRect Equ $4146C8 ; <PMAB543 BAL/JDB>
else
ShowCursor Equ $4082F8
ShieldCursor Equ $4082FE
MaskTab Equ $408438
PatExpand Equ $408498
ColorMap Equ $408560
XorSlab Equ $408642
DrawSlab Equ $408686
SlabMode Equ $408716
FastSlabMode Equ $408770
PushVerb Equ $409EE0
RSect Equ $40A110
SeekMask Equ $40B654
FrPoly Equ $40BB60
TrimRect Equ $40C1BA
InitRgn Equ $40C2C6
DPutPicByte Equ $40E2A4
PutPicRgn Equ $40E32C
PutPicVerb Equ $40E34A
CheckPic Equ $40E448
ROMDrawRect Equ $409f58 ; <PMAB543 BAL/JDB>
endif
endif
;-------------------------------------------------------------
;
; 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
Move.L (SP)+,A0 ; grab return address
AddA.L #ParamSize,SP ; bump the stack
Jmp (A0) ; we're out of here
;---------------------------------------------------
;
; 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
;-------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
EXPAT EQU -64 ;16 LONGS
MINRECT EQU EXPAT-8 ;RECT
STATEA EQU MINRECT-RGNREC ;RGN STATE RECORD
STATEB EQU STATEA-RGNREC ;RGN STATE RECORD
STATEC EQU STATEB-RGNREC ;RGN STATE RECORD
SAVESTK EQU STATEC-4 ;LONG
RECTFLAG EQU SAVESTK-2 ;WORD
MASKBUF EQU RECTFLAG-4 ;LONG
BUFLEFT EQU MASKBUF-2 ;WORD
BUFFSIZE EQU BUFLEFT-2 ;WORD
MODECASE EQU BUFFSIZE-4 ;LONG
DSTLEFT EQU MODECASE-4 ;LONG
SAVEA5 EQU DSTLEFT-4 ;LONG
PORT EQU SAVEA5-4 ;LONG
FASTFLAG EQU PORT-2 ;BYTE
TMPRECT EQU FASTFLAG-8 ;RECT
PATINDEX EQU TMPRECT-2 ;WORD
; Stack frame variables used only in DrawPoly
FreeList Equ PatIndex-4
StackLimit Equ FreeList-4
ActiveList Equ StackLimit-4
VarSize Equ ActiveList
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARS
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER
MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A3 ;GET CURRENT GRAFPORT
TST PNVIS(A3) ;IS PNVIS NEG ?
BLT GOHOME ;YES, QUIT
MOVE.L A3,PORT(A6) ;SAVE CURRENT GRAFPORT
;-------------------------------------------------------
;
; QUIT IF MODE NOT IN 8..15
;
MOVEQ #-8,D0 ;MASK TO KILL BOTTOM 3 BITS
AND MODE(A6),D0 ;GET ALL BUT 3 BITS OF MODE
CMP #8,D0 ;IS PEN MODE 8..15 ?
BNE GOHOME ;NO, QUIT
;----------------------------------------------------------------
;
; ADJUST MODE AND PATTERN IF COLOR FILTERING.
;
TST COLRBIT(A3) ;IS COLORBIT NEG ?
BMI.S NOCOLOR ;YES, DON'T MAP
MOVE MODE(A6),-(SP) ;PUSH INPUT MODE
MOVE.L PAT(A6),-(SP) ;PUSH ADDR OF INPUT PATTERN
jsrROM ROMCOLORMAP ;ALTER BY THECOLOR, THEFILTER
MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN
MOVE (SP)+,MODE(A6) ;GET (ALTERED) MODE
NOCOLOR MOVE.L A3,A5 ;PUT GRAFPORT IN A5
;---------------------------------------------------------
;
; GET CLIPRGN AND VISRGN HANDLES AND DE-REFERENCE THEM
;
MOVE.L CLIPRGN(A5),A2 ;GET CLIPRGN HANDLE
MOVE.L (A2),A2 ;GET CLIPRGN POINTER
MOVE.L VISRGN(A5),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 DSTRECT
PEA PORTBITS+BOUNDS(A5) ;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
jsrROM ROMRSECT ;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(A5),-(SP) ;push rgnHandle
PEA minRect(A6) ;push addr of minRect
jsrROM ROMTrimRect ;call trimRect
BLT GOHOME ;quit if intersection empty
BGT.S FLAGOK ;continue if non-rectangular
;
; CHECK FOR BLACK OR WHITE PATTERN
;
CKPAT MOVE.L PAT(A6),A0 ;POINT TO PATTERN
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,MODE(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 MODE(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,MODE(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.
;
PEA MINRECT(A6) ;PUSH SHIELDRECT PARAMETER
MOVE.L PORTBITS+BOUNDS+TOPLEFT(A5),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
jsrROM ROMSHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
MOVE.L PORT(A6),A5 ;RESTORE GRAFPORT IN A5
;------------------------------------
;
; CALC BUFLEFT
;
MOVE MINRECT+LEFT(A6),D2 ;GET MINRECT LEFT
SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT TO GLOBAL COORDS
AND #$FFF0,D2 ;TRUNC TO MULT OF 16
ADD PORTBITS+BOUNDS+LEFT(A5),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 BUFSIZE
;
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
SUB D2,D0 ;CALC MAXH-BUFLEFT
LSR #5,D0 ;DIV BY 32 FOR LONGS
MOVE D0,BUFFSIZE(A6) ;BUFFSIZE = # LONGS - 1
;-------------------------------------------------------------------------
;
; 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,MASKBUF(A6) ;REMEMBER WHERE MASKBUF IS
;-------------------------------------------------------------------------
;
; INIT STATE RECORDS AND ALLOCATE BUFFERS FOR EACH NON-RECTANGULAR REGION
;
CLR D5 ;INIT BOTH ARE RECT
MOVE #-32767,STATEA+THISV(A6) ;INIT REGION STATEA
MOVE #32767,STATEA+NEXTV(A6) ;TO HARMLESS IN CASE RECT
CMP #10,RGNSIZE(A2) ;IS CLIPRGN RECTANGULAR ?
BEQ.S ARECT ;YES, CONTINUE
ADD #2,D5 ;NO, SET ITS FLAG
MOVE.L A2,A0 ;POINT TO CLIPRGN
LEA STATEA(A6),A1 ;POINT TO STATE RECORD A
BSR.S INITONE ;INIT STATE, ALLOC BUFFER
ARECT
MOVE #-32767,STATEB+THISV(A6) ;INIT REGION STATEB
MOVE #32767,STATEB+NEXTV(A6) ;TO HARMLESS IN CASE RECT
CMP #10,RGNSIZE(A3) ;IS VISRGN RECTANGULAR ?
BEQ.S BRECT ;YES, CONTINUE
ADD #4,D5 ;NO, SET ITS FLAG
MOVE.L A3,A0 ;POINT TO VISRGN
LEA STATEB(A6),A1 ;POINT TO STATE RECORD B
PEA BRECT ;PUSH FAKE RETURN ADDR
INITONE MOVE MINRECT+LEFT(A6),D0 ;GET MINH
MOVE MINRECT+RIGHT(A6),D1 ;GET MAXH
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
jmpROM ROMINITRGN ;INIT STATE, ALLOC BUFFER
BRECT
;--------------------------------------------------------------------
;
; IF BOTH REGIONS ARE RECTANGULAR, THEN DRAW MINRECT INTO MASK BUFFER
;
MOVE.W D5,RECTFLAG(A6) ;ARE ALL RGNS RECT ?
BNE.S NOTRECT ;NO, CONTNUE
MOVE.L MASKBUF(A6),A0 ;YES, POINT TO MASK BUFFER
MOVE MINRECT+LEFT(A6),D3 ;SET UP LEFT
SUB BUFLEFT(A6),D3 ;MAKE IT BUFFER RELATIVE
MOVE MINRECT+RIGHT(A6),D4 ;SET UP RIGHT
SUB BUFLEFT(A6),D4 ;MAKE IT BUFFER RELATIVE
jsrROM ROMXorSlab ;AND XOR BETWEEN THEM
NOTRECT
SKIPSETUP
;------------------------------------
;
; CALC STARTING DSTLEFT
;
MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP
SUB PORTBITS+BOUNDS+TOP(A5),D1 ;CONVERT TO GLOBAL COORDS
MULU PORTBITS+ROWBYTES(A5),D1 ;MULT BY DST ROWBYTES
ADD.L PORTBITS+BASEADDR(A5),D1 ;ADD START OF BITMAP
SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT BUFLEFT TO GLOBAL
LSR #3,D2 ;CALC BUFLEFT DIV 8
EXT.L D2 ;CLR HI WORD
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
SUB D1,MINRECT+LEFT(A6)
SUB D1,MINRECT+RIGHT(A6)
;---------------------------------------------------
;
; SET UP CASE JUMP BASED ON MODE AND FASTFLAG
;
MOVE MODE(A6),D2 ;GET (ALTERED) PEN MODE
TST.B FastFlag(A6) ;Rect clipoped and black ?
BEQ.S @1 ;no, use slow drawslab loop
jsrROM ROMFastSlabMode ;yes, get fast modeCase in A4
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
CLR PATINDEX(A6) ;MAKE UNUSED PATINDEX EVEN
BRA.S GOFORIT ;SKIP PATTERN STUFF
@1 jsrROM ROMSlabMode ;get slow modeCase in A4
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
;------------------------------------------------------------------
;
; EXPAND 8 BYTE PATTERN TO 16 LONGS AND INIT PATTERN SELECTOR
;
CLR.L D7 ;SAY NOT INVERTED
MOVE MODE(A6),D2 ;GET MODE
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 MOVE PORTBITS+BOUNDS+LEFT(A5),D2 ;GET GLOBAL-LOCAL OFFSET
MOVE.L PAT(A6),A0 ;POINT TO BYTE WIDE PATTERN
LEA EXPAT(A6),A1 ;POINT TO EXPANDED PATTERN
MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
jsrROM ROMPATEXPAND ;EXPAND 8 BYTE PATTERN TO 16 LONGS
MOVE.L PORT(A6),A5 ;RESTORE GRAFPORT IN A5
MOVEQ #$F,D0 ;TREAT COORD MOD 16
AND MINRECT+TOP(A6),D0 ;GET TOP VERT LOCAL COORD
LSL #2,D0 ;QUAD FOR 4 BYTE PATTERNS
MOVE D0,PATINDEX(A6) ;SET UP PATTERN INDEX
;;;;; End of sicko code from DrawArc
GoForIt 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 #$100,D1 ; give us some spare room
Move.L D1,StackLimit(A6) ; save it
Move.L Vector(A6),A3 ; get pointer to VectorArray
Move (A3),D7 ; get CurrentY
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),D7 ; 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
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 AWC.PMAB440
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 D7,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),D7 ;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
JsrROM ROMSeekMask ; make MaskBuf 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),D7 ; is LastY <= CurrentY?
Bge RemoveEdge ; yes => go remove the edge
Move Sign(A1),D0 ; grab the sign
Beq.S DoToggle1 ; 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
DoToggle1 Eor #1,D5 ; toggle D5
Beq.S NoLineMove ; yes => go draw the line
Move XValue(A1),D6 ; save line mvoe
Bra.S BumpX ; continue
ONESLAB MOVEQ #$3F,D6 ;GET WRAP-AROUND MASK
AND PATINDEX(A6),D6 ;GET PATINDEX MOD 64
MOVE.L EXPAT(A6,D6),D6 ;GET THIS ROW'S PATTERN
leaROM ROMMaskTab,A0 ;POINT TO MASK TABLE
MOVE.L DSTLEFT(A6),A1 ;INIT DSTPTR TO LEFT
MOVE.L MASKBUF(A6),A2 ;INIT MASKPTR TO LEFT
LEA MINRECT(A6),A3 ;POINT TO MINRECT
MOVE.L MODECASE(A6),A4 ;GET MODE CASE JUMP
jmpROM ROMDrawSlab
DrawLine CMP MINRECT+TOP(A6),D7 ;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
Bsr.S OneSlab ; jump to ROM calling routine
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),D7 ;IS CURRENT VERT < MINV ?
Blt.S BumpY ;YES, DON'T DRAW
;-------------------------------------------------------------------
;
; BUMP DESTINATION VERTICALLY AND LOOP FOR ALL SCAN LINES
;
NEXTPAT ADD #4,PATINDEX(A6) ;BUMP PATTERN INDEX
MOVE PORTBITS+ROWBYTES(A5),D0 ;GET DST ROWBYTES
EXT.L D0 ;MAKE IT LONG
ADD.L D0,DSTLEFT(A6) ;BUMP DST TO NEXT ROW
BumpY AddQ #1,D7 ; CurrentY += 1
Cmp MinRect+Bottom(A6),D7 ; 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 _ShowCursor ; restore cursor
GoHome Move.L SaveStk(A6),SP ; clean up the free list and strip buffer
MoveM.L (SP)+,D0-D7/A1-A5 ; restore registers
Unlk A6 ; clean up
Move.L (SP)+,A0 ; get return address
AddA.L #Paramsize,SP ; clean up the parameters
Jmp (A0) ; go home
;---------------------------------------------------
;
; PROCEDURE DrawPoly(poly: PolyHandle; mode: integer; VAR pat: Pattern);
;
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
; <25Jul88> PMAB543 BAL/JDB Implemented fast case for rectangular filled polys.
move.l 10(a7),a0 ; pick up polyhdl <Begin PMAB543 BAL/JDB>
move.l (a0),a0 ; deref to polyptr
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
@aRect dc.l 0,0 ; save room for rect
@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 cmp (a0)+,(a1)+ ; cmp h's
seq d1 ; remember equality
cmp (a0)+,(a1)+ ; cmp v's
seq d2 ; remember equality
or.b d1,d2 ; compute h1=h2 | v1=v2
beq.s @notRect ; no, not rect
dbra d0,@nxtPnt
lea -12(a0),a1 ; point to first point
cmp (a0)+,(a1)+ ; cmp h's
seq d1 ; remember equality
cmp (a0)+,(a1)+ ; cmp v's
seq d2 ; remember equality
or.b d1,d2 ; compute h1=h2 | v1=v2
beq.s @notRect ; no, not rect
lea @aRect,a0 ; point to rect
move.l a0,10(a7) ; overwrite polyhandle with rect ptr
move.l -12(a1),(a0)+ ; save top left
move.l -8(a1),(a0) ; save bot rght
jmpROM ROMDrawRect ; go so incredibly blindingly fast <End PMAB543 BAL/JDB>
@notRect Link A6,#VarSize ; no local variables
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
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
Unlk A6 ; clean up
Move.L (SP)+,A0 ; get return address
AddA.L #Paramsize,SP ; clean up the parameters
Jmp (A0) ; go home
PatchStdPoly PROC EXPORT
IMPORT CheckPic, PutPicVerb
;---------------------------------------------------------------
;
; PROCEDURE StdPoly(verb: GrafVerb; poly: PolyHandle);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
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
MOVE.B VERB(A6),D7 ;GET VERB
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP)
jsr PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
MOVEQ #$70,D0 ;PUT POLYNOUN IN HI NIBBLE
ADD D7,D0 ;PUT VERB IN LO NIBBLE
jsrROM ROMDPutPicByte ;PUT OPCODE TO THEPIC
MOVE.L POLY(A6),-(SP) ;PUSH POLYHANDLE
jsrROM ROMPutPicRgn ;treat same as a region
NOTPIC 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 ROMFrPoly ;FrPoly(poly);
BRA.S GOHOME ;AND QUIT
NOTFR MOVE.L (A2),A0 ;DE-REFERANCE 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
jsrROM ROMRSECT ;CALC INTERSECTION
BEQ.S GOHOME ;QUIT IF NO INTERSECT
MOVE.L A2,-(SP) ;PUSH POLYHANDLE
jsrROM ROMPushVerb ;PUSH MODE AND PATTERN
jsr DrawPoly ;DrawPoly(poly,mode,pat);
GOHOME MOVEM.L (SP)+,D5-D7/A2-A4 ;RESTORE REGS
Unlk A6
Move.L (SP)+,A0
AddA.L #ParamSize,SP
Jmp (A0)
ENDPROC