; ; File: SeekRgn.a ; ; Copyright: © 1981-1993 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 9/12/93 SAM Fixed a comment. ; 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