mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-28 13:52:37 +00:00
1206 lines
36 KiB
Plaintext
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
|
|
|
|
|
|
|