mac-rom/QuickDraw/Classic/Stretch.m.a
Elliot Nunn 4325cdcc78 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 09:52:23 +08:00

1206 lines
36 KiB
Plaintext

;
; 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 <KON 8NOV90>
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