mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 01:49:19 +00:00
495 lines
16 KiB
Plaintext
495 lines
16 KiB
Plaintext
;
|
|
; File: RgnOp.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):
|
|
;
|
|
; <2> 7/24/90 gbm change a duplicate def or three
|
|
; <•1.6> 7/14/89 BAL For Aurora: Final CQD
|
|
; <1.5> 6/30/89 BAL Bumped interrupt stack space up to 1600 bytes
|
|
; <•1.4> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
|
|
; <•1.3> 4/12/89 BAL Blasting in 32-Bit QuickDraw 1.0B1
|
|
; <C970> 11/22/87 DAF Changed buffer size calculation in setup to unsigned add from
|
|
; signed add. This allows 2 16K regions to be operated on.
|
|
;
|
|
; To Do:
|
|
;
|
|
|
|
;EASE$$$ READ ONLY COPY of file “rgnop.a”
|
|
;•1.6 BAL 07/14/1989 For Aurora: Final CQD
|
|
; 1.5 BAL 06/30/1989 Bumped interrupt stack space up to 1600 bytes
|
|
;•1.4 BAL 05/29/1989 Blasting in 32-Bit QuickDraw version 1.0 Final
|
|
;•1.3 BAL 04/12/1989 Blasting in 32-Bit QuickDraw 1.0B1
|
|
; File RgnOp.a
|
|
;
|
|
; Copyright Apple Computer, Inc. 1981-1986
|
|
; All Rights Reserved
|
|
;
|
|
; Modification History:
|
|
; ------------------------------------------------------------------
|
|
; C970 22Nov87 DAF Changed buffer size calculation in setup to unsigned add from
|
|
; signed add. This allows 2 16K regions to be operated on.
|
|
;
|
|
|
|
|
|
BLANKS ON
|
|
STRING ASIS
|
|
|
|
RgnOp FUNC EXPORT
|
|
IMPORT SectScan,DiffScan,UnionScan,XorScan,InsetScan,SetHSize
|
|
;-------------------------------------------------------------------
|
|
;
|
|
; FUNCTION RgnOp(rgnA,rgnB: RgnHandle;
|
|
; bufHandle: Handle;
|
|
; maxBytes: INTEGER;
|
|
; op,dh: INTEGER;
|
|
; okGrow: BOOLEAN): INTEGER;
|
|
;
|
|
; Computes the intersection, difference, union, or XOR of two regions,
|
|
; or the horizontal inset of one region, and stores the result as an
|
|
; unpacked array of sorted inversion points in bufHandle. Returns the
|
|
; number of points as the function value. BufHandle will be grown only
|
|
; if more space is needed needed and okGrow is true.
|
|
;
|
|
; OP = 0: SECT
|
|
; 2: DIFF A-B
|
|
; 4: UNION
|
|
; 6: XOR
|
|
; 8: HORIZ INSET
|
|
;
|
|
;
|
|
; A6 OFFSETS OF PARAMETERS AND LOCALS AFTER LINK:
|
|
;
|
|
PARAMSIZE EQU 20 ;TOTAL # BYTES
|
|
RESULT EQU PARAMSIZE+8 ;INTEGER, FUNCTION RESULT
|
|
RGNA EQU RESULT-4 ;LONG, RGNHANDLE
|
|
RGNB EQU RGNA-4 ;LONG, RGNHANDLE
|
|
BUFHANDLE EQU RGNB-4 ;LONG, HANDLE TO POINT BUFFER
|
|
MAXBYTES EQU BUFHANDLE-2 ;WORD
|
|
OP EQU MAXBYTES-2 ;WORD
|
|
DH EQU OP-2 ;WORD
|
|
OKGROW EQU DH-2 ;BOOLEAN
|
|
|
|
SCAN1 EQU -4 ;long
|
|
SCAN2 EQU SCAN1-4 ;long
|
|
SCAN3 EQU SCAN2-4 ;long
|
|
SCAN4 EQU SCAN3-4 ;long
|
|
SCAN5 EQU SCAN4-4 ;long
|
|
NEXTA EQU SCAN5-2 ;WORD
|
|
NEXTB EQU NEXTA-2 ;WORD
|
|
VERT EQU NEXTB-2 ;WORD
|
|
BUFFERPTR EQU VERT-4 ;LONG, ^POINT
|
|
BUFLIMIT EQU BUFFERPTR-4 ;LONG
|
|
FAKEB EQU BUFLIMIT-18 ;18 BYTE FAKE RGN DATA
|
|
MASTERB EQU FAKEB-4 ;LONG
|
|
FAKEA EQU MASTERB-18 ;18 BYTE FAKE RGN DATA
|
|
MASTERA EQU FAKEA-4 ;LONG
|
|
CASEJMP EQU MASTERA-4 ;LONG
|
|
SAVESTK EQU CASEJMP-4 ;LONG
|
|
VARSIZE EQU SAVESTK ;TOTAL BYTES OF LOCALS
|
|
|
|
|
|
|
|
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
|
|
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS
|
|
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK PTR
|
|
|
|
|
|
;------------------------------------------------------------
|
|
;
|
|
; DE-REFERENCE RGNA AND RGNB AND OFFSET TO FIRST RGNDATA.
|
|
; IF EITHER IS RECTANGULAR, REPLACE IT WITH AN EXPANDED ONE.
|
|
;
|
|
LEA MASTERA(A6),A2 ;POINT TO FAKE AREA
|
|
LEA RGNA(A6),A0 ;POINT TO RGNA HANDLE
|
|
BSR EXPAND ;DE-REFERENCE AND EXPAND
|
|
MOVE.L A0,A3 ;SAVE RGNA DATA PTR IN A3
|
|
LEA RGNB(A6),A0 ;POINT TO RGNB HANDLE
|
|
BSR EXPAND ;DE-REFERENCE AND EXPAND
|
|
MOVE.L A0,A4 ;SAVE RGNB DATA PTR IN A4
|
|
|
|
|
|
;-----------------------------------------------------------
|
|
;
|
|
; SET UP A CASE JUMP BASED ON OP
|
|
;
|
|
LEA SECTSCAN,A0
|
|
MOVE OP(A6),D0
|
|
BEQ.S CASEOK ;BR IF OP = SECT
|
|
LEA DIFFSCAN,A0
|
|
SUB #2,D0
|
|
BEQ.S CASEOK ;BR IF OP = DIFF
|
|
LEA UNIONSCAN,A0
|
|
SUB #2,D0
|
|
BEQ.S CASEOK ;BR IF OP = UNION
|
|
LEA XORSCAN,A0
|
|
SUB #2,D0
|
|
BEQ.S CASEOK ;BR IF OP = XOR
|
|
LEA INSETSCAN,A0 ;ELSE OP = INSET
|
|
CASEOK MOVE.L A0,CASEJMP(A6) ;SAVE FOR LATER
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; Calc bufSize based on StackAvail and allocate 5 scan buffers
|
|
;
|
|
_StackAvail ;get stack avail in D0.L
|
|
SUB.L #qdStackXtra,D0 ;subtract slop factor <1.5> BAL
|
|
CMP.L #200,D0 ;is result < 200 bytes ?
|
|
BGE.S STKOK1 ;no, continue
|
|
MOVE #40,D0 ;yes, make bufSize = 40 bytes
|
|
BRA.S ALLOC ;and continue
|
|
STKOK1 DIVS #5,D0 ;no, divide for 5 buffers
|
|
BVC.S STKOK2 ;overflow ?
|
|
MOVE #30000,D0 ;yes, use 30K bytes
|
|
STKOK2 BCLR #0,D0 ;make bufSize even
|
|
ALLOC SUB D0,SP ;allocate one buffer
|
|
MOVE.L SP,SCAN1(A6) ;remember buffer pointer
|
|
SUB D0,SP ;allocate one buffer
|
|
MOVE.L SP,SCAN2(A6) ;remember buffer pointer
|
|
SUB D0,SP ;allocate one buffer
|
|
MOVE.L SP,SCAN3(A6) ;remember buffer pointer
|
|
SUB D0,SP ;allocate one buffer
|
|
MOVE.L SP,SCAN4(A6) ;remember buffer pointer
|
|
SUB D0,SP ;allocate one buffer
|
|
MOVE.L SP,SCAN5(A6) ;remember buffer pointer
|
|
|
|
|
|
|
|
;-----------------------------------------------------------
|
|
;
|
|
; INIT ASSORTED POINTERS
|
|
;
|
|
MOVE.L BUFHANDLE(A6),A0 ;GET BUFHANDLE
|
|
MOVE.L (A0),A0 ;DE-REFERENCE IT
|
|
MOVE.L A0,BUFFERPTR(A6) ;BUFFERPTR := BUFSTART
|
|
AND #$FFF8,MAXBYTES(A6) ;TRUNCATE TO A MULT OF 8 BYTES
|
|
;+++ ADD MAXBYTES(A6),A0
|
|
CLR.L D4 ;zero hi-word of register <C970/22Nov87> DAF
|
|
MOVE.W MAXBYTES(A6),D4 ;get long version of MaxBytes <C970/22Nov87> DAF
|
|
ADD.L D4,A0 ;add MaxBytes to BufStart <C970/22Nov87> DAF
|
|
MOVE.L A0,BUFLIMIT(A6) ;BUFLIMIT:=BUFSTART+MAXBYTES
|
|
MOVE.L SCAN1(A6),A0
|
|
MOVE.L A0,D4 ;SCANA := @SCAN1
|
|
MOVE #32767,D0
|
|
MOVE D0,(A0) ;INIT SCANA TO EMPTY
|
|
MOVE.L SCAN2(A6),A0
|
|
MOVE.L A0,D5 ;SCANB := @SCAN2
|
|
MOVE D0,(A0) ;INIT SCANB TO EMPTY
|
|
MOVE.L SCAN3(A6),A0
|
|
MOVE.L A0,D6 ;SCANC := @SCAN3
|
|
MOVE D0,(A0) ;INIT SCANC TO EMPTY
|
|
MOVE.L SCAN4(A6),A0
|
|
MOVE.L A0,D7 ;TEMPSCAN := @SCAN4
|
|
MOVE (A3)+,NEXTA(A6) ;NEXTA := FIRST VERT IN A
|
|
MOVE (A4)+,NEXTB(A6) ;NEXTB := FIRST VERT IN B
|
|
CMP #8,OP(A6) ;IS OP = INSET ?
|
|
BNE.S NXTVERT ;NO, CONTINUE
|
|
MOVE D0,NEXTB(A6) ;YES, NEXTB := 32767
|
|
NXTVERT MOVE NEXTA(A6),D0 ;GET NEXT VERT IN A
|
|
CMP NEXTB(A6),D0 ;WHICH COMES FIRST ?
|
|
BEQ.S BOTH ;SAME, UPDATE BOTH RGNS
|
|
BGT.S UPDATEB ;B, UPDATE RGNB ONLY
|
|
BSR.S UPDATEA ;A, UPDATE RGNA ONLY
|
|
BRA.S CALC ;CALC NEW C-SCAN
|
|
|
|
|
|
UPDATEA MOVE NEXTA(A6),VERT(A6) ;VERT := NEXTA
|
|
MOVE.L A3,A0 ;SRCA := PTRA
|
|
MOVE.L D4,A1 ;SRCB := SCANA
|
|
MOVE.L D7,A2 ;DSTC := TEMPSCAN
|
|
JSR XORSCAN ;XORSCAN(PTRA,SCANA,TEMPSCAN)
|
|
MOVE.L A0,A3 ;BUMP PTRA TO END OF SCAN
|
|
MOVE (A3)+,NEXTA(A6) ;NEXTA := NEXT VERT
|
|
EXG D4,D7 ;SWAP SCANA AND TEMPSCAN
|
|
RTS ;RETURN TO LOCAL CALLER
|
|
|
|
|
|
BOTH CMP #32767,D0 ;ARE BOTH VERTICALS 32767 ?
|
|
BEQ DONE ;YES, WE'RE ALL FINISHED
|
|
BSR.S UPDATEA ;UPDATE RGNA
|
|
UPDATEB MOVE NEXTB(A6),VERT(A6) ;VERT := NEXTB
|
|
MOVE.L A4,A0 ;SRCA := PTRB
|
|
MOVE.L D5,A1 ;SRCB := SCANB
|
|
MOVE.L D7,A2 ;DSTC := TEMPSCAN
|
|
JSR XORSCAN ;XORSCAN(PTRB,SCANB,TEMPSCAN)
|
|
MOVE.L A0,A4 ;BUMP PTRB TO END OF SCAN
|
|
MOVE (A4)+,NEXTB(A6) ;NEXTB := NEXT VERT
|
|
EXG D7,D5 ;SWAP SCANB AND TEMPSCAN
|
|
|
|
;---------------------------------------------------------
|
|
;
|
|
; CALCULATE SECT, DIFF, UNION, XOR, OR INSET INTO SCANC
|
|
;
|
|
CALC MOVE.L D4,A0 ;POINT TO SCANA
|
|
MOVE.L D5,A1 ;POINT TO SCANB
|
|
MOVE.L D7,A2 ;POINT TO TEMPSCAN
|
|
MOVE DH(A6),D2 ;GET DH IN CASE INSET
|
|
PEA CHANGES ;PUSH RETURN ADDR
|
|
MOVE.L CASEJMP(A6),-(SP) ;PUSH CASE JUMP
|
|
RTS ;DO CASE JSR
|
|
|
|
|
|
;-------------------------------------------------------------
|
|
;
|
|
; FIND ANY CHANGES NOT IN PREVIOUS SCANC, THEN UPDATE SCANC
|
|
;
|
|
CHANGES MOVE.L D7,A0 ;GET TEMPSCAN
|
|
MOVE.L D6,A1 ;GET SCANC
|
|
MOVE.L SCAN5(A6),A2 ;GET OUTPUT SCAN
|
|
JSR XORSCAN ;XorScan(tempScan,scanC,@SCAN5);
|
|
EXG D7,D6 ;SWAP TEMPSCAN AND SCANC
|
|
|
|
MOVE.L SCAN5(A6),A0 ;POINT TO OUTPUT SCAN
|
|
MOVE.L BUFFERPTR(A6),A1 ;POINT TO DST POINT BUFFER
|
|
MOVE.L BUFLIMIT(A6),A2 ;GET BUFLIMIT
|
|
MOVE.L VERT(A6),D0 ;GET VERT COORD IN HI WORD
|
|
BRA.S OUTTEST ;GO TO LOOP START
|
|
OUTLOOP MOVE.W (A0)+,D0 ;GET LEFT HORIZ COORD
|
|
MOVE.L D0,(A1)+ ;PUT LEFT POINT
|
|
MOVE.W (A0)+,D0 ;GET RIGHT HORIZ COORD
|
|
MOVE.L D0,(A1)+ ;PUT RIGHT POINT
|
|
OUTTEST CMP.L A2,A1 ;IS BUFFERPTR >= BUFLIMIT ?
|
|
BLO.S SIZEOK ;NO, CONTINUE
|
|
|
|
|
|
;-----------------------------------------------------------
|
|
;
|
|
; THE POINT BUFFER IS FULL, GROW IT IF OKGROW IS TRUE
|
|
;
|
|
TST.B OKGROW(A6) ;ARE WE ALLOWED TO GROW ?
|
|
BEQ ABORT ;NO, ABORT RGNOP
|
|
MOVE.L A0,D1 ;YES, SAVE OUTPUT SCAN PTR
|
|
MOVE.L RGNA(A6),A0 ;GET RGNA MASTER
|
|
SUB.L (A0),A3 ;MAKE RGNA PTR RELATIVE
|
|
MOVE.L RGNB(A6),A0 ;GET RGNB MASTER
|
|
SUB.L (A0),A4 ;MAKE RGNB PTR RELATIVE
|
|
MOVE.L BUFHANDLE(A6),A0 ;GET BUFHANDLE
|
|
SUB.L (A0),A1 ;MAKE BUFFERPTR RELATIVE
|
|
SUB.L (A0),A2 ;MAKE BUFLIMIT RELATIVE, = SIZE
|
|
ADD #256,A2 ;BUMP BUFLIMIT 256 BYTES
|
|
MOVEM.L D0-D2/A0-A2,-(SP) ;SAVE REGS
|
|
MOVE.L A0,-(SP) ;PUSH BUFHANDLE
|
|
MOVE.W A2,-(SP) ;PUSH NEW BYTECOUNT
|
|
bsr.l SetHSize ;GROW POINT BUFFER
|
|
MOVEM.L (SP)+,D0-D2/A0-A2 ;RESTORE REGS
|
|
MOVE.L RGNA(A6),A0 ;GET RGNA MASTER
|
|
ADD.L (A0),A3 ;MAKE RGNA UN-RELATIVE
|
|
MOVE.L RGNB(A6),A0 ;GET RGNB MASTER
|
|
ADD.L (A0),A4 ;MAKE RGNB UN-RELATIVE
|
|
MOVE.L BUFHANDLE(A6),A0 ;GET BUFHANDLE
|
|
ADD.L (A0),A1 ;MAKE BUFFERPTR UN-RELATIVE
|
|
ADD.L (A0),A2 ;MAKE BUFLIMIT UN-RELATIVE
|
|
MOVE.L A2,BUFLIMIT(A6) ;UPDATE BUFLIMIT
|
|
MOVE.L D1,A0 ;RESTORE OUTPUT SCAN PTR
|
|
|
|
|
|
SIZEOK CMP #32767,(A0) ;END OF SCAN MARKER ?
|
|
BNE OUTLOOP ;NO, GO FOR MORE
|
|
MOVE.L A1,BUFFERPTR(A6) ;UPDATE BUFFERPTR
|
|
BRA NXTVERT ;LOOP FOR NEXT VERT
|
|
|
|
|
|
;------------------------------------------------------------------------
|
|
;
|
|
; LOCAL ROUTINE TO EXPAND A RECTANGULAR REGION TO ITS INVERSION POINTS.
|
|
; ENTER WITH ADDR OF RGNHANDLE IN A0, ADDR OF FAKE MASTER IN A2.
|
|
; RETURNS IN A0 DE-REFERENCED POINTER BUMPED TO FIRST RGNDATA,
|
|
; AND A2 BUMPED TO NEXT AVAILABLE FAKE MASTER.
|
|
;
|
|
EXPAND MOVE.L (A0),A1 ;GET RGNHANDLE
|
|
MOVE.L (A1),A1 ;DE-REFERENCE HANDLE
|
|
CMP #10,RGNSIZE(A1) ;IS REGION RECTANGULAR ?
|
|
BNE.S NOTRECT ;NO, DON'T EXPAND IT
|
|
MOVE.L A2,(A0) ;POINT HANDLE TO FAKE MASTER
|
|
LEA -6(A2),A0 ;POINT 10 BYTES BEFORE DATA
|
|
MOVE.L A0,(A2)+ ;FILL IN FAKE MASTER
|
|
MOVE.L RGNBBOX+TOPLEFT(A1),(A2)+ ;PUT TOP V AND LEFT H
|
|
MOVE RGNBBOX+RIGHT(A1),(A2) ;PUT RIGHT HORIZ
|
|
MOVE #32767,D0
|
|
CMP (A2)+,D0 ;IS RIGHT $7FFF?
|
|
BNE.S @0 ;=>NO, CONTINUE
|
|
SUBQ #1,-2(A2) ;ELSE PIN TO $7FFE
|
|
@0 MOVE D0,(A2)+ ;PUT HORIZ TERMINATOR
|
|
MOVE RGNBBOX+BOTTOM(A1),(A2) ;PUT BOTTOM VERT
|
|
CMP (A2)+,D0 ;IS VERT $7FFF?
|
|
BNE.S @1 ;=>NO, CONTINUE
|
|
SUBQ #1,-2(A2) ;ELSE PIN TO $7FFE
|
|
@1 MOVE RGNBBOX+LEFT(A1),(A2)+ ;PUT LEFT HORIZ
|
|
MOVE RGNBBOX+RIGHT(A1),(A2)+ ;PUT RIGHT HORIZ
|
|
MOVE D0,(A2)+ ;PUT HORIZ TERMINATOR
|
|
MOVE D0,(A2)+ ;PUT VERT TERMINATOR
|
|
MOVE.L A0,A1 ;PUT FAKE RGNPTR IN A1
|
|
NOTRECT LEA RGNDATA(A1),A0 ;OFFSET TO FIRST REGION DATA
|
|
RTS ;AND RETURN
|
|
|
|
|
|
ABORT MOVE.L A1,BUFFERPTR(A6) ;UPDATE BUFFERPTR
|
|
DONE MOVE.L BUFFERPTR(A6),D0 ;GET BUFFERPTR
|
|
MOVE.L BUFHANDLE(A6),A0 ;GET BUFHANDLE
|
|
SUB.L (A0),D0 ;BYTES USED = BUFFERPTR - BUFSTART
|
|
LSR #2,D0 ;DIV BY 4 FOR NPOINTS
|
|
MOVE D0,RESULT(A6) ;RETURN NPOINTS
|
|
MOVE.L SAVESTK(A6),SP ;STRIP SCAN BUFFERS
|
|
MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
|
|
UNLINK PARAMSIZE,'RGNOP '
|
|
|
|
|
|
|
|
SectScan PROC EXPORT
|
|
EXPORT DiffScan,UnionScan
|
|
;---------------------------------------------------------
|
|
;
|
|
; PROCEDURE SectScan(srcA,srcB,dstC: ScanPtr);
|
|
;
|
|
; Calculate the intersection, difference, or union of two inversion scans.
|
|
;
|
|
; Each input scan is a sorted array of integers terminated by 32767.
|
|
; The output scan contains the inversion coordinates for the result.
|
|
;
|
|
; INPUTS: A0 SRCA
|
|
; A1 SRCB
|
|
; A2 DSTC
|
|
;
|
|
; CLOBBERS D0-D3, A0-A2
|
|
;
|
|
SECT CLR D2 ;RESET ASTATE OFF
|
|
CLR D3 ;RESET BSTATE OFF
|
|
BRA.S SHARE ;SHARE CODE
|
|
DIFFSCAN CLR D2 ;RESET ASTATE OFF
|
|
BRA.S UNION2 ;SHARE CODE
|
|
UNIONSCAN MOVEQ #-1,D2 ;SET ASTATE ON
|
|
UNION2 MOVEQ #-1,D3 ;SET BSTATE ON
|
|
|
|
SHARE MOVE (A0)+,D0 ;GET NEXTA
|
|
MOVE (A1)+,D1 ;GET NEXTB
|
|
NEXT CMP D1,D0 ;IS NEXTA < NEXT B ?
|
|
BLT.S ALESS ;YES, BRANCH
|
|
BGT.S BLESS ;BR IF NEXTB IS LESS
|
|
EQUAL CMP #32767,D0 ;ARE WE AT THE END ?
|
|
BEQ.S DONE ;YES, QUIT
|
|
CMP D3,D2 ;ARE ASTATE AND BSTATE SAME ?
|
|
BNE.S SKIP0 ;NO, SKIP
|
|
MOVE D0,(A2)+ ;YES, PUT CHANGE
|
|
SKIP0 MOVE (A0)+,D0 ;GET NEW NEXTA
|
|
NOT D2 ;TOGGLE ASTATE
|
|
MOVE (A1)+,D1 ;GET NEW NEXTB
|
|
NOT D3 ;TOGGLE BSTATE
|
|
BRA NEXT ;LOOP FOR MORE
|
|
ALESS TST D3 ;TEST BSTATE
|
|
BEQ.S SKIP1 ;SKIP IF NOT TRUE
|
|
MOVE D0,(A2)+ ;PUT NEXTA
|
|
SKIP1 MOVE (A0)+,D0 ;GET NEW NEXTA
|
|
NOT D2 ;AND TOGGLE ASTATE
|
|
BRA NEXT ;LOOP FOR MORE
|
|
BLESS TST D2 ;TEST ASTATE
|
|
BEQ.S SKIP2 ;SKIP IF NOT TRUE
|
|
MOVE D1,(A2)+ ;PUT NEXTB
|
|
SKIP2 MOVE (A1)+,D1 ;GET NEW NEXTB
|
|
NOT D3 ;AND TOGGLE BSTATE
|
|
BRA NEXT ;LOOP FOR MORE
|
|
DONE MOVE #32767,(A2)+ ;PUT END MARKER INTO DST
|
|
RTS
|
|
|
|
|
|
InsetScan PROC EXPORT
|
|
EXPORT XorScan
|
|
;---------------------------------------------------------
|
|
;
|
|
; PROCEDURE InsetScan(src,dst: ScanPtr; dh: INTEGER);
|
|
;
|
|
; Horizontally inset an inversion scan by dh;
|
|
;
|
|
; The input scan is a sorted array of integers terminated by 32767.
|
|
; The output scan contains the inversion coordinates for the inset.
|
|
;
|
|
; INPUTS: A0 SRC
|
|
; A2 DST
|
|
; D2 DH
|
|
;
|
|
; CLOBBERS D0-D1/A0-A2
|
|
;
|
|
TST D2 ;IS DH NEG ?
|
|
BLT.S OUTSET ;YES, OUTSET
|
|
|
|
;---------------------------------------------------------------
|
|
;
|
|
; GET EACH PAIR OF COORDS, INSET THEM, AND CANCEL IF THEY CROSS.
|
|
;
|
|
INSET CMP #32767,(A0) ;CHECK FOR TERMINATOR
|
|
BEQ.S DONE ;QUIT WHEN FOUND
|
|
MOVE (A0)+,D0 ;GET LEFT COORD
|
|
MOVE (A0)+,D1 ;GET RIGHT COORD
|
|
ADD.W D2,D0 ;ADD DH TO LEFT
|
|
SUB.W D2,D1 ;SUB DH FROM RIGHT
|
|
CMP D1,D0 ;IS LEFT >= RIGHT ?
|
|
BGE.S INSET ;YES, SKIP BOTH
|
|
MOVE D0,(A2)+ ;PUT LEFT COORD TO DST
|
|
MOVE D1,(A2)+ ;PUT RIGHT COORD TO DST
|
|
BRA.S INSET ;LOOP ENTIRE SCAN
|
|
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; GET EACH PAIR OF COORDS, OUTSET THEM, AND CANCEL IF THEY CROSS.
|
|
;
|
|
OUTSET MOVE #-32767,A1 ;OLDRIGHT := -32767
|
|
BRA.S START ;GO TO LOOP START
|
|
OUTLOOP MOVE (A0)+,D0 ;GET LEFT COORD
|
|
MOVE (A0)+,D1 ;GET RIGHT COORD
|
|
ADD D2,D0 ;ADD DH TO LEFT
|
|
SUB D2,D1 ;SUB DH FROM RIGHT
|
|
CMP A1,D0 ;IS LEFT <= OLDRIGHT ?
|
|
BGT.S OUTOK ;NO, CONTINUE
|
|
SUB #2,A2 ;YES, OVER-WRITE PREVIOUS RIGHT
|
|
BRA.S OUTOK2 ;AND CONTINUE
|
|
OUTOK MOVE D0,(A2)+ ;PUT LEFT COORD
|
|
OUTOK2 MOVE D1,(A2)+ ;PUT RIGHT COORD
|
|
MOVE D1,A1 ;OLDRIGHT := RIGHT
|
|
START CMP #32767,(A0) ;CHECK FOR TERMINATOR
|
|
BNE OUTLOOP ;AND LOOP ENTIRE SCAN
|
|
|
|
DONE MOVE #32767,(A2)+ ;PUT TERMINATOR
|
|
RTS
|
|
|
|
|
|
;--------------------------------------------------------------
|
|
;
|
|
; LOCAL PROCEDURE XorScan(srcA,srcB,dstC: ScanPtr);
|
|
;
|
|
; Form the exclusive-or of two inversion scans.
|
|
;
|
|
; Each input scan is a sorted array of integers terminated by 32767.
|
|
; The output scan contains all input coordinates from each, but
|
|
; with duplicate pairs cancelled. It also is terminated by 32767.
|
|
;
|
|
; INPUTS: A0 SRCA
|
|
; A1 SRCB
|
|
; A2 DSTC
|
|
;
|
|
; CLOBBERS D0-D1, A0-A2
|
|
;
|
|
EQUAL CMP #32767,D0 ;ALL DONE ?
|
|
BEQ.S DONE ;YES, QUIT
|
|
XorScan MOVE (A0)+,D0 ;GET NEXT A
|
|
MOVE (A1)+,D1 ;GET NEXT B
|
|
NEXT CMP D1,D0 ;WHICH IS LESS, A OR B ?
|
|
BEQ.S EQUAL ;THE SAME, SO CANCEL
|
|
BLT.S ALESS ;A IS LESS
|
|
BLESS MOVE D1,(A2)+ ;PUT B TO DST
|
|
MOVE (A1)+,D1 ;GET NEXT B
|
|
BRA.S NEXT ;LOOP FOR MORE
|
|
ALESS MOVE D0,(A2)+ ;PUT A TO DST
|
|
MOVE (A0)+,D0 ;GET NEXT A
|
|
BRA.S NEXT ;LOOP FOR MORE
|
|
|
|
|
|
ENDPROC
|
|
|
|
|