mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-14 21:29:53 +00:00
4325cdcc78
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.
1054 lines
38 KiB
Plaintext
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
|