mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-14 21:29:53 +00:00
4325cdcc78
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.
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
|
|
|
|
|
|
|