; ; File: DrawLine.a ; ; Copyright: © 1981-1990, 1992 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 6/11/92 stb 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. ; 11/7/87 BAL Fixed ChkPat to handle new patterns. ; 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 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 ;---------------------------------------------------- ; ; 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? 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? BEQ.S @oldPat ;=>no, skip pixpat fields MOVE.L (a0),a0 ;get the pixpat handle MOVE.L (a0),a0 ;get the pixpat pointer TST PATTYPE(A0) ;is it an old-style pattern? BNE.S FLAGOK ;=>no, skip fast case MOVE.L patData(a0),a0 ;get handle to pattern data MOVE.L (a0),a0 ;get pattern ptr @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 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 08Nov87 BAL ; ;D4 = MINRECT RIGHT SUB D2,D4 ;CALC MAXH-BUFLEFT move d4,d0 ;save for expansion scanline buffer ext.l d4 ;clear out high word lsl.l d5,d4 ;convert to bits subq.l #1,d4 ;force downward round LSR.l #5,D4 ;GET NUMBER OF LONGS IN SCANBUF - 1 MOVE D4,BUFSIZE(A6) ;BUFSIZE = # LONGS -1 LSR #5,D0 ;get (pixels in scanbuf)/32 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 move.l maskbc,StackFree(a6) ;pretend lots of stack 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 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 MOVE DSTSHIFT(A6),D7 ;GET PIXEL TO BIT SHIFT AMOUNT LSL.L D7,D2 ;CONVERT PIXELS TO BITS LSR.L #3,D2 ;CONVERT BITS TO BYTES ; EXT.L D2 ;CLR HI WORD 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 ; 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 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 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 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 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 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 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