mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-06 14:30:37 +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.
6891 lines
150 KiB
Plaintext
6891 lines
150 KiB
Plaintext
;EASE$$$ READ ONLY COPY of file ÒQuickerDraw.aÓ
|
||
; 1.2 CCH 01/16/1989 Merged 6.0.3 final sources into 7.0.
|
||
;¥1.1 CCH 11/16/1988 Updated to newest version.
|
||
|
||
PRINT ON
|
||
|
||
; File QuickLoops.a
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; High performance Mac II Color QuickDraw Inner Loops (for 8-bit mode)
|
||
;
|
||
; written by Andy Hertzfeld December 22, 1987
|
||
;
|
||
; This INIT patches out some of the Color QuickDraw inner loop traps
|
||
; to improve 8-bit performance by a factor of 2 to 3 (or even more!)
|
||
;
|
||
; Modification History:
|
||
;
|
||
; AJH 11-Jan-88 1st Beta release, version .9
|
||
; AJH 13-Jan-88 made fills work in modes other than 8-bit (.91)
|
||
; AJH 14-Jan-88 fixed bug in unclipped pattern fill (.92)
|
||
; AJH 16-Jan-88 fixed seek region bug in mapped copyBits (.93)
|
||
; AJH 17-Jan-88 fixed scaling rejection bug in mapped copyBits
|
||
; AJH 18-Jan-88 implemented fast 8 to 1 copyBits; fixed 1-8 seekRgn bug (.94)
|
||
; AJH 20-Jan-88 region counting for clipped blit
|
||
; AJH 22-Jan-88 fixed OR mode fill, added $335 for MacDraw Plus
|
||
; AJH 23-Jan-88 fixed bug when region is a mask (CB1to8 from CopyMask)
|
||
; AJH 24-Jan-88 broke LogoPict into separate resource; separate 1-bit logo (.95)
|
||
; AJH 25-Jan-88 region counting for InvertClip
|
||
; AJH 26-Jan-88 significantly improved oval/rrects when unclipped
|
||
; AJH 26-Jan-88 added oval/rrects in OR mode
|
||
; AJH 27-Jan-88 OR mode fills (simple and complex patterns) (.96)
|
||
; AJH 28-Jan-88 INIT wasn't locked bug (.97)
|
||
; AJH 28-Jan-88 check if already installed; if so, display logo
|
||
; AJH 29-Jan-88 removed OR mode complex fills; fixed OR mode simple fills
|
||
; AJH 29-Jan-88 reject patterns > 8 pixels wide
|
||
; AJH 29-Jan-88 added oval/rrects with complex patterns
|
||
; AJH 30-Jan-88 added arithmetic transfer mode fills for rrects/ovals
|
||
; AJH 31-Jan-88 added arithmetic transfer mode fills for unclipped rects
|
||
; AJH 01-Feb-88 added arithmetic transfer mode fills for clipped rects (.98)
|
||
; AJH 02-Feb-88 added blend mode; fixed arithmetic copyBits bug
|
||
; AJH 03-Feb-88 removed hilite by invert hack (.985)
|
||
; AJH 03-Feb-88 further optimized hilite, 1 to 8 copybits
|
||
; AJH 04-Feb-88 added transparent modes
|
||
; AJH 04-Feb-88 fixed arithmetic mode bug with type 0 patterns (-$68, not -68!) (.987)
|
||
; AJH 05-Feb-88 converted to cdev
|
||
; AJH 07-Feb-88 added configuration code at startup time (.99)
|
||
; AJH 18-Feb-88 fixed bug in transparent mode fill (LSR instead of ASR)
|
||
; AJH 18-Feb-88 fixed bug in unclipped, less than 5 wide arithmetic modes
|
||
; AJH 21-Feb-88 fixed bug in arithmetic mode cache initialization
|
||
; AJH 21-Feb-88 fixed wrong reg (A4 -> A2) bump bug in oval handler (MacDraw crash) (1.0)
|
||
; AJH 22-Feb-88 fixed bug in 8-1 copybits (can't assume map is 0 or 1 only)
|
||
; AJH 23-Feb-88 fixed arithmetic mode cache initialization (add and sub modes) (1.1)
|
||
;
|
||
;---- A New Life at Apple --------------------
|
||
;
|
||
; PB415 DAF/BAL 01Mar88 QuickerDraw integrated into system patch files
|
||
; PB427 BAL 17Mar88 Corrected some edge masking bugs in arithmetic modes.
|
||
; Return to ROM if arithmetic mode copybits from left to right.
|
||
; PB428 DAF 18Mar88 Fixed QuickerDraw to be A/UX friendly.
|
||
; PB433 DAF 22Mar88 Improved dispatches to ROM (saved a couple of bytes and cycles)
|
||
; BAL 25Mar88 Converted to use symbolic stack frame references
|
||
; PB446 DBG 29Mar88 Fixed up missed JMPs into ROM in QuickerDraw.a, which cause certain
|
||
; CopyBits cases to crash.
|
||
; PB448 DBG 30Mar88 Fixed erroneous references to HBUMP to be to SRCBUMP
|
||
; PB452 BAL 01Apr88 Fixed bug in DrawSlab OR mode handler ($381) to preserve fgColor
|
||
; PB471 BAL 18Apr88 Fixed 1 to 8 bit expansion to first insure CLUT is B/W.
|
||
; PB473 DAF 19Apr88 Modified PB471 to allow more cases to be accelerated.
|
||
; PB471 BAL/DVB 13Jun88 Fixed 1 to 8 bit expansion to first insure src = scalebuf
|
||
; (i.e. dest not before pixmap's baseAddr).
|
||
; PBnnn dÃb 12Jul88 Fixed error in 8 to 1 when white doesn't map to white.
|
||
;
|
||
;--------------------------------------------------------------------------------------------------
|
||
|
||
|
||
|
||
MACHINE MC68020
|
||
|
||
; for reference, here are the patched traps
|
||
|
||
IF 0 THEN
|
||
|
||
InstToolTp CopyScanLine1,$330
|
||
InstToolTp PatClipScanLine,$362
|
||
InstToolTp PatFillScanLine,$338
|
||
InstToolTp CBClipLine,$35A
|
||
InstToolTp InvertClip,$360
|
||
InstToolTp InvertHiliteClip,$372
|
||
InstToolTp CB1To8Clip,$373
|
||
InstToolTp FillClipScanLine,$380
|
||
InstToolTp FillClipOrLine,$381 ; Removed typo ` <PB446 DBG>
|
||
InstToolTp PatClipVar2,$35E
|
||
InstToolTp FillClipXLine,$384
|
||
|
||
InstToolTp AddOverFillO,$38A
|
||
InstToolTp SubOverFillO,$38E
|
||
InstToolTp AddPinFillO,$389
|
||
InstToolTp SubPinFillO,$38B
|
||
InstToolTp AddMaxFillO,$38D
|
||
InstToolTp AddMinFillO,$38F
|
||
InstToolTp BlendFillO,$388
|
||
InstToolTp TransFillO,$38C
|
||
|
||
InstToolTp AddOverFillR,$368
|
||
InstToolTp SubOverFillR,$36C
|
||
InstToolTp AddPinFillR,$367
|
||
InstToolTp SubPinFillR,$369
|
||
InstToolTp AddMaxFillR,$36B
|
||
InstToolTp AddMinFillR,$36D
|
||
InstToolTp BlendFillR,$366
|
||
InstToolTp TransFillR,$36A
|
||
|
||
InstToolTp AddOverUnClip,$352
|
||
InstToolTp SubOverUnClip,$356
|
||
InstToolTp AddPinUnClip,$351
|
||
InstToolTp SubPinUnClip,$353
|
||
InstToolTp AddMaxUnClip,$355
|
||
InstToolTp AddMinUnClip,$357
|
||
InstToolTp BlendUnClip,$350
|
||
InstToolTp TransUnClip,$354
|
||
|
||
ENDIF
|
||
|
||
;******************************************************************************************
|
||
|
||
;
|
||
; to make scoping for upcoming equates happier, we force the end of the previous procedure here
|
||
;
|
||
|
||
QuickerDraw PROC EXPORT
|
||
|
||
|
||
EXPORT CopyScanLine1
|
||
EXPORT PatClipScanLine
|
||
EXPORT PatClipVar2
|
||
EXPORT PatFillScanLine
|
||
EXPORT CBClipLine
|
||
EXPORT InvertClip
|
||
EXPORT InvertHiliteClip
|
||
EXPORT CB1To8Clip
|
||
EXPORT FillClipScanLine
|
||
EXPORT FillClipOrLine
|
||
EXPORT FillClipXLine
|
||
EXPORT AddOverFillO
|
||
EXPORT SubOverFillO
|
||
EXPORT AddPinFillO
|
||
EXPORT SubPinFillO
|
||
EXPORT AddMaxFillO
|
||
EXPORT AddMinFillO
|
||
EXPORT BlendFillO
|
||
EXPORT AddOverFillR
|
||
EXPORT SubOverFillR
|
||
EXPORT AddPinFillR
|
||
EXPORT SubPinFillR
|
||
EXPORT AddMaxFillR
|
||
EXPORT AddMinFillR
|
||
EXPORT BlendFillR
|
||
EXPORT AddOverUnClip
|
||
EXPORT SubOverUnclip
|
||
EXPORT AddPinUnclip
|
||
EXPORT SubPinUnclip
|
||
EXPORT AddMaxUnclip
|
||
EXPORT AddMinUnclip
|
||
EXPORT BlendUnclip
|
||
EXPORT TransFillO
|
||
EXPORT TransFillR
|
||
EXPORT TransUnClip
|
||
|
||
; now patch the inner loop traps; so far we handle:
|
||
|
||
Old330 EQU $1B8F8 ; bMain0-- copyBits, no clip, copy mode
|
||
|
||
Old338 EQU $1BB7A ; bXMain8-- pattern fill, complex pattern, copy mode, no clipping
|
||
|
||
Old350 EQU $1BF24 ; bAvg-- blend fill, unclipped rects
|
||
Old351 EQU $1BC6A ; bAddPin-- addPin fill, unclipped rects
|
||
Old352 EQU $1BBF4 ; bAddOver-- addOver fill, unclipped rects (and bitmaps)
|
||
Old353 EQU $1BD7C ; bSubPin-- subPin fill, unclipped rects
|
||
Old354 EQU $1C0B0 ; bTransparent-- transparent fill, unclipped rects
|
||
Old355 EQU $1BE18 ; bMax-- addMax fill, unclipped rects
|
||
Old356 EQU $1BD06 ; bSubOver-- subOver fill, unclipped rects
|
||
Old357 EQU $1BE9E ; bMin-- addMin fill, unclipped rects
|
||
|
||
Old35A EQU $1CBF8 ; rMASK0-- copyBits, copy mode, region clipped
|
||
|
||
Old35E EQU $1CCCC ; rMASK8-- one-reg region clipped fill
|
||
|
||
Old360 EQU $1CCFA ; rMASK10-- invert, region clipped, pattern black
|
||
|
||
Old362 EQU $1CD20 ; rXMASK8-- pattern fill, region clipped
|
||
|
||
Old366 EQU $1CF94 ; rAvg-- blend fill, clipped rects
|
||
Old367 EQU $1CDE8 ; rAddPin-- addPin fill, clipped rects
|
||
Old368 EQU $1CD9C ; rAddOver-- addOver fill, clipped rects (and bitmaps)
|
||
Old369 EQU $1CE88 ; rSubPin-- subPin fill, clipped rects
|
||
Old36A EQU $1D094 ; rTransparent-- transparent fill, clipped rects
|
||
Old36B EQU $1CEDC ; rMax-- addMax fill, clipped rects
|
||
Old36C EQU $1CE3C ; rSubOver-- subOver fill, clipped rects
|
||
Old36D EQU $1CF38 ; rMin-- addMin fill, clipped rects
|
||
|
||
Old372 EQU $1D000 ; rHilite-- clipped hilite invert
|
||
Old373 EQU $227EC ; stMASK0-- 1 to 8 clipped copyBits
|
||
|
||
Old380 EQU $1DD7E ; slMASK8-- oval/rrect copy mode scan line handler
|
||
Old381 EQU $1DD9A ; slMASK9-- oval/rrect OR mode scan line handler
|
||
|
||
Old384 EQU $1DDCE ; slXMask8-- oval/rrect complex fill, copy mode
|
||
|
||
Old388 EQU $1E1BE ; slAvg-- blend fill, ovals
|
||
Old389 EQU $1DF50 ; slAddPin-- addPin fill, ovals
|
||
Old38A EQU $1DEBA ; slAddOver-- addOver fill, ovals
|
||
Old38B EQU $1E042 ; slSubPin-- subPin fill, ovals
|
||
Old38C EQU $1E2CE ; slTransparent-- transparent fill, ovals
|
||
Old38D EQU $1E0CE ; slMax-- AddMax fill, ovals
|
||
Old38E EQU $1DFDA ; slSubOver-- subOver fill, ovals
|
||
Old38F EQU $1E146 ; slMin-- AddMin fill, ovals
|
||
|
||
;******************************************************************************************
|
||
|
||
|
||
;--------------------------------------------------------------
|
||
;
|
||
; PROCEDURE StretchBits(srcBits,maskBits,dstBits: BitMap;
|
||
; srcRect,maskRect,dstRect: Rect;
|
||
; mode: INTEGER; pat: Pattern;
|
||
; 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.
|
||
; It is also clipped to the specified mask. If MaskBits is NIL, then
|
||
; no masking is done.
|
||
;
|
||
; 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 44 ;SIZE OF PARAMETERS
|
||
SRCBITS EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
|
||
MASKBITS EQU SRCBITS-4 ;LONG, ADDR OF BITMAP
|
||
DSTBITS EQU MASKBITS-4 ;LONG, ADDR OF BITMAP
|
||
SRCRECT EQU DSTBITS-4 ;LONG, ADDR OF RECT
|
||
MASKRECT EQU SRCRECT-4 ;LONG, ADDR OF RECT
|
||
DSTRECT EQU MASKRECT-4 ;LONG, ADDR OF RECT
|
||
MODE EQU DSTRECT-2 ;WORD
|
||
PAT EQU MODE-4 ;LONG, ADDR OF PATTERN
|
||
RGNA EQU PAT-4 ;LONG, RGNHANDLE
|
||
RGNB EQU RGNA-4 ;LONG, RGNHANDLE
|
||
RGNC EQU RGNB-4 ;LONG, RGNHANDLE
|
||
multColor EQU RGNC-2 ;byte, set if source contains nonblack/white colors
|
||
|
||
;-------------------------------------------------
|
||
;
|
||
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
|
||
;
|
||
; STACK FRAME VARS USED BY SEEKMASK (CALLED BY STRETCHBITS, RGNBLT, DRAWARC, DRAWLINE)
|
||
;
|
||
RECTFLAG EQU -2 ;WORD
|
||
VERT EQU RECTFLAG-2 ;WORD
|
||
RGNBUF EQU VERT-4 ;LONG
|
||
BUFLEFT EQU RGNBUF-2 ;WORD
|
||
BUFSIZE EQU BUFLEFT-2 ;WORD
|
||
EXRTN EQU BUFSIZE-4 ;LONG
|
||
SEEKMASK EQU EXRTN-4 ;LONG
|
||
DSTMASKBUF EQU SEEKMASK-4 ;LONG
|
||
DSTMASKALIGN EQU DSTMASKBUF-4 ;LONG
|
||
STATEA EQU DSTMASKALIGN-RGNREC ;RGN STATE RECORD
|
||
STATEB EQU STATEA-RGNREC ;RGN STATE RECORD
|
||
STATEC EQU STATEB-RGNREC ;RGN STATE RECORD
|
||
|
||
; STACK FRAME VARS USED BY PATEXPAND, COLORMAP, DRAWSLAB
|
||
; CALLED BY STRETCHBITS, RGNBLT, BITBLT, DRAWARC, DRAWLINE
|
||
|
||
; SET UP FOR BITBLT AND RGNBLT
|
||
EXPAT EQU STATEC-4 ;LONG YES
|
||
PATVMASK EQU EXPAT-2 ;WORD (must follow expat)
|
||
PATHMASK EQU PATVMASK-2 ;WORD (must follow PATVMASK)
|
||
PATROW EQU PATHMASK-2 ;WORD (must follow PATHMASK)
|
||
PATHPOS EQU PATROW-2 ;WORD YES
|
||
PATVPOS EQU PATHPOS-2 ;WORD YES
|
||
LOCMODE EQU PATVPOS-2 ;WORD YES
|
||
PIXSRC EQU LOCMODE-1 ;BYTE YES
|
||
NEWPAT EQU LOCMODE-2 ;BYTE YES
|
||
LOCPAT EQU NEWPAT-4 ;LONG YES
|
||
FCOLOR EQU LOCPAT-4 ;LONG YES
|
||
BCOLOR EQU FCOLOR-4 ;LONG YES
|
||
DSTPIX EQU BCOLOR-(PMREC+CTREC+20) ;PIXMAP+COLOR TABLE YES
|
||
DSTSHIFT EQU DSTPIX-2 ;WORD YES
|
||
|
||
; these shared stack frame vars are set up and used by the arithmetic drawing modes
|
||
|
||
weight EQU DSTSHIFT-6 ;RGB weight for averaging
|
||
pin EQU weight ;RGB used by max, min
|
||
notWeight EQU weight-6 ;RGB complement of weight (for average)
|
||
multiColor EQU notWeight-2 ;byte set if source contains nonblack/white colors
|
||
colorTable EQU multiColor-4 ;long pointer to color table
|
||
invColor EQU colorTable-4 ;long pointer to inverse color table
|
||
invSize EQU invColor-2 ;word resolution of inverse color table
|
||
rtShift EQU invSize-2 ;Word used by average how far to shift
|
||
transColor EQU rtShift-4 ;long copy of backcolor for transparent
|
||
hilitColor EQU transColor-4 ;long hilite color pixels
|
||
|
||
; MORE SHARED STACK FRAME VARS (STRETCHBITS, RGNBLT, BITBLT)
|
||
|
||
SRCPIX EQU hilitColor-(PMREC+CTREC+20) ;PIXMAP YES
|
||
MASKPIX EQU SRCPIX-(PMREC+CTREC+20) ;PIXMAP YES
|
||
SRCROW EQU MASKPIX-4 ;LONG YES
|
||
MASKROW EQU SRCROW-4 ;LONG YES
|
||
DSTROW EQU MASKROW-4 ;LONG YES
|
||
SRCSHIFT EQU DSTROW-2 ;WORD YES
|
||
MASKSHIFT EQU SRCSHIFT-2 ;WORD YES
|
||
MINRECT EQU MASKSHIFT-8 ;RECT YES
|
||
INVERT EQU MINRECT-4 ;LONG YES
|
||
SAVESTK EQU INVERT-4 ;LONG YES
|
||
SAVEA5 EQU SAVESTK-4 ;LONG YES
|
||
|
||
SRCBUF EQU SAVEA5-4 ;LONG
|
||
DSTBUF EQU SRCBUF-4 ;LONG
|
||
SCALEBUF EQU DSTBUF-4 ;LONG
|
||
SRCMASKBUF EQU SCALEBUF-4 ;LONG
|
||
SRCLONGS EQU SRCMASKBUF-2 ;WORD
|
||
SRCMASKLONGS EQU SRCLONGS-2 ;WORD
|
||
DSTMASKLONGS EQU SRCMASKLONGS-2 ;WORD
|
||
DSTLONGS EQU DSTMASKLONGS-2 ;WORD
|
||
SCALELONGS EQU DSTLONGS-2 ;WORD
|
||
SRCADDR EQU SCALELONGS-4 ;LONG
|
||
MASKADDR EQU SRCADDR-4 ;LONG
|
||
DSTADDR EQU MASKADDR-4 ;LONG
|
||
SRCLIMIT EQU DSTADDR-4 ;LONG
|
||
NUMER EQU SRCLIMIT-4 ;POINT
|
||
DENOM EQU NUMER-4 ;POINT
|
||
MASKNUMER EQU DENOM-4 ;POINT
|
||
MASKDENOM EQU MASKNUMER-4 ;POINT
|
||
MODECASE EQU MASKDENOM-4 ;LONG
|
||
|
||
; STACK FRAME VARS USED BY STRETCHBITS ONLY
|
||
|
||
STACKFREE EQU MODECASE-4 ;LONG
|
||
VERROR EQU STACKFREE-2 ;INTEGER
|
||
RATIOCASE EQU VERROR-4 ;LONG
|
||
MASKCASE EQU RATIOCASE-4 ;LONG
|
||
FRACTION EQU MASKCASE-2 ;WORD
|
||
MASKFRACT EQU FRACTION-2 ;WORD
|
||
SCALECASE EQU MASKFRACT-4 ;LONG
|
||
SRCSCANS EQU SCALECASE-2 ;WORD
|
||
SRCPIXCNT EQU SRCSCANS-2 ;WORD
|
||
SRCALIGN EQU SRCPIXCNT-4 ;LONG
|
||
DSTALIGN EQU SRCALIGN-4 ;LONG
|
||
MASKALIGN EQU DSTALIGN-4 ;LONG
|
||
ScaleTbl EQU MASKALIGN-4 ;LONG
|
||
CRSRFLAG EQU ScaleTbl-2 ;WORD
|
||
REALBOUNDS EQU CRSRFLAG-4 ;LONG
|
||
|
||
; STACK FRAME VARS USED BY RGNBLT ONLY
|
||
|
||
FIRSTV EQU REALBOUNDS-2 ;WORD
|
||
LASTV EQU FIRSTV-2 ;WORD
|
||
VBUMP EQU LASTV-2 ;WORD, MUST BE ABOVE HBUMP
|
||
HBUMP EQU VBUMP-2 ;WORD
|
||
RGNADDR EQU HBUMP-4 ;LONG
|
||
SRCSIZE EQU RGNADDR-2 ;WORD
|
||
SAVESTK2 EQU SRCSIZE-4 ;LONG
|
||
|
||
; STACK FRAME VARS USED BY BITBLT ONLY
|
||
|
||
SRCV EQU SAVESTK2-2 ;WORD
|
||
DSTV EQU SRCV-2 ;WORD
|
||
SRCBUMP EQU DSTV-2 ;WORD
|
||
HEIGHT EQU SRCBUMP-2 ;WORD
|
||
LONGCNT EQU HEIGHT-2 ;WORD
|
||
SRCRECT2 EQU LONGCNT-8 ;RECT
|
||
FIRSTMASK EQU SRCRECT2-4 ;LONG
|
||
|
||
doneMid EQU FIRSTMASK-1 ;Byte two flags used to control loop
|
||
endSwitch EQU doneMid-1 ;Byte three-way switch chooses from src, pat, bigpat
|
||
lastMask EQU endSwitch-4 ;Long mask for last long blitted on line
|
||
midCount EQU lastMask-2 ;Word # of pixels on line less mask longs - 1
|
||
pixInLong EQU midCount-2 ;Word > # of pixels in a long - 1
|
||
patPos EQU pixInLong-2 ;Word pattern vertical offset
|
||
patOffset EQU patPos-4 ;Long pattern horizontal initial offset
|
||
destPixOffset EQU patOffset-2 ;Word destination pixel offset
|
||
pixInLong1 EQU destPixOffset-2 ;Word same as pixInLong, 1 based (for transparent)
|
||
VARSIZE EQU pixInLong1 ;SIZE OF LOCAL VARIABLES
|
||
|
||
;-----------------------------------------------------
|
||
; Here's where we handle the case of copyBits copy mode without region clipping ($330)
|
||
|
||
UseOld330
|
||
LEARom Old330,A1 ;must use A1 to avoid re-entry
|
||
JMP (A1)
|
||
|
||
CopyScanLine1
|
||
|
||
CMP.W #8,SRCPIX+PIXELSIZE(A6) ;8 bits/pixel?
|
||
BNE.S UseOld330 ;if not, don't handle
|
||
|
||
TST.L D7 ;toggling source?
|
||
BNE.S UseOld330 ;if so, don't handle
|
||
|
||
; it's 8 bit mode, so handle it. Calculate the address adjustments in D7 from the
|
||
; bit offset in D6 and mask in D1. First decode the mask, casing out on the direction
|
||
; in A0
|
||
|
||
|
||
MOVE.L D1,D3 ;get mask
|
||
MOVEQ #0,D1 ;assume minimum
|
||
|
||
MOVE.W D6,D0
|
||
ASR #3,D0 ;turn into byte number
|
||
|
||
MOVE.W A0,D5 ;remember direction
|
||
BPL.S @0 ;if positive, we're cool
|
||
|
||
NOT.L D3 ;invert the mask for other direction
|
||
@0
|
||
TST.L D3
|
||
BMI.S Got1stOffset ;if on, we're done
|
||
|
||
ADDQ #1,D1
|
||
LSL.L #8,D3
|
||
BMI.S Got1stOffset ;if on, we're done
|
||
|
||
ADDQ #1,D1
|
||
LSL.L #8,D3
|
||
BMI.S Got1stOffset ;if on, we're done
|
||
|
||
ADDQ #1,D1
|
||
|
||
; we got the mask offset in D1 and the byte offset in D0, so compute the bump factors
|
||
|
||
Got1stOffset
|
||
ADD.W D1,D0 ;compute byte offset
|
||
|
||
MOVE.W D0,D7 ;remember offset
|
||
SWAP D7
|
||
MOVE.W D1,D7 ;use mask offset for dest
|
||
|
||
; here's the top of the outer loop where we adjust the addresses by the offsets in D7
|
||
|
||
SL1Loop
|
||
ADD.W D7,A5
|
||
SWAP D7
|
||
ADD.W D7,A4
|
||
|
||
; get the byte count and blast the scan line
|
||
|
||
SL1Blast
|
||
MOVE.W MINRECT+RIGHT(A6),D0
|
||
SUB.W MINRECT+LEFT(A6),D0 ;compute pixel count
|
||
EXT.L D0
|
||
MOVE.L A4,A0
|
||
MOVE.L A5,A1
|
||
BSR BlockMove ;blast those bytes!
|
||
|
||
; done with this scan line, so bump to the next scan line and loop until done
|
||
|
||
SUB.W D7,A4 ;undo source offset
|
||
SWAP D7
|
||
SUB.W D7,A5 ;undo dest offset
|
||
|
||
MOVEQ #0,D0
|
||
MOVE.W LONGCNT(A6),D0 ;get long count
|
||
ADDQ #1,D0
|
||
ASL #2,D0 ;turn into byte count
|
||
|
||
TST.W D5
|
||
BPL.S @0 ;if positive, skip
|
||
|
||
NEG.L D0 ;negate it
|
||
@0
|
||
ADD.L D0,A4
|
||
ADD.L D0,A5
|
||
|
||
ADD.W SRCBUMP(A6),A4 ;bump source ; <PB448 DBG>
|
||
ADD.W A3,A5 ;bump destination
|
||
|
||
SUBQ.W #1,HEIGHT(A6) ;decrement scan line count
|
||
BNE.S SL1Loop ;if more, go do it
|
||
|
||
RTS
|
||
|
||
;******************************************************************************************
|
||
|
||
|
||
; Here's where we handle the case of 8-bit pattern fill with region clipping (trap $362)
|
||
; this is used for the more complex patterns that require 2 registers per scan line
|
||
|
||
; this routine uses "region counting" to keep track of the last scan line's region runs
|
||
; for ultra-fast plotting when the region mask hasn't changed. This requires a few different
|
||
; loops to keep track of measuring state implicitly, without performance degradation.
|
||
|
||
UseOld362
|
||
LEARom Old362,A1 ;must use A1 to avoid re-entry
|
||
JMP (A1)
|
||
|
||
PatClipScanLine
|
||
|
||
CMP.W #4,D7 ;is pattern too complex?
|
||
BGT.S UseOld362 ;if so, can't handle
|
||
|
||
LEA PatClipOuter,A0
|
||
MOVE.L A0,MODECASE(A6) ;skip initial testing on return
|
||
|
||
MOVEQ #0,D7 ;no runs yet
|
||
SUB.L A2,A2 ;runs not valid
|
||
|
||
; Handle pattern fill with region clipping. Fetch the pattern raster into D3 and D4.
|
||
|
||
PatClipOuter
|
||
ADD.W D6,A3
|
||
SWAP D6 ;bump to next raster
|
||
|
||
MOVE.L 0(A3,D6),D3 ;get 1st 4 pixels
|
||
EOR.W #4,D6
|
||
MOVE.L 0(A3,D6),D4 ;get next 4 pixels
|
||
|
||
MOVEQ #-1,D5 ;mask for comparing
|
||
|
||
; first handle the left edge outside of the inner loop so we don't count it in the runs
|
||
|
||
MOVE.L (A4)+,D1 ;fetch region mask
|
||
MOVE.L D3,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
EXG.L D3,D4
|
||
SUBQ #1,D2
|
||
BMI.S DonePCV1Line
|
||
|
||
; if the region runs in D4 are still valid, we can use special code to really plot super
|
||
; fast.
|
||
|
||
MOVE.L A2,D0 ;is it valid?
|
||
BNE V1PlotRgnRuns ;if so, go super fast
|
||
|
||
ADDQ #1,A2 ;validate it for next time
|
||
MOVEQ #0,D7 ;zero the run count
|
||
|
||
; see what the next region longword is. Go to three different loops depending on whether
|
||
; the region is all ones, zeros or both
|
||
|
||
MOVE.L (A4)+,D1 ;fetch next word of region mask
|
||
BEQ V1FirstZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE V1StartSecondRun ;if not, skip
|
||
|
||
BRA.S V1FirstOnes1
|
||
|
||
; here's the loop that counts and plots the first run of all ones
|
||
|
||
V1FirstOnes
|
||
MOVE.L (A4)+,D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE V1StartSecondRun ;if not, end the run
|
||
V1FirstOnes1
|
||
ADDQ.W #1,D7 ;bump the run count
|
||
|
||
MOVE.L D3,(A5)+
|
||
EXG.L D3,D4
|
||
|
||
DBRA D2,V1FirstOnes ;loop until we're done
|
||
|
||
; done with this scan line, so bump to the next
|
||
|
||
DonePCV1Line
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6) ;bump to next line of destination
|
||
|
||
; bump pattern index
|
||
|
||
MOVE.W PATHPOS(A6),D6
|
||
SWAP D6
|
||
ADD.W PATROW(A6),D6
|
||
AND.W PATVMASK(A6),D6 ;wrap around
|
||
|
||
; bump line count and see if we're done
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADDQ #1,D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W MINRECT+BOTTOM(A6),D0 ;all done?
|
||
BEQ DonePatClip ;if so, use common exit
|
||
|
||
; create the region mask for the new scan line, and maintain the all one's flag
|
||
|
||
CMP.W STATEB+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S V1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEB+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S V1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S V1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S V1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S V1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S V1NewRgn ;if so, go do it
|
||
|
||
TST.L DSTMASKBUF(A6) ;can we skip it?
|
||
BEQ.S V1SkipRgn ;if so, skip
|
||
V1NewRgn
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;make new region mask
|
||
|
||
SUB.L A2,A2 ;invalidate region counts
|
||
|
||
; set up registers and go handle the next line
|
||
|
||
V1SkipRgn
|
||
MOVE.L SRCADDR(A6),A3
|
||
MOVE.L RGNBUF(A6),A4
|
||
MOVE.L DSTADDR(A6),A5
|
||
MOVE.W BUFSIZE(A6),D2
|
||
|
||
BRA PatClipOuter
|
||
|
||
; here's the loop that counts and plots the first run of all zeros
|
||
|
||
V1FirstZero
|
||
MOVE.L (A4)+,D1
|
||
BNE.S V1StartSecondRun
|
||
V1FirstZero0
|
||
SUBQ.W #1,D7 ;decrement run count for zeros
|
||
|
||
ADDQ #4,A5
|
||
EXG.L D3,D4
|
||
DBRA D2,V1FirstZero
|
||
|
||
BRA.S DonePCV1Line
|
||
|
||
; the region mask is heterogenous, so plot the word and start the second run.
|
||
|
||
V1StartSecondRun
|
||
SWAP D7
|
||
|
||
MOVE.L D3,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
EXG.L D3,D4
|
||
SUBQ #1,D2
|
||
BMI.S DoneV1SecondRun
|
||
|
||
; sample the region and case out for the 2nd time
|
||
|
||
MOVE.L (A4)+,D1 ;fetch next word of region mask
|
||
BEQ.S V1stZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE.S V1StartLastRun ;if not, skip
|
||
|
||
BRA.S V1stOnes1
|
||
|
||
; here's the loop that counts and plots the second run of all ones
|
||
|
||
V1stOnes
|
||
MOVE.L (A4)+,D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE.S V1StartLastRun ;if not, end the run
|
||
V1stOnes1
|
||
ADDQ.W #1,D7 ;bump the run count
|
||
|
||
MOVE.L D3,(A5)+
|
||
EXG.L D3,D4
|
||
DBRA D2,V1stOnes ;loop until we're done
|
||
DoneV1SecondRun
|
||
SWAP D7
|
||
BRA DonePCV1Line ;all done
|
||
|
||
; here's the loop that counts the 2nd run of zeros
|
||
|
||
V1stZero
|
||
MOVE.L (A4)+,D1
|
||
BNE.S V1StartLastRun
|
||
V1stZero0
|
||
SUBQ.W #1,D7
|
||
ADDQ #4,A5 ;bump dest reg
|
||
EXG.L D3,D4
|
||
DBRA D2,V1stZero ;loop until it changes
|
||
|
||
BRA.S DoneV1SecondRun
|
||
|
||
; OK, we've accumulated two runs, so finish up the line without counting
|
||
|
||
V1StartLastRun
|
||
SWAP D7
|
||
|
||
TST.L D1
|
||
BEQ.S V1LastZero
|
||
BRA.S V1LastLoopA
|
||
V1LastLoop
|
||
MOVE.L (A4)+,D1 ;get region
|
||
BEQ.S V1LastZero
|
||
V1LastLoopA
|
||
CMP.L D5,D1
|
||
BNE.S V1LastHard
|
||
|
||
MOVE.L D3,(A5)+ ;plot it
|
||
EXG.L D3,D4
|
||
DBRA D2,V1LastLoop
|
||
|
||
BRA DonePCV1Line
|
||
V1LastZero
|
||
ADDQ #4,A5
|
||
EXG.L D3,D4
|
||
DBRA D2,V1LastLoop
|
||
BRA DonePCV1Line
|
||
V1LastHard
|
||
MOVE.L D3,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
EXG.L D3,D4
|
||
|
||
DBRA D2,V1LastLoop
|
||
BRA DonePCV1Line
|
||
|
||
; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D7.
|
||
|
||
V1PlotRgnRuns
|
||
TST.W D7 ;which type of run?
|
||
BPL.S V1BlastPat1 ;if ones, go blast it
|
||
BEQ V1PlotRHard1 ;if zero, plot one slowly, then plot 2nd run
|
||
|
||
; it's negative, so just skip over 4 times the count
|
||
|
||
MOVE.W D7,D0
|
||
|
||
NEG.W D0 ;turn into longword count
|
||
|
||
BTST #0,D0 ;is the run odd?
|
||
BEQ.S @0 ;if not, skip
|
||
|
||
EXG.L D3,D4
|
||
@0
|
||
LSL.W #2,D0 ;times 4
|
||
ADD.W D0,A4 ;skip over region
|
||
ADD.W D0,A5 ;skip over destination
|
||
|
||
ADD.W D7,D2 ;decrement count
|
||
BMI DonePCV1Line ;if done, skip
|
||
|
||
; now handle the second run
|
||
|
||
V1PRRun2
|
||
LEA @0,A0 ;plot the break longword
|
||
BRA V1PlotHardCommon
|
||
@0
|
||
MOVE.L D7,D0 ;which type of run?
|
||
BPL.S V1BlastPat2 ;if ones, go blast it
|
||
BEQ V1PlotRHard2
|
||
|
||
; it's negative, so we can skip over like above
|
||
|
||
SWAP D0
|
||
NEG.W D0 ;turn into longword count
|
||
|
||
BTST #0,D0 ;is the run odd?
|
||
BEQ.S @1 ;if not, skip
|
||
|
||
EXG.L D3,D4
|
||
@1
|
||
SUB.W D0,D2 ;decrement count
|
||
|
||
LSL.W #2,D0 ;times 4
|
||
ADD.W D0,A4 ;skip over region
|
||
ADD.W D0,A5 ;skip over destination
|
||
|
||
TST.W D2
|
||
BMI DonePCV1Line ;if done, skip
|
||
|
||
; we've interpreted both runs, so finish up using common code
|
||
|
||
BRA V1LastLoop
|
||
|
||
; Handle blasting out the first run
|
||
|
||
V1BlastPat1
|
||
MOVE.W D7,D0 ;get the size
|
||
LEA V1PRRun2,A0
|
||
BRA.S V1BlastPat
|
||
|
||
; Blast out the second run
|
||
|
||
V1BlastPat2
|
||
SWAP D0 ;use high word for 2nd run
|
||
LEA V1LastLoop,A0
|
||
|
||
; Here's the unwound loop to blast the # of longwords in D0 out.
|
||
|
||
V1BlastPat
|
||
CMP.W #8,D0 ;8 left to do?
|
||
BLT.S V1BlastFinishUp
|
||
|
||
MOVE.W D0,D1
|
||
LSR #3,D1
|
||
SUBQ #1,D1
|
||
V1BlastLoop
|
||
MOVE.L D3,(A5)+
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+
|
||
MOVE.L D4,(A5)+
|
||
|
||
DBRA D1,V1BlastLoop
|
||
V1BlastFinishUp
|
||
MOVE.W D0,D1
|
||
AND #7,D1
|
||
EOR #7,D1
|
||
|
||
BTST #0,D1
|
||
BEQ.S @0
|
||
|
||
EXG.L D3,D4
|
||
@0
|
||
JMP V1FinishTable(D1.W*2)
|
||
V1FinishTable
|
||
MOVE.L D3,(A5)+
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+ ;15 total to finish up
|
||
|
||
EXG.L D3,D4
|
||
|
||
; all done with plotting so adjust the region pointer and count, then return
|
||
|
||
@0
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
ADD.W D1,A4 ;bump region ptr
|
||
|
||
SUB.W D0,D2
|
||
BMI DonePCV1Line
|
||
V1BlastDone
|
||
JMP (A0)
|
||
|
||
; handle the heterogenous plots between runs
|
||
|
||
V1PlotRHard1
|
||
LEA V1PRRun2,A0
|
||
BRA.S V1PlotHardCommon
|
||
V1PlotRHard2
|
||
LEA V1LastLoop,A0
|
||
V1PlotHardCommon
|
||
MOVE.L (A4)+,D1
|
||
|
||
MOVE.L D3,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
EXG.L D3,D4
|
||
|
||
SUBQ #1,D2 ;count it
|
||
BMI DonePCV1Line
|
||
|
||
JMP (A0)
|
||
|
||
;******************************************************************************************
|
||
|
||
|
||
; Here's where we handle a case of 8-bit pattern fill with region clipping (trap $35E)
|
||
; where there's only 4 pixel repeating pattern so it fits in a single register.
|
||
|
||
; this routine uses "region counting" to keep track of the last scan line's region runs
|
||
; for ultra-fast plotting when the region mask hasn't changed. This requires 5 different
|
||
; loops to keep track of measuring state implicitly, without performance degradation.
|
||
|
||
; D3 has 2 runs in its two words; negative numbers are runs of zeros, positive numbers ones
|
||
; D4 has the "scan line valid" flag; if it's non-zero, it's valid.
|
||
|
||
; this routine works for any bits/pixel
|
||
|
||
UseOld35E
|
||
LEARom Old35E,A1 ;must use A1 to avoid re-entry <PB446 DBG>
|
||
JMP (A1)
|
||
|
||
PatClipVar2
|
||
|
||
LEA PatClipV2Outer,A0
|
||
MOVE.L A0,MODECASE(A6) ;skip initial testing on return
|
||
|
||
MOVEQ #0,D3 ;zero run counts
|
||
MOVEQ #0,D4 ;runs are currently invalid
|
||
|
||
; Handle pattern fill with region clipping. Fetch the pattern raster into D3 and D4.
|
||
|
||
PatClipV2Outer
|
||
MOVEQ #-1,D5 ;mask for comparing
|
||
|
||
; first handle the left edge outside of the inner loop so we don't count it in the runs
|
||
|
||
MOVE.L (A4)+,D1 ;fetch region mask
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DonePCV2Line
|
||
|
||
; if the region runs in D4 are still valid, we can use special code to really plot super
|
||
; fast.
|
||
|
||
TST.W D4 ;is it valid?
|
||
BNE V2PlotRgnRuns ;if so, go super fast
|
||
|
||
MOVEQ #-1,D4 ;validate it for next time
|
||
MOVEQ #0,D3 ;zero the run count
|
||
|
||
; see what the next region longword is. Go to three different loops depending on whether
|
||
; the region is all ones, zeros or both
|
||
|
||
MOVE.L (A4)+,D1 ;fetch next word of region mask
|
||
BEQ V2FirstZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE V2StartSecondRun ;if not, skip
|
||
|
||
BRA.S V2FirstOnes1
|
||
|
||
; here's the loop that counts and plots the first run of all ones
|
||
|
||
V2FirstOnes
|
||
MOVE.L (A4)+,D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE V2StartSecondRun ;if not, end the run
|
||
V2FirstOnes1
|
||
ADDQ.W #1,D3 ;bump the run count
|
||
|
||
MOVE.L D6,(A5)+
|
||
DBRA D2,V2FirstOnes ;loop until we're done
|
||
|
||
; done with this scan line, so bump to the next
|
||
|
||
DonePCV2Line
|
||
ADDQ #1,D7
|
||
AND.W #15,D7
|
||
MOVE.L ([EXPAT,A6],D7.W*4),D6 ;bump the pattern
|
||
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6) ;bump to next line of destination
|
||
|
||
; bump line count and see if we're done
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADDQ #1,D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W MINRECT+BOTTOM(A6),D0 ;all done?
|
||
BEQ DonePatClip ;if so, use common exit
|
||
|
||
; create the region mask for the new scan line, and maintain the all one's flag
|
||
|
||
CMP.W STATEB+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S V2NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEB+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S V2NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S V2NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S V2NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S V2NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S V2NewRgn ;if so, go do it
|
||
|
||
TST.L DSTMASKBUF(A6) ;can we skip it?
|
||
BEQ.S V2SkipRgn ;if so, skip
|
||
V2NewRgn
|
||
MOVEQ #0,D4 ;invalidate region counts
|
||
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;make new region mask
|
||
|
||
; set up registers and go handle the next line
|
||
|
||
V2SkipRgn
|
||
MOVE.L RGNBUF(A6),A4
|
||
MOVE.L DSTADDR(A6),A5
|
||
MOVE.W BUFSIZE(A6),D2
|
||
|
||
BRA PatClipV2Outer
|
||
|
||
; here's the loop that counts and plots the first run of all zeros
|
||
|
||
V2FirstZero
|
||
MOVE.L (A4)+,D1
|
||
BNE.S V2StartSecondRun
|
||
V2FirstZero0
|
||
SUBQ.W #1,D3 ;decrement run count for zeros
|
||
|
||
ADDQ #4,A5
|
||
DBRA D2,V2FirstZero
|
||
|
||
BRA.S DonePCV2Line
|
||
|
||
; the region mask is heterogenous, so plot the word and start the second run.
|
||
|
||
V2StartSecondRun
|
||
SWAP D3
|
||
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoneSecondRun
|
||
|
||
; sample the region and case out for the 2nd time
|
||
|
||
MOVE.L (A4)+,D1 ;fetch next word of region mask
|
||
BEQ.S V2ndZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE.S V2StartLastRun ;if not, skip
|
||
|
||
BRA.S V2ndOnes1
|
||
|
||
; here's the loop that counts and plots the second run of all ones
|
||
|
||
V2ndOnes
|
||
MOVE.L (A4)+,D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE.S V2StartLastRun ;if not, end the run
|
||
V2ndOnes1
|
||
ADDQ.W #1,D3 ;bump the run count
|
||
|
||
MOVE.L D6,(A5)+
|
||
DBRA D2,V2ndOnes ;loop until we're done
|
||
DoneSecondRun
|
||
SWAP D3
|
||
BRA DonePCV2Line ;all done
|
||
|
||
; here's the loop that counts the 2nd run of zeros
|
||
|
||
V2ndZero
|
||
MOVE.L (A4)+,D1
|
||
BNE.S V2StartLastRun
|
||
V2ndZero0
|
||
SUBQ.W #1,D3
|
||
ADDQ #4,A5 ;bump dest reg
|
||
DBRA D2,V2ndZero ;loop until it changes
|
||
|
||
BRA.S DoneSecondRun
|
||
|
||
; OK, we've accumulated two runs, so finish up the line without counting
|
||
|
||
V2StartLastRun
|
||
SWAP D3
|
||
|
||
TST.L D1
|
||
BEQ.S V2LastZero
|
||
BRA.S V2LastLoopA
|
||
V2LastLoop
|
||
MOVE.L (A4)+,D1 ;get region
|
||
BEQ.S V2LastZero
|
||
V2LastLoopA
|
||
CMP.L D5,D1
|
||
BNE.S V2LastHard
|
||
|
||
MOVE.L D6,(A5)+ ;plot it
|
||
DBRA D2,V2LastLoop
|
||
|
||
BRA DonePCV2Line
|
||
V2LastZero
|
||
ADDQ #4,A5
|
||
DBRA D2,V2LastLoop
|
||
BRA DonePCV2Line
|
||
V2LastHard
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
DBRA D2,V2LastLoop
|
||
BRA DonePCV2Line
|
||
|
||
; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D3.
|
||
|
||
V2PlotRgnRuns
|
||
TST.W D3 ;which type of run?
|
||
BPL.S V2BlastPat1 ;if ones, go blast it
|
||
BEQ V2PlotRHard1 ;if zero, plot one slowly, then plot 2nd run
|
||
|
||
; it's negative, so just skip over 4 times the count
|
||
|
||
MOVE.W D3,D0
|
||
|
||
NEG.W D0 ;turn into longword count
|
||
LSL.W #2,D0 ;times 4
|
||
ADD.W D0,A4 ;skip over region
|
||
ADD.W D0,A5 ;skip over destination
|
||
|
||
ADD.W D3,D2 ;decrement count
|
||
BMI DonePCV2Line ;if done, skip
|
||
|
||
; now handle the second run
|
||
|
||
V2PRRun2
|
||
LEA @0,A0 ;plot the break longword
|
||
BRA V2PlotHardCommon
|
||
@0
|
||
MOVE.L D3,D0 ;which type of run?
|
||
BPL.S V2BlastPat2 ;if ones, go blast it
|
||
BEQ.S V2PlotRHard2
|
||
|
||
; it's negative, so we can skip over like above
|
||
|
||
SWAP D0
|
||
NEG.W D0 ;turn into longword count
|
||
SUB.W D0,D2 ;decrement count
|
||
|
||
LSL.W #2,D0 ;times 4
|
||
ADD.W D0,A4 ;skip over region
|
||
ADD.W D0,A5 ;skip over destination
|
||
|
||
TST.W D2
|
||
BMI DonePCV2Line ;if done, skip
|
||
|
||
; we've interpreted both runs, so finish up using common code
|
||
|
||
BRA.S V2LastLoop
|
||
|
||
; Handle blasting out the first run
|
||
|
||
V2BlastPat1
|
||
MOVE.W D3,D0 ;get the size
|
||
LEA V2PRRun2,A0
|
||
BRA.S V2BlastPat
|
||
|
||
; Blast out the second run
|
||
|
||
V2BlastPat2
|
||
SWAP D0 ;use high word for 2nd run
|
||
LEA V2LastLoop,A0
|
||
|
||
; Here's the unwound loop to blast the # of longwords in D0 out.
|
||
|
||
V2BlastPat
|
||
CMP.W #8,D0 ;8 left to do?
|
||
BLT.S V2BlastFinishUp
|
||
|
||
MOVE.W D0,D1
|
||
LSR #3,D1
|
||
SUBQ #1,D1
|
||
V2BlastLoop
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
|
||
DBRA D1,V2BlastLoop
|
||
V2BlastFinishUp
|
||
MOVE.W D0,D1
|
||
AND #7,D1
|
||
EOR #7,D1
|
||
JMP V2FinishTable(D1.W*2)
|
||
V2FinishTable
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+
|
||
MOVE.L D6,(A5)+ ;15 total to finish up
|
||
|
||
; all done with plotting so adjust the region pointer and count, then return
|
||
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
ADD.W D1,A4 ;bump region ptr
|
||
|
||
SUB.W D0,D2
|
||
BMI DonePCV2Line
|
||
|
||
JMP (A0)
|
||
|
||
; handle the heterogenous plots between runs
|
||
|
||
V2PlotRHard1
|
||
LEA V2PRRun2,A0
|
||
BRA.S V2PlotHardCommon
|
||
V2PlotRHard2
|
||
LEA V2LastLoop,A0
|
||
V2PlotHardCommon
|
||
MOVE.L (A4)+,D1
|
||
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
SUBQ #1,D2 ;count it
|
||
BMI DonePCV2Line
|
||
|
||
JMP (A0)
|
||
|
||
;******************************************************************************************
|
||
|
||
; Here's where we handle the case of 8-bit pattern fill with no clipping (trap $338)
|
||
; (with complex pattern, copy mode)
|
||
|
||
UseOld338
|
||
LEARom Old338,A1 ;must use A1 to avoid re-entry
|
||
JMP (A1)
|
||
|
||
PatFillScanLine
|
||
|
||
CMP.W #4,D7 ;is pattern too complex?
|
||
BGT.S UseOld338 ;if so, can't handle
|
||
|
||
; Handle pattern fill with no clipping. Fetch the pattern raster into D3 and D4. The
|
||
; basic strategy is to do the edge in the general (masking) way, then blast away for
|
||
; the middle, finally handling the right edge generally.
|
||
|
||
PatFillOuter
|
||
MOVE.L 0(A4,D6),D3 ;get left pattern
|
||
EOR.W #4,D6
|
||
MOVE.L 0(A4,D6),D4 ;get right pattern
|
||
|
||
; first special case the left edge before falling into the loop
|
||
|
||
MOVE.L D1,D0 ;get left mask
|
||
AND.L D3,D0 ;use left pattern
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;get dest
|
||
OR.L D1,D0 ;combine with source
|
||
MOVE.L D0,(A5)+ ;stuff it
|
||
|
||
; now blast away for the bulk of it
|
||
|
||
MOVE.W D2,D0
|
||
BEQ.S NextPFillLine
|
||
|
||
CMP.W #4,D2 ;near the end?
|
||
BLE.S PatFillFinish ;if so, go handle
|
||
|
||
SUBQ #1,D0 ;do last one with mask
|
||
LSR #2,D0 ;divide by 4 for unwound loop
|
||
SUBQ #1,D0 ;bias for DBRA
|
||
PatFillInner
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+ ;store 32 pixels worth real fast
|
||
|
||
DBRA D0,PatFillInner
|
||
|
||
; finish up the last few pixels
|
||
|
||
PatFillFinish
|
||
MOVE.L D4,D0
|
||
|
||
MOVE.W D2,D1
|
||
AND #3,D1
|
||
JMP PatFinTable(D1.W*2)
|
||
Finish4
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+
|
||
Finish2
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,D0
|
||
BRA.S Finish1
|
||
PatFinTable
|
||
BRA.S Finish4
|
||
BRA.S Finish1
|
||
BRA.S Finish2
|
||
BRA.S Finish3
|
||
Finish3
|
||
MOVE.L D4,(A5)+
|
||
MOVE.L D3,(A5)+
|
||
Finish1
|
||
MOVE.L D5,D1 ;get mask
|
||
AND.L D1,D0 ;mask pattern in D0
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;get dest
|
||
OR.L D1,D0 ;combine with source
|
||
MOVE.L D0,(A5)+ ;stuff it
|
||
NextPFillLine
|
||
SWAP D6
|
||
SUB.W D6,A4
|
||
|
||
ADD.W PATROW(A6),D6
|
||
AND.W PATVMASK(A6),D6 ;wrap around
|
||
ADD.W D6,A4
|
||
SWAP D6
|
||
|
||
MOVE.W PATHPOS(A6),D6
|
||
ADD.W A3,A5
|
||
|
||
MOVE.L FIRSTMASK(A6),D1
|
||
MOVE.W LONGCNT(A6),D2
|
||
|
||
SUBQ.W #1,HEIGHT(A6) ;decrement scan line count
|
||
BNE PatFillOuter
|
||
|
||
RTS
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
|
||
; Handle copyBits, copy mode, with region clipping. Use the region clipping technique
|
||
; for fast plotting
|
||
|
||
UseOld35A
|
||
LEARom Old35A,A1 ; <PB446 DBG>
|
||
JMP (A1)
|
||
|
||
CBClipLine
|
||
|
||
CMP.W #8,SRCPIX+PIXELSIZE(A6) ;8 bits/pixel?
|
||
BNE.S UseOld35A ;if not, don't handle
|
||
|
||
TST.L D7 ;toggling source?
|
||
BNE.S UseOld35A ;if so, don't handle
|
||
|
||
LEA CBClipCommon,A0
|
||
MOVE.L A0,MODECASE(A6) ;skip initial testing on return
|
||
|
||
MOVEQ #0,D4 ;count invalid 1st time through
|
||
CBClipCommon
|
||
MOVEQ #-1,D5 ;get all ones for comparing
|
||
CBClipOuter
|
||
MOVE.W D6,D0 ;get bit index
|
||
ASR.W #3,D0 ;convert to byte index
|
||
ADD.W D0,A3 ;factor in the byte offset
|
||
|
||
TST.W D3 ;forwards or backwards?
|
||
BMI CBClipNeg ;if backwards, handle specially
|
||
|
||
; the first set of loops is for the plotting forward case (moving towards the left)
|
||
|
||
; first handle the left edge outside of the inner loop so we don't count it in the runs
|
||
|
||
CBClipLoop
|
||
MOVE.L (A4)+,D1 ;fetch region mask
|
||
MOVE.L (A3)+,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoneCBCLine
|
||
|
||
; if the region runs in D4 are still valid, we can use special code to really plot super
|
||
; fast.
|
||
|
||
TST.W D4 ;is it valid?
|
||
BNE CBCPlotRgnRuns ;if so, go super fast
|
||
|
||
MOVEQ #-1,D4 ;validate it for next time
|
||
MOVEQ #0,D7 ;zero the run count
|
||
|
||
; see what the next region longword is. Go to three different loops depending on whether
|
||
; the region is all ones, zeros or both
|
||
|
||
MOVE.L (A4)+,D1 ;fetch next word of region mask
|
||
BEQ CBCFirstZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE CBCStartSecondRun ;if not, skip
|
||
|
||
BRA.S CBCFirstOnes1
|
||
|
||
; here's the loop that counts and plots the first run of all ones
|
||
|
||
CBCFirstOnes
|
||
MOVE.L (A4)+,D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE CBCStartSecondRun ;if not, end the run
|
||
CBCFirstOnes1
|
||
ADDQ.W #1,D7 ;bump the run count
|
||
|
||
MOVE.L (A3)+,(A5)+
|
||
DBRA D2,CBCFirstOnes ;loop until we're done
|
||
|
||
; all done with the scan line so bump the pointers, generate a new region mask if
|
||
; necessary, and loop until we're done
|
||
|
||
DoneCBCLine
|
||
MOVE.L SRCROW(A6),D0
|
||
ADD.L D0,SRCADDR(A6)
|
||
|
||
; now bump the output scan line pointer
|
||
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6) ;bump to next line
|
||
|
||
; bump line count and see if we're done
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADD.W VBUMP(A6),D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W LASTV(A6),D0 ;all done?
|
||
BEQ.S DonePatClip ;if not, skip
|
||
|
||
; create the region mask for the new scan line, and maintain the all one's flag
|
||
|
||
CMP.W STATEB+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CBCNewRgn ;if so, go do it
|
||
|
||
CMP.W STATEB+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CBCNewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CBCNewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CBCNewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CBCNewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CBCNewRgn ;if so, go do it
|
||
|
||
TST.L DSTMASKBUF(A6) ;can we skip it?
|
||
BEQ.S CBCSkipRgn ;if so, skip
|
||
CBCNewRgn
|
||
MOVEQ #0,D4 ;invalidate region counts
|
||
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;make new region mask
|
||
|
||
; set up registers and go handle the next line
|
||
|
||
CBCSkipRgn
|
||
MOVE.L SRCADDR(A6),A3
|
||
MOVE.L RGNADDR(A6),A4
|
||
MOVE.L DSTADDR(A6),A5
|
||
MOVE.W BUFSIZE(A6),D2
|
||
|
||
MOVE.L MODECASE(A6),A2
|
||
JMP (A2)
|
||
|
||
; all done so strip stack and return
|
||
|
||
DonePatClip
|
||
MOVE.L SAVESTK2(A6),A7
|
||
DonePClipRTS
|
||
RTS
|
||
|
||
; here's the loop that counts and plots the first run of all zeros
|
||
|
||
CBCFirstZero
|
||
MOVE.L (A4)+,D1
|
||
BNE.S CBCStartSecondRun
|
||
CBCFirstZero0
|
||
SUBQ.W #1,D7 ;decrement run count for zeros
|
||
|
||
ADDQ #4,A3
|
||
ADDQ #4,A5
|
||
DBRA D2,CBCFirstZero
|
||
|
||
BRA.S DoneCBCLine
|
||
|
||
; the region mask is heterogenous, so plot the word and start the second run.
|
||
|
||
CBCStartSecondRun
|
||
SWAP D7
|
||
|
||
MOVE.L (A3)+,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoneCBCSecondRun
|
||
|
||
; sample the region and case out for the 2nd time
|
||
|
||
MOVE.L (A4)+,D1 ;fetch next word of region mask
|
||
BEQ.S CBCndZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE.S CBCStartLastRun ;if not, skip
|
||
|
||
BRA.S CBCndOnes1
|
||
|
||
; here's the loop that counts and plots the second run of all ones
|
||
|
||
CBCndOnes
|
||
MOVE.L (A4)+,D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE.S CBCStartLastRun ;if not, end the run
|
||
CBCndOnes1
|
||
ADDQ.W #1,D7 ;bump the run count
|
||
|
||
MOVE.L (A3)+,(A5)+
|
||
DBRA D2,CBCndOnes ;loop until we're done
|
||
DoneCBCSecondRun
|
||
SWAP D7
|
||
BRA DoneCBCLine ;all done
|
||
|
||
; here's the loop that counts the 2nd run of zeros
|
||
|
||
CBCndZero
|
||
MOVE.L (A4)+,D1
|
||
BNE.S CBCStartLastRun
|
||
CBCndZero0
|
||
SUBQ.W #1,D7
|
||
|
||
ADDQ #4,A3
|
||
ADDQ #4,A5 ;bump dest reg
|
||
DBRA D2,CBCndZero ;loop until it changes
|
||
|
||
BRA.S DoneCBCSecondRun
|
||
|
||
; OK, we've accumulated two runs, so finish up the line without counting
|
||
|
||
CBCStartLastRun
|
||
SWAP D7
|
||
|
||
TST.L D1
|
||
BEQ.S CBCLastZero
|
||
BRA.S CBCLastLoopA
|
||
CBCLastLoop
|
||
MOVE.L (A4)+,D1 ;get region
|
||
BEQ.S CBCLastZero
|
||
CBCLastLoopA
|
||
CMP.L D5,D1
|
||
BNE.S CBCLastHard
|
||
|
||
MOVE.L (A3)+,(A5)+ ;plot it
|
||
DBRA D2,CBCLastLoop
|
||
|
||
BRA DoneCBCLine
|
||
CBCLastZero
|
||
ADDQ #4,A3
|
||
ADDQ #4,A5
|
||
DBRA D2,CBCLastLoop
|
||
BRA DoneCBCLine
|
||
CBCLastHard
|
||
MOVE.L (A3)+,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
DBRA D2,CBCLastLoop
|
||
BRA DoneCBCLine
|
||
|
||
; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D7.
|
||
|
||
CBCPlotRgnRuns
|
||
TST.W D7 ;which type of run?
|
||
BPL.S CBCBlastPat1 ;if ones, go blast it
|
||
BEQ CBCPlotRHard1 ;if zero, plot one slowly, then plot 2nd run
|
||
|
||
; it's negative, so just skip over 4 times the count
|
||
|
||
MOVE.W D7,D0
|
||
|
||
NEG.W D0 ;turn into longword count
|
||
LSL.W #2,D0 ;times 4
|
||
|
||
ADD.W D0,A3
|
||
ADD.W D0,A4 ;skip over region
|
||
ADD.W D0,A5 ;skip over destination
|
||
|
||
ADD.W D7,D2 ;decrement count
|
||
BMI DoneCBCLine ;if done, skip
|
||
|
||
; now handle the second run
|
||
|
||
CBCPRRun2
|
||
LEA @0,A0 ;plot the break longword
|
||
BRA CBCPlotHardCommon
|
||
@0
|
||
MOVE.L D7,D0 ;which type of run?
|
||
BPL.S CBCBlastPat2 ;if ones, go blast it
|
||
BEQ.S CBCPlotRHard2
|
||
|
||
; it's negative, so we can skip over like above
|
||
|
||
SWAP D0
|
||
NEG.W D0 ;turn into longword count
|
||
SUB.W D0,D2 ;decrement count
|
||
|
||
LSL.W #2,D0 ;times 4
|
||
|
||
ADD.W D0,A3
|
||
ADD.W D0,A4 ;skip over region
|
||
ADD.W D0,A5 ;skip over destination
|
||
|
||
TST.W D2
|
||
BMI DoneCBCLine ;if done, skip
|
||
|
||
; we've interpreted both runs, so finish up using common code
|
||
|
||
BRA.S CBCLastLoop
|
||
|
||
; Handle blasting out the first run
|
||
|
||
CBCBlastPat1
|
||
MOVE.W D7,D0 ;get the size
|
||
LEA CBCPRRun2,A0
|
||
BRA.S CBCBlastPat
|
||
|
||
; Blast out the second run
|
||
|
||
CBCBlastPat2
|
||
SWAP D0 ;use high word for 2nd run
|
||
LEA CBCLastLoop,A0
|
||
|
||
; Here's the unwound loop to blast the # of longwords in D0 out.
|
||
|
||
CBCBlastPat
|
||
CMP.W #8,D0 ;8 left to do?
|
||
BLT.S CBCBlastFinishUp
|
||
|
||
MOVE.W D0,D1
|
||
LSR #3,D1
|
||
SUBQ #1,D1
|
||
CBCBlastLoop
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
|
||
DBRA D1,CBCBlastLoop
|
||
CBCBlastFinishUp
|
||
MOVE.W D0,D1
|
||
AND #7,D1
|
||
EOR #7,D1
|
||
JMP CBCFinishTable(D1.W*2)
|
||
CBCFinishTable
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+
|
||
MOVE.L (A3)+,(A5)+ ;15 total to finish up
|
||
|
||
; all done with plotting so adjust the region pointer and count, then return
|
||
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
ADD.W D1,A4 ;bump region ptr
|
||
|
||
SUB.W D0,D2
|
||
BMI DoneCBCLine
|
||
|
||
JMP (A0)
|
||
|
||
; handle the heterogenous plots between runs
|
||
|
||
CBCPlotRHard1
|
||
LEA CBCPRRun2,A0
|
||
BRA.S CBCPlotHardCommon
|
||
CBCPlotRHard2
|
||
LEA CBCLastLoop,A0
|
||
CBCPlotHardCommon
|
||
MOVE.L (A4)+,D1
|
||
|
||
MOVE.L (A3)+,D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5)+ ;deposit it
|
||
|
||
SUBQ #1,D2 ;count it
|
||
BMI DoneCBCLine
|
||
|
||
JMP (A0)
|
||
|
||
; here's a whole different set of loops for the backwards case
|
||
|
||
CBClipNeg
|
||
ADDQ #4,A3 ;ditto for source
|
||
ADDQ #4,A4 ;bias region ptr
|
||
ADDQ #4,A5 ;and dest
|
||
CBClipNegLoop
|
||
MOVE.L -(A4),D1 ;fetch region mask
|
||
MOVE.L -(A3),D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L -(A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5) ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI DoneCBCLine
|
||
|
||
; if the region runs in D4 are still valid, we can use special code to really plot super
|
||
; fast.
|
||
|
||
TST.W D4 ;is it valid?
|
||
BNE CBCNegPlotRgnRuns ;if so, go super fast
|
||
|
||
MOVEQ #-1,D4 ;validate it for next time
|
||
MOVEQ #0,D7 ;zero the run count
|
||
|
||
; see what the next region longword is. Go to three different loops depending on whether
|
||
; the region is all ones, zeros or both
|
||
|
||
MOVE.L -(A4),D1 ;fetch next word of region mask
|
||
BEQ.S CBCNegFirstZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE.S CBCNegStartSecondRun ;if not, skip
|
||
|
||
BRA.S CBCNegFirstOnes1
|
||
|
||
; here's the loop that counts and plots the first run of all ones
|
||
|
||
CBCNegFirstOnes
|
||
MOVE.L -(A4),D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE.S CBCNegStartSecondRun ;if not, end the run
|
||
CBCNegFirstOnes1
|
||
ADDQ.W #1,D7 ;bump the run count
|
||
|
||
MOVE.L -(A3),-(A5)
|
||
DBRA D2,CBCNegFirstOnes ;loop until we're done
|
||
|
||
BRA DoneCBCLine
|
||
|
||
; here's the loop that counts and plots the first run of all zeros
|
||
|
||
CBCNegFirstZero
|
||
MOVE.L -(A4),D1
|
||
BNE.S CBCNegStartSecondRun
|
||
CBCNegFirstZero0
|
||
SUBQ.W #1,D7 ;decrement run count for zeros
|
||
|
||
SUBQ #4,A3
|
||
SUBQ #4,A5
|
||
DBRA D2,CBCNegFirstZero
|
||
|
||
BRA DoneCBCLine
|
||
|
||
; the region mask is heterogenous, so plot the word and start the second run.
|
||
|
||
CBCNegStartSecondRun
|
||
SWAP D7
|
||
|
||
MOVE.L -(A3),D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L -(A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5) ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoneCBCNegSecondRun
|
||
|
||
; sample the region and case out for the 2nd time
|
||
|
||
MOVE.L -(A4),D1 ;fetch next word of region mask
|
||
BEQ.S CBCNegndZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE.S CBCNegStartLastRun ;if not, skip
|
||
|
||
BRA.S CBCNegndOnes1
|
||
|
||
; here's the loop that counts and plots the second run of all ones
|
||
|
||
CBCNegndOnes
|
||
MOVE.L -(A4),D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE.S CBCNegStartLastRun ;if not, end the run
|
||
CBCNegndOnes1
|
||
ADDQ.W #1,D7 ;bump the run count
|
||
|
||
MOVE.L -(A3),-(A5)
|
||
DBRA D2,CBCNegndOnes ;loop until we're done
|
||
DoneCBCNegSecondRun
|
||
SWAP D7
|
||
BRA DoneCBCLine ;all done
|
||
|
||
; here's the loop that counts the 2nd run of zeros
|
||
|
||
CBCNegndZero
|
||
MOVE.L -(A4),D1
|
||
BNE.S CBCNegStartLastRun
|
||
CBCNegndZero0
|
||
SUBQ.W #1,D7
|
||
|
||
SUBQ #4,A3
|
||
SUBQ #4,A5 ;bump dest reg
|
||
DBRA D2,CBCNegndZero ;loop until it changes
|
||
|
||
BRA.S DoneCBCNegSecondRun
|
||
|
||
; OK, we've accumulated two runs, so finish up the line without counting
|
||
|
||
CBCNegStartLastRun
|
||
SWAP D7
|
||
|
||
TST.L D1
|
||
BEQ.S CBCNegLastZero
|
||
BRA.S CBCNegLastLoopA
|
||
CBCNegLastLoop
|
||
MOVE.L -(A4),D1 ;get region
|
||
BEQ.S CBCNegLastZero
|
||
CBCNegLastLoopA
|
||
CMP.L D5,D1
|
||
BNE.S CBCNegLastHard
|
||
|
||
MOVE.L -(A3),-(A5) ;plot it
|
||
DBRA D2,CBCNegLastLoop
|
||
|
||
BRA DoneCBCLine
|
||
CBCNegLastZero
|
||
SUBQ #4,A3
|
||
SUBQ #4,A5
|
||
DBRA D2,CBCNegLastLoop
|
||
BRA DoneCBCLine
|
||
CBCNegLastHard
|
||
MOVE.L -(A3),D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L -(A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5) ;deposit it
|
||
|
||
DBRA D2,CBCNegLastLoop
|
||
BRA DoneCBCLine
|
||
|
||
; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D7.
|
||
|
||
CBCNegPlotRgnRuns
|
||
TST.W D7 ;which type of run?
|
||
BPL.S CBCNegBlastPat1 ;if ones, go blast it
|
||
BEQ CBCNegPlotRHard1 ;if zero, plot one slowly, then plot 2nd run
|
||
|
||
; it's negative, so just skip over 4 times the count
|
||
|
||
MOVE.W D7,D0
|
||
|
||
NEG.W D0 ;turn into longword count
|
||
LSL.W #2,D0 ;times 4
|
||
|
||
SUB.W D0,A3
|
||
SUB.W D0,A4 ;skip over region
|
||
SUB.W D0,A5 ;skip over destination
|
||
|
||
ADD.W D7,D2 ;decrement count
|
||
BMI DoneCBCLine ;if done, skip
|
||
|
||
; now handle the second run
|
||
|
||
CBCNegPRRun2
|
||
LEA @0,A0 ;plot the break longword
|
||
BRA CBCNegPlotHardCommon
|
||
@0
|
||
MOVE.L D7,D0 ;which type of run?
|
||
BPL.S CBCNegBlastPat2 ;if ones, go blast it
|
||
BEQ.S CBCNegPlotRHard2
|
||
|
||
; it's negative, so we can skip over like above
|
||
|
||
SWAP D0
|
||
NEG.W D0 ;turn into longword count
|
||
SUB.W D0,D2 ;decrement count
|
||
|
||
LSL.W #2,D0 ;times 4
|
||
|
||
SUB.W D0,A3
|
||
SUB.W D0,A4 ;skip over region
|
||
SUB.W D0,A5 ;skip over destination
|
||
|
||
TST.W D2
|
||
BMI DoneCBCLine ;if done, skip
|
||
|
||
; we've interpreted both runs, so finish up using common code
|
||
|
||
BRA.S CBCNegLastLoop
|
||
|
||
; Handle blasting out the first run
|
||
|
||
CBCNegBlastPat1
|
||
MOVE.W D7,D0 ;get the size
|
||
LEA CBCNegPRRun2,A0
|
||
BRA.S CBCNegBlastPat
|
||
|
||
; Blast out the second run
|
||
|
||
CBCNegBlastPat2
|
||
SWAP D0 ;use high word for 2nd run
|
||
LEA CBCNegLastLoop,A0
|
||
|
||
; Here's the unwound loop to blast the # of longwords in D0 out.
|
||
|
||
CBCNegBlastPat
|
||
CMP.W #8,D0 ;8 left to do?
|
||
BLT.S CBCNegBlastFinishUp
|
||
|
||
MOVE.W D0,D1
|
||
LSR #3,D1
|
||
SUBQ #1,D1
|
||
CBCNegBlastLoop
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
|
||
DBRA D1,CBCNegBlastLoop
|
||
CBCNegBlastFinishUp
|
||
MOVE.W D0,D1
|
||
AND #7,D1
|
||
EOR #7,D1
|
||
JMP CBCNegFinishTable(D1.W*2)
|
||
CBCNegFinishTable
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5)
|
||
MOVE.L -(A3),-(A5) ;15 total to finish up
|
||
|
||
; all done with plotting so adjust the region pointer and count, then return
|
||
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
SUB.W D1,A4 ;bump region ptr
|
||
|
||
SUB.W D0,D2
|
||
BMI DoneCBCLine
|
||
|
||
JMP (A0)
|
||
|
||
; handle the heterogenous plots between runs
|
||
|
||
CBCNegPlotRHard1
|
||
LEA CBCNegPRRun2,A0
|
||
BRA.S CBCNegPlotHardCommon
|
||
CBCNegPlotRHard2
|
||
LEA CBCNegLastLoop,A0
|
||
CBCNegPlotHardCommon
|
||
MOVE.L -(A4),D1
|
||
|
||
MOVE.L -(A3),D0 ;get pattern
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L -(A5),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A5) ;deposit it
|
||
|
||
SUBQ #1,D2 ;count it
|
||
BMI DoneCBCLine
|
||
|
||
JMP (A0)
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; InvertRgn case ($360) -- ie, invert clipped to region. Use the standard region
|
||
; counting stuff
|
||
|
||
UseOld360
|
||
LEARom Old360,A1
|
||
JMP (A1)
|
||
|
||
InvertClip
|
||
GoInvertClip
|
||
LEA Inv1ClipOuter,A0
|
||
MOVE.L A0,MODECASE(A6) ;skip initial testing on return
|
||
|
||
MOVEQ #0,D4 ;no runs yet
|
||
SUB.L A2,A2 ;runs not valid
|
||
|
||
MOVEQ #-1,D5 ;mask for comparing
|
||
Inv1ClipOuter
|
||
|
||
; first handle the left edge outside of the inner loop so we don't count it in the runs
|
||
|
||
MOVE.L D6,D0
|
||
AND.L (A4)+,D0
|
||
EOR.L D0,(A5)+
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoneInv1Line
|
||
|
||
; if the region runs in D4 are still valid, we can use special code to really plot super
|
||
; fast.
|
||
|
||
MOVE.L A2,D0 ;is it valid?
|
||
BNE Inv1PlotRgnRuns ;if so, go super fast
|
||
|
||
ADDQ #1,A2 ;validate it for next time
|
||
MOVEQ #0,D4 ;zero the run count
|
||
|
||
; see what the next region longword is. Go to three different loops depending on whether
|
||
; the region is all ones, zeros or both
|
||
|
||
MOVE.L (A4)+,D1 ;fetch next word of region mask
|
||
BEQ Inv1FirstZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE Inv1StartSecondRun ;if not, skip
|
||
|
||
BRA.S Inv1FirstOnes1
|
||
|
||
; here's the loop that counts and plots the first run of all ones
|
||
|
||
Inv1FirstOnes
|
||
MOVE.L (A4)+,D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE Inv1StartSecondRun ;if not, end the run
|
||
Inv1FirstOnes1
|
||
ADDQ.W #1,D4 ;bump the run count
|
||
|
||
EOR.L D6,(A5)+
|
||
|
||
DBRA D2,Inv1FirstOnes ;loop until we're done
|
||
|
||
; done with this scan line, so bump to the next
|
||
|
||
DoneInv1Line
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6) ;bump to next line of destination
|
||
|
||
; bump pattern index
|
||
|
||
ADDQ #1,D7
|
||
AND.W #15,D7
|
||
MOVE.L ([EXPAT,A6],D7.W*4),D6 ;bump the pattern
|
||
|
||
; bump line count and see if we're done
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADD.W VBUMP(A6),D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W LASTV(A6),D0 ;all done?
|
||
BEQ DonePatClip ;if so, use common exit
|
||
|
||
; create the region mask for the new scan line, and maintain the all one's flag
|
||
|
||
CMP.W STATEB+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S Inv1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEB+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S Inv1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S Inv1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S Inv1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S Inv1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S Inv1NewRgn ;if so, go do it
|
||
|
||
TST.L DSTMASKBUF(A6) ;can we skip it?
|
||
BEQ.S Inv1SkipRgn ;if so, skip
|
||
Inv1NewRgn
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;make new region mask
|
||
|
||
SUB.L A2,A2 ;invalidate region counts
|
||
|
||
; set up registers and go handle the next line
|
||
|
||
Inv1SkipRgn
|
||
MOVE.L RGNBUF(A6),A4
|
||
MOVE.L DSTADDR(A6),A5
|
||
MOVE.W BUFSIZE(A6),D2
|
||
|
||
BRA Inv1ClipOuter
|
||
|
||
; here's the loop that counts and plots the first run of all zeros
|
||
|
||
Inv1FirstZero
|
||
MOVE.L (A4)+,D1
|
||
BNE.S Inv1StartSecondRun
|
||
Inv1FirstZero0
|
||
SUBQ.W #1,D4 ;decrement run count for zeros
|
||
|
||
ADDQ #4,A5
|
||
DBRA D2,Inv1FirstZero
|
||
|
||
BRA.S DoneInv1Line
|
||
|
||
; the region mask is heterogenous, so plot the word and start the second run.
|
||
|
||
Inv1StartSecondRun
|
||
SWAP D4
|
||
|
||
AND.L D6,D1 ;mask it
|
||
EOR.L D1,(A5)+ ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoneInv1SecondRun
|
||
|
||
; sample the region and case out for the 2nd time
|
||
|
||
MOVE.L (A4)+,D1 ;fetch next word of region mask
|
||
BEQ.S Inv1stZero0 ;if zero, go handle
|
||
|
||
CMP.L D5,D1 ;all one's?
|
||
BNE.S Inv1StartLastRun ;if not, skip
|
||
|
||
BRA.S Inv1stOnes1
|
||
|
||
; here's the loop that counts and plots the second run of all ones
|
||
|
||
Inv1stOnes
|
||
MOVE.L (A4)+,D1
|
||
|
||
CMP.L D5,D1 ;is it still all ones?
|
||
BNE.S Inv1StartLastRun ;if not, end the run
|
||
Inv1stOnes1
|
||
ADDQ.W #1,D4 ;bump the run count
|
||
|
||
EOR.L D6,(A5)+
|
||
DBRA D2,Inv1stOnes ;loop until we're done
|
||
DoneInv1SecondRun
|
||
SWAP D4
|
||
BRA DoneInv1Line ;all done
|
||
|
||
; here's the loop that counts the 2nd run of zeros
|
||
|
||
Inv1stZero
|
||
MOVE.L (A4)+,D1
|
||
BNE.S Inv1StartLastRun
|
||
Inv1stZero0
|
||
SUBQ.W #1,D4
|
||
ADDQ #4,A5 ;bump dest reg
|
||
DBRA D2,Inv1stZero ;loop until it changes
|
||
|
||
BRA.S DoneInv1SecondRun
|
||
|
||
; OK, we've accumulated two runs, so finish up the line without counting
|
||
|
||
Inv1StartLastRun
|
||
SWAP D4
|
||
|
||
TST.L D1
|
||
BEQ.S Inv1LastZero
|
||
BRA.S Inv1LastLoopA
|
||
Inv1LastLoop
|
||
MOVE.L (A4)+,D1 ;get region
|
||
BEQ.S Inv1LastZero
|
||
Inv1LastLoopA
|
||
CMP.L D5,D1
|
||
BNE.S Inv1LastHard
|
||
|
||
EOR.L D6,(A5)+ ;plot it
|
||
DBRA D2,Inv1LastLoop
|
||
|
||
BRA DoneInv1Line
|
||
Inv1LastZero
|
||
ADDQ #4,A5
|
||
DBRA D2,Inv1LastLoop
|
||
BRA DoneInv1Line
|
||
Inv1LastHard
|
||
AND.L D6,D1
|
||
EOR.L D1,(A5)+ ;deposit it
|
||
|
||
DBRA D2,Inv1LastLoop
|
||
BRA DoneInv1Line
|
||
|
||
; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D4.
|
||
|
||
Inv1PlotRgnRuns
|
||
TST.W D4 ;which type of run?
|
||
BPL.S Inv1BlastPat1 ;if ones, go blast it
|
||
BEQ Inv1PlotRHard1 ;if zero, plot one slowly, then plot 2nd run
|
||
|
||
; it's negative, so just skip over 4 times the count
|
||
|
||
MOVE.W D4,D0
|
||
|
||
NEG.W D0 ;turn into longword count
|
||
|
||
LSL.W #2,D0 ;times 4
|
||
ADD.W D0,A4 ;skip over region
|
||
ADD.W D0,A5 ;skip over destination
|
||
|
||
ADD.W D4,D2 ;decrement count
|
||
BMI DoneInv1Line ;if done, skip
|
||
|
||
; now handle the second run
|
||
|
||
Inv1PRRun2
|
||
LEA @0,A0 ;plot the break longword
|
||
BRA Inv1PlotHardCommon
|
||
@0
|
||
MOVE.L D4,D0 ;which type of run?
|
||
BPL.S Inv1BlastPat2 ;if ones, go blast it
|
||
BEQ.S Inv1PlotRHard2
|
||
|
||
; it's negative, so we can skip over like above
|
||
|
||
SWAP D0
|
||
NEG.W D0 ;turn into longword count
|
||
|
||
SUB.W D0,D2 ;decrement count
|
||
|
||
LSL.W #2,D0 ;times 4
|
||
ADD.W D0,A4 ;skip over region
|
||
ADD.W D0,A5 ;skip over destination
|
||
|
||
TST.W D2
|
||
BMI DoneInv1Line ;if done, skip
|
||
|
||
; we've interpreted both runs, so finish up using common code
|
||
|
||
BRA.S Inv1LastLoop
|
||
|
||
; Handle blasting out the first run
|
||
|
||
Inv1BlastPat1
|
||
MOVE.W D4,D0 ;get the size
|
||
LEA Inv1PRRun2,A0
|
||
BRA.S Inv1BlastPat
|
||
|
||
; Blast out the second run
|
||
|
||
Inv1BlastPat2
|
||
SWAP D0 ;use high word for 2nd run
|
||
LEA Inv1LastLoop,A0
|
||
|
||
; Here's the unwound loop to blast the # of longwords in D0 out.
|
||
|
||
Inv1BlastPat
|
||
CMP.W #8,D0 ;8 left to do?
|
||
BLT.S Inv1BlastFinishUp
|
||
|
||
MOVE.W D0,D1
|
||
LSR #3,D1
|
||
SUBQ #1,D1
|
||
Inv1BlastLoop
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
|
||
DBRA D1,Inv1BlastLoop
|
||
Inv1BlastFinishUp
|
||
MOVE.W D0,D1
|
||
AND #7,D1
|
||
EOR #7,D1
|
||
|
||
JMP Inv1FinishTable(D1.W*2)
|
||
Inv1FinishTable
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
EOR.L D6,(A5)+
|
||
|
||
; all done with plotting so adjust the region pointer and count, then return
|
||
|
||
@0
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
ADD.W D1,A4 ;bump region ptr
|
||
|
||
SUB.W D0,D2
|
||
BMI DoneInv1Line
|
||
Inv1BlastDone
|
||
JMP (A0)
|
||
|
||
; handle the heterogenous plots between runs
|
||
|
||
Inv1PlotRHard1
|
||
LEA Inv1PRRun2,A0
|
||
BRA.S Inv1PlotHardCommon
|
||
Inv1PlotRHard2
|
||
LEA Inv1LastLoop,A0
|
||
Inv1PlotHardCommon
|
||
MOVE.L D6,D1
|
||
AND.L (A4)+,D1
|
||
EOR.L D1,(A5)+ ;deposit it
|
||
|
||
SUBQ #1,D2 ;count it
|
||
BMI DoneInv1Line
|
||
|
||
JMP (A0)
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
|
||
; InvertHiliteClip ($372) speeds up region clipped hiliting; no more invert hack
|
||
|
||
UseOld372
|
||
LEARom Old372,A1
|
||
JMP (A1)
|
||
|
||
InvertHiliteClip
|
||
|
||
CMP.W #8,SRCPIX+PIXELSIZE(A6) ;8 bits/pixel?
|
||
BNE.S UseOld372 ;if not, don't handle
|
||
|
||
LEA InvertHiOuter,A0
|
||
MOVE.L A0,MODECASE(A6) ;come back here
|
||
|
||
; if the background/hilite colors are black and white, we can expedite matters significantly
|
||
|
||
InvertHiOuter
|
||
MOVE.L D4,D7 ;get hilite
|
||
EOR.L D5,D7 ;compute toggle mask
|
||
|
||
; OK, here's the inner loop. If the whole longword at the destination is background or
|
||
; hilite color, toggle it with the hilite mask. Otherwise, we have to process it a
|
||
; byte at a time
|
||
|
||
InvertHInner
|
||
MOVE.L (A4)+,D1 ;get the region mask
|
||
BEQ.S InvertEmpty ;if empty, skip
|
||
|
||
MOVE.L (A5),D0 ;get the current destination
|
||
CMP.L D0,D4 ;all hilite?
|
||
BEQ.S @0 ;if so, it's easy
|
||
|
||
CMP.L D0,D5 ;all background?
|
||
BNE.S InvertHPixels ;if not, it's harder
|
||
@0
|
||
AND.L D7,D1 ;mask toggle with region
|
||
EOR.L D1,D0 ;toggle dest
|
||
MOVE.L D0,(A5)+ ;stuff it
|
||
NextInvertH
|
||
DBRA D2,InvertHInner ;loop till done
|
||
|
||
; all done with the scan line, so bump the appropriate pointers, and loop until done
|
||
|
||
BumpNextScanLine
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6) ;bump to next line
|
||
|
||
; bump line count and see if we're done
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADD.W VBUMP(A6),D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W LASTV(A6),D0 ;all done?
|
||
BEQ.S DoneInvertSL ;if not, skip
|
||
|
||
; create the region mask for the new scan line
|
||
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;make new region mask
|
||
|
||
; set up registers and go handle the next line
|
||
|
||
MOVE.L SRCADDR(A6),A3
|
||
MOVE.L RGNADDR(A6),A4
|
||
MOVE.L DSTADDR(A6),A5
|
||
MOVE.W BUFSIZE(A6),D2
|
||
|
||
MOVE.L MODECASE(A6),A2
|
||
JMP (A2)
|
||
|
||
; all done so strip stack and return
|
||
|
||
DoneInvertSL
|
||
MOVE.L SAVESTK2(A6),A7
|
||
RTS
|
||
|
||
; handle the case of the empty region by simply bumping the output pointer
|
||
|
||
InvertEmpty
|
||
ADDQ #4,A5 ;bump ptr
|
||
DBRA D2,InvertHInner
|
||
|
||
BRA.S BumpNextScanLine
|
||
|
||
; handle the more difficult case of a non-homogenous line, which we must process a pixel
|
||
; at a time. Destination value is in D0, region mask in D1. Repeat in-line for 4 pixels
|
||
|
||
; try to do a word at a time, if we can
|
||
|
||
|
||
InvertHPixels
|
||
CMP.W D4,D0
|
||
BEQ.S IHBumpWord1
|
||
|
||
CMP.W D5,D0
|
||
BEQ.S IHBumpWord1
|
||
|
||
CMP.B D4,D0 ;same as hilite?
|
||
BEQ.S IHBump1 ;if so, let it through
|
||
|
||
CMP.B D5,D0 ;same as background
|
||
BEQ.S IHBump1 ;if so, let it through
|
||
|
||
CLR.B D1 ;don't use this one
|
||
IHBump1
|
||
ROR.L #8,D0
|
||
ROR.L #8,D1
|
||
|
||
CMP.B D4,D0 ;same as hilite?
|
||
BEQ.S IHBump2 ;if so, let it through
|
||
|
||
CMP.B D5,D0 ;same as background
|
||
BEQ.S IHBump2 ;if so, let it through
|
||
|
||
CLR.B D1 ;don't use this one
|
||
IHBump2
|
||
ROR.L #8,D0
|
||
ROR.L #8,D1
|
||
IHWord2
|
||
CMP.W D4,D0
|
||
BEQ.S IHBumpWord2
|
||
|
||
CMP.W D5,D0
|
||
BEQ.S IHBumpWord2
|
||
|
||
CMP.B D4,D0 ;same as hilite?
|
||
BEQ.S IHBump3 ;if so, let it through
|
||
|
||
CMP.B D5,D0 ;same as background
|
||
BEQ.S IHBump3 ;if so, let it through
|
||
|
||
CLR.B D1 ;don't use this one
|
||
IHBump3
|
||
ROR.L #8,D0
|
||
ROR.L #8,D1
|
||
|
||
CMP.B D4,D0 ;same as hilite?
|
||
BEQ.S IHBump4 ;if so, let it through
|
||
|
||
CMP.B D5,D0 ;same as background?
|
||
BEQ.S IHBump4 ;if so, let it through
|
||
|
||
CLR.B D1 ;don't use this one
|
||
IHBump4
|
||
ROR.L #8,D0
|
||
ROR.L #8,D1
|
||
|
||
; OK, now we can plot it
|
||
|
||
IHPlotIt
|
||
AND.L D7,D1 ;mask toggle with region
|
||
EOR.L D1,D0 ;toggle dest
|
||
MOVE.L D0,(A5)+ ;stuff it
|
||
|
||
DBRA D2,InvertHInner ;loop till done
|
||
BRA BumpNextScanLine
|
||
|
||
; handle word hits
|
||
|
||
IHBumpWord1
|
||
SWAP D0
|
||
SWAP D1
|
||
|
||
BRA.S IHWord2
|
||
|
||
IHBumpWord2
|
||
SWAP D0
|
||
SWAP D1
|
||
|
||
BRA.S IHPlotIt
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
|
||
; CB1To8Clip ($373) is the clipped copyBits loop used in the 1 to 8 expansion blits,
|
||
; common in programs like HyperCard and Servant. If it's the typical case we can handle
|
||
; (black and white, source 1 bit,dest 8 bits), expand on the fly, right onto the screen,
|
||
; for a pretty big gain.
|
||
|
||
; it really shouldn't be named CB1to8, as it's the routine used for any scaling or lookup
|
||
; blit. We also optimize the 8-bit to 8-bit blits that require table lookup, and also
|
||
; handle the 8 to 1 case
|
||
|
||
UseOld373
|
||
LEARom Old373,A1
|
||
JMP (A1)
|
||
|
||
CB1To8Clip
|
||
TST.L D7 ;toggle mode?
|
||
BNE.S UseOld373 ;if so, don't handle
|
||
|
||
MOVE.L NUMER(A6),D0
|
||
CMP.L DENOM(A6),D0 ;botRights the same?
|
||
BNE.S UseOld373 ;if so, don't handle
|
||
|
||
MOVE.L MASKNUMER(A6),D0
|
||
CMP.L MASKDENOM(A6),D0 ;how about topLefts?
|
||
BNE.S UseOld373 ;if so, don't handle
|
||
|
||
TST.L DSTMASKBUF(A6) ;is mask a bitmap?
|
||
BNE.S UseOld373 ;if so, don't handle!
|
||
|
||
MOVE.W SRCPIX+PIXELSIZE(A6),D0 ;get source bits/pixel
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;destination 1 bits/pixel?
|
||
BNE ChkDst1Bit ;if not, skip
|
||
|
||
SUBQ #8,D0
|
||
BEQ CB8to8Clip ;if source is 8 bits, go handle
|
||
|
||
ADDQ #7,D0 ;is it one bit?
|
||
BNE.S UseOld373 ;if not, don't handle
|
||
|
||
Eight EQU $23344 ; offset to the expand by eight, non-colormap routine
|
||
|
||
CmpRA Eight,ScaleCase(A6) ; is this doing a 1-8bit stretch? <PB473 DAF 19Apr88>
|
||
bne.s UseOld373 ; no, can't handle this one. <PB471 BAL 18Apr88>
|
||
|
||
CMP.L #-1,FCOLOR(A6) ;foreground = black?
|
||
BNE.S UseOld373
|
||
|
||
TST.L BCOLOR(A6) ;background = white?
|
||
BNE.S UseOld373
|
||
|
||
cmp.l scalebuf(a6),a3 ;has src been advanced (i.e. dest < baseAddr) <PB501 BAL/DVB 13Jun88>
|
||
bne.s UseOld373 ;if so, don't handle <PB501 BAL/DVB 13Jun88>
|
||
|
||
MOVE.L SRCROW(A6),D0
|
||
SUB.L D0,SRCADDR(A6) ;back up one line
|
||
|
||
SUBQ #1,BUFSIZE(A6) ;one less than they say
|
||
|
||
; its our case, so handle it. Pick up the shifted source with a bit-field instruction,
|
||
; then use it to plot 8 longwords, indirecting a nibble at a time through an expansion
|
||
; table. Special case the edges, so we can really zoom if the middle's region is all ones.
|
||
|
||
; A2 has the region mask, A4 has the destination; use A3 to hold the source.
|
||
; D7 holds the "OK to zoom" (region all ones) flag
|
||
|
||
CB1to8Outer
|
||
MOVE.L DSTALIGN(A6),D0
|
||
ASR.L #3,D0
|
||
|
||
MOVEQ #15,D3 ;D3 has 4 bit mask
|
||
MOVEQ #-1,D6 ;D6 has -1 for region compare
|
||
LEA Expand1to8,A1
|
||
|
||
MOVE.L SRCADDR(A6),A3 ;get source pointer
|
||
|
||
MOVE.L SRCALIGN(A6),D5 ;get shift count
|
||
ADD.L D0,D5
|
||
|
||
; OK, first do the left edge (one nybble worth)
|
||
|
||
BFEXTU (A3){D5:16},D4 ;pick up next word of source
|
||
ADDQ.L #4,D5 ;bump to next nibble
|
||
ROL.W #4,D4 ;get next nibble
|
||
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),D0 ;get source longword
|
||
AND.L D1,D0
|
||
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1
|
||
OR.L D1,D0 ;combine source and dest
|
||
MOVE.L D0,(A4)+ ;stuff it
|
||
|
||
; OK, here's the loop that handles the middle, which is where all the action is
|
||
|
||
MOVE.W BUFSIZE(A6),D2 ;get destination count
|
||
|
||
CMP.W #4,D2 ;four or less we can't optimize
|
||
BLE FinishLastFew
|
||
|
||
; if we have a multiple of 4 left to do, don't do last 4
|
||
|
||
MOVE.W D2,D0
|
||
AND #3,D0
|
||
BNE.S @1
|
||
|
||
SUBQ #1,D2
|
||
@1
|
||
LSR #2,D2 ;do 4 longwords each iteration
|
||
SUBQ #1,D2
|
||
|
||
TST.B D7 ;is region all ones?
|
||
BNE CB1to8SpLoop0 ;if so, we can go super-fast
|
||
|
||
ST D7 ;assume next like is special
|
||
CB1to8Loop
|
||
BFEXTU (A3){D5:16},D4 ;pick up next word of source
|
||
ADDQ #2,A3 ;bump it
|
||
BEQ CB1to8AllZeros ;special case all zeros
|
||
CB1to8AltEntry
|
||
ROL.W #4,D4 ;get high nibble first
|
||
|
||
; OK, expand the low 4 bits in D4 into a longword, then plot it. Fetch the region mask
|
||
; first, since it may not even be necessary
|
||
|
||
CB1to8Inner
|
||
LEA CB1to8Nib2,A5
|
||
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),D0 ;get source longword
|
||
|
||
CMP.L D6,D1 ;mask all ones?
|
||
BNE CB1to8HardPlot ;if not, plot it the hard way
|
||
|
||
MOVE.L D0,(A4)+ ;plot the longword
|
||
|
||
; now plot the 2nd nibble
|
||
|
||
CB1to8Nib2
|
||
LEA CB1to8Nib3,A5
|
||
|
||
ROL.W #4,D4 ;get next nybble
|
||
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),D0 ;get source longword
|
||
|
||
CMP.L D6,D1 ;mask all ones?
|
||
BNE.S CB1to8HardPlot ;if not, plot it the hard way
|
||
|
||
MOVE.L D0,(A4)+ ;plot the longword
|
||
|
||
; now plot the 3rd nibble
|
||
|
||
CB1to8Nib3
|
||
LEA CB1to8Nib4,A5
|
||
ROL.W #4,D4 ;get next nybble
|
||
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),D0 ;get source longword
|
||
|
||
CMP.L D6,D1 ;mask all ones?
|
||
BNE.S CB1to8HardPlot ;if not, plot it the hard way
|
||
|
||
MOVE.L D0,(A4)+ ;plot the longword
|
||
|
||
; now plot the last nibble
|
||
|
||
CB1to8Nib4
|
||
LEA CB1to8NibBot,A5
|
||
|
||
ROL.W #4,D4 ;get next nybble
|
||
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),D0 ;get source longword
|
||
|
||
CMP.L D6,D1 ;mask all ones?
|
||
BNE.S CB1to8HardPlot ;if not, plot it the hard way
|
||
|
||
MOVE.L D0,(A4)+ ;plot the longword
|
||
CB1to8NibBot
|
||
DBRA D2,CB1to8Loop ;loop until done
|
||
|
||
; clean up the last 0 to 3 nibbles; 4 remaining handled specially
|
||
|
||
FinishLastFew
|
||
BFEXTU (A3){D5:16},D4 ;pick up last word of source
|
||
LEA BotFin1to8Loop,A5
|
||
MOVE.W BUFSIZE(A6),D2 ;get the number left to do
|
||
BEQ CB1to8NextLine ;if zero, we're done
|
||
|
||
AND.W #3,D2 ;0 to 3 only
|
||
BNE.S BotFin1to8Loop
|
||
|
||
MOVEQ #3,D2 ;4 to do
|
||
TopFin1to8Loop
|
||
ROL.W #4,D4
|
||
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),D0 ;get source longword
|
||
|
||
CMP.L D6,D1 ;mask all ones?
|
||
BNE.S CB1to8HPNoInval ;if not, plot it the hard way (no edge)
|
||
|
||
MOVE.L D0,(A4)+ ;plot the longword
|
||
BotFin1to8Loop
|
||
DBRA D2,TopFin1to8Loop
|
||
BRA.S CB1to8NextLine
|
||
|
||
; handle the case where the region mask is all zeros
|
||
|
||
CB1to8NoPlot
|
||
ADDQ.L #4,A4 ;bump dest ptr
|
||
JMP (A5) ;advance to next one
|
||
|
||
; handle the more difficult case of a heterogenous region mask
|
||
|
||
CB1to8HardPlot
|
||
MOVEQ #0,D7 ;not all ones
|
||
CB1to8HPNoInval
|
||
TST.L D1
|
||
BEQ.S CB1to8NoPlot
|
||
|
||
AND.L D1,D0
|
||
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1
|
||
OR.L D1,D0 ;combine source and dest
|
||
MOVE.L D0,(A4)+ ;stuff it
|
||
JMP (A5)
|
||
|
||
; to speed things up, we special case words of all zero and blast 4 long words of zero out as
|
||
; fast as we can, without having to do any lookups.
|
||
|
||
CB1to8AllZeros
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
BEQ.S CBZEmpty1 ;if all zeros, skip
|
||
|
||
CMP.L D6,D1 ;all ones?
|
||
BNE.S CBZBIC1 ;if not, skip
|
||
|
||
CLR.L (A4)+ ;plot the zeros
|
||
CBZLong2
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
BEQ.S CBZEmpty2 ;if all zeros, skip
|
||
|
||
CMP.L D6,D1 ;all ones?
|
||
BNE.S CBZBIC2 ;if not, skip
|
||
|
||
CLR.L (A4)+ ;plot the zeros
|
||
CBZLong3
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
BEQ.S CBZEmpty3 ;if all zeros, skip
|
||
|
||
CMP.L D6,D1 ;all ones?
|
||
BNE.S CBZBIC3 ;if not, skip
|
||
|
||
CLR.L (A4)+ ;plot the zeros
|
||
CBZLong4
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
BEQ.S CBZEmpty4 ;if all zeros, skip
|
||
|
||
CMP.L D6,D1 ;all ones?
|
||
BNE.S CBZBIC4 ;if not, skip
|
||
|
||
CLR.L (A4)+ ;plot the zeros
|
||
BRA.S CB1to8NibBot ;dive back in
|
||
CBZEmpty1
|
||
MOVEQ #0,D7
|
||
ADDQ #4,A4
|
||
BRA.S CBZLong2
|
||
CBZEmpty2
|
||
MOVEQ #0,D7
|
||
ADDQ #4,A4
|
||
BRA.S CBZLong3
|
||
CBZEmpty3
|
||
MOVEQ #0,D7
|
||
ADDQ #4,A4
|
||
BRA.S CBZLong4
|
||
CBZEmpty4
|
||
MOVEQ #0,D7
|
||
ADDQ #4,A4
|
||
BRA CB1to8NibBot
|
||
CBZBIC1
|
||
MOVEQ #0,D7
|
||
NOT.L D1
|
||
AND.L D1,(A4)+
|
||
BRA.S CBZLong2
|
||
CBZBIC2
|
||
MOVEQ #0,D7
|
||
NOT.L D1
|
||
AND.L D1,(A4)+
|
||
BRA.S CBZLong3
|
||
CBZBIC3
|
||
MOVEQ #0,D7
|
||
NOT.L D1
|
||
AND.L D1,(A4)+
|
||
BRA.S CBZLong4
|
||
CBZBIC4
|
||
MOVEQ #0,D7
|
||
NOT.L D1
|
||
AND.L D1,(A4)+
|
||
BRA CB1to8NibBot
|
||
|
||
|
||
; all done with this line, so bump the pointers and loop until done
|
||
|
||
CB1to8NextLine
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6) ;bump to next line of destination
|
||
|
||
MOVE.L SRCROW(A6),D0
|
||
ADD.L D0,SRCADDR(A6) ;bump to next line of source
|
||
|
||
; bump line count and see if we're done
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADDQ #1,D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W MINRECT+BOTTOM(A6),D0 ;all done?
|
||
BEQ.S Done1To8Clip ;if so, skip
|
||
|
||
; create the region mask for the new scan line, and maintain the all one's flag
|
||
|
||
CMP.W STATEB+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB1to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEB+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CB1to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB1to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CB1to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB1to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+THISV(A6),D0 ;need to rebuild?
|
||
BGE.S Skip1to8Rgn ;if not, skip
|
||
CB1to8NewRgn
|
||
MOVEQ #0,D7 ;invalidate region all ones flag
|
||
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;make new region mask
|
||
|
||
; set up registers and go handle the next line
|
||
|
||
Skip1to8Rgn
|
||
MOVE.L RGNBUF(A6),A2
|
||
MOVE.L DSTADDR(A6),A4
|
||
|
||
BRA CB1to8Outer ;go process next line
|
||
|
||
; all done so strip stack and return
|
||
|
||
Done1To8Clip
|
||
MOVE.L SAVEA5(A6),A5
|
||
|
||
TST.B CRSRFLAG(A6)
|
||
BEQ.S @0
|
||
|
||
JSR ([$0F4C]) ;SHOWCURSOR
|
||
@0
|
||
BSET #7,HILITEMODE ;$938
|
||
|
||
MOVE.L SAVESTK(A6),A7
|
||
MOVEM.L (SP)+,D0-D7/A1-A5
|
||
UNLK A6
|
||
RTD #44
|
||
|
||
; here's where we go when we've detected that region masking isn't necessary, so we can really
|
||
; blast things 4 longwords at a time
|
||
|
||
CB1to8SpLoop0
|
||
MOVE.W D2,D7 ;remember the count
|
||
|
||
CB1to8SpLoop
|
||
BFEXTU (A3){D5:16},D4 ;pick up next word of source
|
||
ADDQ #2,A3 ;bump it
|
||
BEQ.S CB1to8SpAllZeros ;special case all zeros
|
||
|
||
CMP.W D4,D6 ;all ones?
|
||
BEQ.S CB1to8SpAllOnes
|
||
|
||
ROL.W #4,D4 ;get first nibble
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),(A4)+ ;plot expanded longword
|
||
|
||
ROL.W #4,D4 ;get next nibble
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),(A4)+ ;plot expanded longword
|
||
|
||
ROL.W #4,D4 ;get next nibble
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),(A4)+ ;plot expanded longword
|
||
|
||
ROL.W #4,D4 ;get next nibble
|
||
MOVE.W D4,D0 ;get low 4 bits
|
||
AND.W D3,D0
|
||
MOVE.L 0(A1,D0.W*4),(A4)+ ;plot expanded longword
|
||
|
||
BotCB1to8SpLoop
|
||
DBRA D2,CB1to8SpLoop
|
||
|
||
; finish up the special case by adjusting A2 and diving back into common code
|
||
|
||
Finish1to8Sp
|
||
ADDQ #1,D7 ;add one for real count
|
||
LSL.W #4,D7 ;4 longs (16 bytes) per iteration
|
||
ADD.W D7,A2 ;bump region pointer
|
||
BRA FinishLastFew ;finish the last few
|
||
|
||
; handle the case when the source word is all zero and there's no region clipping -- we
|
||
; can go as fast as we can.
|
||
|
||
CB1to8SpAllZeros
|
||
CLR.L (A4)+
|
||
CLR.L (A4)+
|
||
CLR.L (A4)+
|
||
CLR.L (A4)+
|
||
|
||
BRA.S BotCB1to8SpLoop
|
||
|
||
CB1to8SpAllOnes
|
||
MOVE.L D6,(A4)+
|
||
MOVE.L D6,(A4)+
|
||
MOVE.L D6,(A4)+
|
||
MOVE.L D6,(A4)+
|
||
|
||
BRA.S BotCB1to8SpLoop
|
||
|
||
|
||
; here is the nybble to longword expansion table
|
||
|
||
ALIGN 4
|
||
Expand1To8
|
||
DC.L $00000000,$000000FF,$0000FF00,$0000FFFF
|
||
DC.L $00FF0000,$00FF00FF,$00FFFF00,$00FFFFFF
|
||
DC.L $FF000000,$FF0000FF,$FF00FF00,$FF00FFFF
|
||
DC.L $FFFF0000,$FFFF00FF,$FFFFFF00,$FFFFFFFF
|
||
|
||
;******************************************************************************************
|
||
|
||
CB8to81st0
|
||
ADDQ #4,A3 ;bump source ptr
|
||
ADDQ #4,A4 ;bump dest ptr
|
||
BRA CB8to8Middle
|
||
|
||
|
||
; Handler for the 8 to 8 copyBits case (with mapping). The basic strategy is the usual
|
||
; region counting, with the added twist of a single element cache for the longword mapping,
|
||
; using A1 to hold the pre-map and D7 to hold the post-mapped values.
|
||
|
||
CB8to8Clip
|
||
TST.L MASKBITS(A6) ;should we handle it?
|
||
BNE UseOld373 ;if not, skip
|
||
|
||
MOVE.L SRCROW(A6),D0
|
||
SUB.L D0,SRCADDR(A6) ;back up one line
|
||
|
||
SUBQ #1,BUFSIZE(A6) ;one less than they say
|
||
MOVEQ #-1,D6 ;D6 has -1 for region compare
|
||
|
||
MOVEQ #0,D4
|
||
MOVEQ #0,D3 ;init region counting regs
|
||
|
||
SUB.L A1,A1
|
||
SUBQ.L #1,A1 ;all ones for initial
|
||
MOVEQ #-1,D7 ;map cache values
|
||
CB8to8Outer
|
||
MOVE.L RGNBUF(A6),A2
|
||
MOVE.L SRCADDR(A6),A3 ;get source pointer
|
||
MOVE.L DSTADDR(A6),A4 ;get destptr
|
||
MOVE.L SCALETBL(A6),A5 ;get mapping table
|
||
|
||
; offset source pointer according to bit offsets
|
||
|
||
MOVE.L DSTALIGN(A6),D0 ;get shift count
|
||
ASR.L #3,D0
|
||
MOVE.L SRCALIGN(A6),D1
|
||
ASR.L #3,D1
|
||
ADD.L D1,D0
|
||
ADD.L D0,A3 ;offset source ptr
|
||
|
||
; OK, first do the left edge
|
||
|
||
MOVE.W BUFSIZE(A6),D2 ;get the count
|
||
|
||
MOVEQ #0,D5
|
||
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
BEQ.S CB8to81st0 ;if zero, handle it
|
||
|
||
; fetch the 1st source longword and map it through the table pointed to by A5
|
||
|
||
MOVE.L (A3)+,D0 ;get source longword
|
||
MOVE.L D0,A1 ;remember it
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 1st byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 2nd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 3rd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 4th byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.L D0,D7 ;remember result of mapping
|
||
|
||
; plot it using the region mask
|
||
|
||
AND.L D1,D0
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1
|
||
OR.L D1,D0 ;combine source and dest
|
||
MOVE.L D0,(A4)+ ;stuff it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S CB8to8NextLine
|
||
|
||
; if the region runs in D4 are still valid, we can use special code to really plot super
|
||
; fast.
|
||
|
||
CB8to8Middle
|
||
TST.W D4 ;is it valid?
|
||
BNE V8to8PlotRgnRuns ;if so, go super fast
|
||
|
||
MOVEQ #-1,D4 ;validate it for next time
|
||
MOVEQ #0,D3 ;zero the run count
|
||
|
||
; see what the next region longword is. Go to three different loops depending on whether
|
||
; the region is all ones, zeros or both
|
||
|
||
MOVE.L (A2)+,D1 ;fetch next word of region mask
|
||
BEQ V8to8FirstZero0 ;if zero, go handle
|
||
|
||
CMP.L D6,D1 ;all one's?
|
||
BNE V8to8StartSecondRun ;if not, skip
|
||
|
||
BRA.S V8to8FirstOnes1
|
||
|
||
; here's the loop that counts and plots the first run of all ones
|
||
|
||
V8to8FirstOnes
|
||
MOVE.L (A2)+,D1
|
||
|
||
CMP.L D6,D1 ;is it still all ones?
|
||
BNE V8to8StartSecondRun ;if not, end the run
|
||
V8to8FirstOnes1
|
||
ADDQ.W #1,D3 ;bump the run count
|
||
|
||
MOVE.L (A3)+,D0 ;fetch from source
|
||
CMP.L D0,A1 ;same as before?
|
||
BNE.S @0
|
||
|
||
MOVE.L D7,D0
|
||
BRA.S @1
|
||
@0
|
||
MOVE.L D0,A1
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 1st byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 2nd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 3rd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 4th byte
|
||
ROL.L #8,D0
|
||
MOVE.L D0,D7
|
||
@1
|
||
MOVE.L D0,(A4)+ ;store at destination
|
||
|
||
DBRA D2,V8to8FirstOnes ;loop until we're done
|
||
|
||
; OK, all done with this line, so bump the pointers and loop until done
|
||
|
||
CB8to8NextLine
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6) ;bump to next line of destination
|
||
|
||
MOVE.L SRCROW(A6),D0
|
||
ADD.L D0,SRCADDR(A6) ;bump to next line of source
|
||
|
||
; bump line count and see if we're done
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADDQ #1,D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W MINRECT+BOTTOM(A6),D0 ;all done?
|
||
BEQ Done1To8Clip ;if so, use common exit
|
||
|
||
; create the region mask for the new scan line, and maintain the all ones flag
|
||
|
||
CMP.W STATEB+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB8to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEB+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CB8to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB8to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CB8to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB8to8NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+THISV(A6),D0 ;need to rebuild?
|
||
BGE CB8to8Outer ;if not, skip
|
||
CB8to8NewRgn
|
||
MOVEQ #0,D4 ;invalidate region all ones flag
|
||
|
||
MOVE.L A1,-(SP)
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;make new region mask
|
||
MOVE.L (SP)+,A1
|
||
|
||
; go handle the next line
|
||
|
||
BRA CB8to8Outer ;go process next line
|
||
|
||
Fin8to8Zeros
|
||
ADDQ #4,A4
|
||
BRA.S CB8to8NextLine
|
||
|
||
; here's the loop that counts and plots the first run of all zeros
|
||
|
||
V8to8FirstZero
|
||
MOVE.L (A2)+,D1
|
||
BNE.S V8to8StartSecondRun
|
||
V8to8FirstZero0
|
||
SUBQ.W #1,D3 ;decrement run count for zeros
|
||
|
||
ADDQ #4,A3
|
||
ADDQ #4,A4
|
||
DBRA D2,V8to8FirstZero
|
||
|
||
BRA.S CB8to8NextLine
|
||
|
||
; the region mask is heterogenous, so plot the word and start the second run.
|
||
|
||
V8to8StartSecondRun
|
||
SWAP D3
|
||
|
||
MOVE.L (A3)+,D0 ;fetch from source
|
||
CMP.L D0,A1 ;same as before?
|
||
BNE.S @0
|
||
|
||
MOVE.L D7,D0
|
||
BRA.S @1
|
||
@0
|
||
MOVE.L D0,A1
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 1st byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 2nd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 3rd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 4th byte
|
||
ROL.L #8,D0
|
||
MOVE.L D0,D7
|
||
@1
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A4)+ ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S Done8to8SecondRun
|
||
|
||
; sample the region and case out for the 2nd time
|
||
|
||
MOVE.L (A2)+,D1 ;fetch next word of region mask
|
||
BEQ.S V8to8Zero0 ;if zero, go handle
|
||
|
||
CMP.L D6,D1 ;all one's?
|
||
BNE.S V8to8StartLastRun ;if not, skip
|
||
|
||
BRA.S V8to8Ones1
|
||
|
||
; here's the loop that counts and plots the second run of all ones
|
||
|
||
V8to8Ones
|
||
MOVE.L (A2)+,D1
|
||
|
||
CMP.L D6,D1 ;is it still all ones?
|
||
BNE.S V8to8StartLastRun ;if not, end the run
|
||
V8to8Ones1
|
||
ADDQ.W #1,D3 ;bump the run count
|
||
|
||
MOVE.L (A3)+,D0 ;fetch from source
|
||
CMP.L D0,A1 ;same as before?
|
||
BNE.S @0
|
||
|
||
MOVE.L D7,D0
|
||
BRA.S @1
|
||
@0
|
||
MOVE.L D0,A1
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 1st byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 2nd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 3rd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 4th byte
|
||
ROL.L #8,D0
|
||
MOVE.L D0,D7
|
||
@1
|
||
MOVE.L D0,(A4)+ ;store at destination
|
||
|
||
DBRA D2,V8to8Ones ;loop until we're done
|
||
Done8to8SecondRun
|
||
SWAP D3
|
||
BRA CB8to8NextLine ;all done
|
||
|
||
; here's the loop that counts the 2nd run of zeros
|
||
|
||
V8to8Zero
|
||
MOVE.L (A2)+,D1
|
||
BNE.S V8to8StartLastRun
|
||
V8to8Zero0
|
||
SUBQ.W #1,D3
|
||
|
||
ADDQ #4,A3
|
||
ADDQ #4,A4 ;bump dest reg
|
||
|
||
DBRA D2,V8to8Zero ;loop until it changes
|
||
|
||
BRA.S Done8to8SecondRun
|
||
|
||
; OK, we've accumulated two runs, so finish up the line without counting
|
||
|
||
V8to8StartLastRun
|
||
SWAP D3
|
||
|
||
TST.L D1
|
||
BEQ.S V8to8LastZero
|
||
BRA.S V8to8LastLoopA
|
||
V8to8LastLoop
|
||
MOVE.L (A2)+,D1 ;get region
|
||
BEQ.S V8to8LastZero
|
||
V8to8LastLoopA
|
||
CMP.L D6,D1
|
||
BNE.S V8to8LastHard
|
||
|
||
MOVE.L (A3)+,D0 ;fetch from source
|
||
CMP.L D0,A1 ;same as before?
|
||
BNE.S @0
|
||
|
||
MOVE.L D7,D0
|
||
BRA.S @1
|
||
@0
|
||
MOVE.L D0,A1
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 1st byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 2nd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 3rd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 4th byte
|
||
ROL.L #8,D0
|
||
MOVE.L D0,D7
|
||
@1
|
||
MOVE.L D0,(A4)+ ;store at destination
|
||
DBRA D2,V8to8LastLoop
|
||
|
||
BRA CB8to8NextLine
|
||
V8to8LastZero
|
||
ADDQ #4,A4
|
||
ADDQ #4,A3
|
||
DBRA D2,V8to8LastLoop
|
||
BRA CB8to8NextLine
|
||
V8to8LastHard
|
||
MOVE.L (A3)+,D0 ;fetch from source
|
||
CMP.L D0,A1 ;same as before?
|
||
BNE.S @0
|
||
|
||
MOVE.L D7,D0
|
||
BRA.S @1
|
||
@0
|
||
MOVE.L D0,A1
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 1st byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 2nd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 3rd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 4th byte
|
||
ROL.L #8,D0
|
||
MOVE.L D0,D7
|
||
@1
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A4)+ ;deposit it
|
||
|
||
DBRA D2,V8to8LastLoop
|
||
BRA CB8to8NextLine
|
||
|
||
; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D3.
|
||
|
||
V8to8PlotRgnRuns
|
||
TST.W D3 ;which type of run?
|
||
BPL.S V8to8BlastPat1 ;if ones, go blast it
|
||
BEQ V8to8PlotRHard1 ;if zero, plot one slowly, then plot 2nd run
|
||
|
||
; it's negative, so just skip over 4 times the count
|
||
|
||
MOVE.W D3,D0
|
||
|
||
NEG.W D0 ;turn into longword count
|
||
LSL.W #2,D0 ;times 4
|
||
|
||
ADD.W D0,A2 ;skip over region
|
||
ADD.W D0,A3 ;skip over source
|
||
ADD.W D0,A4 ;skip over destination
|
||
|
||
ADD.W D3,D2 ;decrement count
|
||
BMI CB8to8NextLine ;if done, skip
|
||
|
||
; now handle the second run
|
||
|
||
V8to8PRRun2
|
||
LEA @0,A0 ;plot the break longword
|
||
BRA V8to8PlotHardCommon
|
||
@0
|
||
MOVE.L D3,D0 ;which type of run?
|
||
BPL.S V8to8BlastPat2 ;if ones, go blast it
|
||
BEQ.S V8to8PlotRHard2
|
||
|
||
; it's negative, so we can skip over like above
|
||
|
||
SWAP D0
|
||
NEG.W D0 ;turn into longword count
|
||
SUB.W D0,D2 ;decrement count
|
||
|
||
LSL.W #2,D0 ;times 4
|
||
|
||
ADD.W D0,A2 ;skip over region
|
||
ADD.W D0,A3 ;skip over source
|
||
ADD.W D0,A4 ;skip over destination
|
||
|
||
TST.W D2
|
||
BMI CB8to8NextLine ;if done, skip
|
||
|
||
; we've interpreted both runs, so finish up using common code
|
||
|
||
BRA V8to8LastLoop
|
||
|
||
; Handle blasting out the first run
|
||
|
||
V8to8BlastPat1
|
||
MOVE.W D3,D0 ;get the size
|
||
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
ADD.W D1,A2 ;bump region ptr
|
||
SUB.W D0,D2
|
||
|
||
LEA V8to8PRRun2,A0
|
||
BRA.S V8to8BlastPatBot
|
||
|
||
; Blast out the second run
|
||
|
||
V8to8BlastPat2
|
||
SWAP D0 ;use high word for 2nd run
|
||
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
ADD.W D1,A2 ;bump region ptr
|
||
SUB.W D0,D2
|
||
|
||
LEA V8to8LastLoop,A0
|
||
BRA.S V8to8BlastPatBot
|
||
V8to8BlastPat
|
||
MOVE.L (A3)+,D1 ;fetch from source
|
||
CMP.L D1,A1 ;same as before?
|
||
BNE.S @0
|
||
|
||
MOVE.L D7,D1
|
||
BRA.S @1
|
||
@0
|
||
MOVE.L D1,A1
|
||
MOVE.B D1,D5
|
||
MOVE.B 1(A5,D5.W*2),D1 ;map 1st byte
|
||
ROL.L #8,D1
|
||
|
||
MOVE.B D1,D5
|
||
MOVE.B 1(A5,D5.W*2),D1 ;map 2nd byte
|
||
ROL.L #8,D1
|
||
|
||
MOVE.B D1,D5
|
||
MOVE.B 1(A5,D5.W*2),D1 ;map 3rd byte
|
||
ROL.L #8,D1
|
||
|
||
MOVE.B D1,D5
|
||
MOVE.B 1(A5,D5.W*2),D1 ;map 4th byte
|
||
ROL.L #8,D1
|
||
MOVE.L D1,D7
|
||
@1
|
||
MOVE.L D1,(A4)+ ;store at destination
|
||
V8to8BlastPatBot
|
||
DBRA D0,V8to8BlastPat
|
||
|
||
; all done with plotting run of ones
|
||
|
||
TST.W D2
|
||
BMI CB8to8NextLine
|
||
|
||
JMP (A0)
|
||
|
||
; handle the heterogenous plots between runs
|
||
|
||
V8to8PlotRHard1
|
||
LEA V8to8PRRun2,A0
|
||
BRA.S V8to8PlotHardCommon
|
||
V8to8PlotRHard2
|
||
LEA V8to8LastLoop,A0
|
||
V8to8PlotHardCommon
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
|
||
MOVE.L (A3)+,D0 ;fetch from source
|
||
CMP.L D0,A1 ;same as before?
|
||
BNE.S @0
|
||
|
||
MOVE.L D7,D0
|
||
BRA.S @1
|
||
@0
|
||
MOVE.L D0,A1
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 1st byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 2nd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 3rd byte
|
||
ROL.L #8,D0
|
||
|
||
MOVE.B D0,D5
|
||
MOVE.B 1(A5,D5.W*2),D0 ;map 4th byte
|
||
ROL.L #8,D0
|
||
MOVE.L D0,D7
|
||
@1
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A4)+ ;deposit it
|
||
|
||
SUBQ #1,D2 ;count it
|
||
BMI CB8to8NextLine
|
||
|
||
JMP (A0)
|
||
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
|
||
; Handler for the 8 to 1 copyBits case (mapped ). The basic strategy is the usual
|
||
; region counting, with the added twist of a single element cache for the longword mapping,
|
||
; using A1 to hold the pre-map and D7 to hold the post-mapped values.
|
||
|
||
|
||
CB8to11st0
|
||
ADD.W #32,A3 ;bump source ptr
|
||
ADDQ #4,A4 ;bump dest ptr
|
||
BRA.S CB8to1Middle
|
||
|
||
ChkDst1Bit
|
||
CMP.W #1,DSTPIX+PIXELSIZE(A6) ;destination 8 bits/pixel?
|
||
BNE UseOld373 ;if not, can't handle
|
||
|
||
SUBQ #8,D0 ;source 8 bits/pixel?
|
||
BNE UseOld373 ;if not, can't handle
|
||
CB8to1Clip
|
||
TST.L MASKBITS(A6) ;should we handle it?
|
||
BNE UseOld373 ;if not, skip
|
||
|
||
MOVE.L SRCROW(A6),D0
|
||
SUB.L D0,SRCADDR(A6) ;back up one line
|
||
|
||
SUBQ #1,BUFSIZE(A6) ;one less than they say
|
||
MOVEQ #-1,D6 ;D6 has -1 for region compare
|
||
|
||
MOVEQ #0,D4
|
||
MOVEQ #0,D3 ;init region counting regs
|
||
|
||
SUB.L A1,A1
|
||
SUBQ.L #1,A1 ;all ones for initial
|
||
MOVEQ #-1,D7 ;map cache values
|
||
CB8to1Outer
|
||
MOVE.L RGNBUF(A6),A2
|
||
MOVE.L SRCADDR(A6),A3 ;get source pointer
|
||
MOVE.L DSTADDR(A6),A4 ;get destptr
|
||
MOVE.L SCALETBL(A6),A5 ;get mapping table
|
||
|
||
; offset source pointer according to bit offsets
|
||
|
||
MOVE.L DSTALIGN(A6),D0 ;get shift count
|
||
MOVE.L SRCALIGN(A6),D1
|
||
ASR.L #3,D1
|
||
ADD.L D1,D0
|
||
ADD.L D0,A3 ;offset source ptr
|
||
|
||
; OK, first do the left edge
|
||
|
||
MOVE.W BUFSIZE(A6),D2 ;get the count
|
||
|
||
MOVEQ #0,D5
|
||
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
BEQ.S CB8to11st0 ;if zero, handle it
|
||
|
||
; fetch the 1st source longword and map it through the table pointed to by A5
|
||
|
||
BSR Map8to1
|
||
|
||
; plot it using the region mask
|
||
|
||
AND.L D1,D0
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1
|
||
OR.L D1,D0 ;combine source and dest
|
||
MOVE.L D0,(A4)+ ;stuff it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S CB8to1NextLine
|
||
|
||
; if the region runs in D4 are still valid, we can use special code to really plot super
|
||
; fast.
|
||
|
||
CB8to1Middle
|
||
TST.W D4 ;is it valid?
|
||
BNE V8to1PlotRgnRuns ;if so, go super fast
|
||
|
||
MOVEQ #-1,D4 ;validate it for next time
|
||
MOVEQ #0,D3 ;zero the run count
|
||
|
||
; see what the next region longword is. Go to three different loops depending on whether
|
||
; the region is all ones, zeros or both
|
||
|
||
MOVE.L (A2)+,D1 ;fetch next word of region mask
|
||
BEQ.S V8to1FirstZero0 ;if zero, go handle
|
||
|
||
CMP.L D6,D1 ;all one's?
|
||
BNE V8to1StartSecondRun ;if not, skip
|
||
|
||
BRA.S V8to1FirstOnes1
|
||
|
||
; here's the loop that counts and plots the first run of all ones
|
||
|
||
V8to1FirstOnes
|
||
MOVE.L (A2)+,D1
|
||
|
||
CMP.L D6,D1 ;is it still all ones?
|
||
BNE.S V8to1StartSecondRun ;if not, end the run
|
||
V8to1FirstOnes1
|
||
ADDQ.W #1,D3 ;bump the run count
|
||
|
||
BSR Map8to1
|
||
MOVE.L D0,(A4)+ ;store at destination
|
||
|
||
DBRA D2,V8to1FirstOnes ;loop until we're done
|
||
|
||
; OK, all done with this line, so bump the pointers and loop until done
|
||
|
||
CB8to1NextLine
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6) ;bump to next line of destination
|
||
|
||
MOVE.L SRCROW(A6),D0
|
||
ADD.L D0,SRCADDR(A6) ;bump to next line of source
|
||
|
||
; bump line count and see if we're done
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADDQ #1,D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W MINRECT+BOTTOM(A6),D0 ;all done?
|
||
BEQ Done1To8Clip ;if so, use common exit
|
||
|
||
; create the region mask for the new scan line, and maintain the all ones flag
|
||
|
||
CMP.W STATEB+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB8to1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEB+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CB8to1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB8to1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEC+THISV(A6),D0 ;need to rebuild?
|
||
BLT.S CB8to1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+NEXTV(A6),D0 ;rebuild the region?
|
||
BGE.S CB8to1NewRgn ;if so, go do it
|
||
|
||
CMP.W STATEA+THISV(A6),D0 ;need to rebuild?
|
||
BGE CB8to1Outer ;if so, go do it
|
||
CB8to1NewRgn
|
||
MOVEQ #0,D4 ;invalidate region all ones flag
|
||
|
||
MOVE.L A1,-(SP)
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;make new region mask
|
||
MOVE.L (SP)+,A1
|
||
|
||
; go handle the next line
|
||
|
||
BRA CB8to1Outer ;go process next line
|
||
|
||
Fin8to1Zeros
|
||
ADDQ #4,A4
|
||
BRA.S CB8to1NextLine
|
||
|
||
; here's the loop that counts and plots the first run of all zeros
|
||
|
||
V8to1FirstZero
|
||
MOVE.L (A2)+,D1
|
||
BNE.S V8to1StartSecondRun
|
||
V8to1FirstZero0
|
||
SUBQ.W #1,D3 ;decrement run count for zeros
|
||
|
||
ADD.W #32,A3
|
||
ADDQ #4,A4
|
||
DBRA D2,V8to1FirstZero
|
||
|
||
BRA.S CB8to1NextLine
|
||
|
||
; the region mask is heterogenous, so plot the word and start the second run.
|
||
|
||
V8to1StartSecondRun
|
||
SWAP D3
|
||
|
||
BSR Map8to1
|
||
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A4)+ ;deposit it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S Done8to1SecondRun
|
||
|
||
; sample the region and case out for the 2nd time
|
||
|
||
MOVE.L (A2)+,D1 ;fetch next word of region mask
|
||
BEQ.S V8to1Zero0 ;if zero, go handle
|
||
|
||
CMP.L D6,D1 ;all one's?
|
||
BNE.S V8to1StartLastRun ;if not, skip
|
||
|
||
BRA.S V8to1Ones1
|
||
|
||
; here's the loop that counts and plots the second run of all ones
|
||
|
||
V8to1Ones
|
||
MOVE.L (A2)+,D1
|
||
|
||
CMP.L D6,D1 ;is it still all ones?
|
||
BNE.S V8to1StartLastRun ;if not, end the run
|
||
V8to1Ones1
|
||
ADDQ.W #1,D3 ;bump the run count
|
||
BSR Map8to1 ;fetch and map it
|
||
MOVE.L D0,(A4)+ ;store at destination
|
||
|
||
DBRA D2,V8to1Ones ;loop until we're done
|
||
Done8to1SecondRun
|
||
SWAP D3
|
||
BRA CB8to1NextLine ;all done
|
||
|
||
; here's the loop that counts the 2nd run of zeros
|
||
|
||
V8to1Zero
|
||
MOVE.L (A2)+,D1
|
||
BNE.S V8to1StartLastRun
|
||
V8to1Zero0
|
||
SUBQ.W #1,D3
|
||
|
||
ADD.W #32,A3
|
||
ADDQ #4,A4 ;bump dest reg
|
||
|
||
DBRA D2,V8to1Zero ;loop until it changes
|
||
|
||
BRA.S Done8to1SecondRun
|
||
|
||
; OK, we've accumulated two runs, so finish up the line without counting
|
||
|
||
V8to1StartLastRun
|
||
SWAP D3
|
||
|
||
TST.L D1
|
||
BEQ.S V8to1LastZero
|
||
BRA.S V8to1LastLoopA
|
||
V8to1LastLoop
|
||
MOVE.L (A2)+,D1 ;get region
|
||
BEQ.S V8to1LastZero
|
||
V8to1LastLoopA
|
||
CMP.L D6,D1
|
||
BNE.S V8to1LastHard
|
||
|
||
BSR Map8to1
|
||
|
||
MOVE.L D0,(A4)+ ;store at destination
|
||
DBRA D2,V8to1LastLoop
|
||
|
||
BRA CB8to1NextLine
|
||
V8to1LastZero
|
||
ADDQ #4,A4
|
||
ADD.W #32,A3
|
||
DBRA D2,V8to1LastLoop
|
||
BRA CB8to1NextLine
|
||
V8to1LastHard
|
||
BSR Map8to1
|
||
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A4)+ ;deposit it
|
||
|
||
DBRA D2,V8to1LastLoop
|
||
BRA CB8to1NextLine
|
||
|
||
; Here's where we have the ultra fast plotting by interpreting the 2 region runs in D3.
|
||
|
||
V8to1PlotRgnRuns
|
||
TST.W D3 ;which type of run?
|
||
BPL.S V8to1BlastPat1 ;if ones, go blast it
|
||
BEQ.S V8to1PlotRHard1 ;if zero, plot one slowly, then plot 2nd run
|
||
|
||
; it's negative, so just skip over 4 times the count
|
||
|
||
MOVE.W D3,D0
|
||
|
||
NEG.W D0 ;turn into longword count
|
||
LSL.W #2,D0 ;times 4
|
||
|
||
ADD.W D0,A2 ;skip over region
|
||
ADD.W D0,A4 ;skip over destination
|
||
LSL #3,D0 ;times 8 for source
|
||
ADD.W D0,A3 ;skip over source
|
||
|
||
ADD.W D3,D2 ;decrement count
|
||
BMI CB8to1NextLine ;if done, skip
|
||
|
||
; now handle the second run
|
||
|
||
V8to1PRRun2
|
||
LEA @0,A0 ;plot the break longword
|
||
BRA.S V8to1PlotHardCommon
|
||
@0
|
||
MOVE.L D3,D0 ;which type of run?
|
||
BPL.S V8to1BlastPat2 ;if ones, go blast it
|
||
BEQ.S V8to1PlotRHard2
|
||
|
||
; it's negative, so we can skip over like above
|
||
|
||
SWAP D0
|
||
NEG.W D0 ;turn into longword count
|
||
SUB.W D0,D2 ;decrement count
|
||
|
||
LSL.W #2,D0 ;times 4
|
||
|
||
ADD.W D0,A2 ;skip over region
|
||
ADD.W D0,A4 ;skip over destination
|
||
LSL #3,D0 ;times 8 for source
|
||
ADD.W D0,A3 ;skip over source
|
||
|
||
TST.W D2
|
||
BMI CB8to1NextLine ;if done, skip
|
||
|
||
; we've interpreted both runs, so finish up using common code
|
||
|
||
BRA.S V8to1LastLoop
|
||
|
||
; Handle blasting out the first run
|
||
|
||
V8to1BlastPat1
|
||
MOVE.W D3,D0 ;get the size
|
||
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
ADD.W D1,A2 ;bump region ptr
|
||
SUB.W D0,D2
|
||
|
||
MOVE.W D0,D1
|
||
LEA V8to1PRRun2,A0
|
||
BRA.S V8to1BlastPatBot
|
||
|
||
; Blast out the second run
|
||
|
||
V8to1BlastPat2
|
||
SWAP D0 ;use high word for 2nd run
|
||
|
||
MOVE.W D0,D1
|
||
LSL #2,D1 ;times 4
|
||
ADD.W D1,A2 ;bump region ptr
|
||
SUB.W D0,D2
|
||
|
||
MOVE.W D0,D1
|
||
LEA V8to1LastLoop,A0
|
||
BRA.S V8to1BlastPatBot
|
||
V8to1BlastPat
|
||
BSR.S Map8to1
|
||
MOVE.L D0,(A4)+ ;store at destination
|
||
V8to1BlastPatBot
|
||
DBRA D1,V8to1BlastPat
|
||
|
||
; all done with plotting run of ones
|
||
|
||
TST.W D2
|
||
BMI CB8to1NextLine
|
||
|
||
JMP (A0)
|
||
|
||
; handle the heterogenous plots between runs
|
||
|
||
V8to1PlotRHard1
|
||
LEA V8to1PRRun2,A0
|
||
BRA.S V8to1PlotHardCommon
|
||
V8to1PlotRHard2
|
||
LEA V8to1LastLoop,A0
|
||
V8to1PlotHardCommon
|
||
MOVE.L (A2)+,D1 ;get region mask
|
||
|
||
BSR.S Map8to1
|
||
|
||
AND.L D1,D0 ;mask it
|
||
NOT.L D1 ;flip mask
|
||
AND.L (A4),D1 ;combine with source
|
||
OR.L D1,D0 ;form dest longword
|
||
MOVE.L D0,(A4)+ ;deposit it
|
||
|
||
SUBQ #1,D2 ;count it
|
||
BMI CB8to1NextLine
|
||
|
||
JMP (A0)
|
||
|
||
; Map8to1 is the routine that takes 8 longwords from the source (pointed to by A3)
|
||
; and returns the single longword result in D0.
|
||
|
||
Map8to1
|
||
MOVEQ #0,D0 ;start dest at 0
|
||
TST.W (A5) ;check mapping for color 0 <dÃb> 12Jul88
|
||
BEQ.s @a ;if white->white, ok <dÃb> 12Jul88
|
||
MOVEQ #$F,D0 ;else, its black <dÃb> 12Jul88
|
||
@a ; <dÃb> 12Jul88
|
||
|
||
MOVEQ #7,D7 ;8 longs to process
|
||
SUB.L A1,A1 ;set last source to 0
|
||
Map8to1Loop
|
||
MOVE.L (A3)+,D6 ;fetch from source
|
||
CMP.L A1,D6 ;same as last time?
|
||
BEQ.S Map8to1Fast ;if so, we've got the
|
||
|
||
MOVE.L D6,A1 ;remember for next time
|
||
|
||
ROL.L #8,D6 ;get next pixel
|
||
MOVE.B D6,D5 ;get current pixel
|
||
MOVE.B 1(A5,D5.W*2),D5 ;get mapped bit
|
||
LSR.W #1,D5 ;get bit into carry
|
||
ROXL.L #1,D0 ;shift it in
|
||
|
||
ROL.L #8,D6 ;get next pixel
|
||
MOVE.B D6,D5 ;get current pixel
|
||
MOVE.B 1(A5,D5.W*2),D5 ;get mapped bit
|
||
LSR.W #1,D5 ;get bit into carry
|
||
ROXL.L #1,D0 ;shift it in
|
||
|
||
ROL.L #8,D6 ;get next pixel
|
||
MOVE.B D6,D5 ;get current pixel
|
||
MOVE.B 1(A5,D5.W*2),D5 ;get mapped bit
|
||
LSR.W #1,D5 ;get bit into carry
|
||
ROXL.L #1,D0 ;shift it in
|
||
|
||
ROL.L #8,D6 ;get next pixel
|
||
MOVE.B D6,D5 ;get current pixel
|
||
MOVE.B 1(A5,D5.W*2),D5 ;get mapped bit
|
||
LSR.W #1,D5 ;get bit into carry
|
||
ROXL.L #1,D0 ;shift it in
|
||
|
||
DBRA D7,Map8to1Loop
|
||
|
||
MOVEQ #-1,D6 ;restore comparison mask
|
||
RTS
|
||
|
||
; handle the case where it was the same as the last one, so we can repeat the
|
||
; high 4 bits
|
||
|
||
Map8to1Fast
|
||
MOVE.B D0,D5
|
||
AND.W #15,D5
|
||
LSL.L #4,D0
|
||
OR.B D5,D0
|
||
|
||
DBRA D7,Map8to1Loop
|
||
|
||
MOVEQ #-1,D6
|
||
RTS
|
||
|
||
;******************************************************************************************
|
||
|
||
; Scan line handler for clipped pattern fill copy mode (called by oval, rrect) -- trap $380
|
||
|
||
UseOld380
|
||
TST.W D2
|
||
|
||
LEARom Old380,A0
|
||
JMP (A0)
|
||
|
||
FillClipScanLine
|
||
FCSL1 ; << PB452 BAL>>
|
||
FCSL2
|
||
AND.L (A2)+,D3 ;use left mask to start with
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoFCLast0
|
||
|
||
; special case the left edge
|
||
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D3,D0 ;mask it
|
||
NOT.L D3 ;flip mask
|
||
AND.L (A1),D3 ;combine with source
|
||
OR.L D3,D0 ;form dest longword
|
||
MOVE.L D0,(A1)+ ;deposit it
|
||
|
||
MOVE.L (A2)+,D3
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoFCLast0
|
||
|
||
; see if we're in the unclipped case; if so, use a faster loop
|
||
|
||
MOVE.L SEEKMASK(A6),A0 ;get seekRgn address
|
||
CMP.W #$4E75,(A0) ;is it a RTS?
|
||
BEQ.S DoFCUnclipped ;if so, handle specially
|
||
|
||
BRA.S FCNotOn1
|
||
|
||
; here's the loop -- use standard technique of special casing region masks
|
||
|
||
FCLineLoop
|
||
MOVE.L (A2)+,D3 ;fetch region mask
|
||
BEQ.S FCOff ;if all zero, can optimize
|
||
FCNotOff1
|
||
CMP.L MINUSONE,D3 ;all ones? << PB452 BAL>>
|
||
BEQ.S FCOn ;if so, optimize
|
||
FCNotOn1
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D3,D0 ;mask it
|
||
NOT.L D3 ;flip mask
|
||
AND.L (A1),D3 ;combine with source
|
||
OR.L D3,D0 ;form dest longword
|
||
MOVE.L D0,(A1)+ ;deposit it
|
||
|
||
DBRA D2,FCLineLoop
|
||
|
||
; handle the last one, using the mask in D1
|
||
|
||
DoFCLast
|
||
MOVE.L (A2)+,D3
|
||
DoFCLast0
|
||
AND.L D1,D3 ;use right mask
|
||
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D3,D0 ;mask it
|
||
NOT.L D3 ;flip mask
|
||
AND.L (A1),D3 ;combine with source
|
||
OR.L D3,D0 ;form dest longword
|
||
MOVE.L D0,(A1)+ ;deposit it
|
||
|
||
RTS
|
||
|
||
; handle the case of an all zero region mask
|
||
|
||
FCOff
|
||
ADDQ #4,A1 ;skip over it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoFCLast
|
||
|
||
FCOffLoop
|
||
MOVE.L (A2)+,D3
|
||
BNE.S FCNotOff1
|
||
|
||
ADDQ #4,A1 ;skip it
|
||
|
||
DBRA D2,FCOffLoop
|
||
BRA.S DoFCLast
|
||
|
||
; handle the case of an all one's region mask
|
||
|
||
FCOn
|
||
MOVE.L D6,(A1)+
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoFCLast
|
||
FCOnLoop
|
||
MOVE.L (A2)+,D3
|
||
CMP.L MINUSONE,D3 ; << PB452 BAL>>
|
||
BNE.S FCNotOn1
|
||
|
||
MOVE.L D6,(A1)+
|
||
|
||
DBRA D2,FCOnLoop
|
||
BRA.S DoFCLast
|
||
|
||
; handle the unclipped case with faster unwound code
|
||
|
||
DoFCUnclipped
|
||
LEA 0(A2,D2.W*4),A2 ;bump region ptr
|
||
|
||
ADDQ #1,D2 ;compute count to do
|
||
|
||
CMP.W #8,D2
|
||
BLT.S FinishFCUnClip
|
||
|
||
MOVE.W D2,D0
|
||
LSR #3,D0 ;divide by 8
|
||
SUBQ #1,D0 ;bias for DBRA
|
||
FCUnClipLoop
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
|
||
DBRA D0,FCUnClipLoop
|
||
|
||
; now finish up the last 7 or less
|
||
|
||
FinishFCUnClip
|
||
AND #7,D2
|
||
EOR #7,D2
|
||
JMP FinishFCUCTab(D2.W*2)
|
||
FinishFCUCTab
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
|
||
BRA.S DoFCLast
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Scan line handler for clipped pattern fill OR mode (called by oval, rrect) -- trap $381
|
||
; similar to above, but in OR mode. We can only handle if the foreground pattern
|
||
; is all ones; if so, use the copy mode routine to fill.
|
||
|
||
UseOld381
|
||
TST.W D2
|
||
|
||
LEARom Old381,A0
|
||
JMP (A0)
|
||
|
||
FillClipOrLine
|
||
|
||
CMP.L #-1,D6 ;all foreground?
|
||
BNE.S UseOld381 ;if not, we can't handle
|
||
|
||
MOVE.L D4,D6 ;set up fill pattern
|
||
BRA FCSL1 ;use common code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Scan line handler for clipped pattern fill copy mode (called by oval, rrect)
|
||
; for complex patterns-- trap $384
|
||
|
||
UseOld384
|
||
TST.W D2
|
||
|
||
LEARom Old384,A0
|
||
JMP (A0)
|
||
|
||
FillClipXLine
|
||
|
||
CMP.W #4,PATHMASK(A6) ;pattern too complex?
|
||
BGT.S UseOld384 ;if so, don't handle
|
||
|
||
MOVE.L D7,-(SP) ;save work register
|
||
|
||
; keep the pattern in D6 and D7
|
||
|
||
ADD.W PATHPOS(A6),D0
|
||
AND #4,D0
|
||
|
||
MOVE.L EXPAT(A6),A0
|
||
ADD.W PATVPOS(A6),A0
|
||
|
||
MOVE.L 0(A0,D0),D6 ;get left pattern
|
||
EOR.W #4,D0
|
||
MOVE.L 0(A0,D0),D7 ;get right pattern
|
||
|
||
; fetch the leftmost region mask
|
||
|
||
MOVEQ #-1,D4 ;all ones for comparing
|
||
AND.L (A2)+,D3 ;use left mask to start with
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoFCXLast0
|
||
|
||
; special case the left edge
|
||
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D3,D0 ;mask it
|
||
NOT.L D3 ;flip mask
|
||
AND.L (A1),D3 ;combine with source
|
||
OR.L D3,D0 ;form dest longword
|
||
MOVE.L D0,(A1)+ ;deposit it
|
||
|
||
EXG.L D6,D7
|
||
|
||
MOVE.L (A2)+,D3
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoFCXLast0
|
||
|
||
; see if we're in the unclipped case; if so, use a faster loop
|
||
|
||
MOVE.L SEEKMASK(A6),A0 ;get seekRgn address
|
||
CMP.W #$4E75,(A0) ;is it a RTS?
|
||
BEQ.S DoFCXUnclipped ;if so, handle specially
|
||
|
||
BRA.S FCXNotOn1
|
||
|
||
; here's the loop -- use standard technique of special casing region masks
|
||
|
||
FCXLineLoop
|
||
MOVE.L (A2)+,D3 ;fetch region mask
|
||
BEQ.S FCXOff ;if all zero, can optimize
|
||
FCXNotOff1
|
||
CMP.L D4,D3 ;all ones?
|
||
BEQ.S FCXOn ;if so, optimize
|
||
FCXNotOn1
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D3,D0 ;mask it
|
||
NOT.L D3 ;flip mask
|
||
AND.L (A1),D3 ;combine with source
|
||
OR.L D3,D0 ;form dest longword
|
||
MOVE.L D0,(A1)+ ;deposit it
|
||
|
||
EXG.L D6,D7
|
||
DBRA D2,FCXLineLoop
|
||
|
||
; handle the last one, using the mask in D1
|
||
|
||
DoFCXLast
|
||
MOVE.L (A2)+,D3
|
||
DoFCXLast0
|
||
AND.L D1,D3 ;use right mask
|
||
|
||
MOVE.L D6,D0 ;get pattern
|
||
AND.L D3,D0 ;mask it
|
||
NOT.L D3 ;flip mask
|
||
AND.L (A1),D3 ;combine with source
|
||
OR.L D3,D0 ;form dest longword
|
||
MOVE.L D0,(A1)+ ;deposit it
|
||
|
||
MOVE.L (SP)+,D7 ;restore work reg
|
||
RTS
|
||
|
||
; handle the case of an all zero region mask
|
||
|
||
FCXOff
|
||
ADDQ #4,A1 ;skip over it
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoFCXLast
|
||
|
||
FCXOffLoop
|
||
MOVE.L (A2)+,D3
|
||
BNE.S FCXNotOff1
|
||
|
||
ADDQ #4,A1 ;skip it
|
||
|
||
DBRA D2,FCXOffLoop
|
||
BRA.S DoFCXLast
|
||
|
||
; handle the case of an all one's region mask
|
||
|
||
FCXOn
|
||
MOVE.L D6,(A1)+
|
||
EXG.L D6,D7
|
||
|
||
SUBQ #1,D2
|
||
BMI.S DoFCXLast
|
||
FCXOnLoop
|
||
MOVE.L (A2)+,D3
|
||
CMP.L D4,D3
|
||
BNE.S FCXNotOn1
|
||
|
||
MOVE.L D6,(A1)+
|
||
EXG.L D6,D7
|
||
|
||
DBRA D2,FCXOnLoop
|
||
BRA.S DoFCXLast
|
||
|
||
; handle the unclipped case with faster unwound code
|
||
|
||
DoFCXUnclipped
|
||
LEA 0(A2,D2.W*4),A2 ;bump region ptr
|
||
|
||
ADDQ #1,D2 ;compute count to do
|
||
|
||
CMP.W #8,D2
|
||
BLT.S FinishFCXUnClip
|
||
|
||
MOVE.W D2,D0
|
||
LSR #3,D0 ;divide by 8
|
||
SUBQ #1,D0 ;bias for DBRA
|
||
FCXUnClipLoop
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D7,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D7,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D7,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D7,(A1)+
|
||
|
||
DBRA D0,FCXUnClipLoop
|
||
|
||
; now finish up the last 7 or less
|
||
|
||
FinishFCXUnClip
|
||
AND #7,D2
|
||
EOR #7,D2
|
||
|
||
BTST #0,D2
|
||
BEQ.S @0
|
||
|
||
EXG.L D6,D7
|
||
@0
|
||
JMP FinishFCXUCTab(D2.W*2)
|
||
FinishFCXUCTab
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D7,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D7,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
MOVE.L D7,(A1)+
|
||
MOVE.L D6,(A1)+
|
||
|
||
EXG.L D6,D7
|
||
BRA DoFCXLast
|
||
|
||
;******************************************************************************************
|
||
|
||
; Arithmetic transfer modes start here...
|
||
|
||
;******************************************************************************************
|
||
|
||
; Here's where we implement the arithmetic transfer mode fills for ovals/rrects
|
||
; Use a common loop for all the transfer modes, with specialized handlers to do the
|
||
; pixel arithmetic.
|
||
|
||
; the first receiver is for AddOver mode for ovals and roundRects
|
||
|
||
AddOverFillO
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BEQ.S @0 ;if not, skip
|
||
JMPRom Old38A ; continue in ROM <S433>
|
||
|
||
; OK, first do the pattern setup
|
||
@0
|
||
MOVE.L A0,A3 ;set up pattern base
|
||
LEA AddOverHandler,A0 ;use addOver
|
||
DoArithMode
|
||
MOVEM.L D7/A4-A5,-(SP) ;save work regs
|
||
|
||
BSR.S ArithModeHandler ;invoke the handler
|
||
|
||
MOVEM.L (SP)+,D7/A4-A5 ;restore regs
|
||
RTS
|
||
|
||
; here is the general handler for a scan line of arithmetic fills
|
||
|
||
ArithModeHandler
|
||
MOVEQ #0,D6 ;init pattern index
|
||
|
||
MOVE.W PATROW(A6),D4 ;get pattern size in bytes
|
||
SUBQ #4,D4 ;is it a simple one?
|
||
BLE ArithSimplePat ;if so, handle faster
|
||
|
||
; sometimes simple patterns come in as 8 byte ones, so check for that
|
||
|
||
MOVE.W D0,D6
|
||
ADD.W PATHPOS(A6),D6
|
||
|
||
SUBQ #4,D4 ;is it 8 long?
|
||
BNE.S ArithComplexPat ;if not, skip
|
||
|
||
; fetch both halves of the pattern and see if they match
|
||
|
||
MOVE.W PATHMASK(A6),D4 ;get pattern mask
|
||
ASR #3,D4 ;turn bit index to byte index
|
||
AND.W D4,D6 ;mask it
|
||
|
||
MOVE.L EXPAT(A6),A4
|
||
ADD.W PATVPOS(A6),A4 ;compute pattern address
|
||
|
||
MOVE.L 0(A4,D6),D4 ;get source longword
|
||
EOR #4,D6
|
||
CMP.L 0(A4,D6),D4 ;is it really simple?
|
||
BEQ ArithSimplePat ;if so, go handle
|
||
|
||
EOR #4,D6 ;restore D6
|
||
|
||
; set up the pattern variables, since it's a complex pattern
|
||
|
||
ArithComplexPat
|
||
MOVE.L EXPAT(A6),A3
|
||
ADD.W PATVPOS(A6),A3 ;compute pattern address
|
||
ArithComplex1
|
||
MOVE.L D1,-(SP) ;remember right edge mask
|
||
|
||
MOVEQ #0,D1
|
||
MOVEQ #0,D7 ;clear for pixCache
|
||
|
||
; set up A0 to point to the proper handler, depending on the width of the inverse table
|
||
|
||
MOVE.L A0,A4 ;remember handler base
|
||
|
||
MOVE.W INVSIZE(A6),D4 ;get shift count (3,4,5)
|
||
SUBQ #3,D4
|
||
ADD.W 0(A0,D4.W*2),A0 ;point to proper handler
|
||
|
||
; init the single pixel cache, where D1 is last source, D7 is last dest, and D0 is last result
|
||
|
||
MOVEQ #0,D5
|
||
MOVE.L COLORTABLE(A6),A5 ;get color table ptr
|
||
|
||
MOVE.B D1,D5
|
||
LEA 0(A5,D5.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D7,D5
|
||
LEA 0(A5,D5.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map it
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D0 ;look up in inverse table
|
||
|
||
; test for the single long case
|
||
|
||
TST.W D2
|
||
BRA ArithBot0
|
||
|
||
; here's the main loop for complex patterns, where we process a longword at a time
|
||
; use a single pixel cache for speed using D0, D1 and D7
|
||
|
||
ArithRight0
|
||
AND.L (SP)+,D3
|
||
ArithLoop0
|
||
MOVE.W PATHMASK(A6),D4 ;get pattern mask
|
||
ASR #3,D4 ;turn bit index to byte index
|
||
AND.W D4,D6 ;mask it
|
||
|
||
MOVE.L 0(A3,D6),D4 ;get source longword
|
||
ADDQ #4,D6
|
||
|
||
MOVE.L A2,D5 ;no clipping?
|
||
BEQ.S @0 ;if none, skip
|
||
|
||
AND.L (A2)+,D3 ;get region/edge mask in D3
|
||
BEQ ArithMask0
|
||
@0
|
||
MOVE.L (A1),D5 ;get dest longword
|
||
|
||
; map 1st byte
|
||
|
||
TST.B D3
|
||
BEQ.S @8 ;if mask zero, we can skip
|
||
|
||
; if same as previous, we can short-circuit the mapping
|
||
|
||
CMP.B D4,D1 ;source the same?
|
||
BNE.S @9 ;if not, skip
|
||
|
||
CMP.B D5,D7 ;dest the same?
|
||
BNE.S @9 ;if not, skip
|
||
|
||
; it's the same, so use it
|
||
|
||
MOVE.B D0,D5 ;use last result
|
||
BRA.S @8 ;skip the mapping
|
||
|
||
; it's different than the last one, so map it
|
||
|
||
@9
|
||
MOVE.B D4,D1
|
||
|
||
MOVE.L COLORTABLE(A6),A5
|
||
LEA 0(A5,D1.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D5,D7
|
||
LEA 0(A5,D7.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map according to Xfer mode
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table
|
||
MOVE.B D5,D0
|
||
@8
|
||
LSR.L #8,D3
|
||
LSR.L #8,D4
|
||
ROR.L #8,D5
|
||
|
||
; map 2nd byte
|
||
|
||
TST.B D3
|
||
BEQ.S @2 ;if mask zero, we can skip
|
||
|
||
; if same as previous, we can short-circuit the mapping
|
||
|
||
CMP.B D4,D1 ;source the same?
|
||
BNE.S @1 ;if not, skip
|
||
|
||
CMP.B D5,D7 ;dest the same?
|
||
BNE.S @1 ;if not, skip
|
||
|
||
; it's the same, so use it
|
||
|
||
MOVE.B D0,D5 ;use last result
|
||
BRA.S @2 ;skip the mapping
|
||
|
||
; it's different than the last one, so map it
|
||
|
||
@1
|
||
MOVE.B D4,D1
|
||
MOVE.L COLORTABLE(A6),A5
|
||
|
||
LEA 0(A5,D1.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D5,D7
|
||
LEA 0(A5,D7.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map according to Xfer mode
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table
|
||
MOVE.B D5,D0
|
||
@2
|
||
LSR.L #8,D3
|
||
LSR.L #8,D4
|
||
ROR.L #8,D5
|
||
|
||
; map 3rd byte
|
||
|
||
TST.B D3
|
||
BEQ.S @4 ;if mask zero, we can skip
|
||
|
||
; if same as previous, we can short-circuit the mapping
|
||
|
||
CMP.B D4,D1 ;source the same?
|
||
BNE.S @3 ;if not, skip
|
||
|
||
CMP.B D5,D7 ;dest the same?
|
||
BNE.S @3 ;if not, skip
|
||
|
||
; it's the same, so use it
|
||
|
||
MOVE.B D0,D5 ;use last result
|
||
BRA.S @4 ;skip the mapping
|
||
|
||
; it's different than the last one, so map it
|
||
|
||
@3
|
||
MOVE.B D4,D1
|
||
|
||
MOVE.L COLORTABLE(A6),A5
|
||
LEA 0(A5,D1.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D5,D7
|
||
LEA 0(A5,D7.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map according to Xfer mode
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table
|
||
MOVE.B D5,D0
|
||
@4
|
||
LSR.L #8,D3
|
||
LSR.L #8,D4
|
||
ROR.L #8,D5
|
||
|
||
; map final byte
|
||
|
||
TST.B D3
|
||
BEQ.S @6 ;if mask zero, we can skip
|
||
|
||
; if same as previous, we can short-circuit the mapping
|
||
|
||
CMP.B D4,D1 ;source the same?
|
||
BNE.S @5 ;if not, skip
|
||
|
||
CMP.B D5,D7 ;dest the same?
|
||
BNE.S @5 ;if not, skip
|
||
|
||
; it's the same, so use it
|
||
|
||
MOVE.B D0,D5 ;use last result
|
||
BRA.S @6 ;skip the mapping
|
||
|
||
; it's different than the last one, so map it
|
||
|
||
@5
|
||
MOVE.B D4,D1
|
||
|
||
MOVE.L COLORTABLE(A6),A5
|
||
LEA 0(A5,D1.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D5,D7
|
||
LEA 0(A5,D7.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map according to Xfer mode
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table
|
||
MOVE.B D5,D0
|
||
@6
|
||
ROR.L #8,D5
|
||
|
||
; it's all mapped, so store the result
|
||
|
||
MOVE.L D5,(A1)+ ;store the destination
|
||
ArithBotCommon
|
||
MOVEQ #-1,D3 ;set up the mask for the middle
|
||
SUBQ #1,D2
|
||
ArithBot0
|
||
BGT ArithLoop0
|
||
BEQ ArithRight0
|
||
|
||
; all done with this scan line
|
||
|
||
RTS
|
||
|
||
; handle a region of all zeros
|
||
|
||
ArithMask0
|
||
ADDQ #4,A1 ;skip over destination
|
||
BRA.S ArithBotCommon
|
||
|
||
; the pattern is simpler (it fits in a register), so use a separate loop to make things
|
||
;faster. Use a longword cache instead of the single pixel caches.
|
||
|
||
ArithSimplePat
|
||
MOVE.L D1,-(SP) ;save right edge mask
|
||
|
||
MOVEQ #0,D7 ;clear for pixIndexing
|
||
|
||
MOVE.L (A3),D4 ;keep pattern in D4
|
||
MOVE.L COLORTABLE(A6),A3 ;use A3 for color table ptr
|
||
|
||
; set up A0 to point to the proper handler, depending on the width of the inverse table
|
||
|
||
MOVE.L A0,A4 ;remember handler base
|
||
|
||
MOVE.W INVSIZE(A6),D0 ;get shift count (3,4,5)
|
||
SUBQ #3,D0
|
||
ADD.W 0(A0,D0.W*2),A0 ;point to proper handler
|
||
|
||
; init the longword pattern cache by mapping the four pixels in D4
|
||
|
||
MOVEQ #3,D5
|
||
MOVE.L D4,D6 ;init lastDest
|
||
BRA.S CacheILoop0 ;skip cache check 1st time
|
||
|
||
; if the next pixel in D4 is the same as the previous (in D7), take a shortcut
|
||
|
||
CacheInitLoop
|
||
CMP.B D4,D7 ;does it match?
|
||
BNE.S CacheILoop0 ;if not, must do the hard way
|
||
|
||
MOVE.B D0,D1 ;use last result
|
||
|
||
ROL.L #8,D1
|
||
ROL.L #8,D4
|
||
|
||
DBRA D5,CacheInitLoop
|
||
BRA.S CacheIDone
|
||
|
||
; it's not the same, so do it the hard way
|
||
|
||
CacheILoop0
|
||
MOVE.B D4,D7
|
||
LEA 0(A3,D7.W*8),A4 ;point to source color
|
||
MOVE.L A4,A5 ;source and dest are same
|
||
|
||
JSR (A0) ;map next pixel
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D1 ;look up in inverse table
|
||
|
||
MOVE.L D1,D0 ;remember last result
|
||
ROL.L #8,D1
|
||
ROL.L #8,D4
|
||
|
||
DBRA D5,CacheInitLoop
|
||
|
||
; OK, here's the start of the main loop; first, see if there's only one long to do
|
||
|
||
CacheIDone
|
||
TST.W D2
|
||
BNE.S ArithLoop1
|
||
|
||
; here's the main loop for simple patterns, where we process a longword at a time
|
||
; We use a longword cache in D6
|
||
|
||
ArithRight1
|
||
AND.L (SP)+,D3
|
||
ArithLoop1
|
||
MOVE.L A2,D5 ;no clipping?
|
||
BEQ.S @0 ;if none, skip
|
||
|
||
AND.L (A2)+,D3 ;get mask in D4
|
||
BEQ ArithMask1
|
||
@0
|
||
MOVE.L (A1),D5 ;get dest longword
|
||
|
||
CMP.L #-1,D3 ;mask all ones?
|
||
BNE.S ArithMapIt1A ;if not, can't use cache
|
||
|
||
CMP.L D5,D6 ;same as last time?
|
||
BNE.S ArithMapIt1 ;if not, skip
|
||
|
||
; the long was the same as last time, so we can skip the mapping. Better make sure
|
||
; the mask was the same, too
|
||
|
||
MOVE.L D1,D5 ;use last result
|
||
BRA ArithStoreIt ;skip the mapping
|
||
|
||
; it was different, so we have to map it the hard way
|
||
|
||
ArithMapIt1
|
||
MOVE.L D5,D6 ;remember for next time
|
||
ArithMapIt1A
|
||
TST.B D3
|
||
BEQ.S @0 ;if mask zero, we can skip
|
||
|
||
MOVE.B D4,D7
|
||
LEA 0(A3,D7.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D5,D7
|
||
LEA 0(A3,D7.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map according to Xfer mode
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table
|
||
@0
|
||
ROR.L #8,D3
|
||
ROR.L #8,D4
|
||
ROR.L #8,D5
|
||
|
||
; map 2nd byte
|
||
|
||
TST.B D3
|
||
BEQ.S @2 ;if mask zero, we can skip
|
||
|
||
MOVE.B D4,D7
|
||
LEA 0(A3,D7.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D5,D7
|
||
LEA 0(A3,D7.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map according to Xfer mode
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table
|
||
@2
|
||
ROR.L #8,D3
|
||
ROR.L #8,D4
|
||
ROR.L #8,D5
|
||
|
||
; map 3rd byte
|
||
|
||
TST.B D3
|
||
BEQ.S @4 ;if mask zero, we can skip
|
||
|
||
; map it
|
||
MOVE.B D4,D7
|
||
LEA 0(A3,D7.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D5,D7
|
||
LEA 0(A3,D7.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map according to Xfer mode
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table
|
||
@4
|
||
ROR.L #8,D3
|
||
ROR.L #8,D4
|
||
ROR.L #8,D5
|
||
|
||
; map final byte
|
||
|
||
TST.B D3
|
||
BEQ.S @6 ;if mask zero, we can skip
|
||
|
||
; it's different than the last one, so map it
|
||
|
||
MOVE.B D4,D7
|
||
LEA 0(A3,D7.W*8),A4 ;point to source color
|
||
|
||
MOVE.B D5,D7
|
||
LEA 0(A3,D7.W*8),A5 ;point to dest color
|
||
|
||
JSR (A0) ;map according to Xfer mode
|
||
MOVE.B ([INVCOLOR,A6],D0.W,6),D5 ;look up in inverse table
|
||
@6
|
||
ROR.L #8,D4
|
||
ROR.L #8,D5
|
||
|
||
; it's all mapped, so store the result
|
||
|
||
ArithStoreIt
|
||
MOVE.L D5,(A1)+ ;store the destination
|
||
ADDQ.L #1,D3 ;was mask all ones?
|
||
BNE.S ArithCom1 ;if not, skip
|
||
|
||
MOVE.L D5,D1 ;remember last result
|
||
ArithCom1
|
||
MOVEQ #-1,D3 ;set up the mask for the middle
|
||
SUBQ #1,D2
|
||
ArithBot1
|
||
BGT ArithLoop1
|
||
BEQ ArithRight1
|
||
|
||
; all done with this scan line
|
||
|
||
RTS
|
||
|
||
; handle a region of all zeros
|
||
|
||
ArithMask1
|
||
ADDQ #4,A1 ;skip over destination
|
||
BRA.S ArithCom1
|
||
|
||
; Here is the handler for the AddOver mode. A4 points to the source RGBColor, while
|
||
; A5 points to the destination. Return the index in D0 (to be looked up in the
|
||
; inverse table). First there is a case table for using a static shift count
|
||
|
||
AddOverHandler
|
||
DC.W AddOver3-AddOverHandler
|
||
DC.W AddOver4-AddOverHandler
|
||
DC.W AddOver5-AddOverHandler
|
||
|
||
AddOver3
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0 ;red
|
||
ADD.W (A5)+,D0
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A4)+,D0 ;green
|
||
ADD.W (A5)+,D0
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A4),D0 ;blue
|
||
ADD.W (A5),D0
|
||
LSL.L #3,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
AddOver4
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0 ;red
|
||
ADD.W (A5)+,D0
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A4)+,D0 ;green
|
||
ADD.W (A5)+,D0
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A4),D0 ;blue
|
||
ADD.W (A5),D0
|
||
LSL.L #4,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
AddOver5
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0 ;red
|
||
ADD.W (A5)+,D0
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A4)+,D0 ;green
|
||
ADD.W (A5)+,D0
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A4),D0 ;blue
|
||
ADD.W (A5),D0
|
||
LSL.L #5,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
;*************************************************************************************
|
||
|
||
|
||
; Here is the receiver for the SubOver arithmetic fill mode, for ovals and roundRects.
|
||
; It uses mainly common code with the other oval handlers
|
||
|
||
|
||
SubOverFillO
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BEQ.S @0 ;if not, skip <S433>
|
||
|
||
JMPRom Old38E ; <S433>
|
||
|
||
; OK, first do the pattern setup
|
||
|
||
@0 MOVE.L A0,A3 ;set up pattern base
|
||
LEA SubOverHandler,A0 ;use subOver
|
||
BRA DoArithMode
|
||
|
||
; Here is the handler for the SubOver mode. A4 points to the source RGBColor, while
|
||
; A5 points to the destination. Return the index in D0 (to be looked up in the
|
||
; inverse table). First there is a case table for using a static shift count
|
||
|
||
SubOverHandler
|
||
DC.W SubOver3-SubOverHandler
|
||
DC.W SubOver4-SubOverHandler
|
||
DC.W SubOver5-SubOverHandler
|
||
|
||
SubOver3
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #3,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
SubOver4
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #4,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
SubOver5
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
LSL.L #5,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
|
||
;*************************************************************************************
|
||
|
||
; Here is the receiver for the AddPin arithmetic fill mode, for ovals and roundRects.
|
||
; It uses mainly common code with the other oval handlers
|
||
|
||
AddPinFillO
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BEQ.S @0 ;if not, skip <S433>
|
||
|
||
JMPRom Old389 ; <S433>
|
||
|
||
; set up handlers and use common code
|
||
|
||
@0 MOVE.L A0,A3 ;set up pattern base
|
||
LEA AddPinHandler,A0 ;use addPin
|
||
BRA DoArithMode
|
||
|
||
|
||
; Here is the handler for the AddPin mode. A4 points to the source RGBColor, while
|
||
; A5 points to the destination. Return the index in D0 (to be looked up in the
|
||
; inverse table). First there is a case table for using a static shift count
|
||
|
||
AddPinHandler
|
||
DC.W AddPin3-AddPinHandler
|
||
DC.W AddPin4-AddPinHandler
|
||
DC.W AddPin5-AddPinHandler
|
||
|
||
AddPin3
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0 ;red
|
||
ADD.W (A5)+,D0
|
||
BCS.S @0
|
||
|
||
CMP.W WEIGHT+BLUE(A6),D0
|
||
BLS.S @1
|
||
@0
|
||
MOVE.W WEIGHT+BLUE(A6),D0
|
||
@1
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A4)+,D0 ;green
|
||
ADD.W (A5)+,D0
|
||
BCS.S @2
|
||
|
||
CMP.W WEIGHT+GREEN(A6),D0
|
||
BLS.S @3
|
||
@2
|
||
MOVE.W WEIGHT+GREEN(A6),D0
|
||
@3
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A4),D0 ;blue
|
||
ADD.W (A5),D0
|
||
BCS.S @4
|
||
|
||
CMP.W WEIGHT+RED(A6),D0
|
||
BLS.S @5
|
||
@4
|
||
MOVE.W WEIGHT+RED(A6),D0
|
||
@5
|
||
LSL.L #3,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
AddPin4
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0 ;red
|
||
ADD.W (A5)+,D0
|
||
BCS.S @0
|
||
|
||
CMP.W WEIGHT+BLUE(A6),D0
|
||
BLS.S @1
|
||
@0
|
||
MOVE.W WEIGHT+BLUE(A6),D0
|
||
@1
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A4)+,D0 ;green
|
||
ADD.W (A5)+,D0
|
||
BCS.S @2
|
||
|
||
CMP.W WEIGHT+GREEN(A6),D0
|
||
BLS.S @3
|
||
@2
|
||
MOVE.W WEIGHT+GREEN(A6),D0
|
||
@3
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A4),D0 ;blue
|
||
ADD.W (A5),D0
|
||
BCS.S @4
|
||
|
||
CMP.W WEIGHT+RED(A6),D0
|
||
BLS.S @5
|
||
@4
|
||
MOVE.W WEIGHT+RED(A6),D0
|
||
@5
|
||
LSL.L #4,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
AddPin5
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0 ;red
|
||
ADD.W (A5)+,D0
|
||
BCS.S @0
|
||
|
||
CMP.W WEIGHT+BLUE(A6),D0
|
||
BLS.S @1
|
||
@0
|
||
MOVE.W WEIGHT+BLUE(A6),D0
|
||
@1
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A4)+,D0 ;green
|
||
ADD.W (A5)+,D0
|
||
BCS.S @2
|
||
|
||
CMP.W WEIGHT+GREEN(A6),D0
|
||
BLS.S @3
|
||
@2
|
||
MOVE.W WEIGHT+GREEN(A6),D0
|
||
@3
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A4),D0 ;blue
|
||
ADD.W (A5),D0
|
||
BCS.S @4
|
||
|
||
CMP.W WEIGHT+RED(A6),D0
|
||
BLS.S @5
|
||
@4
|
||
MOVE.W WEIGHT+RED(A6),D0
|
||
@5
|
||
LSL.L #5,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
;*************************************************************************************
|
||
|
||
; Here is the receiver for the SubPin arithmetic fill mode, for ovals and roundRects.
|
||
; It uses mainly common code with the other oval handlers
|
||
|
||
SubPinFillO
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BEQ.S @0 ;if not, skip <S433>
|
||
|
||
JMPRom Old38B ; <S433>
|
||
|
||
; set up handlers and use common code
|
||
|
||
@0 MOVE.L A0,A3 ;set up pattern base
|
||
LEA SubPinHandler,A0 ;use SubPin
|
||
BRA DoArithMode
|
||
|
||
|
||
; Here is the handler for the SubPin mode. A4 points to the source RGBColor, while
|
||
; A5 points to the destination. Return the index in D0 (to be looked up in the
|
||
; inverse table). First there is a case table for using a static shift count
|
||
|
||
SubPinHandler
|
||
DC.W SubPin3-SubPinHandler
|
||
DC.W SubPin4-SubPinHandler
|
||
DC.W SubPin5-SubPinHandler
|
||
|
||
SubPin3
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @0
|
||
|
||
CMP.W WEIGHT+BLUE(A6),D0
|
||
BCC.S @1
|
||
@0
|
||
MOVE.W WEIGHT+BLUE(A6),D0
|
||
@1
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @2
|
||
|
||
CMP.W WEIGHT+GREEN(A6),D0
|
||
BCC.S @3
|
||
@2
|
||
MOVE.W WEIGHT+GREEN(A6),D0
|
||
@3
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @4
|
||
|
||
CMP.W WEIGHT+RED(A6),D0
|
||
BCC.S @5
|
||
@4
|
||
MOVE.W WEIGHT+RED(A6),D0
|
||
@5
|
||
LSL.L #3,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
SubPin4
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @0
|
||
|
||
CMP.W WEIGHT+BLUE(A6),D0
|
||
BCC.S @1
|
||
@0
|
||
MOVE.W WEIGHT+BLUE(A6),D0
|
||
@1
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @2
|
||
|
||
CMP.W WEIGHT+GREEN(A6),D0
|
||
BCC.S @3
|
||
@2
|
||
MOVE.W WEIGHT+GREEN(A6),D0
|
||
@3
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @4
|
||
|
||
CMP.W WEIGHT+RED(A6),D0
|
||
BCC.S @5
|
||
@4
|
||
MOVE.W WEIGHT+RED(A6),D0
|
||
@5
|
||
LSL.L #4,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
SubPin5
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @0
|
||
|
||
CMP.W WEIGHT+BLUE(A6),D0
|
||
BCC.S @1
|
||
@0
|
||
MOVE.W WEIGHT+BLUE(A6),D0
|
||
@1
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @2
|
||
|
||
CMP.W WEIGHT+GREEN(A6),D0
|
||
BCC.S @3
|
||
@2
|
||
MOVE.W WEIGHT+GREEN(A6),D0
|
||
@3
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A5)+,D0 ;red
|
||
SUB.W (A4)+,D0
|
||
BCS.S @4
|
||
|
||
CMP.W WEIGHT+RED(A6),D0
|
||
BCC.S @5
|
||
@4
|
||
MOVE.W WEIGHT+RED(A6),D0
|
||
@5
|
||
LSL.L #5,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
;*************************************************************************************
|
||
|
||
|
||
; Here is the receiver for the AddMax arithmetic fill mode, for ovals and roundRects.
|
||
; It uses mainly common code with the other oval handlers
|
||
|
||
AddMaxFillO
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BEQ.S @0 ;if not, skip <S433>
|
||
|
||
JMPRom Old38D ; <S433>
|
||
|
||
; OK, first do the pattern setup
|
||
|
||
@0 MOVE.L A0,A3 ;set up pattern base
|
||
LEA AddMaxHandler,A0 ;use AddMax
|
||
BRA DoArithMode
|
||
|
||
; Here is the handler for the AddMax mode. A4 points to the source RGBColor, while
|
||
; A5 points to the destination. Return the index in D0 (to be looked up in the
|
||
; inverse table). First there is a case table for using a static shift count
|
||
|
||
AddMaxHandler
|
||
DC.W AddMax3-AddMaxHandler
|
||
DC.W AddMax4-AddMaxHandler
|
||
DC.W AddMax5-AddMaxHandler
|
||
|
||
AddMax3
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @0
|
||
MOVE.W (A5),D0
|
||
@0
|
||
ADDQ #2,A5
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @1
|
||
MOVE.W (A5),D0
|
||
@1
|
||
ADDQ #2,A5
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @2
|
||
MOVE.W (A5),D0
|
||
@2
|
||
ADDQ #2,A5
|
||
LSL.L #3,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
AddMax4
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @0
|
||
MOVE.W (A5),D0
|
||
@0
|
||
ADDQ #2,A5
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @1
|
||
MOVE.W (A5),D0
|
||
@1
|
||
ADDQ #2,A5
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @2
|
||
MOVE.W (A5),D0
|
||
@2
|
||
ADDQ #2,A5
|
||
LSL.L #4,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
AddMax5
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @0
|
||
MOVE.W (A5),D0
|
||
@0
|
||
ADDQ #2,A5
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @1
|
||
MOVE.W (A5),D0
|
||
@1
|
||
ADDQ #2,A5
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BCC.S @2
|
||
MOVE.W (A5),D0
|
||
@2
|
||
ADDQ #2,A5
|
||
LSL.L #5,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
|
||
;*************************************************************************************
|
||
|
||
|
||
; Here is the receiver for the AddMin arithmetic fill mode, for ovals and roundRects.
|
||
; It uses mainly common code with the other oval handlers
|
||
|
||
|
||
AddMinFillO
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BEQ.S @0 ;if not, skip <S433>
|
||
|
||
JMPRom Old38F ; <S433>
|
||
|
||
; OK, first do the pattern setup
|
||
|
||
@0 MOVE.L A0,A3 ;set up pattern base
|
||
LEA AddMinHandler,A0 ;use addMin
|
||
BRA DoArithMode
|
||
|
||
; Here is the handler for the AddMin mode. A4 points to the source RGBColor, while
|
||
; A5 points to the destination. Return the index in D0 (to be looked up in the
|
||
; inverse table). First there is a case table for using a static shift count
|
||
|
||
AddMinHandler
|
||
DC.W AddMin3-AddMinHandler
|
||
DC.W AddMin4-AddMinHandler
|
||
DC.W AddMin5-AddMinHandler
|
||
|
||
AddMin3
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @0
|
||
MOVE.W (A5),D0
|
||
@0
|
||
ADDQ #2,A5
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @1
|
||
MOVE.W (A5),D0
|
||
@1
|
||
ADDQ #2,A5
|
||
LSL.L #3,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @2
|
||
MOVE.W (A5),D0
|
||
@2
|
||
ADDQ #2,A5
|
||
LSL.L #3,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
AddMin4
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @0
|
||
MOVE.W (A5),D0
|
||
@0
|
||
ADDQ #2,A5
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @1
|
||
MOVE.W (A5),D0
|
||
@1
|
||
ADDQ #2,A5
|
||
LSL.L #4,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @2
|
||
MOVE.W (A5),D0
|
||
@2
|
||
ADDQ #2,A5
|
||
LSL.L #4,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
AddMin5
|
||
MOVEQ #0,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @0
|
||
MOVE.W (A5),D0
|
||
@0
|
||
ADDQ #2,A5
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @1
|
||
MOVE.W (A5),D0
|
||
@1
|
||
ADDQ #2,A5
|
||
LSL.L #5,D0
|
||
|
||
MOVE.W (A4)+,D0
|
||
CMP.W (A5),D0
|
||
BLS.S @2
|
||
MOVE.W (A5),D0
|
||
@2
|
||
ADDQ #2,A5
|
||
LSL.L #5,D0
|
||
|
||
SWAP D0 ;return inverse table index
|
||
RTS
|
||
|
||
|
||
;*************************************************************************************
|
||
|
||
|
||
; Here is the receiver for the blend arithmetic fill mode, for ovals and roundRects.
|
||
; It uses mainly common code with the other oval handlers
|
||
|
||
|
||
BlendFillO
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BEQ.S @0 ;if not, skip <S433>
|
||
|
||
JMPRom Old388 ; <S433>
|
||
|
||
; OK, first do the pattern setup
|
||
|
||
@0 MOVE.L A0,A3 ;set up pattern base
|
||
LEA BlendHandler,A0 ;use blend
|
||
BRA DoArithMode
|
||
|
||
; Here is the handler for the Blend mode. A4 points to the source RGBColor, while
|
||
; A5 points to the destination. Return the index in D0 (to be looked up in the
|
||
; inverse table). First there is a case table for using a static shift count
|
||
|
||
BlendHandler
|
||
DC.W Blend3-BlendHandler
|
||
DC.W Blend4-BlendHandler
|
||
DC.W Blend5-BlendHandler
|
||
|
||
Blend3
|
||
MOVEM.L D1-D3,-(SP)
|
||
|
||
MOVEQ #3,D2 ;set up shift count
|
||
BRA.S BlendCommon
|
||
Blend4
|
||
MOVEM.L D1-D3,-(SP)
|
||
MOVEQ #4,D2
|
||
BlendCommon
|
||
MOVEQ #0,D0 ;clear accum reg
|
||
|
||
; do red
|
||
|
||
MOVE.W (A4)+,D1
|
||
MULU WEIGHT+BLUE(A6),D1
|
||
|
||
MOVE.W (A5)+,D3
|
||
MULU NOTWEIGHT+BLUE(A6),D3
|
||
|
||
ADD.L D1,D3
|
||
SWAP D3
|
||
MOVE.W D3,D0
|
||
ASL.L D2,D0
|
||
|
||
; do green
|
||
|
||
MOVE.W (A4)+,D1
|
||
MULU WEIGHT+GREEN(A6),D1
|
||
|
||
MOVE.W (A5)+,D3
|
||
MULU NOTWEIGHT+GREEN(A6),D3
|
||
|
||
ADD.L D1,D3
|
||
SWAP D3
|
||
MOVE.W D3,D0
|
||
ASL.L D2,D0
|
||
|
||
; do blue
|
||
|
||
MOVE.W (A4)+,D1
|
||
MULU WEIGHT+RED(A6),D1
|
||
|
||
MOVE.W (A5)+,D3
|
||
MULU NOTWEIGHT+RED(A6),D3
|
||
|
||
ADD.L D1,D3
|
||
SWAP D3
|
||
MOVE.W D3,D0
|
||
ASL.L D2,D0
|
||
|
||
SWAP D0
|
||
|
||
MOVEM.L (SP)+,D1-D3
|
||
RTS
|
||
Blend5
|
||
MOVEM.L D1-D3,-(SP)
|
||
MOVEQ #5,D2
|
||
BRA.S BlendCommon
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Now we start on the arithmetic fills for clipped rectangles. Use the common
|
||
; scan line handler for ovals/rrects to save code.
|
||
|
||
; First we handle AddOver mode
|
||
|
||
UseOld368
|
||
JMPROM Old368 ; <S433>
|
||
|
||
AddOverFillR
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld368 ;if not, skip
|
||
tst.l d3 ;right to left? <PB427 BAL>
|
||
bmi.s UseOld368 ;if so, skip <PB427 BAL>
|
||
|
||
LEA AddOverHandler,A0 ;set up the handler
|
||
ArithFillCommon
|
||
MOVE.L A0,-(SP) ;remember handler address
|
||
|
||
; set up the registers and invoke the common scan-line handler
|
||
|
||
MOVE.L A4,A2 ;set up region pointer
|
||
ASR #3,D6 ;bit index to byte index
|
||
MOVE.L A5,A1 ;set up destination
|
||
ArithFillLoop
|
||
MOVEQ #-1,D1
|
||
MOVEQ #-1,D3 ;edge masks all ones (edges in region)
|
||
|
||
MOVE.W BUFSIZE(A6),D2 ;set up the count
|
||
ADDQ #4,D2 ;make one based <PB427 BAL>
|
||
LSR.W #2,D2
|
||
SUBQ #1,D2 ;make zero based <PB427 BAL>
|
||
|
||
MOVE.L (SP),A0 ;get handler address
|
||
|
||
; call the appropriate handle, depending on whether the pattern is simple or complex
|
||
|
||
CMP.W #8,PATROW(A6) ;is pattern real complex?
|
||
BGT.S @0 ;if so, go handle it
|
||
|
||
TST.B SRCV(A6) ;test pattern mode
|
||
BMI.S @0 ;treat bitmap as complex
|
||
|
||
MOVE.L 0(A3,D6),D0 ;get left pattern
|
||
EOR #4,D6
|
||
CMP.L 0(A3,D6),D0 ;left same as right?
|
||
BEQ.S @1 ;if so, it's simple
|
||
|
||
EOR #4,D6 ;restore D6
|
||
@0
|
||
BSR ArithComplex1 ;invoke scan-line handler for complex pats
|
||
BRA.S @2
|
||
@1
|
||
EOR #4,D6
|
||
BSR ArithSimplePat
|
||
|
||
; bump pointers to next time, and loop until done
|
||
|
||
@2
|
||
MOVE.L HEIGHT(A6),D6 ;get pattern index
|
||
ASR.L #3,D6 ;bit index to byte index
|
||
|
||
MOVE.W DSTV(A6),D0
|
||
|
||
TST.B SRCV(A6) ;test pattern mode
|
||
BEQ.S AFPat1 ;if zero, handle
|
||
BMI.S AFBitMap1 ;if <0, go handle bitmap
|
||
|
||
; handle bumping the pattern pointers
|
||
|
||
MOVE.L SRCADDR(A6),A3 ;set up pattern pointer
|
||
SUB.W D0,A3
|
||
ADD.W PATROW(A6),D0
|
||
AND.W PATVMASK(A6),D0
|
||
MOVE.W D0,DSTV(A6)
|
||
ADD.W D0,A3
|
||
|
||
BRA.S AFSetPatPtr
|
||
|
||
; handle second type of pattern
|
||
|
||
AFPat1
|
||
ADDQ #1,D0
|
||
AND #15,D0
|
||
LEA ([EXPAT,A6],D0.W*4),A3
|
||
|
||
MOVE.W D0,HEIGHT(A6)
|
||
AFSetPatPtr
|
||
MOVE.L A3,SRCADDR(A6)
|
||
|
||
; bump to the next scan line
|
||
|
||
ArithFillNextLine
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6)
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADD.W VBUMP(A6),D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W LASTV(A6),D0
|
||
BNE.S @0
|
||
|
||
; all done, so strip stack and return
|
||
|
||
MOVE.L SAVESTK2(A6),A7
|
||
RTS
|
||
|
||
; set up registers and loop for the next line
|
||
|
||
@0
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;seek new region
|
||
|
||
MOVE.L SRCADDR(A6),A3 ;set up pattern pointer
|
||
MOVE.L DSTADDR(A6),A1 ;set up dest ptr
|
||
MOVE.L RGNADDR(A6),A2 ;set up region ptr
|
||
|
||
BRA ArithFillLoop
|
||
|
||
; handle bumping the source if it's a bitmap
|
||
|
||
AFBitMap1
|
||
MOVE.L SRCROW(A6),D0
|
||
ADD.L D0,SRCADDR(A6)
|
||
|
||
BRA.S ArithFillNextLine
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle SubOver clipped rectangle fill
|
||
|
||
UseOld36C
|
||
JMPRom Old36C ; <PB433>
|
||
|
||
SubOverFillR
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld36C ;if not, skip
|
||
tst.l d3 ;right to left? <PB427 BAL>
|
||
bmi.s UseOld36c ;if so, skip <PB427 BAL>
|
||
|
||
LEA SubOverHandler,A0 ;set up the handler
|
||
BRA ArithFillCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle AddPin clipped rectangle fill
|
||
|
||
UseOld367
|
||
JMPRom Old367 ; <PB433>
|
||
|
||
AddPinFillR
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld367 ;if not, skip
|
||
tst.l d3 ;right to left? <PB427 BAL>
|
||
bmi.s UseOld367 ;if so, skip <PB427 BAL>
|
||
|
||
LEA AddPinHandler,A0 ;set up the handler
|
||
BRA ArithFillCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle SubPin clipped rectangle fill
|
||
|
||
UseOld369
|
||
JMPRom Old369 ; <PB433>
|
||
|
||
SubPinFillR
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld369 ;if not, skip
|
||
tst.l d3 ;right to left? <PB427 BAL>
|
||
bmi.s UseOld369 ;if so, skip <PB427 BAL>
|
||
|
||
LEA SubPinHandler,A0 ;set up the handler
|
||
BRA ArithFillCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle AddMax clipped rectangle fill
|
||
|
||
UseOld36B
|
||
JMPRom Old36B ; <PB433>
|
||
|
||
AddMaxFillR
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld36B ;if not, skip
|
||
tst.l d3 ;right to left? <PB427 BAL>
|
||
bmi.s UseOld36B ;if so, skip <PB427 BAL>
|
||
|
||
LEA AddMaxHandler,A0 ;set up the handler
|
||
BRA ArithFillCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle AddMin clipped rectangle fill
|
||
|
||
UseOld36D
|
||
JMPRom Old36D ; <PB433>
|
||
|
||
AddMinFillR
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld36D ;if not, skip
|
||
tst.l d3 ;right to left? <PB427 BAL>
|
||
bmi.s UseOld36D ;if so, skip <PB427 BAL>
|
||
|
||
LEA AddMinHandler,A0 ;set up the handler
|
||
BRA ArithFillCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle Blend clipped rectangle fill
|
||
|
||
UseOld366
|
||
JMPRom Old366 ; <PB433>
|
||
|
||
BlendFillR
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld366 ;if not, skip
|
||
tst.l d3 ;right to left? <PB427 BAL>
|
||
bmi.s UseOld366 ;if s0, skip <PB427 BAL>
|
||
|
||
LEA BlendHandler,A0 ;set up the handler
|
||
BRA ArithFillCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Now we start on the arithmetic fills for unclipped rectangles. Use the common
|
||
; scan line handler for ovals/rrects to save code.
|
||
|
||
; First we handle AddOver mode, unclipped
|
||
|
||
UseOld352
|
||
JMPRom Old352 ; <PB433>
|
||
|
||
AddOverUnClip
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld352 ;if not, skip
|
||
tst.l (sp) ;right to left? <PB427 BAL>
|
||
bmi.s UseOld352 ;if so, skip <PB427 BAL>
|
||
|
||
LEA AddOverHandler,A0 ;set up the handler
|
||
ArithUCCommon
|
||
MOVE.L A0,-(SP) ;remember handler address
|
||
|
||
; set up the registers and invoke the common scan-line handler
|
||
|
||
SUB.L A2,A2 ;no region pointer
|
||
ASR #3,D6 ;bit index to byte index
|
||
MOVE.L A4,A3 ;set up pattern pointer
|
||
MOVE.L A5,A1 ;set up destination
|
||
ArithUCLoop
|
||
MOVE.L FIRSTMASK(A6),D3 ;set up left edge
|
||
MOVE.L LASTMASK(A6),D1 ;set up right edge
|
||
|
||
; compute the count from the three pieces: left, mid and right
|
||
|
||
MOVE.W LONGCNT(A6),D2 ;get left count
|
||
BPL.S @3 ;if positive, we're cool
|
||
|
||
MOVEQ #0,D2 ;only one word
|
||
BRA.S @4
|
||
@3
|
||
ADD.W MIDCOUNT(A6),D2 ;add in the middle
|
||
ADD.W PIXINLONG(A6),D2 ;add in the right
|
||
ADDQ.W #2,D2 ;add for count bias
|
||
LSR.W #2,D2 ;bytes -> longs
|
||
@4
|
||
MOVE.L (SP),A0 ;get handler address
|
||
|
||
; call the appropriate handle, depending on whether the pattern is simple or complex
|
||
|
||
CMP.W #8,PATROW(A6) ;is pattern real complex?
|
||
BGT.S @0 ;if so, go handle it
|
||
|
||
TST.B ENDSWITCH(A6) ;test pattern mode
|
||
BMI.S @0 ;if bitmap, it's complex
|
||
|
||
MOVE.L 0(A3,D6),D0 ;get left pattern
|
||
EOR #4,D6
|
||
CMP.L 0(A3,D6),D0 ;left same as right?
|
||
BEQ.S @1 ;if so, it's simple
|
||
|
||
EOR #4,D6 ;restore D6
|
||
@0
|
||
MOVE.L A1,-(SP)
|
||
BSR ArithComplex1 ;invoke scan-line handler for complex pats
|
||
MOVE.L (SP)+,A1
|
||
|
||
BRA.S @2
|
||
@1
|
||
EOR #4,D6
|
||
|
||
MOVEM.L A1/A3,-(SP)
|
||
BSR ArithSimplePat
|
||
MOVEM.L (SP)+,A1/A3
|
||
|
||
; bump pointers to next time, and loop until done
|
||
|
||
@2
|
||
TST.B ENDSWITCH(A6) ;test pattern mode
|
||
BEQ.S AFUCPat1 ;if zero, handle
|
||
BMI.S AFUCBitMap1 ;if <0, go handle bitmap
|
||
|
||
; handle bumping the pattern pointers
|
||
|
||
MOVE.W PATPOS(A6),D0
|
||
SUB.W D0,A3
|
||
ADD.W PATROW(A6),D0
|
||
AND.W PATVMASK(A6),D0
|
||
MOVE.W D0,PATPOS(A6)
|
||
ADD.W D0,A3
|
||
|
||
BRA.S ArithUCNextLine
|
||
|
||
; handle second type of pattern
|
||
|
||
AFUCPat1
|
||
MOVE.W PATPOS(A6),D0
|
||
ADDQ #1,D0
|
||
AND #15,D0
|
||
LEA ([EXPAT,A6],D0.W*4),A3
|
||
|
||
MOVE.W D0,PATPOS(A6)
|
||
|
||
; bump to the next scan line
|
||
|
||
ArithUCNextLine
|
||
MOVE.L PATOFFSET(A6),D6
|
||
ASR.L #3,D6 ;bits to bytes
|
||
ArithUCNL2
|
||
ADD.W DSTROW+2(A6),A1 ;bump destination
|
||
|
||
SUBQ.W #1,HEIGHT(A6)
|
||
BNE ArithUCLoop
|
||
|
||
ADDQ #8,SP
|
||
RTS
|
||
|
||
; handle unclipped blits source setup
|
||
|
||
AFUCBitMap1
|
||
ADD.W D6,A3
|
||
ADD.W SRCBUMP(A6),A3 ;bump to next line <PB448 DBG>
|
||
MOVEQ #0,D6
|
||
BRA.S ArithUCNL2
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle SubOver unclipped rectangle fill
|
||
|
||
UseOld356
|
||
JMPRom Old356 ; <PB433>
|
||
|
||
SubOverUnclip
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld356 ;if not, skip
|
||
tst.l (sp) ;right to left? <PB427 BAL>
|
||
bmi.s UseOld356 ;if so, skip <PB427 BAL>
|
||
|
||
LEA SubOverHandler,A0 ;set up the handler
|
||
BRA ArithUCCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle AddPin unclipped rectangle fill
|
||
|
||
UseOld351
|
||
JMPRom Old351 ; <PB433>
|
||
|
||
AddPinUnclip
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld351 ;if not, skip
|
||
tst.l (sp) ;right to left? <PB427 BAL>
|
||
bmi.s UseOld351 ;if so, skip <PB427 BAL>
|
||
|
||
LEA AddPinHandler,A0 ;set up the handler
|
||
BRA ArithUCCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle SubPin unclipped rectangle fill
|
||
|
||
UseOld353
|
||
JMPRom Old353 ; <PB433>
|
||
|
||
SubPinUnclip
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld353 ;if not, skip
|
||
tst.l (sp) ;right to left? <PB427 BAL>
|
||
bmi.s UseOld353 ;if so, skip <PB427 BAL>
|
||
|
||
LEA SubPinHandler,A0 ;set up the handler
|
||
BRA ArithUCCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle AddMax unclipped rectangle fill
|
||
|
||
UseOld355
|
||
JMPRom Old355 ; <PB433>
|
||
|
||
AddMaxUnclip
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld355 ;if not, skip
|
||
tst.l (sp) ;right to left? <PB427 BAL>
|
||
bmi.s UseOld355 ;if so, skip <PB427 BAL>
|
||
|
||
LEA AddMaxHandler,A0 ;set up the handler
|
||
BRA ArithUCCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle AddMin unclipped rectangle fill
|
||
|
||
UseOld357
|
||
JMPRom Old357 ; <PB433>
|
||
|
||
AddMinUnclip
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld357 ;if not, skip
|
||
tst.l (sp) ;right to left? <PB427 BAL>
|
||
bmi.s UseOld357 ;if so, skip <PB427 BAL>
|
||
|
||
LEA AddMinHandler,A0 ;set up the handler
|
||
BRA ArithUCCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Handle Blend unclipped rectangle fill
|
||
|
||
UseOld350
|
||
JMPRom Old350 ; <PB433>
|
||
|
||
BlendUnclip
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld350 ;if not, skip
|
||
tst.l (sp) ;right to left? <PB427 BAL>
|
||
bmi.s UseOld350 ;if so, skip <PB427 BAL>
|
||
|
||
LEA BlendHandler,A0 ;set up the handler
|
||
BRA ArithUCCommon ;use comon code
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Here's where we handle transparent mode. The basic strategy is to create a mask from
|
||
; the pattern (for one and two long patterns) so we don't have to keep examining it
|
||
; pixel by pixel. (If the mask is all ones, fall into the standard fills).
|
||
|
||
; the first one is for transparent mode for ovals and roundRects
|
||
|
||
TransFillO
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BEQ.S @0 ;if not, skip
|
||
|
||
JMPRom Old38C ;
|
||
|
||
@0 CMP.W #4,PATROW(A6) ;is it a simple pattern?
|
||
BGT.S TransComplexPat ;if not, inspect it closer
|
||
|
||
; it's a simple pattern, so make a mask according to the see-through color
|
||
|
||
TransSimple1
|
||
MOVE.L (A0),D6 ;fetch the pattern
|
||
MOVEQ #-1,D4 ;mask is initially all ones
|
||
MOVE.B TRANSCOLOR(A6),D5 ;get color to compare with
|
||
|
||
CMP.B D6,D5
|
||
BNE.S @0
|
||
|
||
CLR.B D4
|
||
@0
|
||
ROR.L #8,D4
|
||
ROR.L #8,D6
|
||
|
||
CMP.B D6,D5
|
||
BNE.S @1
|
||
|
||
CLR.B D4
|
||
@1
|
||
ROR.L #8,D4
|
||
ROR.L #8,D6
|
||
|
||
CMP.B D6,D5
|
||
BNE.S @2
|
||
|
||
CLR.B D4
|
||
@2
|
||
ROR.L #8,D4
|
||
ROR.L #8,D6
|
||
|
||
CMP.B D6,D5
|
||
BNE.S @3
|
||
|
||
CLR.B D4
|
||
@3
|
||
ROR.L #8,D4
|
||
ROR.L #8,D6
|
||
|
||
; if the mask is all ones, plot it quickly using the standard fill routine
|
||
|
||
MOVE.L A2,D0 ;if no clipping
|
||
BEQ.S @4 ;skip optimization (things not set up)
|
||
|
||
CMP.L #-1,D4 ;is mask all ones?
|
||
BEQ FCSL2 ;use standard pattern fill
|
||
|
||
; OK, mask is in D4, A2 points to the region, pattern in D6 and A1 is the destination.
|
||
; use the straightforward loop, since region optimizations aren't worth it since we
|
||
; always have to read the destination.
|
||
|
||
@4
|
||
TST.W D2 ;only one long?
|
||
BNE.S TransSimpleLoop ;if not, skip
|
||
TSL0
|
||
AND.L D1,D3 ;combine edges for last one
|
||
TransSimpleLoop
|
||
MOVE.L A2,D0
|
||
BEQ.S @0
|
||
|
||
AND.L (A2)+,D3 ;pick up the region mask
|
||
@0
|
||
AND.L D4,D3 ;punch out transparent part
|
||
|
||
MOVE.L D6,D0
|
||
AND.L D3,D0
|
||
|
||
NOT.L D3
|
||
AND.L (A1),D3
|
||
OR.L D0,D3
|
||
MOVE.L D3,(A1)+
|
||
|
||
MOVEQ #-1,D3
|
||
|
||
SUBQ.W #1,D2 ;decrement counter
|
||
BGT.S TransSimpleLoop ;loop until done
|
||
BEQ.S TSL0
|
||
|
||
RTS
|
||
|
||
; see if the complex pattern is really a simple one, if so, we can speed things up
|
||
|
||
TransComplexPat
|
||
MOVE.W D0,D6
|
||
ADD.W PATHPOS(A6),D6
|
||
|
||
MOVE.W PATHMASK(A6),D4 ;get pattern mask
|
||
ASR #3,D4 ;turn bit index to byte index
|
||
AND.W D4,D6 ;mask it
|
||
|
||
MOVE.L EXPAT(A6),A3
|
||
ADD.W PATVPOS(A6),A3 ;compute pattern address
|
||
|
||
CMP.W #8,PATROW(A6) ;is it a double pattern?
|
||
BGT.S TransComplex1 ;if not, must be complex
|
||
|
||
MOVE.L 0(A3,D6),D4 ;get source longword
|
||
EOR #4,D6
|
||
CMP.L 0(A3,D6),D4 ;is it really simple?
|
||
BEQ TransSimple1 ;if so, go handle
|
||
|
||
EOR #4,D6 ;restore D6
|
||
TransComplex1
|
||
MOVE.L D7,-(SP)
|
||
MOVE.L TRANSCOLOR(A6),D5 ;get color to compare with
|
||
|
||
TST.W D2
|
||
BNE.S TCPatLoop
|
||
|
||
; it's complex, so plot it ourselves. First fetch the pattern.
|
||
|
||
TCPLoop0
|
||
AND.L D1,D3
|
||
TCPatLoop
|
||
MOVE.W PATHMASK(A6),D4 ;get pattern mask
|
||
ASR #3,D4 ;turn bit index to byte index
|
||
AND.W D4,D6 ;mask it
|
||
|
||
MOVE.L 0(A3,D6),D7 ;get source longword
|
||
ADDQ #4,D6
|
||
|
||
CMP.L D7,D5 ;all transparent?
|
||
BEQ.S TCPSkip
|
||
|
||
; now create a mask for it
|
||
|
||
MOVEQ #-1,D4 ;mask is initially all ones
|
||
|
||
CMP.B D7,D5
|
||
BNE.S @0
|
||
|
||
CLR.B D4
|
||
@0
|
||
ROR.L #8,D4
|
||
ROR.L #8,D7
|
||
|
||
CMP.B D7,D5
|
||
BNE.S @1
|
||
|
||
CLR.B D4
|
||
@1
|
||
ROR.L #8,D4
|
||
ROR.L #8,D7
|
||
|
||
CMP.B D7,D5
|
||
BNE.S @2
|
||
|
||
CLR.B D4
|
||
@2
|
||
ROR.L #8,D4
|
||
ROR.L #8,D7
|
||
|
||
CMP.B D7,D5
|
||
BNE.S @3
|
||
|
||
CLR.B D4
|
||
@3
|
||
ROR.L #8,D4
|
||
ROR.L #8,D7
|
||
|
||
; now we can finally plot it
|
||
|
||
MOVE.L A2,D0
|
||
BEQ.S @8
|
||
|
||
AND.L (A2)+,D3 ;pick up the region mask
|
||
@8
|
||
AND.L D4,D3 ;punch out transparent part
|
||
|
||
MOVE.L D7,D0
|
||
AND.L D3,D0
|
||
|
||
NOT.L D3
|
||
AND.L (A1),D3
|
||
OR.L D0,D3
|
||
MOVE.L D3,(A1)+
|
||
|
||
; loop until done
|
||
|
||
NextTCP
|
||
MOVEQ #-1,D3
|
||
|
||
SUBQ.W #1,D2 ;decrement counter
|
||
BGT.S TCPatLoop ;loop until done
|
||
BEQ.S TCPLoop0
|
||
|
||
MOVE.L (SP)+,D7
|
||
RTS
|
||
|
||
TCPSkip
|
||
MOVE.L A2,D0
|
||
BEQ.S @0
|
||
|
||
ADDQ.L #4,A2
|
||
@0
|
||
ADDQ #4,A1
|
||
|
||
BRA.S NextTCP
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
; Here's where we handle the clipped transparent mode rectangle fill
|
||
|
||
UseOld36A
|
||
JMPRom Old36A ; <PB433>
|
||
|
||
|
||
TransFillR
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld36A ;if not, skip
|
||
tst.l d3 ;right to left? <PB427 BAL>
|
||
bmi.s UseOld36A ;if s0, skip <PB427 BAL>
|
||
|
||
; set up the registers and invoke the common scan-line handler
|
||
|
||
MOVE.L A4,A2 ;set up region pointer
|
||
ASR #3,D6 ;bit index to byte index
|
||
MOVE.L A5,A1 ;set up destination
|
||
TransFillLoop
|
||
MOVEQ #-1,D1
|
||
MOVEQ #-1,D3 ;edge masks all ones (edges in region)
|
||
|
||
MOVE.W BUFSIZE(A6),D2 ;set up the count
|
||
ADDQ #4,D2 ;make one based <PB427 BAL>
|
||
LSR.W #2,D2
|
||
SUBQ #1,D2 ;make zero based <PB427 BAL>
|
||
|
||
; call the appropriate handle, depending on whether the pattern is simple or complex
|
||
|
||
CMP.W #8,PATROW(A6) ;is pattern real complex?
|
||
BGT.S @0 ;if so, go handle it
|
||
|
||
TST.B SRCV(A6) ;test pattern mode
|
||
BMI.S @0 ;treat bitmap as complex
|
||
|
||
MOVE.L 0(A3,D6),D0 ;get left pattern
|
||
EOR #4,D6
|
||
CMP.L 0(A3,D6),D0 ;left same as right?
|
||
BEQ.S @1 ;if so, it's simple
|
||
|
||
EOR #4,D6 ;restore D6
|
||
@0
|
||
BSR TransComplex1 ;invoke scan-line handler for complex pats
|
||
BRA.S @2
|
||
@1
|
||
EOR #4,D6
|
||
MOVE.L A3,A0
|
||
BSR TransSimple1
|
||
|
||
; bump pointers to next time, and loop until done
|
||
|
||
@2
|
||
MOVE.W DSTV(A6),D0
|
||
|
||
TST.B SRCV(A6) ;test pattern mode
|
||
BEQ.S TransPat1 ;if zero, handle
|
||
BMI.S TransBitMap1 ;if <0, go handle bitmap
|
||
|
||
MOVE.L HEIGHT(A6),D6 ;get pattern index
|
||
ASR.L #3,D6 ;bit index to byte index
|
||
|
||
; handle bumping the pattern pointers
|
||
|
||
MOVE.L SRCADDR(A6),A3 ;set up pattern pointer
|
||
SUB.W D0,A3
|
||
ADD.W PATROW(A6),D0
|
||
AND.W PATVMASK(A6),D0
|
||
MOVE.W D0,DSTV(A6)
|
||
ADD.W D0,A3
|
||
|
||
BRA.S TransSetPatPtr
|
||
|
||
; handle second type of pattern
|
||
|
||
TransPat1
|
||
MOVE.L HEIGHT(A6),D6 ;get pattern index
|
||
ASR.L #3,D6 ;bit index to byte index
|
||
|
||
ADDQ #1,D0
|
||
AND #15,D0
|
||
LEA ([EXPAT,A6],D0.W*4),A3
|
||
|
||
MOVE.W D0,HEIGHT(A6)
|
||
TransSetPatPtr
|
||
MOVE.L A3,SRCADDR(A6)
|
||
|
||
; bump to the next scan line
|
||
|
||
TransFillNextLine
|
||
MOVE.L DSTROW(A6),D0
|
||
ADD.L D0,DSTADDR(A6)
|
||
|
||
MOVE.W VERT(A6),D0
|
||
ADD.W VBUMP(A6),D0
|
||
MOVE.W D0,VERT(A6)
|
||
|
||
CMP.W LASTV(A6),D0
|
||
BNE.S @0
|
||
|
||
; all done, so strip stack and return
|
||
|
||
MOVE.L SAVESTK2(A6),A7
|
||
RTS
|
||
|
||
; set up registers and loop for the next line
|
||
|
||
@0
|
||
MOVE.L SEEKMASK(A6),A0
|
||
JSR (A0) ;seek new region
|
||
|
||
MOVE.L SRCADDR(A6),A3 ;set up pattern pointer
|
||
MOVE.L DSTADDR(A6),A1 ;set up dest ptr
|
||
MOVE.L RGNADDR(A6),A2 ;set up region ptr
|
||
|
||
BRA TransFillLoop
|
||
|
||
; handle bumping the source if it's a bitmap
|
||
|
||
TransBitMap1
|
||
MOVE.L SRCROW(A6),D0
|
||
;<PB427 BAL>
|
||
ADD.L D0,SRCADDR(A6)
|
||
|
||
MOVE.l HEIGHT(A6),D6
|
||
asr.l #3,d6 ;make byte offset <PB427 BAL>
|
||
BRA.S TransFillNextLine
|
||
|
||
|
||
;******************************************************************************************
|
||
|
||
|
||
UseOld354
|
||
JMPRom Old354 ; <PB433>
|
||
|
||
|
||
TransUnClip
|
||
|
||
CMP.W #8,DSTPIX+PIXELSIZE(A6) ;is it 8 bit mode?
|
||
BNE.S UseOld354 ;if not, skip
|
||
tst.l (sp) ;right to left? <PB427 BAL>
|
||
bmi.s UseOld354 ;if so, skip <PB427 BAL>
|
||
|
||
; set up the registers and invoke the common scan-line handler
|
||
|
||
SUB.L A2,A2 ;no region pointer
|
||
ASR #3,D6 ;bit index to byte index
|
||
MOVE.L A4,A3 ;set up pattern pointer
|
||
MOVE.L A5,A1 ;set up destination
|
||
TransUCLoop
|
||
MOVE.L FIRSTMASK(A6),D3 ;set up left edge
|
||
MOVE.L LASTMASK(A6),D1 ;set up right edge
|
||
|
||
; compute the count from the three pieces: left, mid and right
|
||
|
||
MOVE.W LONGCNT(A6),D2 ;get left count
|
||
BPL.S @3 ;if positive, we're cool
|
||
|
||
MOVEQ #0,D2 ;only one word
|
||
BRA.S @4
|
||
@3
|
||
ADD.W MIDCOUNT(A6),D2 ;add in the middle
|
||
ADD.W PIXINLONG(A6),D2 ;add in the right
|
||
ADDQ.W #2,D2 ;add for count bias
|
||
LSR.W #2,D2 ;bytes -> longs
|
||
|
||
; call the appropriate handle, depending on whether the pattern is simple or complex
|
||
|
||
@4
|
||
CMP.W #8,PATROW(A6) ;is pattern real complex?
|
||
BGT.S @0 ;if so, go handle it
|
||
|
||
TST.B ENDSWITCH(A6) ;test pattern mode
|
||
BMI.S @0 ;if bitmap, handle as complex
|
||
|
||
MOVE.L 0(A3,D6),D0 ;get left pattern
|
||
EOR #4,D6
|
||
CMP.L 0(A3,D6),D0 ;left same as right?
|
||
BEQ.S @1 ;if so, it's simple
|
||
|
||
EOR #4,D6 ;restore D6
|
||
@0
|
||
MOVE.L A1,-(SP)
|
||
BSR TransComplex1 ;invoke scan-line handler for complex pats
|
||
MOVE.L (SP)+,A1
|
||
|
||
BRA.S @2
|
||
@1
|
||
EOR #4,D6
|
||
|
||
MOVEM.L A1/A3,-(SP)
|
||
MOVE.L A3,A0
|
||
BSR TransSimple1
|
||
MOVEM.L (SP)+,A1/A3
|
||
|
||
; bump pointers to next time, and loop until done
|
||
|
||
@2
|
||
TST.B ENDSWITCH(A6) ;test pattern mode
|
||
BEQ.S TransUCPat1 ;if zero, handle
|
||
BMI.S TransUCBitMap1 ;if <0, go handle bitmap
|
||
|
||
; handle bumping the pattern pointers
|
||
|
||
MOVE.W PATPOS(A6),D0
|
||
SUB.W D0,A3
|
||
ADD.W PATROW(A6),D0
|
||
AND.W PATVMASK(A6),D0
|
||
MOVE.W D0,PATPOS(A6)
|
||
ADD.W D0,A3
|
||
|
||
BRA.S TransUCNextLine
|
||
|
||
; handle second type of pattern
|
||
|
||
TransUCPat1
|
||
MOVE.W PATPOS(A6),D0
|
||
ADDQ #1,D0
|
||
AND #15,D0
|
||
LEA ([EXPAT,A6],D0.W*4),A3
|
||
|
||
MOVE.W D0,PATPOS(A6)
|
||
|
||
; bump to the next scan line
|
||
|
||
TransUCNextLine
|
||
MOVE.L PATOFFSET(A6),D6
|
||
ASR.L #3,D6 ;bits to bytes
|
||
TransUCNL2
|
||
ADD.W DSTROW+2(A6),A1 ;bump destination
|
||
|
||
SUBQ.W #1,HEIGHT(A6)
|
||
BNE TransUCLoop
|
||
|
||
ADDQ #4,SP
|
||
RTS
|
||
|
||
; handle unclipped blits source setup
|
||
|
||
TransUCBitMap1
|
||
ADD.W D6,A3
|
||
ADD.W SRCBUMP(A6),A3 ;bump to next line <PB448 DBG>
|
||
MOVEQ #0,D6
|
||
BRA.S TransUCNL2
|
||
|
||
;******************************************************************************************
|
||
|
||
; End of arithmetic transfer modes!
|
||
|
||
;******************************************************************************************
|
||
|
||
; Special BlockMove subroutine optimized for this situation. The source is in A0
|
||
; and dest in A1, with byte count in D0. Note things are already pre-bumped for
|
||
; the MoveRight case. Note that we assume that no move is bigger than 32KBytes,
|
||
; to save a little speed (no scanline is that big!)
|
||
|
||
BlockMove
|
||
|
||
TST.W D5 ;test direction
|
||
BMI MoveRight ;if right, skip
|
||
|
||
; for small moves, all this casing out is a losing battle, so dive in quickly
|
||
|
||
CMP.W #32,D0 ;is it really small?
|
||
BLT.S FinishUpLeft ;if so, finish up last few
|
||
|
||
; make sure the destination is always longword aligned by moving up to 3 bytes
|
||
|
||
MOVE.W A1,D1 ;get destination
|
||
AND.W #3,D1 ;low two bits only
|
||
BEQ.S MediumLeft ;if 0, skip
|
||
|
||
JMP LeftAlign(D1.W*4)
|
||
LeftAlign
|
||
NOP
|
||
NOP
|
||
|
||
MOVE.B (A0)+,(A1)+
|
||
SUBQ #1,D0
|
||
|
||
MOVE.B (A0)+,(A1)+
|
||
SUBQ #1,D0
|
||
|
||
MOVE.B (A0)+,(A1)+
|
||
SUBQ #1,D0
|
||
|
||
; we've got a medium-sized block to move (at least 32), so handle it with an unwound MOVE.L loop
|
||
|
||
MediumLeft
|
||
MOVE.W D0,D1
|
||
LSR.W #5,D1 ;divide by 32
|
||
BRA.S @2
|
||
|
||
@1
|
||
MOVE.L (A0)+,(A1)+ ;move 32 bytes
|
||
MOVE.L (A0)+,(A1)+
|
||
MOVE.L (A0)+,(A1)+
|
||
MOVE.L (A0)+,(A1)+
|
||
MOVE.L (A0)+,(A1)+
|
||
MOVE.L (A0)+,(A1)+
|
||
MOVE.L (A0)+,(A1)+
|
||
MOVE.L (A0)+,(A1)+
|
||
@2
|
||
DBRA D1,@1 ;move it
|
||
|
||
; now we have 31 or less bytes left to move
|
||
|
||
AND #31,D0
|
||
FinishUpLeft
|
||
MOVE.W LOffsetTable(D0.W*2),D0
|
||
JMP LastLeft(D0)
|
||
LastLeft
|
||
|
||
Left1F
|
||
MOVE.L (A0)+,(A1)+
|
||
Left1B
|
||
MOVE.L (A0)+,(A1)+
|
||
Left17
|
||
MOVE.L (A0)+,(A1)+
|
||
Left13
|
||
MOVE.L (A0)+,(A1)+
|
||
LeftF
|
||
MOVE.L (A0)+,(A1)+ ;move next 32 (64 total)
|
||
LeftB
|
||
MOVE.L (A0)+,(A1)+
|
||
Left7
|
||
MOVE.L (A0)+,(A1)+
|
||
Left3
|
||
MOVE.W (A0)+,(A1)+
|
||
Left1
|
||
MOVE.B (A0)+,(A1)+
|
||
Left0
|
||
|
||
DoneBlockMove
|
||
RTS
|
||
Left1E
|
||
MOVE.L (A0)+,(A1)+
|
||
Left1A
|
||
MOVE.L (A0)+,(A1)+
|
||
Left16
|
||
MOVE.L (A0)+,(A1)+
|
||
Left12
|
||
MOVE.L (A0)+,(A1)+
|
||
LeftE
|
||
MOVE.L (A0)+,(A1)+
|
||
LeftA
|
||
MOVE.L (A0)+,(A1)+
|
||
Left6
|
||
MOVE.L (A0)+,(A1)+
|
||
Left2
|
||
MOVE.W (A0)+,(A1)+
|
||
|
||
RTS
|
||
|
||
Left1C
|
||
MOVE.L (A0)+,(A1)+
|
||
Left18
|
||
MOVE.L (A0)+,(A1)+
|
||
Left14
|
||
MOVE.L (A0)+,(A1)+
|
||
Left10
|
||
MOVE.L (A0)+,(A1)+
|
||
LeftC
|
||
MOVE.L (A0)+,(A1)+
|
||
Left8
|
||
MOVE.L (A0)+,(A1)+
|
||
Left4
|
||
MOVE.L (A0)+,(A1)+
|
||
RTS
|
||
Left1D
|
||
MOVE.L (A0)+,(A1)+
|
||
Left19
|
||
MOVE.L (A0)+,(A1)+
|
||
Left15
|
||
MOVE.L (A0)+,(A1)+
|
||
Left11
|
||
MOVE.L (A0)+,(A1)+
|
||
LeftD
|
||
MOVE.L (A0)+,(A1)+
|
||
Left9
|
||
MOVE.L (A0)+,(A1)+
|
||
Left5
|
||
MOVE.L (A0)+,(A1)+
|
||
MOVE.B (A0)+,(A1)+
|
||
RTS
|
||
|
||
LOffsetTable
|
||
DC.W Left0-LastLeft
|
||
DC.W Left1-LastLeft
|
||
DC.W Left2-LastLeft
|
||
DC.W Left3-LastLeft
|
||
DC.W Left4-LastLeft
|
||
DC.W Left5-LastLeft
|
||
DC.W Left6-LastLeft
|
||
DC.W Left7-LastLeft
|
||
DC.W Left8-LastLeft
|
||
DC.W Left9-LastLeft
|
||
DC.W LeftA-LastLeft
|
||
DC.W LeftB-LastLeft
|
||
DC.W LeftC-LastLeft
|
||
DC.W LeftD-LastLeft
|
||
DC.W LeftE-LastLeft
|
||
DC.W LeftF-LastLeft
|
||
DC.W Left10-LastLeft
|
||
DC.W Left11-LastLeft
|
||
DC.W Left12-LastLeft
|
||
DC.W Left13-LastLeft
|
||
DC.W Left14-LastLeft
|
||
DC.W Left15-LastLeft
|
||
DC.W Left16-LastLeft
|
||
DC.W Left17-LastLeft
|
||
DC.W Left18-LastLeft
|
||
DC.W Left19-LastLeft
|
||
DC.W Left1A-LastLeft
|
||
DC.W Left1B-LastLeft
|
||
DC.W Left1C-LastLeft
|
||
DC.W Left1D-LastLeft
|
||
DC.W Left1E-LastLeft
|
||
DC.W Left1F-LastLeft
|
||
|
||
|
||
; Handle the case of moving to the right
|
||
|
||
MoveRight
|
||
CMP.W #32,D0 ;is it really small?
|
||
BLT.S FinishUpRight ;if so, finish up last few
|
||
|
||
; make sure the destination is always longword aligned by moving up to 3 bytes
|
||
|
||
MOVE.W A1,D1 ;get destination
|
||
AND.W #3,D1 ;low two bits only
|
||
|
||
EOR.W #3,D1 ;flip sense
|
||
JMP RightAlign(D1.W*4)
|
||
RightAlign
|
||
MOVE.B -(A0),-(A1)
|
||
SUBQ #1,D0
|
||
|
||
MOVE.B -(A0),-(A1)
|
||
SUBQ #1,D0
|
||
|
||
MOVE.B -(A0),-(A1)
|
||
SUBQ #1,D0
|
||
|
||
; we've got a medium-sized block to move (at least 32), so handle it with an unwound MOVE.L loop
|
||
|
||
MediumRight
|
||
MOVE.W D0,D1
|
||
LSR.W #5,D1 ;divide by 32
|
||
BRA.S @2
|
||
@1
|
||
MOVE.L -(A0),-(A1) ;move 32 bytes
|
||
MOVE.L -(A0),-(A1)
|
||
MOVE.L -(A0),-(A1)
|
||
MOVE.L -(A0),-(A1)
|
||
MOVE.L -(A0),-(A1)
|
||
MOVE.L -(A0),-(A1)
|
||
MOVE.L -(A0),-(A1)
|
||
MOVE.L -(A0),-(A1)
|
||
@2
|
||
DBRA D1,@1 ;move the bulk of it
|
||
|
||
; now we have 31 or less bytes left to move
|
||
|
||
AND #31,D0
|
||
FinishUpRight
|
||
MOVE.W ROffsetTable(D0.W*2),D0
|
||
;+++ JMP LastRight(D0)
|
||
JMP (QGLastRight,PC,D0) ; this is a hack - this JMP must be immediately before the table
|
||
QGLastRight
|
||
|
||
Right1F
|
||
MOVE.L -(A0),-(A1)
|
||
Right1B
|
||
MOVE.L -(A0),-(A1)
|
||
Right17
|
||
MOVE.L -(A0),-(A1)
|
||
Right13
|
||
MOVE.L -(A0),-(A1)
|
||
RightF
|
||
MOVE.L -(A0),-(A1) ;move next 32 (64 total)
|
||
RightB
|
||
MOVE.L -(A0),-(A1)
|
||
Right7
|
||
MOVE.L -(A0),-(A1)
|
||
Right3
|
||
MOVE.W -(A0),-(A1)
|
||
Right1
|
||
MOVE.B -(A0),-(A1)
|
||
Right0
|
||
RTS
|
||
Right1E
|
||
MOVE.L -(A0),-(A1)
|
||
Right1A
|
||
MOVE.L -(A0),-(A1)
|
||
Right16
|
||
MOVE.L -(A0),-(A1)
|
||
Right12
|
||
MOVE.L -(A0),-(A1)
|
||
RightE
|
||
MOVE.L -(A0),-(A1)
|
||
RightA
|
||
MOVE.L -(A0),-(A1)
|
||
Right6
|
||
MOVE.L -(A0),-(A1)
|
||
Right2
|
||
MOVE.W -(A0),-(A1)
|
||
|
||
RTS
|
||
|
||
Right1C
|
||
MOVE.L -(A0),-(A1)
|
||
Right18
|
||
MOVE.L -(A0),-(A1)
|
||
Right14
|
||
MOVE.L -(A0),-(A1)
|
||
Right10
|
||
MOVE.L -(A0),-(A1)
|
||
RightC
|
||
MOVE.L -(A0),-(A1)
|
||
Right8
|
||
MOVE.L -(A0),-(A1)
|
||
Right4
|
||
MOVE.L -(A0),-(A1)
|
||
|
||
RTS
|
||
Right1D
|
||
MOVE.L -(A0),-(A1)
|
||
Right19
|
||
MOVE.L -(A0),-(A1)
|
||
Right15
|
||
MOVE.L -(A0),-(A1)
|
||
Right11
|
||
MOVE.L -(A0),-(A1)
|
||
RightD
|
||
MOVE.L -(A0),-(A1)
|
||
Right9
|
||
MOVE.L -(A0),-(A1)
|
||
Right5
|
||
MOVE.L -(A0),-(A1)
|
||
MOVE.B -(A0),-(A1)
|
||
|
||
RTS
|
||
|
||
ROffsetTable
|
||
DC.W Right0-QGLastRight
|
||
DC.W Right1-QGLastRight
|
||
DC.W Right2-QGLastRight
|
||
DC.W Right3-QGLastRight
|
||
DC.W Right4-QGLastRight
|
||
DC.W Right5-QGLastRight
|
||
DC.W Right6-QGLastRight
|
||
DC.W Right7-QGLastRight
|
||
DC.W Right8-QGLastRight
|
||
DC.W Right9-QGLastRight
|
||
DC.W RightA-QGLastRight
|
||
DC.W RightB-QGLastRight
|
||
DC.W RightC-QGLastRight
|
||
DC.W RightD-QGLastRight
|
||
DC.W RightE-QGLastRight
|
||
DC.W RightF-QGLastRight
|
||
DC.W Right10-QGLastRight
|
||
DC.W Right11-QGLastRight
|
||
DC.W Right12-QGLastRight
|
||
DC.W Right13-QGLastRight
|
||
DC.W Right14-QGLastRight
|
||
DC.W Right15-QGLastRight
|
||
DC.W Right16-QGLastRight
|
||
DC.W Right17-QGLastRight
|
||
DC.W Right18-QGLastRight
|
||
DC.W Right19-QGLastRight
|
||
DC.W Right1A-QGLastRight
|
||
DC.W Right1B-QGLastRight
|
||
DC.W Right1C-QGLastRight
|
||
DC.W Right1D-QGLastRight
|
||
DC.W Right1E-QGLastRight
|
||
DC.W Right1F-QGLastRight
|
||
|
||
EndQPatches
|
||
|
||
|
||
PRINT OFF
|