mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-28 13:52:37 +00:00
784 lines
25 KiB
Plaintext
784 lines
25 KiB
Plaintext
;
|
|
; File: DrawLine.m.a
|
|
;
|
|
; Contains: xxx put contents here (or delete the whole line) xxx
|
|
;
|
|
; Written by: xxx put name of writer here (or delete the whole line) xxx
|
|
;
|
|
; Copyright: © 1988-1990 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <2> 10/10/90 JL Change FixRatio to MFixRatio to avoid conflict with Traps.a
|
|
; <1.1> 11/11/88 CCH Fixed Header.
|
|
; <1.0> 11/9/88 CCH Adding to EASE.
|
|
; <1.2> 10/12/88 CCH Changed “m.GrafType.a” to “GrafType.m.a”.
|
|
; <1.1> 5/18/88 MSH Changed inclides to use m.GRAPHTYPES to work under EASE.
|
|
; <1.0> 2/11/88 BBM Adding file for the first time into EASE…
|
|
;
|
|
; To Do:
|
|
;
|
|
|
|
;EASE$$$ READ ONLY COPY of file “DRAWLINE.m.a”
|
|
; 1.1 CCH 11/11/1988 Fixed Header.
|
|
; 1.0 CCH 11/ 9/1988 Adding to EASE.
|
|
; OLD REVISIONS BELOW
|
|
; 1.2 CCH 10/12/1988 Changed “m.GrafType.a” to “GrafType.m.a”.
|
|
; 1.1 MSH 5/18/88 Changed inclides to use m.GRAPHTYPES to work under EASE.
|
|
; 1.0 BBM 2/11/88 Adding file for the first time into EASE…
|
|
; END EASE MODIFICATION HISTORY
|
|
|
|
|
|
BLANKS ON
|
|
STRING ASIS
|
|
|
|
INCLUDE 'GRAFTYPES.m.a'
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; --> DRAWLINE.TEXT
|
|
;
|
|
|
|
|
|
DrawLine PROC EXPORT
|
|
IMPORT RgnBlt,RSect,ShieldCursor,ShowCursor,TrimRect
|
|
IMPORT InitRgn,SeekRgn,PatExpand,ColorMap
|
|
IMPORT XorSlab,DrawSlab,SlabMode,FastSlabMode,MaskTab
|
|
;----------------------------------------------------------------
|
|
;
|
|
; 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:
|
|
;
|
|
EXPAT EQU -64 ;16 LONGS
|
|
LINERECT EQU EXPAT-8 ;RECT
|
|
MINRECT EQU LINERECT-8 ;RECT
|
|
STATEA EQU MINRECT-RGNREC ;RGN STATE RECORD
|
|
STATEB EQU STATEA-RGNREC ;RGN STATE RECORD
|
|
STATEC EQU STATEB-RGNREC ;RGN STATE RECORD
|
|
SAVESTK EQU STATEC-4 ;LONG
|
|
RECTFLAG EQU SAVESTK-2 ;WORD
|
|
MASKBUF EQU RECTFLAG-4 ;LONG
|
|
BUFLEFT EQU MASKBUF-2 ;WORD
|
|
BUFSIZE EQU BUFLEFT-2 ;WORD
|
|
VERT EQU BUFSIZE-2 ;WORD
|
|
MODECASE EQU VERT-4 ;LONG
|
|
PAT EQU MODECASE-4 ;LONG, ADDR OF PAT
|
|
LEFTEDGE EQU PAT-4 ;LONG, FIXED POINT
|
|
RIGHTEDGE EQU LEFTEDGE-4 ;LONG, FIXED POINT
|
|
SLOPE EQU RIGHTEDGE-4 ;LONG, FIXED POINT
|
|
DSTLEFT EQU SLOPE-4 ;LONG
|
|
SAVEA5 EQU DSTLEFT-4 ;LONG
|
|
PORT EQU SAVEA5-4 ;LONG
|
|
MODE EQU PORT-2 ;WORD
|
|
FASTFLAG EQU MODE-2 ;BYTE
|
|
BIGRGN EQU FASTFLAG-4 ;LONG, RgnHandle
|
|
VARSIZE EQU BIGRGN ;SIZE OF LOCAL VARIABLES
|
|
|
|
|
|
|
|
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
|
|
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.L A3,PORT(A6) ;SAVE PORT FOR LATER
|
|
|
|
|
|
;-------------------------------------------------------
|
|
;
|
|
; QUIT IF PEN MODE NOT IN 8..15
|
|
;
|
|
MOVEQ #-8,D0
|
|
AND PNMODE(A3),D0 ;GET ALL BUT 3 BITS OF PEN MODE
|
|
CMP #8,D0 ;IS PEN MODE 8..15 ?
|
|
BNE GOHOME ;NO, QUIT
|
|
|
|
|
|
;-------------------------------------------------------
|
|
;
|
|
; Check for color filtering. Alter mode and pattern accordingly.
|
|
;
|
|
MOVE PNMODE(A3),-(SP) ;PUSH PEN MODE
|
|
PEA PNPAT(A3) ;PUSH ADDR OF PEN PATTERN
|
|
TST COLRBIT(A3) ;IS COLORBIT NEG ?
|
|
BMI.S NOCOLOR ;YES, DON'T MAP
|
|
JSR COLORMAP ;CHECK AGAINST THECOLOR, THEFILTER
|
|
NOCOLOR MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN
|
|
MOVE (SP)+,MODE(A6) ;AND (ALTERED) MODE
|
|
|
|
|
|
;---------------------------------------------------------
|
|
;
|
|
; 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 PORTBITS+BOUNDS(A5) ;PUSH BITMAP 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
|
|
JSR RSECT ;CALC INTERSECTION
|
|
BEQ GOHOME ;QUIT IF NO INTERSECT
|
|
|
|
;
|
|
; HIDE CURSOR IF CURSOR INTERSECTS MINRECT.
|
|
;
|
|
PEA MINRECT(A6) ;PUSH SHIELDRECT PARAMETER
|
|
MOVE.L PORTBITS+BOUNDS+TOPLEFT(A5),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
|
|
MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
|
|
JSR SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
|
|
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
|
|
JSR TrimRect ;call trimRect
|
|
BLT DONE ;quit if intersection empty
|
|
BGT.S FLAGOK ;continue if non-rectangular
|
|
;
|
|
; CHECK FOR BLACK OR WHITE PATTERN
|
|
;
|
|
CKPAT MOVE.L PAT(A6),A0 ;POINT TO PATTERN
|
|
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,MODE(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 MODE(A6),D0 ;GET 3 BITS OF MODE
|
|
MOVE.B MODEMAP(D0),D0 ;MAP TO BLACK,XOR,WHITE,NOP
|
|
BMI DONE ;QUIT IF DO-NOTHING MODE
|
|
MOVE D0,MODE(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 ?
|
|
BEQ FASTLINE ;YES, DO IT FAST !
|
|
|
|
|
|
;--------------------------------------------------------------------
|
|
;
|
|
; NOT FASTLINE. PUSH PARAMS AND CALL RGNBLT FOR HORIZ OR VERT LINE.
|
|
;
|
|
NOTFAST PEA PORTBITS(A5) ;PUSH SRCBITS = DSTBITS
|
|
MOVE.L (SP),-(SP) ;PUSH DSTBITS
|
|
PEA MINRECT(A6) ;PUSH SRCRECT = DSTRECT
|
|
MOVE.L (SP),-(SP) ;PUSH DSTRECT
|
|
MOVE PNMODE(A5),-(SP) ;PUSH MODE
|
|
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
|
|
JSR RGNBLT ;DRAW THE HORIZ OR VERT LINE
|
|
BRA DONE ;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 RGNBBOX+TOP(A2),D0 ;IS RESULT <= CLIP TOP ?
|
|
BLE DONE ;YES, RESTORE CURSOR AND QUIT
|
|
CMP RGNBBOX+BOTTOM(A2),D1 ;IS TOP >= CLIP BOTTOM ?
|
|
BGE DONE ;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 DONE ;QUIT IF PENWIDTH <= 0
|
|
ADD.W D0,RIGHTEDGE(A6) ;ADD TO RIGHTEDGE.INT
|
|
MOVE PNSIZE+V(A5),D6 ;GET PEN HEIGHT
|
|
BLE DONE ;QUIT IF PEN HEIGHT <= 0
|
|
|
|
|
|
;----------------------------------------------------
|
|
;
|
|
; CALC FIXED POINT SLOPE = FixRatio(dh,dv);
|
|
;
|
|
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
|
|
MOVE D4,-(SP) ;PUSH BOTTOM HORIZ
|
|
SUB D2,(SP) ;CALC DH
|
|
MOVE D3,-(SP) ;PUSH BOTTOM VERT
|
|
SUB D1,(SP) ;CALC DV
|
|
_MFixRatio ;CALC FIXED POINT SLOPE DH/DV
|
|
MOVE.L (SP)+,D7 ;POP RESULT
|
|
MOVE.L D7,SLOPE(A6) ;SAVE FOR LATER
|
|
|
|
;
|
|
; CALC adjust := pen height * slope
|
|
;
|
|
CLR.L -(SP) ;PUSH ROOM FOR FCN RESULT
|
|
CLR.W -(SP) ;PUSH LOWORD = 0
|
|
MOVE.W D6,-(SP) ;PUSH HIWORD = PEN HEIGHT
|
|
MOVE.L D7,-(SP) ;PUSH SLOPE
|
|
_MFixMul ;CALC FixMul(pnSize.v,slope)
|
|
MOVE.L (SP)+,D6 ;POP ANSWER INTO D6
|
|
|
|
;
|
|
; ADJUST LEFTEDGE AND RIGHTEDGE DEPENDING ON SIGN AND MAGNITUDE OF SLOPE
|
|
;
|
|
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 D6,LEFTEDGE(A6) ;SUBTRACT ADJUST FROM LEFTEDGE
|
|
CMP.L #$00010000,D7 ;IS SLOPE < ONE ?
|
|
BGE.S LESSV1 ;NO, BRANCH
|
|
|
|
MOREV1 ADD.L D7,LEFTEDGE(A6) ;ADD SLOPE TO LEFTEDGE
|
|
BRA.S SLOPEOK ;CONTINUE
|
|
|
|
LESSV1 SUB.W #1,RIGHTEDGE(A6) ;RIGHTEDGE := RIGHTEDGE - 1
|
|
BRA.S SLOPEOK ;CONTINUE
|
|
|
|
|
|
;----------------------------------------------------
|
|
;
|
|
; SLOPE IS NEGATIVE
|
|
;
|
|
NEGSLOPE SUB.L D6,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
|
|
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 AMMOUNT
|
|
MOVE.L D7,D5 ;GET 32 BIT SLOPE
|
|
SWAP D5 ;GET HI WORD OF SLOPE
|
|
MULS D0,D5 ;MULT TIMES DISCARD
|
|
SWAP D5 ;PUT RESULT IN HI WORD
|
|
CLR.W D5 ;CLEAR LO WORD
|
|
MOVE.L D7,D6 ;GET NEW COPY OF SLOPE
|
|
MULU D0,D6 ;MULT LO WORD TIMES DISCARD
|
|
ADD.L D6,D5 ;CALC 32BIT SLOPE*DISCARD
|
|
ADD.L D5,LEFTEDGE(A6) ;BUMP LEFTEDGE TO NEW TOP
|
|
ADD.L D5,RIGHTEDGE(A6) ;BUMP RIGHTEDGE TO NEW TOP
|
|
TOPOK
|
|
;
|
|
; CALC BUFLEFT
|
|
;
|
|
MOVE MINRECT+LEFT(A6),D2 ;GET MINRECT LEFT
|
|
SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT TO GLOBAL COORDS
|
|
AND #$FFF0,D2 ;TRUNC TO MULT OF 16
|
|
ADD PORTBITS+BOUNDS+LEFT(A5),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 BUFSIZE
|
|
;
|
|
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
|
|
SUB D2,D0 ;CALC MAXH-BUFLEFT
|
|
LSR #5,D0 ;DIV BY 32 FOR LONGS
|
|
MOVE D0,BUFSIZE(A6) ;BUFSIZE = # LONGS - 1
|
|
;
|
|
; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK
|
|
;
|
|
CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR ONE LONG
|
|
DBRA D0,CLRMASK ;LOOP TILL DONE
|
|
MOVE.L SP,MASKBUF(A6) ;REMEMBER WHERE MASKBUF IS
|
|
|
|
|
|
;-------------------------------------------------------------------------
|
|
;
|
|
; INIT STATE RECORDS AND ALLOCATE BUFFERS FOR EACH NON-RECTANGULAR REGION
|
|
;
|
|
CLR D5 ;INIT BOTH ARE RECT
|
|
MOVE #-32767,STATEA+THISV(A6) ;INIT HARMLESS STATE
|
|
MOVE #32767,STATEA+NEXTV(A6) ;IN CASE RECTANGULAR
|
|
CMP #10,RGNSIZE(A2) ;IS CLIPRGN RECTANGULAR ?
|
|
BEQ.S ARECT ;YES, CONTINUE
|
|
ADD #2,D5 ;NO, SET ITS FLAG
|
|
MOVE.L A2,A0 ;POINT TO CLIPRGN
|
|
LEA STATEA(A6),A1 ;POINT TO STATE RECORD A
|
|
BSR.S INITONE ;INIT STATE, ALLOC BUFFER
|
|
ARECT
|
|
MOVE #-32767,STATEB+THISV(A6) ;INIT HARMLESS STATE
|
|
MOVE #32767,STATEB+NEXTV(A6) ;IN CASE RECTANGULAR
|
|
CMP #10,RGNSIZE(A3) ;IS VISRGN RECTANGULAR ?
|
|
BEQ.S BRECT ;YES, CONTINUE
|
|
ADD #4,D5 ;NO, SET ITS FLAG
|
|
MOVE.L A3,A0 ;POINT TO VISRGN
|
|
LEA STATEB(A6),A1 ;POINT TO STATE RECORD B
|
|
PEA BRECT ;PUSH FAKE RETURN ADDR
|
|
INITONE MOVE MINRECT+LEFT(A6),D0 ;GET MINH
|
|
MOVE MINRECT+RIGHT(A6),D1 ;GET MAXH
|
|
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
|
|
JMP INITRGN ;INIT STATE, ALLOC BUFFER
|
|
BRECT
|
|
|
|
|
|
;--------------------------------------------------------------------
|
|
;
|
|
; IF BOTH REGIONS ARE RECTANGULAR, THEN DRAW MINRECT INTO MASK BUFFER
|
|
;
|
|
MOVE.W D5,RECTFLAG(A6) ;ARE BOTH RGNS RECT ?
|
|
BNE.S NOTRECT ;NO, CONTNUE
|
|
MOVE.L MASKBUF(A6),A0 ;YES, POINT TO MASK BUFFER
|
|
MOVE MINRECT+LEFT(A6),D3 ;SET UP LEFT
|
|
SUB BUFLEFT(A6),D3 ;MAKE IT BUFFER RELATIVE
|
|
MOVE MINRECT+RIGHT(A6),D4 ;SET UP RIGHT
|
|
SUB BUFLEFT(A6),D4 ;MAKE IT BUFFER RELATIVE
|
|
JSR XorSlab ;AND XOR BETWEEN THEM
|
|
NOTRECT
|
|
|
|
|
|
SKIPSETUP
|
|
|
|
;------------------------------------
|
|
;
|
|
; CALC STARTING DSTLEFT
|
|
;
|
|
MOVE MINRECT+TOP(A6),D1
|
|
SUB PORTBITS+BOUNDS+TOP(A5),D1 ;CONVERT MINV TO GLOBAL COORDS
|
|
MULU PORTBITS+ROWBYTES(A5),D1 ;MULT BY DST ROWBYTES
|
|
ADD.L PORTBITS+BASEADDR(A5),D1 ;ADD START OF BITMAP
|
|
SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT BUFLEFT TO GLOBAL
|
|
LSR #3,D2 ;CALC BUFLEFT DIV 8
|
|
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 MODE(A6),D2 ;GET (ALTERED) PEN MODE
|
|
JSR FastSlabMode ;Get fast case jump in A4
|
|
LEA MaskTab,A0 ;point to mask table
|
|
LEA MINRECT(A6),A3 ;POINT TO MINRECT
|
|
MOVE.L SLOPE(A6),D7 ;GET FIXED POINT SLOPE
|
|
MOVE PORTBITS+ROWBYTES(A5),D6 ;GET DST ROWBYTES
|
|
MOVE.L DSTLEFT(A6),A5 ;GET DSTLEFT
|
|
MOVE MINRECT+BOTTOM(A6),D5 ;GET MINRECT BOTTOM
|
|
SUB MINRECT+TOP(A6),D5 ;CALC HEIGHT
|
|
SUB #1,D5 ;MINUS 1 FOR DBRA COUNT
|
|
|
|
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
|
|
JSR DrawSlab ;DRAW ONE SLAB IN PENMODE
|
|
ADD D6,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 D5,NXTFAST ;LOOP FOR ALL SCANLINES
|
|
BRA DONE ;AND QUIT
|
|
|
|
|
|
|
|
GOSLOW MOVE MODE(A6),D2 ;GET (ALTERED) PEN MODE
|
|
JSR SlabMode ;GET DrawSlab CASE JUMP IN A4
|
|
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; EXPAND 8 BYTE PATTERN TO 16 LONGS AND INIT PATTERN SELECTOR
|
|
;
|
|
CLR.L D7 ;SAY NOT INVERTED
|
|
MOVE MODE(A6),D2 ;GET (ALTERED) PEN MODE
|
|
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 PORTBITS+BOUNDS+LEFT(A5),D2 ;GET GLOBAL-LOCAL OFFSET
|
|
MOVE.L PAT(A6),A0 ;POINT TO BYTE WIDE PATTERN
|
|
LEA EXPAT(A6),A1 ;POINT TO EXPANDED PATTERN
|
|
MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
|
|
JSR PATEXPAND ;EXPAND 8 BYTES TO 16 LONGS
|
|
MOVE.L PORT(A6),A5 ;RESTORE GRAFPTR IN A5
|
|
MOVEQ #$F,D7 ;TREAT COORD MOD 16
|
|
AND MINRECT+TOP(A6),D7 ;GET TOP VERT LOCAL COORD
|
|
LSL #2,D7 ;QUAD FOR LONG INDEX
|
|
|
|
|
|
;
|
|
; FOR EACH SLAB, MAKE MASK BUFFER CURRENT AND DRAW SLAB
|
|
;
|
|
LEA MINRECT(A6),A3 ;POINT TO MINRECT
|
|
MOVE PORTBITS+ROWBYTES(A5),D5 ;GET DST ROWBYTES
|
|
MOVE.L DSTLEFT(A6),A5 ;GET DSTLEFT
|
|
MOVE.L SLOPE(A6),D4 ;GET FIXED POINT SLOPE
|
|
MOVE MINRECT+TOP(A6),VERT(A6) ;INIT CURRENT VERT:=MINV
|
|
NXTMASK BSR.S SEEKMASK ;MAKE MASK BUFFER CURRENT
|
|
MOVE.L EXPAT(A6,D7),D6 ;GET PATTERN DATA
|
|
MOVE.W LEFTEDGE(A6),D1 ;GET LEFTEDGE.INT
|
|
MOVE.W RIGHTEDGE(A6),D2 ;GET RIGHTEDGE.INT
|
|
LEA MaskTab,A0 ;point to mask table
|
|
MOVE.L A5,A1 ;INIT DSTPTR TO LEFT
|
|
MOVE.L MASKBUF(A6),A2 ;INIT MASKPTR TO LEFT
|
|
JSR DrawSlab ;DRAW ONE SLAB IN PENMODE
|
|
ADD #4,D7 ;BUMP PATTERN SELECTOR
|
|
AND #$3F,D7 ;MOD 64 FOR 16 LONG REPEAT
|
|
ADD D5,A5 ;BUMP DST TO NEXT ROW
|
|
ADD.L D4,LEFTEDGE(A6) ;ADD SLOPE TO LEFT EDGE
|
|
ADD.L D4,RIGHTEDGE(A6) ;ADD SLOPE TO RIGHT EDGE
|
|
ADD #1,VERT(A6) ;BUMP CURRENT VERT
|
|
MOVE VERT(A6),D0 ;GET CURRENT VERT
|
|
CMP MINRECT+BOTTOM(A6),D0 ;ARE WE AT BOTTOM YET ?
|
|
BLT NXTMASK ;NO, LOOP ALL SCAN LINES
|
|
|
|
|
|
DONE MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
|
|
JSR SHOWCURSOR ;RESTORE CURSOR
|
|
GOHOME MOVE.L SAVESTK(A6),SP ;STRIP BUFFER
|
|
MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGISTERS
|
|
UNLINK PARAMSIZE,'DRAWLINE'
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
; LOCAL ROUTINE TO UPDATE THE MASK BUFFER
|
|
; BASED ON WHICH REGIONS ARE RECTANGULAR
|
|
;
|
|
SEEKMASK MOVE VERT(A6),D0 ;GET CURRENT VERT COORD
|
|
MOVE RECTFLAG(A6),D1 ;GET RECTFLAG = 0,2,4
|
|
MOVE RECTJMP(D1),D1 ;GET OFFSET FROM TABLE
|
|
JMP RECTJMP(D1) ;TAKE CASE JUMP
|
|
|
|
RECTJMP DC.W IGNORE-RECTJMP ;DO NOTHING IF BOTH RECT
|
|
DC.W A-RECTJMP
|
|
DC.W B-RECTJMP
|
|
DC.W AB-RECTJMP
|
|
|
|
|
|
;--------------------------------------------------------------------
|
|
;
|
|
; ONLY REGION A IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
|
|
;
|
|
A LEA STATEA(A6),A1
|
|
JSRSEEK JSR SEEKRGN
|
|
MOVE.L SCANBUF(A1),MASKBUF(A6)
|
|
IGNORE RTS
|
|
|
|
|
|
;--------------------------------------------------------------------
|
|
;
|
|
; ONLY REGION B IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
|
|
;
|
|
B LEA STATEB(A6),A1
|
|
BRA.S JSRSEEK
|
|
|
|
|
|
;-------------------------------------------------------------------
|
|
;
|
|
; REGIONS A AND B ARE NON-RECTANGULAR. UPDATE EACH,
|
|
; THEN FORM INTERSECTION IN THE MASK BUFFER.
|
|
;
|
|
AB LEA STATEA(A6),A1
|
|
JSR SEEKRGN
|
|
LEA STATEB(A6),A1
|
|
JSR SEEKRGN
|
|
MOVE.L STATEA+SCANBUF(A6),A0
|
|
MOVE.L STATEB+SCANBUF(A6),A1
|
|
MOVE.L MASKBUF(A6),A2
|
|
MOVE BUFSIZE(A6),D1
|
|
ABLOOP MOVE.L (A0)+,D0
|
|
AND.L (A1)+,D0
|
|
MOVE.L D0,(A2)+
|
|
DBRA D1,ABLOOP
|
|
RTS
|
|
|
|
|
|
;-------------------------------------------------------
|
|
;
|
|
; SET UP AND DRAW A FAST HORIZONTAL OR VERTICAL LINE.
|
|
;
|
|
FASTLINE CMP D1,D3 ;IS LINE HORIZONTAL ?
|
|
BNE VLINE ;NO, MUST BE VERTICAL
|
|
BSR HVSETUP ;GET DSTPTR,ROWBYTES,HGLOBAL
|
|
MOVE 32(A0,D0),D6 ;GET LEFTMASK IN D6
|
|
MOVE MINRECT+RIGHT(A6),D2 ;GET MINRECT RIGHT
|
|
SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT TO GLOBAL
|
|
MOVE D2,D0 ;MAKE A COPY OF RIGHT
|
|
AND #$F,D0 ;TREAT RIGHT MOD 16
|
|
ADD D0,D0 ;DOUBLE FOR TABLE
|
|
MOVE 0(A0,D0),D3 ;GET RIGHTMASK IN D3
|
|
LSR #4,D2 ;CONVERT DOTS TO WORDS
|
|
CMP #1,MODE(A6) ;WHICH MODIFIED MODE ?
|
|
BLT.S HSET ;BR IF BLACK
|
|
BEQ.S HTOGL ;BR IF XOR
|
|
;ELSE WHITE
|
|
|
|
;------------------------------------------------------
|
|
;
|
|
; DRAW A WHITE HORIZONTAL LINE
|
|
;
|
|
NOT D6 ;MAKE NOT LEFTMASK
|
|
NOT D3 ;MAKE NOT RIGHTMASK
|
|
SUB D1,D2 ;CALC WORDCOUNT
|
|
BEQ.S ENDCLR ;BR IF ALL IN ONE WORD
|
|
AND D6,(A4)+ ;DO LEFT WORD WITH MASK
|
|
CLR.L D6 ;FLUSH LEFTMASK FOR END
|
|
SUB #1,D2 ;DEC WORD COUNT
|
|
BEQ.S ENDCLR ;BR IF NO UNMASKED WORDS
|
|
LSR #1,D2 ;HALVE WORDCOUNT FOR LONGCOUNT
|
|
BCC.S CLRONE ;BR IF EVEN # WORDS LEFT
|
|
MOVE D6,(A4)+ ;ELSE MAKE EVEN BY DOING A WORD
|
|
SUB #1,D2 ;ADJUST LONGCOUNT
|
|
BRA.S CLRMORE ;SEE IF ANY LONGS LEFT TO DO
|
|
CLRTWO MOVE.L D6,(A4)+ ;FILL A LONG WITH BLACK
|
|
CLRONE MOVE.L D6,(A4)+ ;FILL ANOTHER LONG
|
|
SUB #2,D2 ;ANY UNMASKED LONGS LEFT ?
|
|
CLRMORE BGT CLRTWO ;YES, AT LEAST TWO LONGS
|
|
BEQ CLRONE ;YES, FINISH UP LAST LONG
|
|
ENDCLR OR D3,D6 ;COMBINE LEFT AND RIGHT MASK
|
|
AND D6,(A4) ;DRAW LINE
|
|
BRA.S DONE ;RESTORE CURSOR AND QUIT
|
|
|
|
|
|
;--------------------------------------------------
|
|
;
|
|
; DRAW AN XOR HORIZONTAL LINE
|
|
;
|
|
HTOGL SUB D1,D2 ;CALC WORDCOUNT
|
|
BEQ.S ENDTOGL ;BR IF ALL IN ONE WORD
|
|
EOR D6,(A4)+ ;DO LEFT WORD WITH MASK
|
|
MOVEQ #-1,D6 ;FLUSH LEFTMASK FOR END
|
|
SUB #1,D2 ;DEC WORD COUNT
|
|
BEQ.S ENDTOGL ;BR IF NO UNMASKED WORDS
|
|
LSR #1,D2 ;HALVE WORDCOUNT FOR LONGCOUNT
|
|
BCC.S TOGLONE ;BR IF EVEN # WORDS LEFT
|
|
EOR D6,(A4)+ ;ELSE MAKE EVEN BY DOING A WORD
|
|
SUB #1,D2 ;ADJUST LONGCOUNT
|
|
BRA.S TOGLMORE ;SEE IF ANY LONGS LEFT TO DO
|
|
TOGLTWO NOT.L (A4)+ ;INVERT A LONG
|
|
TOGLONE NOT.L (A4)+ ;INVERT ANOTHER LONG
|
|
SUB #2,D2 ;ANY UNMASKED LONGS LEFT ?
|
|
TOGLMORE BGT TOGLTWO ;YES, AT LEAST TWO LONGS
|
|
BEQ TOGLONE ;YES, FINISH UP LAST LONG
|
|
ENDTOGL AND D3,D6 ;COMBINE LEFT AND RIGHT MASK
|
|
EOR D6,(A4) ;DRAW LINE
|
|
BRA.S DONE ;RESTORE CURSOR AND QUIT
|
|
|
|
|
|
;--------------------------------------------
|
|
;
|
|
; DRAW A BLACK HORIZONTAL LINE
|
|
;
|
|
HSET SUB D1,D2 ;CALC WORDCOUNT
|
|
BEQ.S ENDSET ;BR IF ALL IN ONE WORD
|
|
OR D6,(A4)+ ;DO LEFT WORD WITH MASK
|
|
MOVEQ #-1,D6 ;FLUSH LEFTMASK FOR END
|
|
SUB #1,D2 ;DEC WORD COUNT
|
|
BEQ.S ENDSET ;BR IF NO UNMASKED WORDS
|
|
LSR #1,D2 ;HALVE WORDCOUNT FOR LONGCOUNT
|
|
BCC.S SETONE ;BR IF EVEN # WORDS LEFT
|
|
MOVE D6,(A4)+ ;ELSE MAKE EVEN BY DOING A WORD
|
|
SUB #1,D2 ;ADJUST LONGCOUNT
|
|
BRA.S SETMORE ;SEE IF ANY LONGS LEFT TO DO
|
|
SETTWO MOVE.L D6,(A4)+ ;FILL A LONG WITH BLACK
|
|
SETONE MOVE.L D6,(A4)+ ;FILL ANOTHER LONG
|
|
SUB #2,D2 ;ANY UNMASKED LONGS LEFT ?
|
|
SETMORE BGT SETTWO ;YES, AT LEAST TWO LONGS
|
|
BEQ SETONE ;YES, FINISH UP LAST LONG
|
|
ENDSET AND D3,D6 ;COMBINE LEFT AND RIGHT MASK
|
|
OR D6,(A4) ;DRAW LINE
|
|
BRA.S DONE ;RESTORE CURSOR AND QUIT
|
|
|
|
|
|
;-------------------------------------------------------
|
|
;
|
|
; DRAW A VERTICAL LINE.
|
|
;
|
|
VLINE BSR.S HVSETUP ;GET DSTPTR,ROWBYTES,HGLOBAL
|
|
MOVE 64(A0,D0),D0 ;GET BITMASK IN D0
|
|
MOVE MINRECT+BOTTOM(A6),D1 ;GET BOTTOM
|
|
SUB MINRECT+TOP(A6),D1 ;CALC HEIGHT
|
|
SUB #1,D1 ;INIT HEIGHT COUNT
|
|
CMP #1,MODE(A6) ;WHICH MODIFIED MODE ?
|
|
BLT.S VSET ;BR IF BLACK
|
|
BEQ.S VTOGL ;BR IF XOR
|
|
;ELSE WHITE
|
|
NOT D0 ;MAKE NOTMASK
|
|
VCLR AND D0,(A4) ;CLEAR ONE DOT
|
|
ADD D7,A4 ;BUMP TO NEXT ROW
|
|
DBRA D1,VCLR ;LOOP ALL DOTS
|
|
BRA.S DONE ;RESTORE CURSOR AND QUIT
|
|
|
|
VTOGL EOR D0,(A4) ;TOGGLE ONE DOT
|
|
ADD D7,A4 ;BUMP TO NEXT ROW
|
|
DBRA D1,VTOGL ;LOOP ALL DOTS
|
|
BRA.S DONE ;RESTORE CURSOR AND QUIT
|
|
|
|
VSET OR D0,(A4) ;SET ONE DOT
|
|
ADD D7,A4 ;BUMP TO NEXT ROW
|
|
DBRA D1,VSET ;LOOP ALL DOTS
|
|
BRA.S DONE ;RESTORE CURSOR AND QUIT
|
|
|
|
|
|
|
|
;------------------------------------------------------------------------
|
|
;
|
|
; LOCAL ROUTINE TO SET UP POINTER TO FIRST WORD, BIT INDEX, AND ROWBYTES
|
|
;
|
|
; INPUTS: MINRECT
|
|
; A5: thePort
|
|
;
|
|
; OUTPUTS: D0: STARTING HORIZ GLOBAL COORDS
|
|
; D1: STARTING HORIZ GLOBAL DIV 16
|
|
; D7: ROWBYTES
|
|
; A0: MaskTab
|
|
; A4: POINTER TO FIRST WORD
|
|
;
|
|
; CLOBBERS: D0,D1,D7,A0,A4
|
|
;
|
|
HVSETUP MOVE.L PORTBITS+BASEADDR(A5),A4 ;GET BITMAP START
|
|
MOVE MINRECT+TOP(A6),D0 ;GET STARTING VERT
|
|
SUB PORTBITS+BOUNDS+TOP(A5),D0 ;CONVERT TO GLOBAL
|
|
MOVE PORTBITS+ROWBYTES(A5),D7 ;GET ROWBYTES
|
|
MULU D7,D0 ;MULT TOP BY ROWBYTES
|
|
ADD.L D0,A4 ;ADD TO BASEADDR
|
|
MOVE MINRECT+LEFT(A6),D0 ;GET STARTING HORIZ
|
|
SUB PORTBITS+BOUNDS+LEFT(A5),D0 ;CONVERT TO GLOBAL
|
|
MOVE D0,D1 ;MAKE A COPY
|
|
LSR #4,D1 ;CONVERT BITS TO WORDS
|
|
ADD D1,A4 ;ADD TO RUNNING TOTAL
|
|
ADD D1,A4 ;TWICE FOR BYTES
|
|
LEA MaskTab,A0 ;return with masktab in A0
|
|
AND #$F,D0 ;TREAT LEFT MOD 16
|
|
ADD D0,D0 ;DOUBLE FOR TABLE
|
|
RTS
|
|
|
|
|
|
END
|
|
|
|
|
|
|
|
|