boot3/QuickDraw/SeekRgn.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

329 lines
9.8 KiB
Plaintext

;
; File: SeekRgn.a
;
; Copyright: © 1981-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM3> 9/12/93 SAM Fixed a comment.
; <SM2> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
; so they can conditionalized out of the build.
;
; To Do:
;_____________________________________________________________________________________________________
;EASE$$$ READ ONLY COPY of file ÒSEEKRGN.aÓ
;¥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 SeekRgn.a
;
; Copyright Apple Computer, Inc. 1981-1986
; All Rights Reserved
BLANKS ON
STRING ASIS
MACHINE MC68020
;------------------------------------------------------------------
;
; --> SEEKRGN.TEXT
;
; Routines to play back a region into a scanline buffer.
;
;------------------------------------------------------------------
;
; MODIFICATION HISTORY
;
; 8May86 EHB Added backwards seekRgn
; 9May86 EHB Optimized InvPair (to make up for time spent calling it)
; 2Oct88 BAL Altered seekRgn to return number of scans until mask changes
;------------------------------------------------------------------
;
; REGION STATE RECORD:
;
; RGNPTR EQU $0 ; [LONG] POINTER TO REGION
; DATAPTR EQU $4 ; [LONG] POINTER TO REGION'S DATA
; SCANBUF EQU $8 ; [LONG] POINTER TO REGION'S SCANLINE BUFFER
; SCANSIZE EQU $C ; [WORD] SIZE OF SCANBUF IN LONGS
; THISV EQU $E ; [WORD] CURRENT VERT POSITION OF SCANBUF
; NEXTV EQU $10 ; [WORD] NEXT VERT IN REGION STRUCTURE
; MINH EQU $12 ; [WORD] LEFT EDGE OF MINRECT
; MAXH EQU $14 ; [WORD] RIGHT EDGE OF MINRECT
; LEFTH EQU $16 ; [WORD] LEFT EDGE OF BUFFER
INITRGN PROC EXPORT
;------------------------------------------------------
;
; INPUTS: A0: RGNPTR
; A1: STATE RECORD
; D0: MINH
; D1: MAXH
; D2: BUFLEFT
;
; OUTPUTS: ALL FIELDS OF STATE RECORD,
; SCANBUF ALLOCATED ON STACK
;
; CLOBBERS: D0,D1,A0
;
MOVE D0,MINH(A1) ;INSTALL MINH
MOVE D1,MAXH(A1) ;INSTALL MAXH
MOVE D2,LEFTH(A1) ;INSTALL LEFTH
move.l a0,d0 ;get master ptr @@@@ BAL 09Apr88
_rTranslate24To32 ;and with high byte mask @@@@ BAL 09Apr88
move.l d0,a0 ;put back in a0 @@@@ BAL 09Apr88
MOVE.L A0,RGNPTR(A1) ;INSTALL RGNPTR
MOVE #-32767,THISV(A1) ;THISV := -32767
MOVE RGNBBOX+TOP(A0),NEXTV(A1) ;NEXTV := RGN BBOX TOP
LEA RGNDATA(A0),A0 ;POINT TO FIRST DATA
MOVE.L A0,DATAPTR(A1) ;INIT DATAPTR
MOVE.L (SP)+,A0 ;POP RETURN ADDR
SUB D2,D1 ;CALC BUFFER WIDTH IN DOTS
SUBQ #1,D1 ;MINUS ONE FOR EDGE CASES
LSR #5,D1 ;DIV BY 32 FOR #LONGS-1
MOVE D1,SCANSIZE(A1) ;SAVE SCANSIZE FOR LATER
CLRLOOP CLR.L -(SP) ;ALLOCATE AND CLEAR BUFFER
DBRA D1,CLRLOOP
MOVE.L SP,SCANBUF(A1) ;REMEMBER BUFFER START
JMP (A0) ;RETURN
SEEKRGN PROC EXPORT
EXPORT SEEKDOWN,SEEKUP
;------------------------------------------------------------------
;
; SeekRgn(rgnState,vert);
;
; ROUTINE TO PLAY BACK A REGION FORWARD OR BACKWARD UNTIL ITS SCAN
; BUFFER CONTAINS THE BITMAP FOR THE GIVEN VERTICAL COORDINATE.
;
; INPUTS: A1 POINTS TO A REGION STATE RECORD
; DO CONTAINS THE DESIRED VERTICAL COORD
;
; OUTPUTS: UPDATES THISV, NEXTV, DATAPTR, AND SCANBUF^ OF STATE RECORD
; D2--> number of scanlines before mask changes
;
; CLOBBERS: A0,D1,D2.
;
;----------------------------------------------------
;
; RETURN QUICKLY IF SCANBUF IS ALREADY CURRENT.
;
CMP NEXTV(A1),D0 ;IS DESIRED VERT >= NEXTV ?
BGE.S SEEKDOWN ;YES, BUMP DOWNWARD
CMP THISV(A1),D0 ;IS DESIRED VERT < CURRENT VERT ?
BLT.S SEEKUP ;YES, BUMP UPWARD
move nextV(a1),d1 ;compute nextV-vert
sub d0,d1
move d0,d2 ;compute vert-thisV+1
sub thisV(a1),d2
cmp d1,d2 ;return d2=min(d1,d2)
blt.s @d2
move d1,d2
@d2 RTS ;AND RETURN
;-----------------------------------------------------
;
; RESET TO START AND MOVE DOWN.
; CALLED BY UP1 WHEN DESIRED LINE < RGNBBOX.TOP
;
UP2 MOVE.L SCANBUF(A1),A0 ;POINT TO SCANBUF
MOVE SCANSIZE(A1),D1 ;GET BUFFER SIZE
CLRLP CLR.L (A0)+ ;CLEAR A LONG
DBRA D1,CLRLP ;LOOP ENTIRE SCANBUF
MOVE.L RGNPTR(A1),A0 ;GET RGNPTR
MOVE RGNBBOX+TOP(A0),NEXTV(A1) ;NEXTV := TOP VERT
MOVE #-32767,THISV(A1) ;RESET THISV TO -32767
LEA RGNDATA(A0),A0 ;POINT TO START OF REGION DATA
MOVE.L A0,DATAPTR(A1) ;RESET DATAPTR
CMP NEXTV(A1),D0 ;IS DESIRED VERT >= NEXTV ?
bge.s SEEKDOWN ;yes, SEEKDOWN
moveq #1,d2 ;no, set count to 1 and return
bra.s done
;------------------------------------------------------
;
; WHILE DESIRED VERT >= NEXTV DO BUMP DOWN.
;
SEEKDOWN MOVEM.L D0/d3-D7/A2-A4,-(SP) ; SAVE REGS
MOVE D0,D2 ; SAVE VERT
MOVE.L DATAPTR(A1),A2 ; POINT TO VERT COORD
LEA NEXTHOR,A4 ; RETURN ADDRESS FOR INVPAIR
MOVE.W MINH(A1),D6 ; D6 = MINH FOR INVPAIR
MOVE.W MAXH(A1),D7 ; D7 = MAXH FOR INVPAIR
DOWN1 MOVE (A2)+,THISV(A1) ; UPDATE CURRENT VERT
;-------------------------------------------------
;
; GET LEFT AND RIGHT HORIZ COORDS
; AND CALL INVPAIR TO TRIM AND INVERT BUFFER
;
NEXTHOR MOVE (A2)+,D3 ; GET LEFT COORD
CMP #32767,D3 ; IS IT A TERMINATOR ?
BEQ.S DONE1 ; YES, QUIT
MOVE (A2)+,D4 ; GET RIGHT COORD
BRA.S INVPAIR ; INVERT THIS PAIR OF COORDINATES
; AND RETURN TO NEXTHOR
DONE1 CMP (A2),D2 ; IS DESIRED VERT >= NEXTV ?
BGE.S DOWN1 ; YES, BUMP DOWN SOME MORE
sub (a2),d2 ; compute scan count = nextV-vert
neg d2 ; return in d1
MOVE (A2),NEXTV(A1) ; UPDATE NEXT VERT
MOVE.L A2,DATAPTR(A1) ; UPDATE DATAPTR
MOVEM.L (SP)+,D0/d3-D7/A2-A4 ; RESTORE REGS
DONE RTS ; AND RETURN
;-----------------------------------------------------
;
; TO MOVE UPWARDS, SCAN BACKWARDS THROUGH RGNDATA.
;
SEEKUP MOVE.L RGNPTR(A1),A0 ; GET THE REGION POINTER
MOVE.W RGNBBOX+TOP(A0),D1 ; GET TOPMOST VERT
CMP.W D1,D0 ; ABOVE REGION?
BLT.S UP2 ; =>YES, RESET TO START
MOVEM.L D0/d3-D7/A2-A5,-(SP) ; SAVE REGS
MOVE D0,D2 ; SAVE VERT
LEA RGNDATA(A0),A5 ; POINT TO START OF REGION DATA
LEA NEXTH1,A4 ; RETURN ADDRESS FOR INVPAIR
MOVE.W MINH(A1),D6 ; D6 = MINH FOR INVPAIR
MOVE.W MAXH(A1),D7 ; D7 = MAXH FOR INVPAIR
NEXTH MOVE.L DATAPTR(A1),A2 ; POINT TO VERT COORD
SUBQ #2,A2 ; POINT TO TERMINATOR
;-------------------------------------------------
;
; GET LEFT AND RIGHT HORIZ COORDS
; AND CALL INVPAIR TO TRIM AND INVERT BUFFER
;
NEXTH1 MOVE -(A2),D4 ; GET RIGHT COORD (OR VERT)
MOVE -(A2),D3 ; GET LEFT COORD (OR TERMINATOR)
CMP #32767,D3 ; IS IT A TERMINATOR ?
BEQ.S DONEH1 ; => YES, DONE WITH THIS SCAN
BRA.S INVPAIR ; ELSE INVERT THIS PAIR
DONEH1 MOVE.L A2,D0 ; GET POINTER TO TERMINATOR
ADDQ.L #2,D0 ; BUMP PAST TERMINATOR
MOVE.L D0,DATAPTR(A1) ; SAVE DATA POINTER
MOVE.W D4,NEXTV(A1) ; AND SAVE VERT
; DONE WITH THIS SCAN. SCAN BACK TO PRIOR VERT TO SET THISV.
NEXTH2 MOVE -(A2),D4 ; GET RIGHT COORD (OR VERT)
CMP.L A5,A2 ; AT BEGINNING OF DATA?
BLE.S DONEH2 ; => YES, DONE
MOVE -(A2),D3 ; GET LEFT COORD (OR TERMINATOR)
CMP #32767,D3 ; IS IT A TERMINATOR ?
BNE.S NEXTH2 ; => NO, KEEP SCANNING
DONEH2 MOVE.W D4,THISV(A1) ; save as first scan in this range
CMP D4,D2 ; IS DESIRED VERT < NEXTV ?
BLT.S NEXTH ; YES, BUMP UP SOME MORE
sub d4,d2 ; compute vert-thisV+1
addq #1,d2 ;
MOVEM.L (SP)+,D0/d3-D7/A2-A5 ; RESTORE REGS
RTS ; AND RETURN
INVPAIR
;-------------------------------------------------
;
; LOCAL PROCEDURE INVPAIR
;
; CLIP THE LEFT AND RIGHT COORDINATES IN D3 AND D4
; TO THE MINRECT, THEN INVERT THAT RANGE IN SCANBUF.
;
; D6 = MINH
; D7 = MAXH
; A4 = RETURN ADDRESS
CMP D6,D4 ;IS RIGHT <= MINH ?
BLE.S IDONE ;YES, IGNORE ON LEFT
CMP D7,D3 ;IS LEFT >= MAXH ?
BGE.S IDONE ;YES, IGNORE ON RIGHT
CMP D6,D3 ;IS LEFT < MINH ?
BGE.S LOK ;NO, CONTINUE
MOVE D6,D3 ;YES, TRIM LEFT
LOK CMP D7,D4 ;IS RIGHT > MAXH ?
BLE.S ROK ;NO, CONTINUE
MOVE D7,D4 ;YES, TRIM RIGHT
ROK SUB LEFTH(A1),D3 ;MAKE COORDS REL TO BUFFER
SUB LEFTH(A1),D4
;------------------------------------------
;
; GET LEFTMASK IN D5 AND RIGHTMASK IN D1
;
MOVEQ #$1F,D0 ;GET MASK FOR LO 5 BITS
MOVE D3,D1 ;COPY LEFT COORD
AND D0,D1 ;CALC LEFT MOD 32
MOVEQ #-1,D5 ;GET ALL ONES
LSR.L D1,D5 ;SHIFT IN 0'S FROM LEFT
AND D4,D0 ;CALC RIGHT MOD 32
MOVEQ #-1,D1 ;GET ALL ONES
LSR.L D0,D1 ;SHIFT IN 0'S FROM LEFT
NOT.L D1 ;AND COMPLEMENT FOR RIGHTMASK
;------------------------------------------
;
; CALC LEFTWORD, BUFPTR, WORDCOUNT
;
LSR #5,D3 ;CONVERT DOTS TO LONGS
MOVE.L SCANBUF(A1),A3 ;COPY BUFSTART
MOVE D3,D0 ;GET LEFT LONGS
LSL #2,D0 ;CONVERT TO BYTES
ADD D0,A3 ;INIT BUFPTR TO LEFTLONG
LSR #5,D4 ;CALC RIGHT DIV 32
SUB D3,D4 ;LONGCOUNT:=RIGHTLONG-LEFTLONG
BGT.S NOTIN1 ;BR IF NOT ALL IN ONE
;------------------------------------------
;
; LEFT AND RIGHT ARE ALL IN ONE WORD
;
AND.L D5,D1 ;COMBINE LEFT AND RIGHT MASKS
EOR.L D1,(A3) ;XOR COMBINATION INTO BUFFER
IDONE JMP (A4) ; => RETURN TO CALLER
;------------------------------------------
;
; NOT ALL IN ONE WORD. DO LEFT, MIDDLE IF ANY, THEN RIGHT
;
NOTIN1 EOR.L D5,(A3)+ ;XOR LEFTMASK INTO BUFFER
BRA.S TEST ;SEE IF ANY FULL LONGS
DO2LONG NOT.L (A3)+ ;INVERT 2 WHOLE LONGS
NOT.L (A3)+
TEST SUBQ #2,D4 ;ANY LONGS LEFT ?
BGT.S DO2LONG ;YES, AT LEAST 2
BLT.S ENDLONG ;NO, FINISH UP LAST WITH MASK
NOT.L (A3)+ ;YES, DO LAST FULL LONG
ENDLONG EOR.L D1,(A3) ;XOR RIGHTMASK INTO BUFFER
JMP (A4) ; => RETURN TO CALLER
ENDPROC