mac-rom/QuickDraw/DrawLine.a
Elliot Nunn 0ba83392d4 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-09-20 18:04:16 +08:00

1780 lines
55 KiB
Plaintext

;
; File: DrawLine.a
;
; Copyright: © 1981-1990, 1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM2> 6/11/92 stb <sm 6/9/92>stb Synched with QDciPatchROM.a; added comments to
; DrawLine, SkipSetup, FASTLINE, HTOGL, VLINE, FASTSLANT.
; <8> 12/13/90 SMC Refixed <7>. With KON.
; <7> 11/26/90 SMC Fixed call to StretchBits to use locmode with pattern bit
; forced. PnMode was being used. With BAL.
; <6> 10/31/90 SMC Fixed alpha channel bugs with BAL.
; <5> 9/17/90 BG Removed <3>. 040s are now behaving more reliably.
; <4> 7/20/90 gbm Change some identifiers to cease conflicting with interface
; files
; <3> 6/26/90 BG Added EclipseNOPs for flakey 040s.
; <2> 2/13/90 BAL Ensure that the initial bit offset is calculated in a long
; instead of a word so that lines drawn into really wide pixmaps
; don't freak out.
; <¥1.6> 7/14/89 BAL For Aurora: Final CQD
; <1.5> 6/30/89 BAL Cleared runBuf(a6) before calling getSeek
; <¥1.4> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
; <¥1.3> 4/12/89 BAL Blasting in 32-Bit QuickDraw 1.0B1
; 1/22/89 BAL Made patVPos a long.
; 9/22/88 BAL Moved initialization of region state records into GetSeek.
; 9/19/88 BAL Altered to use common stack frame file 'Drawing Vars.a'
; 9/18/88 BAL Altered to get CRSRFLAG value from _BitsToPix; Removed
; references to PIXSRC;
; 11/8/87 BAL Fixed computation of bufSize for more accurate region clipping
; at at depths greater than 1. <C954>
; 11/7/87 BAL Fixed ChkPat to handle new patterns. <C945>
; 6/4/87 CRC preserve hilite mode across calls to colormap; set patmode in
; case user forgot
; 1/3/87 CRC pass color param to stretch
; 12/12/86 CRC Added support for arithmetic modes
; 10/9/86 EHB Added mask parameters to stretchbits calls
; 7/29/86 EHB Allocate EXPAT buffer on stack so long aligned
; 7/26/86 EHB Added support for expanded patterns
; 7/22/86 EHB Pass MODE to PatExpand
; 7/5/86 EHB Replaced SeekMask and GetXRtn with GetMask
; 6/20/86 EHB New params to COLORMAP; Added FCOLOR and BCOLOR to stack frame
; 6/18/86 EHB Call StretchBits instead of RgnBlt
; 6/15/86 EHB Make sure stack is longword aligned (for fast buffers); If one
; 1-bit region, play directly into RGNBUFFER Convert BitsToPix and
; use pixelSize
; 6/14/86 EHB Call GetXRtn to set expand routine for SeekMask; Added DSTPIX to
; stack frame
; 6/13/86 EHB Updated SeekMask to check rgn changed flag Moved SeekMask to
; another file; Rearranged stack frame with SeekMask stuff at top
; 6/10/86 EHB Modified to use 32-bit DrawSlab
; 6/5/86 EHB Clear flag bits from all references to rowBytes
BLANKS ON
STRING ASIS
MACHINE MC68020
;-----------------------------------------------------------------
;
; --> DRAWLINE.TEXT
;
;------------------------------------------------------------------
DrawLine PROC EXPORT
IMPORT SHFTTBL
Export steepBlitTab,shallowBlitTab,FastLine,FastSlant
;----------------------------------------------------------------
;
; PROCEDURE DRAWLINE(P1,P2: POINT);
;
; DRAWS A LINE CLIPPED TO CURRENT PORT'S CLIPRGN AND VISRGN
;
; P1 AND P2 ARE GIVEN IN LOCAL COORDINATES OF THEPORT.
;
;------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE EQU 8 ;SIZE OF PARAMETERS
P1 EQU PARAMSIZE+8-4 ;POINT
P2 EQU P1-4 ;POINT
;-------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
; STACK FRAME VARS USED BY SEEKMASK (CALLED BY STRETCHBITS, RGNBLT, DRAWARC, DRAWLINE)
;
&CurFile SETC 'DRAWLINE'
INCLUDE 'DrawingVars.a'
;-------------------------------------------------
; includes fixes as seen in QDciPatchROM.a <sm 6/9/92>stb
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARS
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER
MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR
CLR.L DSTMASKBUF(A6) ;ASSUME NO MASK
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L WIDEOPEN(A0),BIGRGN(A6) ;STASH WIDEOPEN IN BIGRGN
MOVE.L THEPORT(A0),A3 ;POINT TO CURRENT GRAFPORT
TST PNVIS(A3) ;IS PNVIS NEGATIVE ?
BLT GOHOME ;YES, QUIT
MOVE.W PNMODE(A3),D1 ;get pen mode Start of <7>
_GetStreamMode ;strip off alpha bits
;this code moved up here from below at SET UP NEWPATTERN TO INDICATE OLD OR NEW STYLE PATTERN
BSET #3,D1 ;set the pattern bit in case the user forgot to
MOVEQ #$10,D0 ;1 past normal mode range
BTST #5,D1 ;arithmetic mode?
BEQ.S @noRith
CMP #$3A,D1 ;hilite?
BEQ.S @ok
MOVEQ #$30,D0 ;1 past arithmetic mode range
@noRith CMP D0,D1 ;greater than defined range?
BGT GOHOME
@ok MOVE D1,LOCMODE(A6) ;copy mode for colormap End of <7>
MOVE.L A3,PORT(A6) ;SAVE PORT FOR LATER
;----------------------------------------------------------------
;
; MAKE SURE THE STACK IS ON A LONGWORD BOUNDARY (FOR FAST BUFFERS)
;
MOVE.L SP,D1 ;GET THE STACK POINTER
AND.B #$FC,D1 ;FORCE LONG ALIGNMENT
MOVE.L D1,SP ;USE IT
;----------------------------------------------------
;
; CONVERT DSTBITS TO PIXMAP
; (A5 must contain global ptr)
;
LEA PORTBITS(A3),A1 ;GET POINTER TO DSTBITS
LEA DSTPIX(A6),A2 ;USE DSTPIX IN ITS PLACE
_BitsToPix ;CONVERT BITMAP
MOVE.L D1,REALBOUNDS(A6) ;SAVE REAL DST BOUNDS.TOPLEFT
MOVE.B D2,CRSRFLAG(A6) ;REMEMBER IF DST IS SCREEN <BAL 18Sep88>
;----------------------------------------------------
;
; CONVERT PIXEL DEPTH TO SHIFT AMOUNT TO AVOID MULTIPLIES
;
LEA SHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE DSTPIX+PIXELSIZE(A6),D0 ;GET DST PIXEL SIZE
MOVEQ #0,D1 ;DEFAULT SHIFT = 0
MOVE.B 0(A0,D0),D1 ;GET SRC SHIFT
MOVE D1,DSTSHIFT(A6) ;AND SAVE DST SHIFT AMOUNT
;----------------------------------------------------------------
;
; SET UP NEWPATTERN TO INDICATE OLD OR NEW STYLE PATTERN
; ALSO SET UP LOCAL PATTERN POINTER, LOCPAT(A6)
;
LEA PNPAT(A3),A0 ;POINT TO THE PATTERN
MOVE.L A0,LOCPAT(A6) ;COPY PATTERN POINTER
TST PORTBITS+ROWBYTES(A3) ;IS THE DST OLD OR NEW?
;ciDrawLine from QDciPatchROM.a used to be right here
SMI NEWPATTERN(A6) ;FLAG = TRUE IF NEW PATTERN
;-------------------------------------------------------
;
; Check for color filtering. Alter mode and pattern accordingly.
;
MOVE.B HiliteMode,-(SP) ;preserve the hilite mode
CLR.B multiColor(A6) ;use fg/bg color
_COLORMAP ;CHECK AGAINST THECOLOR, THEFILTER
MOVE.B (SP)+,HiliteMode ;since stretch (and thus ColorMap) may be called later
;---------------------------------------------------------
;
; GET CLIPRGN AND VISRGN HANDLES AND DE-REFERENCE THEM
;
MOVE.L A3,A5 ;PUT GRAFPTR IN A5
MOVE.L CLIPRGN(A5),A2 ;GET CLIPRGN HANDLE
MOVE.L (A2),A2 ;GET CLIPRGN POINTER
MOVE.L VISRGN(A5),A3 ;GET VISRGN HANDLE
MOVE.L (A3),A3 ;GET VISRGN POINTER
;-------------------------------------------------------------
;
; SET UP LINERECT, THE RECTANGLE BOUNDING THE LINE AND PEN
;
MOVEM.W P2(A6),D1/D2/D3/D4 ;GET D1=V1, D2=H1, D3=V2, D4=H2
CMP D3,D1 ;IS V1 > V2 ?
BLE.S VOK2 ;NO, CONTINUE
EXG D1,D3 ;YES, SWAP VERT
VOK2 CMP D4,D2 ;IS H1 > H2 ?
BLE.S HOK2 ;NO, CONTINUE
EXG D2,D4 ;NO SWAP HORIZ
HOK2 ADD PNSIZE+H(A5),D4 ;ADD PEN WIDTH TO RIGHT
ADD PNSIZE+V(A5),D3 ;ADD PEN HEIGHT TO BOTTOM
MOVEM.W D1/D2/D3/D4,LINERECT(A6) ;STORE TOP, LEFT, BOTTOM, RIGHT
;-----------------------------------------------------------------------
;
; CALC MINRECT, THE INTERSECTION OF LINERECT, BITMAP BOUNDS,
; CLIPRGN BBOX, AND VISRGN BBOX. QUIT IF NO INTERSECTION.
;
PEA LINERECT(A6) ;PUSH LINE RECT
PEA DSTPIX+BOUNDS(A6) ;PUSH PIXMAP BOUNDS
PEA RGNBBOX(A2) ;PUSH CLIPRGN BBOX
PEA RGNBBOX(A3) ;PUSH VISRGN BBOX
MOVE #4,-(SP) ;PUSH NRECTS=4
PEA MINRECT(A6) ;PUSH DST ADDR
_RSECT ;CALC INTERSECTION
BEQ GOHOME ;QUIT IF NO INTERSECT
;-----------------------------------------------------------
;
; HIDE CURSOR IF CURSOR INTERSECTS MINRECT AND DST IS SCREEN.
; (A5 must contain global ptr)
;
MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? <BAL 19Sep88>
BEQ.S NOTSCRN ;=>NO
PEA MINRECT(A6) ;PUSH SHIELDRECT PARAMETER
MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL
_SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
NOTSCRN MOVE.L PORT(A6),A5 ;GET BACK THEPORT
;-----------------------------------------------------------
;
; CHECK FOR BOTH VISRGN AND CLIPRGN RECTANGULAR
;
CLR.B FASTFLAG(A6) ;FASTFLAG := FALSE
CMP #10,RGNSIZE(A2) ;IS CLIPRGN RECTANGULAR ?
BNE.S FLAGOK ;NO, CONTINUE
CMP #10,RGNSIZE(A3) ;IS VISRGN RECTANGULAR ?
BEQ.S CKPAT ;YES, CONTINUE
;-----------------------------------------------------------
;
; If only visRgn is non-rectangular, then check if
; its intersection with minrect would be rectangular.
; IF TrimRect(visRgn,minRect) then treat as rectangular.
;
MOVE.L visRgn(A5),-(SP) ;push rgnHandle
PEA minRect(A6) ;push addr of minRect
MOVE.W #-1,-(SP) ;pass Trim = True
_TrimRect ;call trimRect
BLT show ;quit if intersection empty
BGT.S FLAGOK ;continue if non-rectangular
;-----------------------------------------------------------
;
; CHECK FOR BLACK OR WHITE PATTERN
;
CKPAT BTST #5,LocMode+1(A6) ;an arithmetic mode?
BNE.S FlagOK ;skip fast case if so
MOVE.L LOCPAT(A6),A0 ;POINT TO PATTERN
TST.B NEWPATTERN(A6) ;is it a new pattern? <C945 07Nov87 BAL>
BEQ.S @oldPat ;=>no, skip pixpat fields <C945 07Nov87 BAL>
MOVE.L (a0),a0 ;get the pixpat handle <C945 07Nov87 BAL>
MOVE.L (a0),a0 ;get the pixpat pointer <C945 07Nov87 BAL>
TST PATTYPE(A0) ;is it an old-style pattern? <C945 07Nov87 BAL>
BNE.S FLAGOK ;=>no, skip fast case <C945 07Nov87 BAL>
MOVE.L patData(a0),a0 ;get handle to pattern data <C945 07Nov87 BAL>
MOVE.L (a0),a0 ;get pattern ptr <C945 07Nov87 BAL>
@oldPat MOVE.L (A0)+,D0 ;GET 1ST HALF OF PATTERN
CMP.L (A0)+,D0 ;IS IT SAME AS 2ND HALF ?
BNE.S FLAGOK ;NO, CONTINUE
NOT.L D0 ;IS PATTERN BLACK ?
BEQ.S YESFLAG ;YES, WE MADE IT
NOT.L D0 ;IS PATTERN WHITE ?
BNE.S FLAGOK ;NO, CONTINUE
EOR #4,LOCMODE(A6) ;YES, ALTER MODE AS IF BLACK
YESFLAG ST FASTFLAG(A6) ;RECT CLIPPED AND BLACK
;-----------------------------------------------------------
;
; fast case: map mode into black,xor,white, or do-nothing
;
MOVEQ #7,D0 ;GET 3 BIT MASK
AND LOCMODE(A6),D0 ;GET 3 BITS OF MODE
MOVE.B MODEMAP(D0),D0 ;MAP TO BLACK,XOR,WHITE,NOP
BMI show ;QUIT IF DO-NOTHING MODE
MOVE D0,LOCMODE(A6) ;UPDATE MODE
BRA.S FLAGOK ;AND CONTINUE
MODEMAP DC.B 0,0,1,2,2,255,255,255
FLAGOK
;-----------------------------------------------------------
;
; GET THE TWO LINE ENDPOINTS INTO REGISTERS
; AND CHECK FOR HORIZONTAL OR VERTICAL LINE
;
MOVEM.W P2(A6),D1/D2/D3/D4 ;GET D1=V2, D2=H2, D3=V1, D4=H1
CMP D2,D4 ;H1=H2 ?
BEQ.S HVLINE ;YES, DO VERTICAL LINE
CMP D1,D3 ;NO, IS V2 > V1 ?
BGT.S SLANTED ;YES, DRAW SLANTED LINE
BLT.S VSWAP ;SWAP POINTS AND DRAW SLANTED
;ELSE V1=V2, DO HORIZONTAL
;-----------------------------------------------------------
;
; LINE IS EITHER HORIZONTAL OR VERTICAL.
; CHECK FOR ONE DOT LINE, BLACK OR WHITE PATTERN, AND
; CLIPRGN AND VISRGN BOTH RECTANGULAR. IF SO, OPTIMIZE FAST LINES.
;
HVLINE TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
BEQ.S NOTFAST ;NO, CONTINUE
CMP.L #$00010001,PNSIZE(A5) ;IS PEN 1 BY 1 ?
bne.s NotFast ;NO, CONTINUE
_FastLineJmp ;YES, DO IT FAST !
;--------------------------------------------------------------------
;
; NOT FASTLINE. PUSH PARAMS AND CALL STRETCHBITS FOR HORIZ OR VERT LINE.
;
NOTFAST PEA PORTBITS(A5) ;PUSH SRCBITS = PORTBITS
CLR.L -(SP) ;NO MASKBITS
PEA PORTBITS(A5) ;PUSH DSTPIX
PEA MINRECT(A6) ;PUSH SRCRECT = DSTRECT
CLR.L -(SP) ;NO MASKRECT
PEA MINRECT(A6) ;PUSH DSTRECT
MOVE PNMODE(A5),D0 ;GET MODE <8>
AND #$FCFF,D0 ;STRIP SOME BITS <8>
BSET #3,D0 ;set the pattern bit in case the user forgot to <8>
MOVE D0,-(SP) ;PUSH CLEANED MODE <8>
PEA PNPAT(A5) ;PUSH PATTERN
MOVE.L CLIPRGN(A5),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A5),-(SP) ;PUSH VISRGN HANDLE
MOVE.L BIGRGN(A6),-(SP) ;PUSH SAVED WIDEOPEN
MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
CLR -(SP) ;pass multicolor flag false
_STRETCHBITS ;DRAW THE HORIZ OR VERT LINE
BRA show ;RESTORE CURSOR AND QUIT
;-------------------------------------------------------------
;
; THE LINE IS SLANTED. SORT VERTICALLY
; AND DRAW TOP TO BOTTOM AS HORIZONTAL SLABS.
;
VSWAP EXG D1,D3 ;SORT POINTS BY VERTICAL
EXG D2,D4 ;SWAP HORIZ TO MATCH
SLANTED MOVE D3,D0 ;COPY LINE BOTTOM
ADD PNSIZE+V(A5),D0 ;ADD PEN HEIGHT
CMP minRect+TOP(A6),D0 ;IS RESULT <= minRect TOP ? <07Jul89>
BLE show ;YES, RESTORE CURSOR AND QUIT
CMP minRect+BOTTOM(A6),D1 ;IS TOP >= minRect BOTTOM ? <07Jul89>
BGE show ;YES, RESTORE CURSOR AND QUIT
;-------------------------------------------------------------
;
; SET UP INITIAL FIXED POINT LEFTEDGE AND RIGHTEDGE
; AND CHECK FOR ZERO PENSIZE.
;
MOVE.W D2,LEFTEDGE(A6) ;LEFTEDGE.INT := TOP HORIZ
MOVE.W #$8000,LEFTEDGE+2(A6) ;LEFTEDGE.FRACT := 1/2
MOVE.L LEFTEDGE(A6),RIGHTEDGE(A6) ;RIGHTEDGE:=LEFTEDGE
MOVE PNSIZE+H(A5),D0 ;GET PEN WIDTH
BLE show ;QUIT IF PENWIDTH <= 0
ADD.W D0,RIGHTEDGE(A6) ;ADD TO RIGHTEDGE.INT
MOVE PNSIZE+V(A5),D6 ;GET PEN HEIGHT
BLE show ;QUIT IF PEN HEIGHT <= 0
;----------------------------------------------------
;
; CALC FIXED POINT SLOPE = FixRatio(dh,dv);
;
SUB D2,D4 ;CALC DH
SUB D1,D3 ;CALC DV
ext.l D3
moveq #0,d7 ;clear out high word
move.w d4,d7 ;copy DH to d7
swap D7
DIVS.l D3,D7 ;CALC FIXED POINT SLOPE DH/DV
MOVE.L D7,SLOPE(A6) ;SAVE FOR LATER
;
; CALC adjust := pen height * slope
;
move.l d7,d5 ;assume height is 1
cmp.w #1,d6 ;is pen height 1
beq.s @gotAdjust
ext.l d6
MULS.L d6,d5 ;CALC FixMul(pnSize.v,slope)
@gotAdjust
;
; ADJUST LEFTEDGE AND RIGHTEDGE DEPENDING ON SIGN AND MAGNITUDE OF SLOPE
; Set steepFlag in A2: 0->shallow; 1->down&right; -1->down&left
sub.l a2,a2 ;assume shallow
MOVE.L D7,D0 ;COPY SLOPE
ASR.L #1,D0 ;CALC SLOPE/2
ADD.L D0,LEFTEDGE(A6) ;ADD SLOPE/2 TO LEFT EDGE
ADD.L D0,RIGHTEDGE(A6) ;ADD SLOPE/2 TO RIGHT EDGE
TST.L D7 ;IS SLOPE NEGATIVE ?
BMI.S NEGSLOPE ;YES, CONTINUE
SUB.L D5,LEFTEDGE(A6) ;SUBTRACT ADJUST FROM LEFTEDGE
CMP.L #$00010000,D7 ;IS SLOPE < ONE ?
BGT.S LESSV1 ;NO, BRANCH
BEQ.S Pos45 ;NO, BRANCH
MOREV1 ADD.L D7,LEFTEDGE(A6) ;ADD SLOPE TO LEFTEDGE
addq #1,a2 ;remember steep and to right
BRA.S SLOPEOK ;CONTINUE
Pos45 addq #1,a2 ;remember 45¡
LESSV1 SUB.W #1,RIGHTEDGE(A6) ;RIGHTEDGE := RIGHTEDGE - 1
BRA.S SLOPEOK ;CONTINUE
;----------------------------------------------------
;
; SLOPE IS NEGATIVE
;
NEGSLOPE SUB.L D5,RIGHTEDGE(A6) ;SUBTRACT ADJUST FROM RIGHTEDGE
CMP.L #$FFFF0000,D7 ;IS SLOPE > -ONE ?
BLT.S LESSV2 ;NO, CONTINUE
MOREV2 ADD.L D7,RIGHTEDGE(A6) ;ADD SLOPE TO RIGHTEDGE
subq #1,a2 ;remember steep and to left
BRA.S SLOPEOK
LESSV2 ADD.W #1,LEFTEDGE(A6) ;LEFTEDGE := LEFTEDGE + 1
SLOPEOK MOVEM.W MINRECT(A6),D1/D2/D3/D4 ;GET MINRECT TOP,LEFT,BOTTOM,RIGHT
;
; ADJUST LEFTEDGE AND RIGHTEDGE IF LINE WAS CLIPPED VERTICALLY
;
CMP LINERECT+TOP(A6),D1 ;DID TOP GET CLIPPED ?
BEQ.S TOPOK ;NO, CONTINUE
MOVE D1,D0
SUB LINERECT+TOP(A6),D0 ;CALC DISCARD AMOUNT
EXT.L D0 ;MAKE IT LONG
MOVE.L D7,D5 ;GET 32 BIT SLOPE
MULS.L D0,D5 ;SLOPE * SCANS CLIPPED
ADD.L D5,LEFTEDGE(A6) ;BUMP LEFTEDGE TO NEW TOP
ADD.L D5,RIGHTEDGE(A6) ;BUMP RIGHTEDGE TO NEW TOP
;-----------------------------------------------------------
;
; LINE IS SLANTED. IF |SLOPE| <= 1 THEN
; CHECK FOR ONE DOT LINE, BLACK OR WHITE PATTERN, AND CLIPRGN
; AND VISRGN BOTH RECTANGULAR. IF SO THEN OPTIMIZE.
;
TOPOK
; bchg #0,0 ;debugging code
; beq.s CalcBufLeft
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
BEQ.S CalcBufLeft ;NO, CONTINUE
cmp.w LINERECT+left(a6),D2 ;is MinRect.Left>Line's left edge?
bgt.s CalcBufLeft ;horizontally clipped!
cmp.w LINERECT+right(a6),D4 ;is MinRect.Right<Line's right edge?
blt.s CalcBufLeft ;horizontally clipped!
CMP.L #$00010001,PNSIZE(A5) ;IS PEN 1 BY 1 ?
bne.s CalcBufLeft ;no, continue
_FastSlantJmp ;YES, DO IT FAST !
;Assumes: D1,D2,D3,D4 = MinRect T,L,B,R
; D7 = slope (16.16)
CalcBufLeft
;-----------------------------------------------------------
;
; CALC BUFLEFT
;
;D2 = MINRECT LEFT
MOVE DSTSHIFT(A6),D5 ;GET SHIFT FOR PIXEL DEPTH
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT TO GLOBAL COORDS
ext.l d2 ;make it a long <BAL 17Jan89>
LSL.l D5,D2 ;CONVERT PIXELS TO BITS
AND.l #~$1f,D2 ;TRUNC TO MULT OF 32 BITS
MOVE.l D2,D1 ;GET BUFLEFT IN BITS
LSR.l #3,D1 ;CONVERT BITS TO BYTES
MOVE D1,PATHPOS(A6) ;AND SAVE AS HORIZONTAL PATTERN BASE
LSR.l D5,D2 ;CONVERT BITS TO PIXELS
ADD DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BACK TO GLOBAL
MOVE D2,BUFLEFT(A6) ;SAVE AS BUFLEFT
;
; IF FASTFLAG, THEN SKIP REGION SETUP
;
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
BNE SKIPSETUP ;YES, DON'T WASTE TIME WITH SETUP
;_________________________________________________________________________________________
;
; CALC expansion buffer = [ (minRect.right-minRect.left) div 32 + 1 ] * pixelsize - 1
; CALC bufSize = [ (minRect.right-minRect.left) * pixelsize - 1 ] div 32 <C954> 08Nov87 BAL
;
;D4 = MINRECT RIGHT
SUB D2,D4 ;CALC MAXH-BUFLEFT
move d4,d0 ;save for expansion scanline buffer <C954>
ext.l d4 ;clear out high word <C954>
lsl.l d5,d4 ;convert to bits <C954>
subq.l #1,d4 ;force downward round <C954>
LSR.l #5,D4 ;GET NUMBER OF LONGS IN SCANBUF - 1 <C954>
MOVE D4,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 <C954>
LSR #5,D0 ;get (pixels in scanbuf)/32 <C954>
ADDQ #1,D0 ;MAKE IT ONE BASED
LSL D5,D0 ;CONVERT PIXELS TO BITS
SUBQ #1,D0 ;MAKE 0 BASED AGAIN
;
; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK
;
CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR ONE LONG
DBRA D0,CLRMASK ;LOOP TILL DONE
MOVE.L SP,RGNBUFFER(A6) ;REMEMBER WHERE RGNBUFFER IS
;--------------------------------------------------------------------
;
; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION
; GET SEEK ROUTINE INTO SEEKMASK(A6)
; GET EXPAND ROUTINE INTO EXRTN(A6) FOR SEEK ROUTINE
; Clobbers: A0-A3, D0-D4
;
lea Show,a0 ;get go home routine
move.l a0,goShow(a6) ;pass to getSeek <BAL 21Mar89>
move.l maskbc,StackFree(a6) ;pretend lots of stack <BAL 21Mar89>
clr.l DstRow(a6) ;flag as seeking down
clr.l runBuf(a6) ;don't use run clipping <1.5> BAL
MOVE.L VISRGN(A5),-(SP) ;PUSH VIS RGNHANDLE
MOVE.L CLIPRGN(A5),-(SP) ;PUSH CLIP RGNHANDLE
MOVE.L #1,-(SP) ;PUSH HANDLE COUNT - 1
_GETSEEK ;GET EXPAND ROUTINE INTO EXRTN(A6)
;AND SEEK ROUTINE INTO SEEKMASK(A6)
SKIPSETUP
;------------------------------------
;
; CALC STARTING DSTLEFT
;
;Êas seen in QDciPatchROM.a at TryLine, fixes both patches on _FastSlabMode and _GetSeek <sm 6/9/92>stb
MOVE MINRECT+TOP(A6),D1
SUB DSTPIX+BOUNDS+TOP(A6),D1 ;CONVERT MINV TO GLOBAL COORDS
MOVE DSTPIX+ROWBYTES(A6),D0 ;get dst rowbytes
AND #nuRBMask,D0 ;clear off flag bits
MOVE D0,DSTROW(A6) ;SAVE FOR LATER
MULS D0,D1 ;MULT BY DST ROWBYTES; BAL 02Dec88
ADD.L DSTPIX+BASEADDR(A6),D1 ;ADD START OF BITMAP
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT BUFLEFT TO GLOBAL
ext.l d2 ;clear out high end <BAL 13Feb90>
MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT
LSL.L D7,D2 ;CONVERT PIXELS TO BITS <BAL 13Feb90>
LSR.L #3,D2 ;CONVERT BITS TO BYTES <BAL 13Feb90>
; EXT.L D2 ;CLR HI WORD <BAL 13Feb90>
ADD.L D2,D1 ;ADD HORIZ BYTE OFFSET
MOVE.L D1,DSTLEFT(A6) ;SAVE AS DSTLEFT
;----------------------------------------------------
;
; MAKE LEFTEDGE,RIGHTEDGE,MINRECT RELATIVE TO BUFFER LEFT
;
MOVE BUFLEFT(A6),D1
SUB.W D1,LEFTEDGE(A6) ;ADJUST LEFTEDGE.INT
SUB.W D1,RIGHTEDGE(A6) ;ADJUST RIGHTEDGE.INT
SUB D1,MINRECT+LEFT(A6)
SUB D1,MINRECT+RIGHT(A6)
;------------------------------------------------------------
;
; TAKE FAST OR SLOW OUTER CONTROL LOOP FOR SLANTED LINES:
;
TST.B fastFlag(A6) ;ARE WE RECT CLIPPED BLACK ?
BEQ.S GOSLOW ;NO, CONTINUE
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
_FastSlabMode ;Get fast case jump in A4
LEA MINRECT(A6),A3 ;POINT TO MINRECT
MOVE.L SLOPE(A6),D7 ;GET FIXED POINT SLOPE
MOVE.L DSTLEFT(A6),A5 ;GET DSTLEFT
MOVE.L FCOLOR(A6),D4 ;PASS FCOLOR
MOVE.L BCOLOR(A6),D5 ;AND BACKCOLOR
MOVE MINRECT+BOTTOM(A6),D6 ;GET MINRECT BOTTOM
SUB MINRECT+TOP(A6),D6 ;CALC HEIGHT
SUB #1,D6 ;MINUS 1 FOR DBRA COUNT
;-----------------------------------------------------------
;
; Switch to 32 bit addressing mode
;
moveq #true32b,d0 ;switch to 32 bit addressing
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.b d0,MMUsave(a6) ;save previous state for later
NXTFAST MOVE.W LEFTEDGE(A6),D1 ;GET LEFTEDGE.INT
MOVE.W RIGHTEDGE(A6),D2 ;GET RIGHTEDGE.INT
MOVE.L A5,A1 ;INIT DSTPTR TO LEFT
MOVE.W DSTSHIFT(A6),D0 ;GET PIXEL TO BIT SHIFT AMOUNT
_DrawSlab ;DRAW ONE SLAB IN PENMODE
ADD DSTROW(A6),A5 ;BUMP DST TO NEXT ROW
ADD.L D7,LEFTEDGE(A6) ;ADD SLOPE TO LEFT EDGE
ADD.L D7,RIGHTEDGE(A6) ;ADD SLOPE TO RIGHT EDGE
DBRA D6,NXTFAST ;LOOP FOR ALL SCANLINES
BRA DONE ;AND QUIT
GOSLOW
;------------------------------------------------------------------
;
; SET INVERSE FLAG AND CALL PATEXPAND TO EXPAND PATTERN
;
CLR.L D7 ;SAY NOT INVERTED
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
BTST #5,D2 ;a new arithmetic mode?
BNE.S NOTINV ;if so, no invert bit to test
BCLR #2,D2 ;TEST AND CLR INVERT BIT
BEQ.S NOTINV ;SKIP IF NOT INVERTED
NOT.L D7 ;INVERTED; D7 GETS ALL 1'S
NOTINV MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
_PATEXPAND ;EXPAND 8 BYTES TO 16 LONGS
;SETUP PATROW,PATHMASK,PATVMASK
MOVE PATROW(A6),D1 ;GET THE PATTERN ROWBYTES
BNE.S DONEW ;=>NON-ZERO, IT'S A NEW PATTERN
MOVEQ #$F,D6 ;ELSE 16 ROWS OF PATTERN
MOVEQ #$4,D1 ;GET PATTERN ROWBYTES INTO D1
MOVE D1,PATROW(A6) ;AND SET PATTERN ROWBYTES
MOVE #$3,PATHMASK(A6) ;HORIZONTAL MASK FOR PATTERN
MOVE #$3F,PATVMASK(A6) ;VERTICAL MASK FOR PATTERN
BRA.S DOOLD ;=>GO GET STARTING OFFSET INTO PATTERN
; NEW PATTERN. SET STARTING VERT POSITION.
DONEW MOVEQ #0,D6 ;CLEAR HIGH WORD
MOVE PATVMASK(A6),D6 ;GET VERTICAL MASK
ADDQ #1,D6 ;CONVERT TO COUNT
DIVU PATROW(A6),D6 ;DIVIDE BY ROWSIZE
SUBQ #1,D6 ;GET ROWS OF PATTERN
DOOLD AND MINRECT+TOP(A6),D6 ;GET TOP VERT LOCAL COORD
MULU D1,D6 ;CALC OFFSET INTO PATTERN
MOVE.l D6,PATVPOS(A6) ;SAVE AS PATVPOS <BAL 22Jan89>
; GET SLOW SLABMODE IN A4 (RELIES ON PATROW, SET UP BY PATEXPAND)
MOVE LOCMODE(A6),D2 ;GET (ALTERED) PEN MODE
_SlabMode ;GET DrawSlab CASE JUMP IN A4
;-----------------------------------------------------------
;
; Switch to 32 bit addressing mode
;
moveq #true32b,d0 ;switch to 32 bit addressing
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.b d0,MMUsave(a6) ;save previous state for later
; FOR EACH SLAB, MAKE MASK BUFFER CURRENT AND DRAW SLAB
MOVE MINRECT+TOP(A6),VERT(A6) ;INIT CURRENT VERT:=MINV
MOVE.L DSTLEFT(A6),A5 ;GET DSTLEFT
MOVE.L FCOLOR(A6),D4 ;PASS FCOLOR
MOVE.L BCOLOR(A6),D5 ;AND BACKCOLOR
MOVE.L SLOPE(A6),D7 ;GET FIXED POINT SLOPE
NXTMASK JSR ([SEEKMASK,A6]) ;MAKE MASK BUFFER CURRENT
LEA MINRECT(A6),A3 ;POINT TO MINRECT
LEA ([EXPAT,A6],D6.l),A0 ;GET pointer to THIS ROW'S PATTERN
MOVE.L (A0),D6 ;set up the pattern
MOVE.W LEFTEDGE(A6),D1 ;GET LEFTEDGE.INT
MOVE.W RIGHTEDGE(A6),D2 ;GET RIGHTEDGE.INT
MOVE.L A5,A1 ;INIT DSTPTR TO LEFT
MOVE.L RGNBUFFER(A6),A2 ;INIT MASKPTR TO LEFT
MOVE.W DSTSHIFT(A6),D0 ;GET SHIFT FOR PIXEL DEPTH
_DrawSlab ;DRAW ONE SLAB IN PENMODE
MOVE.l PATVPOS(A6),D6 ;GET PATVPOS <BAL 22Jan89>
ADD PATROW(A6),D6 ;BUMP TO NEXT SCAN
AND PATVMASK(A6),D6 ;WRAP AT END OF PATTERN
MOVE.l D6,PATVPOS(A6) ;SAVE PATVPOS FOR DRAWSLAB <BAL 22Jan89>
ADD DSTROW(A6),A5 ;BUMP DST TO NEXT ROW
ADD.L D7,LEFTEDGE(A6) ;ADD SLOPE TO LEFT EDGE
ADD.L D7,RIGHTEDGE(A6) ;ADD SLOPE TO RIGHT EDGE
ADD #1,VERT(A6) ;BUMP CURRENT VERT FOR SEEKMASK
MOVE VERT(A6),D0 ;GET CURRENT VERT
CMP MINRECT+BOTTOM(A6),D0 ;AT BOTTOM YET ?
BLT NXTMASK ;NO, LOOP ALL SCAN LINES
DONE move.b MMUsave(a6),d0 ;get previous MMU state in d0
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
SHOW MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
TST.B CRSRFLAG(A6) ;DRAWING TO SCREEN?
BEQ.S GOHOME ;=>NO, JUST RETURN
_SHOWCURSOR ;RESTORE CURSOR
GOHOME BSET #hiliteBit,HiliteMode ;reset hilite override, in case colormap was skipped
MOVE.L SAVESTK(A6),SP ;STRIP BUFFER
MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'DRAWLINE'
ALIGN Alignment
;-------------------------------------------------------
;
; SET UP AND DRAW A FAST HORIZONTAL OR VERTICAL LINE.
;
; as seen in QDciPatchROM.a <sm 6/9/92>stb
FASTLINE
;-----------------------------------------------------------
;
; Switch to 32 bit addressing mode
;
moveq #true32b,d0 ;switch to 32 bit addressing
move.w d1,-(sp) ;save a register
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.w (sp)+,d1 ;restore d1
move.b d0,MMUsave(a6) ;save previous state for later
MOVE.L alphaMask(A6),D4 ;get alpha mask <6>
CMP D1,D3 ;IS LINE HORIZONTAL ?
BNE VLINE ;NO, MUST BE VERTICAL
BSR HVSETUP ;GET DSTPTR,ROWBYTES,HGLOBAL
MOVEQ #-1,D6 ;GET ONES IN D6
LSR.L D0,D6 ;CONVERT TO LEFTMASK
MOVE MINRECT+RIGHT(A6),D2 ;GET MINRECT RIGHT
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT TO GLOBAL
EXT.L D2 ;MAKE IT LONG
LSL.L D3,D2 ;CONVERT PIXELS TO BITS
MOVEQ #$1F,D0 ;NEED RIGHT MOD 32
AND.L D2,D0 ;MAKE A COPY OF RIGHT
MOVEQ #-1,D3 ;GET ONES IN D3
LSR.L D0,D3 ;SHIFT IN 0'S FOR LEFTMASK
NOT.L D3 ;CONVERT TO RIGHTMASK
AND.L D4,D6 ;clip left mask with alpha mask <6>
AND.L D4,D3 ;clip right mask with alpha mask <6>
LSR.L #5,D2 ;CONVERT BITS TO LONGS
CMP #1,LOCMODE(A6) ;WHICH MODIFIED MODE ?
BLT.S HSET ;BR IF FOREGROUND
BEQ.S HTOGL ;BR IF XOR
;ELSE BACKGROUND
;------------------------------------------------------
;
; DRAW A HORIZONTAL LINE IN THE BACKGROUND COLOR (NORMALLY WHITE)
;
MOVE.L BCOLOR(A6),D5 ;GET THE COLOR
BRA.S HDRAW
;--------------------------------------------
;
; DRAW A HORIZONTAL LINE IN THE FOREGROUND COLOR (NORMALLY BLACK)
;
HSET MOVE.L FCOLOR(A6),D5 ;GET THE FOREGROUND COLOR
HDRAW SUB D1,D2 ;CALC LONG COUNT
BEQ.S ALLONE ;BR IF ALL IN ONE LONG
MOVE.L D5,D1 ;COPY COLOR
AND.L D6,D1 ;MASK COLOR FOR LEFT EDGE
NOT.L D6 ;GET NOT LEFTMASK
AND.L (A4),D6 ;PUNCH HOLE IN DEST
OR.L D1,D6 ;COMBINE SRC AND DST
MOVE.L D6,(A4)+ ;AND DROP COLOR IN
SUB #1,D2 ;DEC LONG COUNT
BEQ.S DOEND ;BR IF NO UNMASKED LONG
NOT.L D4 ;reverse alpha mask <6>
BEQ.S DOONE ;use normal loops if all ones <6>
;
; <6> Draw horizontal line using alpha mask
;
ALPHALINE
MOVE.L (A4),D0 ;get long of dst
EOR.L D5,D0 ;apply color
AND.L D4,D0 ;mask with alpha mask
EOR.L D5,D0 ;reapply color
MOVE.L D0,(A4)+ ;put result to dst
DBRA D2,ALPHALINE ;do another long
BRA.S DOEND ;all done
DOTWO MOVE.L D5,(A4)+ ;FILL A LONG WITH COLOR
DOONE MOVE.L D5,(A4)+ ;FILL ANOTHER LONG
SUB #2,D2 ;ANY UNMASKED LONGS LEFT ?
DOMORE BGT DOTWO ;YES, AT LEAST TWO LONGS
BEQ DOONE ;YES, FINISH UP LAST LONG
DOEND AND.L D3,D5 ;MASK SOURCE FOR RIGHT EDGE
NOT.L D3 ;GET NOTMASK
AND.L (A4),D3 ;PUNCH HOLE IN DST DATA
OR.L D5,D3 ;COMBINE SRC AND DST
MOVE.L D3,(A4) ;AND DROP COLOR IN
BRA.S DONE ;RESTORE CURSOR AND QUIT
ALIGN Alignment
ALLONE AND.L D3,D6 ;COMBINE LEFT AND RIGHT MASKS
AND.L D6,D5 ;GET MASKED COLOR
NOT.L D6 ;GET NOTMASK
AND.L (A4),D6 ;PUNCH OUT DESTINATION
OR.L D5,D6 ;COMBINE SRC AND DST
MOVE.L D6,(A4) ;DRAW LINE
BRA.S DONE ;RESTORE CURSOR AND QUIT
ALIGN Alignment
; as seen in QDciPatchROM.a <sm 6/9/92>stb
;--------------------------------------------------
;
; DRAW AN XOR HORIZONTAL LINE
;
HTOGL SUB D1,D2 ;CALC LONGCOUNT
BEQ.S ONETOGL ;BR IF ALL IN ONE LONG
EOR.L D6,(A4)+ ;DO LEFT LONG WITH MASK
SUB #1,D2 ;DEC LONG COUNT
BEQ.S ENDTOGL ;BR IF NO UNMASKED LONGS
BRA.S TOGLONE ;SEE IF ANY LONGS LEFT TO DO
TOGLTWO EOR.L D4,(A4)+ ;INVERT A LONG <6>
TOGLONE EOR.L D4,(A4)+ ;INVERT ANOTHER LONG <6>
SUB #2,D2 ;ANY UNMASKED LONGS LEFT ?
TOGLMORE BGT TOGLTWO ;YES, AT LEAST TWO LONGS
BEQ TOGLONE ;YES, FINISH UP LAST LONG
ENDTOGL EOR.L D3,(A4) ;DRAW LINE
BRA.S DONE ;RESTORE CURSOR AND QUIT
ONETOGL AND.L D3,D6 ;COMBINE LEFT AND RIGHT MASK
EOR.L D6,(A4) ;DRAW LINE
BRA.S DONE ;RESTORE CURSOR AND QUIT
ALIGN Alignment
;Êas seen in QDciPatchROM.a <sm 6/9/92>stb
;-------------------------------------------------------
;
; DRAW A ONE PIXEL WIDE VERTICAL LINE.
;
VLINE BSR.S HVSETUP ;GET DSTPTR,ROWBYTES,HGLOBAL
MOVEQ #-1,D2 ;GET ONES IN D2
LSR.L D0,D2 ;CONVERT TO LEFTMASK (LEFT MOD 32 IN D0)
MOVE.L D2,D0 ;GET LEFTMASK
MOVE DSTPIX+PIXELSIZE(A6),D1 ;GET PIXEL SIZE
LSR.L D1,D0 ;SHIFT BY PIXEL SIZE FOR RIGHT EDGE
NOT.L D0 ;MAKE IT A RIGHTMASK
AND.L D0,D2 ;AND RIGHTMASK INTO LEFTMASK
AND.L D4,D2 ;MASK WITH ALPHA MASK <6>
MOVE MINRECT+BOTTOM(A6),D1 ;GET BOTTOM
SUB MINRECT+TOP(A6),D1 ;CALC HEIGHT
SUB #1,D1 ;INIT HEIGHT COUNT
CMP #1,LOCMODE(A6) ;WHICH MODIFIED MODE ?
BLT.S VSET ;BR IF FOREGROUND
BEQ.S VTOGL ;BR IF XOR
VCLR MOVE.L BCOLOR(A6),D5 ;GET BACKGROUND COLOR
BRA.S VDRAW ;=>AND DO LINE
VSET MOVE.L FCOLOR(A6),D5 ;GET FOREGROUND COLOR
VDRAW BEQ.S VAND ;COLOR IS ALL 0's SO JUST AND
MOVE.L D5,D0 ;COPY COLOR
NOT.L D0 ;WAS IT ALL 1's?
BEQ.S VOR ;YES, JUST NEED TO OR
AND.L D2,D5 ;GET DATA TO WRITE
NOT.L D2 ;MAKE NOTMASK
NXTV MOVE.L D2,D3 ;GET NOTMASK
AND.L (A4),D3 ;PUNCH A HOLE IN THE DST
OR.L D5,D3 ;COMBINE SRC AND DST
MOVE.L D3,(A4) ;AND PUT TO DST
ADD D7,A4 ;BUMP TO NEXT ROW
DBRA D1,NXTV ;LOOP ALL DOTS
BRA.S DONE ;RESTORE CURSOR AND QUIT
ALIGN Alignment
VTOGL EOR.L D2,(A4) ;TOGGLE ONE DOT
ADD D7,A4 ;BUMP TO NEXT ROW
DBRA D1,VTOGL ;LOOP ALL DOTS
BRA.S DONE ;RESTORE CURSOR AND QUIT
ALIGN Alignment
VOR OR.L D2,(A4) ;TOGGLE ONE DOT
ADD D7,A4 ;BUMP TO NEXT ROW
DBRA D1,VOR ;LOOP ALL DOTS
BRA.S DONE ;RESTORE CURSOR AND QUIT
ALIGN Alignment
VAND NOT.L D2 ;MAKE INTO CLEARING MASK
@AND AND.L D2,(A4) ;TOGGLE ONE DOT
ADD D7,A4 ;BUMP TO NEXT ROW
DBRA D1,@AND ;LOOP ALL DOTS
BRA.S DONE ;RESTORE CURSOR AND QUIT
ALIGN Alignment
;------------------------------------------------------------------------
;
; LOCAL ROUTINE TO SET UP POINTER TO FIRST WORD, BIT INDEX, AND ROWBYTES
;
; INPUTS: MINRECT
; A5: thePort
;
; OUTPUTS: D0: LEFT MOD 32 (for getting mask)
; D1: LEFT DIV 32 (for long position)
; D3: DSTSHIFT
; D7: ROWBYTES
; A4: POINTER TO FIRST WORD
;
; CLOBBERS: D0,D1,D7,A0,A4
;
HVSETUP MOVE.L DSTPIX+BASEADDR(A6),A4 ;GET BITMAP START
MOVE MINRECT+TOP(A6),D0 ;GET STARTING VERT
SUB DSTPIX+BOUNDS+TOP(A6),D0 ;CONVERT TO GLOBAL
MOVE DSTPIX+ROWBYTES(A6),D7 ;GET ROWBYTES
AND #nuRBMask,D7 ;clear off flag bits
MULS D7,D0 ;MULT TOP BY ROWBYTES; BAL 02Dec88
ADD.L D0,A4 ;ADD TO BASEADDR
MOVE MINRECT+LEFT(A6),D0 ;GET STARTING HORIZ
SUB DSTPIX+BOUNDS+LEFT(A6),D0 ;CONVERT TO GLOBAL
EXT.L D0 ;MAKE IT LONG
MOVE DSTSHIFT(A6),D3 ;GET DSTSHIFT
EXT.L D3 ;MAKE IT LONG
LSL.L D3,D0 ;CONVERT PIXELS TO BITS
MOVE.L D0,D1 ;MAKE A COPY
LSR.L #5,D1 ;CONVERT BITS TO LONGS
LEA (A4,D1*4),A4 ;add in byte cnt
AND #$1F,D0 ;TREAT LEFT MOD 32
RTS
ALIGN 4
;-------------------------------------------------------
SteepBlitTab
DC.L steepCopy1-SteepBlitTab
DC.L steepCopy2-SteepBlitTab
DC.L steepCopy4-SteepBlitTab
DC.L steepCopy8-SteepBlitTab
DC.L steepCopy16-SteepBlitTab
DC.L steepCopy32-SteepBlitTab
SteepBlitXorTab
DC.L steepXor1-SteepBlitTab
DC.L steepXor2-SteepBlitTab
DC.L steepXor4-SteepBlitTab
DC.L steepXor8-SteepBlitTab
DC.L steepXor16-SteepBlitTab
DC.L steepXor32-SteepBlitTab
;-------------------------------------------------------
ShallowBlitTab
DC.L shallowCopy1-ShallowBlitTab
DC.L shallowCopy2-ShallowBlitTab
DC.L shallowCopyN-ShallowBlitTab
DC.L shallowCopyN-ShallowBlitTab
DC.L shallowCopyN-ShallowBlitTab
DC.L done-ShallowBlitTab ;never used
ShallowBlitXorTab
DC.L shallowXor1-ShallowBlitTab
DC.L shallowXor2-ShallowBlitTab
DC.L shallowXorN-ShallowBlitTab
DC.L shallowXorN-ShallowBlitTab
DC.L shallowXorN-ShallowBlitTab
DC.L done-ShallowBlitTab ;never used
ALIGN Alignment
;-------------------------------------------------------
;
; SET UP AND DRAW A FAST SLANTED LINE.
; Only steep lines are currently implemented: (45¡<=¿<=135¡)
;
; Assumes: D1,D2,D3,D4 = MinRect top,left,bottom,right
; D7 = slope (16.16)
FASTSLANT
;------------------------------------------------------------------------
;
; SET UP REGISTERS FOR FAST SLANT LOOPS
;
; INPUTS: MINRECT, DSTPIX, SLOPE
;
;-------------------------------------------------------
; a0 = d0 =
; a1 = d1 = fgColor/bkColor
; a2 = d2 = dst pixel size (bit width)
; a3 = rowBytes d3 = dstShift
; a4 = dstPtr d4 = bit offset to pixel left
; a5 = d5 = leftEdge (16.16)
; a6 = locals d6 = scan count (zero based)
; a7^= d7 = slope (16.16)
;-------------------------------------------------------
; includes fix as seen in QDciPatchROM.a <sm 6/9/92>stb
SLANTSETUP
TST.B alphaMode(A6) ;if alphamode == 0, stay in all cases <6>
BEQ.S @stay ; <6>
TST A2 ;leave if shallow and alphamode != 0 <6>
BEQ goBack ; <6>
MOVE LOCMODE(A6),D0 ;get the local mode <6>
ADDQ #1,D0 ;convert from xor=1 to xor=srcXor <6>
CMP #srcXor,D0 ; <6>
BNE goBack ;if copying, leave because alphamode != 0
@stay MOVE.L DSTPIX+BASEADDR(A6),A4 ;GET BITMAP START
MOVE D1,D0 ;GET STARTING VERT
SUB DSTPIX+BOUNDS+TOP(A6),D0 ;CONVERT TO GLOBAL
MOVE DSTPIX+ROWBYTES(A6),D6 ;GET ROWBYTES
AND #nuRBMask,D6 ;clear off flag bits
MULS D6,D0 ;MULT TOP BY ROWBYTES
MOVE D6,A3 ;REMEMBER ROWBYTES
ADD.L D0,A4 ;ADD TO BASEADDR
tst.w a2 ;taller or wider?
beq Shallow
SUB D1,D3 ;CALC HEIGHT
MOVEQ #-1,D6 ;
ADD D3,D6 ;D6 IS HEIGHT-1
MOVE.L LEFTEDGE(A6),D5 ;GET LEFTEDGE
MOVE.L D5,D2 ;Get LeftEdge.int
SWAP D2
SUB DSTPIX+BOUNDS+LEFT(A6),D2 ;CONVERT TO GLOBAL
EXT.L D2 ;MAKE IT LONG
MOVE DSTSHIFT(A6),D3 ;GET DSTSHIFT
LSL.L D3,D2 ;CONVERT PIXELS TO BITS
MOVE.L D2,D4 ;MAKE A COPY
LSR.L #5,D2 ;CONVERT BITS TO LONGS
LSL.L #2,D2 ;Convert back to bytes
ADD.L D2,A4 ;ADD TO RUNNING TOTAL
AND #$1F,D4 ;TREAT LEFT MOD 32
;-----------------------------------------------------------
;
; Switch to 32 bit addressing mode
;
moveq #true32b,d0 ;switch to 32 bit addressing
_rSwapMMUMode ;(can trash a0/a1/a2, d0/d1/d2)
move.b d0,MMUsave(a6) ;save previous state for later
tst.l d7 ;are we going right to left
bpl.s @toRight ;fractions ok
neg.w d7 ;make fraction positive
not.w d5 ;measure distance from right
;(plus one for boundary cases)
@toRight
tst.w d7 ;are we ± 45¡?
bne.s @not45 ;FOR REED:
not.w d7 ;hack slope and fraction so that
move.w d7,d5 ;every scanline generates a carry
@not45
MOVE DSTPIX+PIXELSIZE(A6),D2 ;GET DST PIXEL SIZE
MOVE.L FCOLOR(A6),D1 ;ASSUME FOREGROUND COLOR
moveq #0,d0 ;init zero register for loops
LEA SteepBlitTab,a0 ;point to mode table
CMP #1,LOCMODE(A6) ;WHICH MODIFIED MODE ?
BLT.S @useFG ;BR IF FOREGROUND
BEQ.S @doXor ;BR IF XOR
;ELSE BACKGROUND
MOVE.L BCOLOR(A6),D1 ;GET THE COLOR
@useFG ADD.L (A0,D3*4),A0 ;GET MODECASE
JMP (A0) ;GO THERE
@doXor MOVE.L alphaMask(A6),D1 ;get xoring mask
ADD.L SteepBlitXorTab-SteepBlitTab(A0,D3*4),A0 ;Adjusted modecase
JMP (A0) ;GO THERE
ALIGN Alignment
;-------------------------------------------------------
;
; DRAW ONE PIXEL WIDE STEEP SLANTED LINES
;
;-------------------------------------------------------
; a0 = d0 = zero
; a1 = d1 = fgColor/bkColor/(-1 for xor)
; a2 = d2 = dst pixel size (bit width)
; a3 = rowBytes d3 = dstShift
; a4 = dstPtr d4 = bit offset to pixel left
; a5 = d5 = leftEdge (16.16)
; a6 = locals d6 = scan count (zero based)
; a7^= d7 = slope (16.16)
;-------------------------------------------------------
steepCopy1
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
bfins d1,(a4){d4:d2} ;blit one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
addx.l d0,d4
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
bfins d1,(a4){d4:d2} ;blit one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
subx.l d0,d4
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepCopy2
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
bfins d1,(a4){d4:2} ;blit one pixel
add.l a3,a4 ;bump to next row
move.l d0,d2 ;start with zero
add.w d7,d5 ;add fractions
addx.l d0,d2 ;get a one or zero
add.l d2,d4 ;bump a bit
add.l d2,d4 ;bump a bit
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
bfins d1,(a4){d4:2} ;blit one pixel
add.l a3,a4 ;bump to next row
move.l d0,d2 ;start with zero
add.w d7,d5 ;add fractions
addx.l d0,d2
sub.l d2,d4 ;bump a bit
sub.l d2,d4 ;bump a bit
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepCopy4
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
bfins d1,(a4){d4:4} ;blit one pixel
add.l a3,a4 ;bump to next row
move.l d0,d2 ;start with zero
add.w d7,d5 ;add fractions
addx.l d0,d2 ;get a one or zero
lsl.l #2,d2 ;scale up by bit depth
add.l d2,d4 ;bump a pixel
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
bfins d1,(a4){d4:4} ;blit one pixel
add.l a3,a4 ;bump to next row
move.l d0,d2 ;start with zero
add.w d7,d5 ;add fractions
addx.l d0,d2
lsl.l #2,d2 ;scale up by bit depth
sub.l d2,d4 ;bump a pixel
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepCopy8
lsr.l #3,d4 ;convert bit offset to byte offset
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
move.b d1,(a4,d4) ;blit one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
addx.l d0,d4 ;bump a pixel
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
move.b d1,(a4,d4) ;blit one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
subx.l d0,d4
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepCopy16
lsr.l #4,d4 ;convert bit offset to word offset
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
move.w d1,(a4,d4*2) ;blit one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
addx.l d0,d4 ;bump a pixel
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
move.w d1,(a4,d4*2) ;blit one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
subx.l d0,d4
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepCopy32
lsr.l #5,d4 ;convert bit offset to long offset
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
move.l d1,(a4,d4*4) ;blit one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
addx.l d0,d4 ;bump a pixel
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
move.l d1,(a4,d4*4) ;blit one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
subx.l d0,d4
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
;
; XOR ONE PIXEL WIDE STEEP SLANTED LINES
;
;-------------------------------------------------------
steepXor1
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
bfchg (a4){d4:d2} ;toggle one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
addx.l d0,d4
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
bfchg (a4){d4:d2} ;toggle one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
subx.l d0,d4
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepXor2
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
bfchg (a4){d4:2} ;toggle one pixel
add.l a3,a4 ;bump to next row
move.l d0,d2 ;start with zero
add.w d7,d5 ;add fractions
addx.l d0,d2 ;get a one or zero
add.l d2,d4 ;bump a bit
add.l d2,d4 ;bump a bit
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
bfchg (a4){d4:2} ;toggle one pixel
add.l a3,a4 ;bump to next row
move.l d0,d2 ;start with zero
add.w d7,d5 ;add fractions
addx.l d0,d2
sub.l d2,d4 ;bump a bit
sub.l d2,d4 ;bump a bit
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepXor4
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
bfchg (a4){d4:4} ;toggle one pixel
add.l a3,a4 ;bump to next row
move.l d0,d2 ;start with zero
add.w d7,d5 ;add fractions
addx.l d0,d2 ;get a one or zero
lsl.l #2,d2 ;scale up by bit depth
add.l d2,d4 ;bump a pixel
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
bfchg (a4){d4:4} ;toggle one pixel
add.l a3,a4 ;bump to next row
move.l d0,d2 ;start with zero
add.w d7,d5 ;add fractions
addx.l d0,d2
lsl.l #2,d2 ;scale up by bit depth
sub.l d2,d4 ;bump a pixel
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepXor8
lsr.l #3,d4 ;convert bit offset to byte offset
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
eor.b d1,(a4,d4) ;toggle one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
addx.l d0,d4 ;bump a pixel
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
eor.b d1,(a4,d4) ;toggle one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
subx.l d0,d4
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepXor16
lsr.l #4,d4 ;convert bit offset to word offset
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
eor.w d1,(a4,d4*2) ;toggle one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
addx.l d0,d4 ;bump a pixel
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
eor.w d1,(a4,d4*2) ;toggle one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
subx.l d0,d4
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
steepXor32
lsr.l #5,d4 ;convert bit offset to long offset
tst.l d7 ;are we backwards
bmi.s @toLeft
@toRight
eor.l d1,(a4,d4*4) ;toggle one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
addx.l d0,d4 ;bump a pixel
dbra d6,@toRight
bra done
ALIGN Alignment
@toLeft
eor.l d1,(a4,d4*4) ;toggle one pixel
add.l a3,a4 ;bump to next row
add.w d7,d5 ;add fractions
subx.l d0,d4
dbra d6,@toLeft
bra done
ALIGN Alignment
;-------------------------------------------------------
;
; DRAW ONE PIXEL WIDE Shallow SLANTED LINES
;
;-------------------------------------------------------
; a0 = d0 = actual slab width
; a1 = d1 = fgColor/bkColor/(-1 for xor)
; a2 = |dx/dy| d2 = zero
; a3 = rowBytes d3 = dstShift
; a4 = dstPtr d4 = bit offset to pixel left
; a5 = bits to right d5 = integer slab width
; a6 = locals d6 = scan count (zero based)
; a7^= d7 = (high)slope,(low)rightEdge
;-------------------------------------------------------
goBack
; move.w minRect+left(a6),d2 ;restore minRect left
; move.w minRect+right(a6),d4 ;restore minRect right
bra CalcBufLeft
Shallow
cmp.w lineRect+top(a6),d1 ;was top clipped?
bgt.s goBack ;yes, take slow case
cmp.w lineRect+bottom(a6),d3 ;is bottom clipped?
blt.s goBack ;yes, take slow case
SUB D1,D3 ;CALC HEIGHT
MOVEQ #-2,D6 ;
ADD D3,D6 ;D6 IS HEIGHT-2
move.w d2,d0 ;assume left to right
tst.l d7 ;dx/dy < 0?
bpl.s @useLeft ;yes, left to right
move.w d4,d0 ;no, MinRect.right instead
@useLeft
SUB DSTPIX+BOUNDS+LEFT(A6),D0 ;CONVERT MinRect.Left TO GLOBAL
EXT.L D0 ;MAKE IT LONG
MOVE DSTSHIFT(A6),D3 ;GET DSTSHIFT
LSL.L D3,D0 ;CONVERT PIXELS TO BITS
MOVE.L D0,D1 ;MAKE A COPY
LSR.L #5,D0 ;CONVERT BITS TO LONGS
LSL.L #2,D0 ;Convert back to bytes
ADD.L D0,A4 ;ADD TO RUNNING TOTAL
AND #$1F,D1 ;TREAT LEFT MOD 32
move.l d7,d5 ;copy slope
bpl.s @notNeg
neg.l d5 ;get |slope|
@notNeg move.l d5,a2 ;copy |slope| for later
cmp.l #$10800,d5 ;is it nearly 45¡?
blt.s goBack ;yes, can't be as inaccurate as before
clr.w d5
swap d5 ;|slope|.int
lsl.l d3,d5 ;|slope|.int * pixelSize
cmp.w #32,d5 ;does max slab fit in a long?
bge.s goBack ;no, punt for now
SUB D2,D4 ;get pixel width
move.w rightEdge+2(a6),d7 ;get rightEdge.frac
LSL.L D3,D4 ;CONVERT PIXELS TO BITS
ADD D1,D4 ;D4 is bit offset to rightedge of last slab
MOVE.W D4,A5 ;save for later
MOVE.L D1,D4 ;save initial bit offset
tst.l d7 ;right to left?
bpl.s @widthOK
SUB D1,A5 ;undo the damage
SUB D1,A5 ;do it right
@widthOK
;
; Switch to 32 bit addressing mode
;
moveq #true32b,d0 ;switch to 32 bit addressing
_rSwapMMUMode ;(can trash a0/a1/a2, d0/d1/d2)
move.b d0,MMUsave(a6) ;save previous state for later
moveq #0,d0 ;compute first (clipped) slab width in d0
move.w minrect+right(a6),d0 ;get right clip
sub.w leftEdge(a6),d0 ;get initial slab width
tst.l d7 ;right to left?
bmi.s @yesNeg ;yes, all ok
move.w rightEdge(a6),d0 ;get rightEdge.int
sub.w minrect+left(a6),d0 ;get initial slab width
@yesNeg LSL.L D3,D0 ;CONVERT PIXELS TO BITS
moveq #0,d2 ;get a useful constant
MOVE.L FCOLOR(A6),D1 ;ASSUME FOREGROUND COLOR
LEA ShallowBlitTab,a0 ;point to mode table
CMP #1,LOCMODE(A6) ;WHICH MODIFIED MODE ?
BLT.S @useFG ;BR IF FOREGROUND
BEQ.S @doXor ;BR IF XOR
;ELSE BACKGROUND
MOVE.L BCOLOR(A6),D1 ;GET THE COLOR
@useFG ADD.L (A0,D3*4),A0 ;GET MODECASE
JMP (A0) ;GO THERE
@doXor ;Use alternate table
ADD.L ShallowBlitXorTab-ShallowBlitTab(A0,D3*4),A0 ;Adjusted modecase
JMP (A0) ;GO THERE
ALIGN Alignment
;-------------------------------------------------------
shallowCopy1 ;start with first clipped slab
tst.l d7 ;slope negative?
bmi.s @toLeft ;draw from right to left
@midR bfins d1,(a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
add.l d0,d4 ;bump offset by slab width
move.w d5,d0 ;prime slab width with slope.int
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add one
dbra d6,@midR
sub d4,a5 ;compute width of last slab
move a5,d0
bfins d1,(a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
@toLeft ;start with first clipped slab
@midL sub.l d0,d4 ;bump offset by slab width
bfins d1,(a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
move.w d5,d0 ;prime slab width with slope.int
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add one
dbra d6,@midL
add d4,a5 ;compute width of last slab
move a5,d0
sub.l d0,d4 ;bump offset by slab width
bfins d1,(a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
;-------------------------------------------------------
shallowCopy2 ;start with first clipped slab
tst.l d7 ;slope negative?
bmi.s @toLeft ;draw from right to left
@midR bfins d1,(a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
add.l d0,d4 ;bump offset by slab width
move.l d2,d0 ;zero working register
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add 1
add.l d0,d0 ;double it
add.l d5,d0 ;add in base slab width (slope.int)
dbra d6,@midR
sub d4,a5 ;compute width of last slab
move a5,d0
bfins d1,(a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
@toLeft ;start with first clipped slab
@midL sub.l d0,d4 ;bump offset by slab width
bfins d1,(a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
move.l d2,d0 ;zero working register
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add 1
add.l d0,d0 ;double it
add.l d5,d0 ;add in base slab width (slope.int)
dbra d6,@midL
add d4,a5 ;compute width of last slab
move a5,d0
sub.l d0,d4 ;bump offset by slab width
bfins d1,(a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
;-------------------------------------------------------
shallowCopyN ;start with first clipped slab
tst.l d7 ;slope negative?
bmi.s @toLeft ;draw from right to left
@midR bfins d1,(a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
add.l d0,d4 ;bump offset by slab width
move.l d2,d0 ;zero working register
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add 1
lsl.l d3,d0 ;quad it
add.l d5,d0 ;add in base slab width (slope.int)
dbra d6,@midR
sub d4,a5 ;compute width of last slab
move a5,d0
bfins d1,(a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
@toLeft ;start with first clipped slab
@midL sub.l d0,d4 ;bump offset by slab width
bfins d1,(a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
move.l d2,d0 ;zero working register
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add 1
lsl.l d3,d0 ;quad it
add.l d5,d0 ;add in base slab width (slope.int)
dbra d6,@midL
add d4,a5 ;compute width of last slab
move a5,d0
sub.l d0,d4 ;bump offset by slab width
bfins d1,(a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
;-------------------------------------------------------
shallowXor1 ;start with first clipped slab
tst.l d7 ;slope negative?
bmi.s @toLeft ;draw from right to left
@midR bfchg (a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
add.l d0,d4 ;bump offset by slab width
move.w d5,d0 ;prime slab width with slope.int
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add one
dbra d6,@midR
sub d4,a5 ;compute width of last slab
move a5,d0
bfchg (a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
@toLeft ;start with first clipped slab
@midL sub.l d0,d4 ;bump offset by slab width
bfchg (a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
move.w d5,d0 ;prime slab width with slope.int
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add one
dbra d6,@midL
add d4,a5 ;compute width of last slab
move a5,d0
sub.l d0,d4 ;bump offset by slab width
bfchg (a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
;-------------------------------------------------------
shallowXor2 ;start with first clipped slab
tst.l d7 ;slope negative?
bmi.s @toLeft ;draw from right to left
@midR bfchg (a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
add.l d0,d4 ;bump offset by slab width
move.l d2,d0 ;zero working register
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add 1
add.l d0,d0 ;double it
add.l d5,d0 ;add in base slab width (slope.int)
dbra d6,@midR
sub d4,a5 ;compute width of last slab
move a5,d0
bfchg (a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
@toLeft ;start with first clipped slab
@midL sub.l d0,d4 ;bump offset by slab width
bfchg (a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
move.l d2,d0 ;zero working register
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add 1
add.l d0,d0 ;double it
add.l d5,d0 ;add in base slab width (slope.int)
dbra d6,@midL
add d4,a5 ;compute width of last slab
move a5,d0
sub.l d0,d4 ;bump offset by slab width
bfchg (a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
;-------------------------------------------------------
shallowXorN ;start with first clipped slab
tst.l d7 ;slope negative?
bmi.s @toLeft ;draw from right to left
@midR bfchg (a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
add.l d0,d4 ;bump offset by slab width
move.l d2,d0 ;zero working register
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add 1
lsl.l d3,d0 ;quad it
add.l d5,d0 ;add in base slab width (slope.int)
dbra d6,@midR
sub d4,a5 ;compute width of last slab
move a5,d0
bfchg (a4){d4:d0} ;blit last slab
bra done
ALIGN Alignment
@toLeft ;start with first clipped slab
@midL sub.l d0,d4 ;bump offset by slab width
bfchg (a4){d4:d0} ;blit a slab
add.l a3,a4 ;bump to next row
move.l d2,d0 ;zero working register
add.w a2,d7 ;add fractions
addx.l d2,d0 ;conditionally add 1
lsl.l d3,d0 ;quad it
add.l d5,d0 ;add in base slab width (slope.int)
dbra d6,@midL
add d4,a5 ;compute width of last slab
move a5,d0
sub.l d0,d4 ;bump offset by slab width
bfchg (a4){d4:d0} ;blit last slab
bra done
;-------------------------------------------------------
ENDPROC