; ; File: Stretch.m.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: © 1988-1990 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; <4> 11/8/90 KON Stretch chokes when horizonally scaling bitmaps with rowbytes >= ; $100. The problem is that ratiocase assumes reg. D0 is cleared ; (except the low byte) which it ain't. ; <3> 10/10/90 JL Change FixRatio to MFixRatio to avoid conflict with Traps.a ; <2> 7/20/90 gbm Fix some conflicting symbols ; <1.1> 11/11/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <1.2> 10/12/88 CCH Changed “m.GrafType.a” to “GrafType.m.a”. ; <1.1> 5/18/88 MSH Changed inclides to use m.GRAPHTYPES to work under EASE. ; <1.0> 2/11/88 BBM Adding file for the first time into EASE… ; ; To Do: ; ;EASE$$$ READ ONLY COPY of file “STRETCH.m.a” ; 1.1 CCH 11/11/1988 Fixed Header. ; 1.0 CCH 11/ 9/1988 Adding to EASE. ; OLD REVISIONS BELOW ; 1.2 CCH 10/12/1988 Changed “m.GrafType.a” to “GrafType.m.a”. ; 1.1 MSH 5/18/88 Changed inclides to use m.GRAPHTYPES to work under EASE. ; 1.0 BBM 2/11/88 Adding file for the first time into EASE… ; END EASE MODIFICATION HISTORY BLANKS ON STRING ASIS INCLUDE 'GRAFTYPES.m.a' ;------------------------------------------------------------------ ; ; --> STRETCH.TEXT ; StretchBits PROC EXPORT IMPORT RgnBlt,RSect,ShieldCursor,ShowCursor IMPORT InitRgn,SeekRgn,SetupStretch,ColorMap,XorSlab ;-------------------------------------------------------------- ; ; PROCEDURE StretchBits(srcBits,dstBits: BitMap; ; srcRect,dstRect: Rect; ; mode: INTEGER ; rgnA,rgnB,rgnC: RgnHandle); ; ; Transfer a rectangle of bits from srcBits to dstBits, ; stretching or compressing according to srcRect and dstRect. ; The transfer is clipped to the intersection of rgnA, rgnB, and rgnC. ; ; ; Restrictions: ; ; transfer mode 0..7 only. ; if numer <> denom, then src and dst bitmaps do not overlap. ; ; ; COPYRIGHT APPLE COMPUTER INC. ; DESIGNED AND WRITTEN BY BILL ATKINSON ; ;---------------------------------------------------- ; ; A6 OFFSETS OF PARAMETERS AFTER LINK: ; PARAMSIZE EQU 30 ;TOTAL BYTES OF PARAMETERS SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP DSTBITS EQU SRCBITS-4 ;LONG, ADDR OF BITMAP SRCRECT EQU DSTBITS-4 ;LONG, ADDR OF RECT DSTRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT MODE EQU DSTRECT-2 ;WORD RGNA EQU MODE-4 ;RGNHANDLE RGNB EQU RGNA-4 ;RGNHANDLE RGNC EQU RGNB-4 ;RGNHANDLE ;------------------------------------------------- ; ; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK: ; NUMER EQU -4 ;POINT DENOM EQU NUMER-4 ;POINT VERROR EQU DENOM-4 ;INTEGER MINRECT EQU VERROR-8 ;RECT SRCBUF EQU MINRECT-4 ;LONG DSTBUF EQU SRCBUF-4 ;LONG SRCLONGS EQU DSTBUF-2 ;WORD DSTLONGS EQU SRCLONGS-2 ;WORD STATEA EQU DSTLONGS-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 BUFSIZE EQU BUFLEFT-2 ;WORD SRCADDR EQU BUFSIZE-4 ;LONG DSTADDR EQU SRCADDR-4 ;LONG SRCROW EQU DSTADDR-4 ;LONG DSTROW EQU SRCROW-4 ;LONG SRCLIMIT EQU DSTROW-4 ;LONG VERT EQU SRCLIMIT-2 ;WORD MODECASE EQU VERT-4 ;LONG PAT EQU MODECASE-4 ;LONG, ADDR OF PAT RATIOCASE EQU PAT-4 ;LONG HORIZFRACTION EQU RATIOCASE-2 ;WORD VARSIZE EQU HORIZFRACTION ;SIZE OF LOCAL VARIABLES LINK A6,#VARSIZE ;ALLOCATE LOCAL VARIABLES MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER ;---------------------------------------------------------------- ; ; CALC NUMER AND DENOM BASED ON DSTRECT AND SRCRECT. ; IF NUMER = DENOM THEN JUST CALL RGNBLT. ; MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT MOVE BOTTOM(A0),D0 SUB TOP(A0),D0 ;CALC DST HEIGHT SWAP D0 ;PUT IN HI WORD MOVE RIGHT(A0),D0 SUB LEFT(A0),D0 ;CALC DST WIDTH MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT MOVE BOTTOM(A0),D1 SUB TOP(A0),D1 ;CALC SRC HEIGHT SWAP D1 ;PUT IN HI WORD MOVE RIGHT(A0),D1 SUB LEFT(A0),D1 ;CALC SRC WIDTH CMP.L D0,D1 ;ARE BOTH RECTS SAME SIZE BNE.S STRETCH ;NO, CAN'T USE RGNBLT XRGNBLT MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS MOVE.L DSTBITS(A6),-(SP) ;PUSH DSTBITS MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT MOVE MODE(A6),-(SP) ;PUSH MODE MOVE.L PAT(A6),-(SP) ;PAT ONLY USED FROM BELOW MOVE.L RGNA(A6),-(SP) ;PUSH RGNA MOVE.L RGNB(A6),-(SP) ;PUSH RGNB MOVE.L RGNC(A6),-(SP) ;PUSH RGNC JSR RGNBLT ;CALL RGNBLT BRA GOHOME ;AND QUIT STRETCH MOVE.L D0,NUMER(A6) ;NUMER := DST SIZE MOVE.L D1,DENOM(A6) ;DENOM := SRC SIZE JSR SetupStretch ;CALC CASEJUMP AND HORIZ FRACT MOVE.L A0,RATIOCASE(A6) ;SAVE CASE JUMP FOR LATER MOVE D0,HORIZFRACTION(A6) ;SAVE FRACTION FOR LATER ;---------------------------------------------------------------- ; ; ADJUST MODE AND PATTERN FOR COLOR SEPARATION. ; MOVE MODE(A6),-(SP) ;PUSH INPUT MODE MOVE.L PAT(A6),-(SP) ;PUSH ADDR OF DUMMY PATTERN JSR COLORMAP ;ALTER FOR COLOR SEPARATION MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN MOVE (SP)+,D2 ;GET (ALTERED) MODE MOVE D2,D3 ;COPY MODE ROR #4,D3 ;IS PATTERN BIT SET ? BCS.S XRGNBLT ;YES, USE RGNBLT TO DO PAT MOVE D2,MODE(A6) ;NO, UPDATE (ALTERED) MODE ;------------------------------------------------------------------- ; ; CALC MINRECT = INTERSECTION OF DSTRECT, DSTBITS.BOUNDS, AND THREE ; REGION BOUNDING BOXES. QUIT IF THE INTERSECTION IS EMPTY. ; MOVE.L DSTBITS(A6),A3 ;POINT TO DST BITMAP MOVE.L DSTRECT(A6),-(SP) ;PUSH ADDR OF DSTRECT PEA BOUNDS(A3) ;PUSH ADDR OF DSTBITS.BOUNDS MOVE.L RGNA(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT PEA RGNBBOX(A0) ;PUSH RGN BBOX MOVE.L RGNB(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT PEA RGNBBOX(A0) ;PUSH RGN BBOX MOVE.L RGNC(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT PEA RGNBBOX(A0) ;PUSH RGN BBOX MOVE #5,-(SP) ;PUSH NRECTS PEA MINRECT(A6) ;PUSH WHERE TO PUT RESULT JSR RSECT ;INTERSECT ALL RECTS BEQ GOHOME ;QUIT IF RESULT IS EMPTY ;---------------------------------------------------- ; ; HIDE THE CURSOR IF IT INTERSECTS MINRECT ; PEA MINRECT(A6) ;PUSH SHIELD RECT MOVE.L BOUNDS+TOPLEFT(A3),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL JSR SHIELDCURSOR ;REMOVE CURSOR IF INTERSECT ;----------------------------------------------------------------------- ; ; ALLOCATE AND CLEAR SRCBUF TO HOLD SRCWIDTH. ; MOVE DENOM+H(A6),D0 ;GET SRC WIDTH SUB #1,D0 ;SUBTRACT 1 PIXEL LSR #5,D0 ;AND DIV BY 32 FOR LONGS MOVE D0,SRCLONGS(A6) ;SAVE FOR LATER CLR.L -(SP) ;CLEAR A LONG OF SLOP AT RIGHT CLRSRC CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG DBRA D0,CLRSRC ;LOOP ENTIRE BUFFER MOVE.L SP,SRCBUF(A6); ;REMEMBER WHERE SRCBUF IS ;----------------------------------------------------------------------- ; ; ALLOCATE AND CLEAR DSTBUF TO HOLD DSTWIDTH. ; MOVE NUMER+H(A6),D0 ;GET DST WIDTH SUB #1,D0 ;SUBTRACT 1 PIXEL LSR #5,D0 ;AND DIV BY 32 FOR LONGS MOVE D0,DSTLONGS(A6) ;SAVE FOR LATER CLR.L -(SP) ;CLEAR A LONG OF SLOP AT RIGHT CLR.L -(SP) ;CLEAR ANOTHER LONG OF SLOP CLRDST CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG DBRA D0,CLRDST ;LOOP ENTIRE BUFFER MOVE.L SP,DSTBUF(A6); ;REMEMBER WHERE DSTBUF IS ;-------------------------------------------------------- ; ; CALC BUFLEFT AND BUFSIZE FOR RGN SCANLINE BUFFERS ; MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT MOVE LEFT(A0),D1 ;GET DSTRECT LEFT SUB BOUNDS+LEFT(A3),D1 ;CONVERT TO GLOBAL COORDS AND #$FFF0,D1 ;TRUNC TO MULT OF 16 ADD BOUNDS+LEFT(A3),D1 ;CONVERT BACK TO LOCAL MOVE D1,BUFLEFT(A6) ;SAVE AS BUFLEFT MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT SUB D1,D0 ;CALC WIDTH IN DOTS LSR #5,D0 ;DIV BY 32 FOR LONGS MOVE D0,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 ;----------------------------------------------------------------------- ; ; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK. ; CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR DBRA D0,CLRMASK ;LOOP TILL DONE MOVE.L SP,MASKBUF(A6); ;REMEMBER WHERE MASKBUF IS ;------------------------------------------------------------------- ; ; INIT STATE RECORDS VERT0 AND VERT1 IN CASE RECTANGULAR ; MOVE #32767,D0 MOVE D0,STATEA+NEXTV(A6) MOVE D0,STATEB+NEXTV(A6) MOVE D0,STATEC+NEXTV(A6) NEG D0 MOVE D0,STATEA+THISV(A6) MOVE D0,STATEB+THISV(A6) MOVE D0,STATEC+THISV(A6) ;---------------------------------------------------------------------- ; ; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION ; MOVEQ #10,D7 CLR D5 ;INIT ALL RGNS RECT MOVE.L RGNA(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT CMP RGNSIZE(A0),D7 ;IS RGNA RECTANGULAR ? BEQ.S ARECT ;YES, SKIP IT ADD #2,D5 ;NO, SET UP FLAG LEA STATEA(A6),A1 ;POINT TO STATE RECORD A BSR.S INITONE ;INIT STATE, ALLOC BUFFER ARECT MOVE.L RGNB(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT CMP RGNSIZE(A0),D7 ;IS RGNB RECTANGULAR ? BEQ.S BRECT ;YES, SKIP IT ADD #4,D5 ;NO, BUMP FLAG LEA STATEB(A6),A1 ;POINT TO STATE RECORD B BSR.S INITONE ;INIT STATE, ALLOC BUFFER BRECT MOVE.L RGNC(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT CMP RGNSIZE(A0),D7 ;IS RGNC RECTANGULAR ? BEQ.S CRECT ;YES, SKIP IT ADD #8,D5 ;NO, BUMP FLAG LEA STATEC(A6),A1 ;POINT TO STATE RECORD C PEA CRECT ;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 JMP INITRGN ;INIT STATE, ALLOC BUFFER CRECT ;-------------------------------------------------------------------- ; ; IF ALL 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 JSR XorSlab ;AND XOR BETWEEN THEM NOTRECT ;------------------------------------------------------ ; ; SET UP INVERT FLAG IN D7 TO REFLECT MODE BIT 2 ; CLR.L D7 ;SAY NOT INVERTED MOVE MODE(A6),D2 ;GET TRANSFER MODE BMI DONE ;QUIT IF MODE NEGATIVE BCLR #2,D2 ;TEST AND CLR INVERT BIT BEQ.S SETMODE ;SKIP IF NOT INVERTED NOT.L D7 ;INVERTED; D7 GETS ALL 1'S ;-------------------------------------------------- ; ; CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES ; SETMODE CMP #7,D2 ;IS MODE > 7 ? BGT DONE ;YES, QUIT LEA MODETAB,A0 ;POINT TO MODE TABLE MOVE.B 0(A0,D2),D2 ;GET OFFSET SUB D2,A0 ;COMPUTE ADDRESS MOVE.L A0,MODECASE(A6) ;SAVE FOR LATER ;------------------------------------------------ ; ; SET UP SRCROW, SRCLIMIT, SRCSHIFT, AND SRCADDR ; MOVE.L SRCBITS(A6),A2 ;POINT TO SRCBITS MOVE ROWBYTES(A2),D0 ;GET SRC ROWBYTES EXT.L D0 ;AND EXTEND TO LONG MOVE.L D0,SRCROW(A6) ;SRCROW := SRC ROWBYTES MOVE BOUNDS+BOTTOM(A2),D1 ;GET SRCBITS.BOUNDS.BOTTOM SUB BOUNDS+TOP(A2),D1 ;MAKE IT GLOBAL MULU D0,D1 ;MULT BY SRC ROWBYTES ADD.L BASEADDR(A2),D1 ;ADD BASEADDR ADD.L #2,D1 ;ADJUST FOR -2(A0) SRC PICKUP MOVE.L D1,SRCLIMIT(A6) ;SAVE RESULT AS SRCLIMIT MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT MOVE LEFT(A0),D1 ;GET SRCRECT LEFT SUB BOUNDS+LEFT(A2),D1 ;CONVERT TO SRC GLOBAL MOVE D1,D5 ;MAKE A COPY NEG D5 ;NEGATE IT AND AND #$F,D5 ;TREAT MOD 16 FOR SRCSHIFT MOVE TOP(A0),D0 ;GET SRCRECT TOP SUB BOUNDS+TOP(A2),D0 ;CONVERT TO SRC GLOBAL MULU ROWBYTES(A2),D0 ;MULT BY SRC ROWBYTES MOVE.L BASEADDR(A2),A0 ;GET START OF SRC BITMAP ADD.L D0,A0 ;ADD VERTICAL OFFSET ADD D5,D1 ;ADJUST SRCLEFT FOR SRCSHIFT ASR #4,D1 ;CONVERT DOTS TO WORDS ADD D1,A0 ;ADD HORIZONTAL OFFSET ADD D1,A0 ;TWICE FOR BYTES MOVE.L A0,SRCADDR(A6) ;SAVE AS SRCADDR ;---------------------------------------------------- ; ; CALC STARTING DSTROW, DSTSHIFT, AND DSTADDR ; MOVE ROWBYTES(A3),D0 ;GET DST ROWBYTES EXT.L D0 ;EXTEND TO LONG MOVE.L D0,DSTROW(A6) ;DSTROW := DST ROWBYTES MOVE.L DSTRECT(A6),A0 MOVE TOP(A0),VERT(A6) ;INIT CURRENT VERTICAL MOVE LEFT(A0),D1 ;GET DSTRECT LEFT SUB BOUNDS+LEFT(A3),D1 ;CONVERT TO GLOBAL COORDS MOVEQ #$F,D6 AND D1,D6 ;TREAT MOD 16 FOR SHIFTCNT MOVE MINRECT+TOP(A6),D0 ;GET MINRECT TOP SUB BOUNDS+TOP(A3),D0 ;CONVERT TO GLOBAL COORDS MULU ROWBYTES(A3),D0 ;MULT BY DST ROWBYTES MOVE.L BASEADDR(A3),A0 ;GET START OF DST BITMAP ADD.L D0,A0 ;ADD VERTICAL OFFSET ASR #4,D1 ;CONVERT DOTS TO WORDS ADD D1,A0 ;ADD HORIZ OFFSET ADD D1,A0 ;TWICE FOR BYTES MOVE.L A0,DSTADDR(A6) ;SAVE AS DSTADDR ;----------------------------------------------------- ; ; INIT ERROR TERM FOR DDA ; MOVE DENOM+V(A6),D0 LSR #1,D0 NEG D0 MOVE D0,VERROR(A6) ;VERROR := -DENOM.V/2 ;----------------------------------------------------- ; ; GET FIRST SCANLINE OF SRC INTO SRCBUF ; NEXTSRC MOVE.L SRCADDR(A6),A0 ;POINT TO SRC BITMAP CMP.L SRCLIMIT(A6),A0 ;IS IT EXHAUSTED ? BHS DONE ;YES, QUIT MOVE.L SRCBUF(A6),A1 ;POINT TO SRCBUF MOVE SRCLONGS(A6),D1 ;GET COUNT OF LONGS NXTSRC2 MOVE.L -2(A0),D0 ;GET A LONG OF SRC LSR.L D5,D0 ;ALIGN TO SRCBUF MOVE D0,(A1)+ ;PUT A WORD TO SRCBUF MOVE.L (A0)+,D0 ;GET A SECOND LONG LSR.L D5,D0 ;ALIGN TO SRCBUF MOVE D0,(A1)+ ;PUT A WORD TO SRCBUF DBRA D1,NXTSRC2 ;LOOP FOR ALL LONGS MOVE.L SRCROW(A6),D2 ;GET SRC ROWBYTES ADD.L D2,SRCADDR(A6) ;BUMP SRC TO NEXT ROW MOVE NUMER+V(A6),D0 ;GET NUMER.V ADD D0,VERROR(A6) ;VERROR := VERROR + NUMER.V BGT.S SRCOK ;SKIP IF VERROR > 0 ;----------------------------------------------------- ; ; WHILE (VERROR < 0) DO MERGE OTHER SCANLINES INTO SRCBUF. ; SRCLOOP MOVE.L SRCADDR(A6),A0 ;POINT TO SRC BITMAP CMP.L SRCLIMIT(A6),A0 ;IS IT EXHAUSTED ? BHS.S SRCOK ;YES, DONT GET ANY MORE MOVE.L SRCBUF(A6),A1 ;POINT TO SRCBUF MOVE SRCLONGS(A6),D1 ;GET COUNT OF LONGS NXTSRC3 MOVE.L -2(A0),D0 ;GET A LONG OF SRC LSR.L D5,D0 ;ALIGN TO SRCBUF OR D0,(A1)+ ;OR A WORD TO SRCBUF MOVE.L (A0)+,D0 ;GET A SECOND LONG LSR.L D5,D0 ;ALIGN TO SRCBUF OR D0,(A1)+ ;OR A WORD TO SRCBUF DBRA D1,NXTSRC3 ;LOOP FOR ALL LONGS ADD.L D2,SRCADDR(A6) ;BUMP SRC TO NEXT ROW MOVE NUMER+V(A6),D0 ;GET NUMER.V ADD D0,VERROR(A6) ;VERROR := VERROR + NUMER.V MORESRC BLE.S SRCLOOP ;LOOP WHILE VERROR <= 0 SRCOK ;---------------------------------------------------------- ; ; HORIZONTALLY STRETCH SRCBUF INTO DSTBUF ; MOVE.L SRCBUF(A6),A0 ;POINT TO SRCBUF MOVE.L DSTBUF(A6),A1 ;POINT TO DSTBUF MOVE DSTLONGS(A6),D0 ;GET DSTLONGS LSL #2,D0 ;QUAD FOR BYTE OFFSET LEA 4(A1,D0),A2 ;SET UP DSTLIMIT MOVE HORIZFRACTION(A6),D4 ;GET HORIZONTAL FRACTION MOVE.L RATIOCASE(A6),A3 ;GET CASE JUMP moveq #0,d0 ;RatioCase assumes D0 is clear JSR (A3) ;AND CALL STRETCHROW ;------------------------------------------------------- ; ; TRANSFER ONE OR MORE COPIES OF DSTBUF INTO DSTBITS ; NXTMASK MOVE VERT(A6),D0 ;GET CURRENT VERT COORD CMP MINRECT+TOP(A6),D0 ;IS VERT < MINV ? BLT.S NODRAW ;YES, DON'T DRAW BSR SEEKMASK ;MAKE MASK BUFFER CURRENT MOVE.L DSTBUF(A6),A3 ;INIT SRCPTR MOVE.L DSTADDR(A6),A4 ;INIT DSTPTR FOR ROW MOVE.L MASKBUF(A6),A2 ;INIT MASKPTR FOR ROW MOVE BUFSIZE(A6),D2 ;INIT COUNT OF LONGS MOVE.L MODECASE(A6),A0 ;GET MODE CASE JUMP JMP (A0) ;TAKE MODE JUMP NEXTDST MOVE.L DSTROW(A6),D0 ;GET DST ROWBYTES ADD.L D0,DSTADDR(A6) ;BUMP DST TO NEXT ROW NODRAW ADD #1,VERT(A6) ;BUMP TO NEXT VERT MOVE VERT(A6),D0 ;GET VERT CMP MINRECT+BOTTOM(A6),D0 ;ARE WE AT THE LAST SCAN LINE ? BEQ.S DONE ;YES, QUIT MOVE DENOM+V(A6),D0 SUB D0,VERROR(A6) ;VERROR := VERROR - DENOM.V BGE NXTMASK ;IF VERROR >= 0 THEN DRAW MORE BRA NEXTSRC ;ELSE GET NEXT SRC ;----------------------------------------------------------------- ; ; ENTIRE STRETCHBITS COMPLETE. RESTORE REGS AND STACK AND GO HOME. ; DONE JSR SHOWCURSOR ;RESTORE CURSOR GOHOME MOVE.L SAVESTK(A6),SP ;STRIP VARIABLE SIZED BUFFER MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGISTERS UNLINK PARAMSIZE,'STRETCHB' ;----------------------------------------------------------------- ; ; LOCAL ROUTINE TO UPDATE MASK BUFFER TO CURRENT VERTICAL COORD. ; SEEKMASK MOVE VERT(A6),D0 ;GET CURRENT VERT COORD MOVE RECTFLAG(A6),D1 ;GET RECTFLAG = 0,2,4 MOVE RECTJMP(D1),D1 ;GET OFFSET FROM TABLE JMP RECTJMP(D1) ;TAKE CASE JUMP RECTJMP DC.W SEEKOK-RECTJMP DC.W A-RECTJMP DC.W B-RECTJMP DC.W AB-RECTJMP DC.W C-RECTJMP DC.W AC-RECTJMP DC.W BC-RECTJMP DC.W ABC-RECTJMP ;-------------------------------------------------------------------- ; ; ONLY REGION A IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK ; A LEA STATEA(A6),A1 BRA.S JMPSEEK ;-------------------------------------------------------------------- ; ; ONLY REGION B IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK ; B LEA STATEB(A6),A1 BRA.S JMPSEEK ;-------------------------------------------------------------------- ; ; ONLY REGION C IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK ; C LEA STATEC(A6),A1 JMPSEEK MOVE.L MASKBUF(A6),SCANBUF(A1) ;PLAY DIRECTLY INTO MASKBUF JMP SEEKRGN ;------------------------------------------------------------------- ; ; REGIONS A AND B ARE NON-RECTANGULAR. UPDATE EACH, ; THEN FORM INTERSECTION IN THE MASK BUFFER. ; AB LEA STATEA(A6),A1 JSR SEEKRGN MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED LEA STATEB(A6),A1 JSR SEEKRGN OR (SP)+,D1 ;HAS EITHER RGN CHANGED ? BEQ.S SEEKOK ;NO, WE'RE DONE MOVE.L STATEA+SCANBUF(A6),A0 MOVE.L STATEB+SCANBUF(A6),A1 BRA.S CPY2BUF ;------------------------------------------------------------------- ; ; REGIONS A AND C ARE NON-RECTANGULAR. UPDATE EACH, ; THEN FORM INTERSECTION IN THE MASK BUFFER. ; AC LEA STATEA(A6),A1 JSR SEEKRGN MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED LEA STATEC(A6),A1 JSR SEEKRGN OR (SP)+,D1 ;HAS EITHER RGN CHANGED ? BEQ.S SEEKOK ;NO, WE'RE DONE MOVE.L STATEA+SCANBUF(A6),A0 MOVE.L STATEC+SCANBUF(A6),A1 BRA.S CPY2BUF ;------------------------------------------------------------------- ; ; REGIONS B AND C ARE NON-RECTANGULAR. UPDATE EACH, ; THEN FORM INTERSECTION IN THE MASK BUFFER. ; BC LEA STATEB(A6),A1 JSR SEEKRGN MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED LEA STATEC(A6),A1 JSR SEEKRGN OR (SP)+,D1 ;HAS EITHER RGN CHANGED ? BEQ.S SEEKOK ;NO, WE'RE DONE MOVE.L STATEB+SCANBUF(A6),A0 MOVE.L STATEC+SCANBUF(A6),A1 CPY2BUF MOVE.L MASKBUF(A6),A2 MOVE BUFSIZE(A6),D1 BCLOOP MOVE.L (A0)+,D0 AND.L (A1)+,D0 MOVE.L D0,(A2)+ DBRA D1,BCLOOP SEEKOK RTS ;ALL 3 ARE RECT, DO NOTHING ;------------------------------------------------------------------- ; ; REGIONS A, B AND C ARE ALL NON-RECTANGULAR. UPDATE EACH, ; THEN FORM INTERSECTION IN THE MASK BUFFER. ; ABC LEA STATEA(A6),A1 JSR SEEKRGN MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED LEA STATEB(A6),A1 JSR SEEKRGN OR D1,(SP) ;REMEMBER IF RGN CHANGED LEA STATEC(A6),A1 JSR SEEKRGN OR (SP)+,D1 ;HAS EITHER RGN CHANGED ? BEQ.S ABCDONE ;NO, WE'RE DONE MOVE.L STATEA+SCANBUF(A6),A0 MOVE.L STATEB+SCANBUF(A6),A1 MOVE.L STATEC+SCANBUF(A6),A2 MOVE.L MASKBUF(A6),A3 MOVE BUFSIZE(A6),D1 ABCLOOP MOVE.L (A0)+,D0 AND.L (A1)+,D0 AND.L (A2)+,D0 MOVE.L D0,(A3)+ DBRA D1,ABCLOOP ABCDONE RTS ;---------------------------------------------------------------; ; ; ; INTERFACE TO EACH OF THE STRETCHBITS SCANLINE LOOPS: ; ; ; ; REGISTERS: A0: D0: ; ; A1: D1: ; ; A2: MASKPTR D2: LONGCNT ; ; A3: SRCPTR D3: ; ; A2: DSTPTR D4: ; ; A4: D5: SRCSHIFT ; ; A6: D6: DSTSHIFT ; ; A7: D7: INVERT ; ; ; ;---------------------------------------------------------------; ;------------------------------------------------------- ; ; MODE 0 OR 4: SRC --> DST ; MASK0 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP LSR.L D6,D0 ;ALIGN TO DST SWAP D0 ;PUT INTO HI HALF OF D0 MOVE.L (A3)+,D1 ;GET SRC FROM BITMAP AND BUMP RIGHT LSR.L D6,D1 ;ALIGN TO DST MOVE D1,D0 ;ASSEMBLE ONE LONG EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET MOVE.L (A2)+,D1 ;GET MASK AND.L D1,D0 ;MASK SRC NOT.L D1 ;FORM NOTMASK AND.L (A4),D1 ;GET DST DATA OR.L D1,D0 ;MERGE WITH SRC DATA MOVE.L D0,(A4)+ ;PUT RESULT IN DST DBRA D2,MASK0 ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;GO FOR NEXT ROW ;------------------------------------------------------- ; ; MODE 1 OR 5: SRC OR DST --> DST ; MASK1 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP LSR.L D6,D0 ;ALIGN TO DST SWAP D0 ;PUT INTO HI HALF OF D0 MOVE.L (A3)+,D1 ;GET SRC FROM BITMAP LSR.L D6,D1 ;ALIGN TO DST MOVE D1,D0 ;ASSEMBLE ONE LONG EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L (A2)+,D0 ;AND WITH MASK OR.L D0,(A4)+ ;OR RESULT INTO DST DBRA D2,MASK1 ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ;------------------------------------------------------- ; ; MODE 2 OR 6: SRC XOR DST --> DST ; MASK2 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP LSR.L D6,D0 ;ALIGN TO DST SWAP D0 ;PUT INTO HI HALF OF D0 MOVE.L (A3)+,D1 ;GET SRC FROM BITMAP LSR.L D6,D1 ;ALIGN TO DST MOVE D1,D0 ;ASSEMBLE ONE LONG EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L (A2)+,D0 ;AND WITH MASK EOR.L D0,(A4)+ ;XOR RESULT INTO DST DBRA D2,MASK2 ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW ;------------------------------------------------------- ; ; MODE 3 OR 7: SRC BIC DST --> DST ; MASK3 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP LSR.L D6,D0 ;ALIGN TO DST SWAP D0 ;PUT INTO HI HALF OF D0 MOVE.L (A3)+,D1 ;GET SRC FROM BITMAP LSR.L D6,D1 ;ALIGN TO DST MOVE D1,D0 ;ASSEMBLE ONE LONG EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET AND.L (A2)+,D0 ;AND WITH MASK NOT.L D0 ;INVERT FOR BIC AND.L D0,(A4)+ ;BIC RESULT INTO DST DBRA D2,MASK3 ;LOOP ALL LONGS THIS ROW BRA NEXTDST ;LOOP FOR NEXT ROW MODETAB DC.B MODETAB-MASK0 DC.B MODETAB-MASK1 DC.B MODETAB-MASK2 DC.B MODETAB-MASK3 SetupStretch PROC EXPORT ;-------------------------------------------------------------- ; ; Routine to setup case jump for StretchRow, ; based on horiz numer and denom. ; ; Call SetupStretch with numer in D0, denom in D1. ; Returns case jump in A0, fraction in D0. ; ; Call resulting case jump with: ; ; A0: srcPtr ; A1: dstPtr ; A2: dstLimit ; D4: fraction ; ; clobbers D0-D3,A0-A1 ; LEA DONE,A0 ;POINT TO ABORT TST D0 ;IS NUMER <= 0 ? BLE FOUND ;YES, POINT TO ABORT TST D1 ;IS DENOM <= 0 ? BLE FOUND ;YES, POINT TO ABORT LEA ONE,A0 ;POINT TO FAST COPY CMP D1,D0 ;IS NUMER = DENOM ? BEQ FOUND ;YES, USE FAST COPY BLT.S SHRNKING ;NO, BRANCH IF SHRINKING ; ; We will be stretching. Calc fract = denom/numer and check for fast. ; STRCHING MOVE D0,D3 ;MAKE A COPY OF NUMER MOVE D1,D4 ;MAKE A COPY OF DENOM CLR.L -(SP) ;ROOM FOR FCN RESULT MOVE D1,-(SP) ;PUSH DENOM MOVE D0,-(SP) ;PUSH NUMER _MFixRatio ;CALL FIXRATIO, < 1.0 MOVE.L (SP)+,D0 ;POP RESULT LEA DOUBLE,A0 ;CHECK FOR FAST RATIOS CMP #$8000,D0 BEQ.S FOUND LEA QUAD,A0 CMP #$4000,D0 BEQ.S FOUND LEA EIGHT,A0 CMP #$2000,D0 BEQ.S FOUND LEA SIXTEEN,A0 CMP #$1000,D0 BEQ.S FOUND LEA ONE_5,A0 CMP #$AAAA,D0 BEQ.S FOUND LEA TRIPLE,A0 CMP #$5555,D0 BEQ.S FOUND LEA SIX,A0 CMP #$2AAA,D0 BEQ.S FOUND ; ; check for any multiple of 8: ; EXT.L D3 ;CLEAR HI WORD OF NUMER DIVU D4,D3 ;CALC NUMER DIV DENOM MOVE D3,D1 ;SAVE QUOTIENT AND.L #$FFFF0007,D3 ;IS SCALE AN EVEN MULT OF 8 ? BNE.S NOMATCH ;NO, USE GENERAL STRETCH MOVE D1,D0 ;YES RETURN QUOTIENT IN D0 LEA EIGHTS,A0 ;POINT TO FAST ROUTINE RTS ;AND RETURN NOMATCH LEA STRETCH,A0 ;POINT TO SLOW GENERAL CODE FOUND RTS ;RETURN WITH CASE JUMP IN A0 ; ; We will be shrinking. Calc fract = numer/denom and check for fast. ; SHRNKING CLR.L -(SP) ;ROOM FOR FCN RESULT MOVE D0,-(SP) ;PUSH NUMER MOVE D1,-(SP) ;PUSH DENOM _MFixRatio ;CALL FIXRATIO, < 1.0 MOVE.L (SP)+,D0 ;POP RESULT LEA HALF,A0 ;CHECK FOR FAST RATIOS CMP #$8000,D0 BEQ.S FOUND LEA QRTR,A0 CMP #$4000,D0 BEQ.S FOUND LEA THREE4,A0 CMP #$C000,D0 BEQ.S FOUND LEA SHRINK,A0 BRA FOUND ;----------------------------------------------- ; ; NUMERATOR = DENOMINATOR, JUST COPY LONGS ; ONE MOVE.L (A0)+,(A1)+ ;COPY ONE LONG MOVE.L (A0)+,(A1)+ ;COPY ANOTHER LONG CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO ONE ;NO, LOOP FOR MORE RTS ;ALL DONE ;--------------------------------------------------- ; ; SHRINK TO THREE QUARTERS. ; THREE4 MOVEQ #3,D3 ;MASK FOR HI 2 BITS ROR.L #2,D3 ;IE. $C0000000 CLR.L -(SP) ;ALLOCATE A LONG OF TEMP THREE4A MOVE.L (A0)+,D0 ;GET A LONG OF SRC MOVEQ #7,D2 ;INIT COUNT OF 24 DST BITS THREE4B ADD.L D0,D0 ;GET 1 BIT OF SRC ADDX.L D1,D1 ;PUT 1 BIT TO DST ADD.L D3,D0 ;PUT HI 2 BITS INTO CARRY ADDX.L D1,D1 ;SHIFT INTO DST LSL.L #3,D0 ;SHIFT LEFT 3 BITS ADDX.L D1,D1 ;PUT CARRY BIT INTO DST DBRA D2,THREE4B ;LOOP 8 TIMES MOVE.L D1,(SP) ;STASH 3 DST BYTES IN TEMP MOVE.B 1(SP),(A1)+ ;PUT FIRST BYTE TO DST MOVE.B 2(SP),(A1)+ ;PUT SECOND BYTE TO DST MOVE.B 3(SP),(A1)+ ;PUT THIRD BYTE TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO THREE4A ;NO, CONTINUE ADD #4,SP ;YES, STRIP TEMP RTS ;AND QUIT ;--------------------------------------------------- ; ; SHRINK TO ONE HALF. ; HALF MOVEQ #3,D3 ;MASK FOR HI 2 BITS ROR.L #2,D3 ;IE. $C0000000 HALF1 MOVE.L (A0)+,D0 ;GET A LONG OF SRC MOVEQ #7,D2 ;INIT COUNT OF 16 DST BITS HALF2 ADD.L D3,D0 ;PUT OR OF HI BITS INTO CARRY ADDX D1,D1 ;SHIFT BIT INTO DST LSL.L #2,D0 ;SHIFT LEFT 2 BITS ADD.L D3,D0 ;PUT OR OF HI BITS INTO CARRY ADDX.L D1,D1 ;SHIFT BIT INTO DST LSL.L #2,D0 ;SHIFT LEFT 2 BITS DBRA D2,HALF2 ;LOOP 8 TIMES MOVE D1,(A1)+ ;THEN PUT A WORD TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO HALF1 ;NO, CONTINUE RTS ;YES, QUIT ;--------------------------------------------------- ; ; SHRINK TO ONE QUARTER. ; QRTR MOVE.L #$F0000000,D3 ;MASK FOR HI 4 BITS QRTR1 MOVE.L (A0)+,D0 ;GET A LONG OF SRC MOVEQ #7,D2 ;INIT COUNT OF 8 DST BITS QRTR2 ADD.L D3,D0 ;PUT OR OF HI BITS INTO CARRY ADDX.L D1,D1 ;SHIFT BIT INTO DST LSL.L #4,D0 ;SHIFT LEFT 4 BITS DBRA D2,QRTR2 ;LOOP 8 TIMES MOVE.B D1,(A1)+ ;THEN PUT A BYTE TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO QRTR1 ;NO, CONTINUE RTS ;YES, QUIT ;----------------------------------------------- ; ; STRETCH TO 1.5 TIMES AS WIDE ; ONE_5 MOVE.B (A0)+,D0 ;GET FIRST BYTE FROM SRC MOVE D0,D1 ;MAKE AN EXTRA COPY LSR.B #4,D1 ;GET HI NIBBLE MOVE.B TABLE15(D1),D2 ;EXPAND TO 6 BITS LSL.L #6,D2 ;SHIFT OVER 6 AND #$F,D0 ;GET LO NIBBLE MOVE.B TABLE15(D0),D2 ;EXPAND TO 6 BITS LSL.L #6,D2 ;SHIFT OVER 6 MOVE.B (A0)+,D0 ;GET SECOND BYTE FROM SRC MOVE D0,D1 ;MAKE AN EXTRA COPY LSR.B #4,D1 ;GET HI NIBBLE MOVE.B TABLE15(D1),D2 ;EXPAND TO 6 BITS LSL.L #6,D2 ;SHIFT OVER 6 AND #$F,D0 ;GET LO NIBBLE MOVE.B TABLE15(D0),D2 ;EXPAND TO 6 BITS LSR.L #2,D2 ;RIGHT JUSTIFY SWAP D2 ;FLIP WORDS MOVE.B D2,(A1)+ ;PUT FIRST BYTE TO DST SWAP D2 ;FLIP BACK AGAIN MOVE D2,D1 ROR #8,D1 MOVE.B D1,(A1)+ ;PUT SECOND BYTE TO DST MOVE.B D2,(A1)+ ;PUT THIRD BYTE TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO ONE_5 ;NO, LOOP FOR MORE RTS ;ALL DONE TABLE15 DC.B $00,$0C,$10,$1C ;1.5 TIMES TABLE DC.B $60,$6C,$70,$7C DC.B $80,$8C,$90,$9C DC.B $E0,$EC,$F0,$FC ;----------------------------------------------- ; ; DOUBLE USING TABLE LOOKUP ; DOUBLE MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC MOVE D0,D1 ;MAKE AN EXTRA COPY LSR.B #4,D1 ;GET HI NIBBLE MOVE.B TABLE2(D1),(A1)+ ;DOUBLE FOR A BYTE AND #$F,D0 ;GET LO NIBBLE MOVE.B TABLE2(D0),(A1)+ ;DOUBLE FOR A BYTE CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO DOUBLE ;NO, LOOP FOR MORE RTS ;ALL DONE TABLE2 DC.B $00,$03,$0C,$0F ;DOUBLING TABLE DC.B $30,$33,$3C,$3F DC.B $C0,$C3,$CC,$CF DC.B $F0,$F3,$FC,$FF ;----------------------------------------------- ; ; TRIPLE USING TABLE LOOKUP ; TRIPLE MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC MOVE D0,D1 ;MAKE AN EXTRA COPY MOVE D0,D2 ;MAKE A THIRD COPY LSR.B #5,D2 ;GET 3 HI BITS MOVE.B TABLE3A(D2),(A1)+ ;PUT FIRST BYTE TO DST LSR.B #2,D1 AND #$F,D1 ;GET MIDDLE 4 BITS MOVE.B TABLE3B(D1),(A1)+ ;PUT SECOND BYTE TO DST AND #$7,D0 ;GET 3 LO BITS MOVE.B TABLE3C(D0),(A1)+ ;PUT THIRD BYTE TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO TRIPLE ;NO, LOOP FOR MORE RTS ;ALL DONE TABLE3A DC.B $00,$03,$1C,$1F ;TRIPLING TABLE DC.B $E0,$E3,$FC,$FF TABLE3B DC.B $00,$01,$0E,$0F DC.B $70,$71,$7E,$7F DC.B $80,$81,$8E,$8F DC.B $F0,$F1,$FE,$FF TABLE3C DC.B $00,$07,$38,$3F DC.B $C0,$C7,$F8,$FF ;----------------------------------------------- ; ; QUADRUPLE USING TABLE LOOKUP ; QUAD MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC MOVE D0,D1 ;MAKE AN EXTRA COPY AND #$F0,D1 ;MASK FOR HI NIBBLE LSR #3,D1 ;SHIFT FOR TABLE INDEX MOVE.W TABLE4(D1),(A1)+ ;PUT FIRST WORD TO DST AND #$F,D0 ;MASK FOR LO NIBBLE ADD D0,D0 ;DOUBLE FOR TABLE INDEX MOVE.W TABLE4(D0),(A1)+ ;PUT SECOND WORD TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO QUAD ;NO, LOOP FOR MORE RTS ;ALL DONE TABLE4 DC.W $0000,$000F,$00F0,$00FF ;QUADRUPLING TABLE DC.W $0F00,$0F0F,$0FF0,$0FFF DC.W $F000,$F00F,$F0F0,$F0FF DC.W $FF00,$FF0F,$FFF0,$FFFF ;----------------------------------------------- ; ; STRETCH BY SIX USING TABLE LOOKUP ; SIX MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC MOVE D0,D1 ;MAKE AN EXTRA COPY AND #$E0,D1 ;MASK FOR HI 3 BITS LSR.B #4,D1 ;SHIFT FOR TABLE INDEX MOVE.W TABLE6A(D1),(A1)+ ;PUT A WORD TO DST MOVE D0,D1 ;GET SRC BYTE AGAIN AND #$3C,D1 ;MASK FOR MIDDLE 4 BITS LSR.B #1,D1 ;SHIFT FOR TABLE INDEX MOVE.W TABLE6B(D1),(A1)+ ;PUT A WORD TO DST MOVE D0,D1 ;GET SRC BYTE AGAIN AND #7,D1 ;MASK FOR LO 3 BITS ADD D1,D1 ;DOUBLE FOR TABLE INDEX MOVE.W TABLE6C(D1),(A1)+ ;PUT A WORD TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO SIX ;NO, LOOP FOR MORE RTS ;ALL DONE TABLE6A DC.W $0000,$000F,$03F0,$03FF ;SIX TIMES TABLE DC.W $FC00,$FC0F,$FFF0,$FFFF TABLE6B DC.W $0000,$0003,$00FC,$00FF DC.W $3F00,$3F03,$3FFC,$3FFF DC.W $C000,$C003,$C0FC,$C0FF DC.W $FF00,$FF03,$FFFC,$FFFF TABLE6C DC.W $0000,$003F,$0FC0,$0FFF DC.W $F000,$F03F,$FFC0,$FFFF ;----------------------------------------------- ; ; SCALE UP BY EIGHT USING TABLE LOOKUP ; EIGHT MOVE.B (A0)+,D0 ;GET A BYTE OF SRC MOVE D0,D1 ;MAKE AN EXTRA COPY AND #$F0,D1 ;MASK FOR HI NIBBLE LSR #2,D1 ;SHIFT FOR TABLE INDEX MOVE.L TABLE8(D1),(A1)+ ;PUT FIRST LONG TO DST AND #$0F,D0 ;MASK FOR LO NIBBLE LSL #2,D0 ;SHIFT FOR TABLE INDEX MOVE.L TABLE8(D0),(A1)+ ;PUT SECOND LONG TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO EIGHT ;NO, GO FOR MORE RTS ;ALL DONE TABLE8 DC.L $00000000,$000000FF,$0000FF00,$0000FFFF DC.L $00FF0000,$00FF00FF,$00FFFF00,$00FFFFFF DC.L $FF000000,$FF0000FF,$FF00FF00,$FF00FFFF DC.L $FFFF0000,$FFFF00FF,$FFFFFF00,$FFFFFFFF ;------------------------------------------------- ; ; SCALE UP BY 16 ; SIXTEEN MOVEQ #-1,D1 ;GET SOME BLACK MOVE #$8000,D0 ;INIT SRC DATA SIXTENA ADD D0,D0 ;GET ONE BIT OF SRC BCC.S WHITE16 ;BR IF WHITE BNE.S BLACK16 ;BR IF BLACK MOVE (A0)+,D0 ;ELSE GET NEXT SRC WORD ADDX D0,D0 ;SHIFT SRC BIT OUT, 1 BIT IN BCS.S BLACK16 ;BR IF BLACK WHITE16 CLR.W (A1)+ ;PUT A WORD OF WHITE TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO SIXTENA ;NO, GO FOR MORE RTS ;ALL DONE BLACK16 MOVE D1,(A1)+ ;PUT A WORD OF BLACK TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? BLO SIXTENA ;NO, GO FOR MORE RTS ;ALL DONE ;----------------------------------------------- ; ; SCALE UP BY ANY MULTIPLE OF 8 GREATER THAN 2 ; EIGHTS LSR #3,D4 ;DIVIDE SCALE FACTOR BY 8 SUB #1,D4 ;SUB 1 FOR LOOP COUNT MOVE #$8000,D0 ;INIT SRC DATA EIGHTS1 ADD D0,D0 ;GET ONE SRC BIT IN CARRY BNE.S EIGHTS2 ;TIME FOR NEW SRC ? MOVE (A0)+,D0 ;YES, GET NEXT SRC LONG ADDX D0,D0 ;SHIFT SRC BIT OUT, 1 BIT IN EIGHTS2 SCS D1 ;SET OR CLR A BYTE MOVE D4,D2 ;INIT LOOP COUNT EIGHTS3 MOVE.B D1,(A1)+ ;PUT ONE BYTE TO DST CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ? DBHI D2,EIGHTS3 ;LOOP TILL SCALE OR DST FULL BLS EIGHTS1 ;MORE SRC IF DST NOT FULL BRA.S DONE ;THEN QUIT ;------------------------------------------------------------------ ; ; DO FULL RATIO SCALING, SHRINKING ONE BIT AT A TIME ; SHRINK CLR D1 ;INIT DST WORD MOVE #$8000,D0 ;INIT SRC WORD MOVE D0,D2 ;INIT MASK MOVE D4,D3 ;COPY RATIO LSR #1,D3 ;INIT ERR TO RATIO/2 NXTSRC1 ADD D0,D0 ;GET SRC BIT BCC.S WHITE1 ;BRANCH IF WHITE BNE.S BLACK1 ;BRANCH IF BLACK MOVE (A0)+,D0 ;ELSE GET NEW SRC WORD ADDX D0,D0 ;GET SRC BIT BCC.S WHITE1 ;AND CONTINUE BLACK1 OR D2,D1 ;SET A BIT IN DST WHITE1 ADD D4,D3 ;TIME FOR NEXT DSTBIT ? BCC NXTSRC1 ;NO, LOOP MORE SRC ROR #1,D2 ;YES, ROTATE MASK BCC NXTSRC1 ;LOOP IF DST WORD OK MOVE D1,(A1)+ ;ELSE WRITE WORD TO DST CLR D1 ;RESET DST WORD CMP.L A2,A1 ;DSTPTR >= DSTLIMIT ? BLO NXTSRC1 ;NO, LOOP RTS ;YES, QUIT ;------------------------------------------------------------------ ; ; DO FULL RATIO SCALING, STRETCHING ONE BIT AT A TIME ; STRETCH CLR D1 ;INIT DST WORD MOVE #$8000,D0 ;INIT SRC WORD MOVE D0,D2 ;INIT MASK MOVE D4,D3 ;COPY RATIO LSR #1,D3 ;INIT ERR TO RATIO/2 NXTSRC2 ADD D0,D0 ;GET SRC BIT BCC.S WHITE2 ;BRANCH IF WHITE BNE.S BLACK2 ;BRANCH IF BLACK MOVE (A0)+,D0 ;ELSE GET NEW SRC WORD ADDX D0,D0 ;GET SRC BIT BCC.S WHITE2 ;CONTINUE WITH WHITE BRA.S BLACK2 ;CONTINUE WITH BLACK BLACKOK ADD D4,D3 ;TIME FOR NEXT SRC BIT ? BCS NXTSRC2 ;YES, LOOP FOR SRC BLACK2 OR D2,D1 ;SET A BIT OF DST ROR #1,D2 ;ROTATE MASK BCC BLACKOK ;LOOP IF DST WORD OK MOVE D1,(A1)+ ;ELSE WRITE WORD TO DST CLR D1 ;RESET DST WORD CMP.L A2,A1 ;DSTPTR >= DSTLIMIT ? BLO BLACKOK ;NO, LOOP RTS ;YES, QUIT WHITEOK ADD D4,D3 ;TIME FOR NEXT SRC BIT ? BCS NXTSRC2 ;YES, LOOP FOR SRC WHITE2 ROR #1,D2 ;ROTATE MASK BCC WHITEOK ;LOOP IF DST WORD OK MOVE D1,(A1)+ ;ELSE WRITE WORD TO DST CLR D1 ;RESET DST WORD CMP.L A2,A1 ;DSTPTR >= DSTLIMIT ? BLO WHITEOK ;NO, LOOP DONE RTS END