QuickDraw/Util.a

838 lines
33 KiB
Plaintext
Executable File

.INCLUDE GRAFTYPES.TEXT
;-------------------------------------------------------------
;
; --> UTIL.TEXT
;
; SMALL UTILITY ROUTINES USED BY QuickDraw.
;
.FUNC BitNot,1
;-----------------------------------------------------------
;
; Function BitNot(long: LongInt): LongInt;
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
NOT.L (SP) ;INVERT LONG
MOVE.L (SP)+,(SP) ;STORE INTO RESULT
JMP (A0) ;AND RETURN
.FUNC BitAnd,2
.DEF BitXor,BitOr,BitShift
;-----------------------------------------------------------
;
; Function BitAnd(long1,long2: LongInt): LongInt;
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;GET ONE LONG
AND.L (SP)+,D0 ;AND IT WITH THE OTHER
BRA.S DONE ;AND STORE RESULT
;-----------------------------------------------------------
;
; Function BitXor(long1,long2: LongInt): LongInt;
;
BitXor MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;GET ONE LONG
MOVE.L (SP)+,D1 ;GET THE SECOND
EOR.L D1,D0 ;XOR BOTH
BRA.S DONE ;AND STORE RESULT
;-----------------------------------------------------------
;
; Function BitOr(long1,long2: LongInt): LongInt;
;
BitOr MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;GET ONE LONG
OR.L (SP)+,D0 ;OR IT WITH THE OTHER
BRA.S DONE ;AND STORE RESULT
;-----------------------------------------------------------
;
; Function BitShift(long: LongInt; count: INTEGER): LongInt;
;
; positive count --> shift left.
; negative count --> shift right.
;
BitShift MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE (SP)+,D1 ;GET COUNT
BPL.S SHLEFT ;SHIFT LEFT IF POSITIVE
NEG D1 ;MAKE COUNT POSITIVE
MOVE.L (SP)+,D0 ;GET LONG
LSR.L D1,D0 ;SHIFT IT RIGHT
BRA.S DONE ;AND STORE RESULT
SHLEFT MOVE.L (SP)+,D0 ;GET LONG
LSL.L D1,D0 ;SHIFT IT LEFT
DONE MOVE.L D0,(SP) ;STORE THE RESULT
JMP (A0) ;AND RETURN
.FUNC BitTst,2
.DEF BitSet,BitClr
;---------------------------------------------------------
;
; FUNCTION BitTst(bytePtr: Ptr; bitNum: LongInt): BOOLEAN;
;
BSR.S SHARE
MOVE.L (SP)+,A1 ;GET PTR
BTST D0,0(A1,D1.L) ;TEST THE BIT
SNE (SP) ;SET OR CLEAR RESULT
NEG.B (SP) ;CONVERT -1 TO 1
JMP (A0) ;RETURN
;---------------------------------------------------------
;
; PROCEDURE BitSet(bytePtr: Ptr; bitNum: LongInt);
;
BitSet BSR.S SHARE
MOVE.L (SP)+,A1 ;GET PTR
BSET D0,0(A1,D1.L) ;SET THE BIT
JMP (A0)
;---------------------------------------------------------
;
; PROCEDURE BitClr(bytePtr: Ptr; bitNum: LongInt);
;
BitClr BSR.S SHARE
MOVE.L (SP)+,A1 ;GET PTR
BCLR D0,0(A1,D1.L) ;SET THE BIT
JMP (A0)
;
;
;
SHARE MOVE.L (A7)+,A1
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D1 ;GET BITNUM
MOVE D1,D0 ;COPY IT
ASR.L #3,D1 ;CONVERT BITS TO BYTES
NOT D0 ;REVERSE BIT SENSE
JMP (A1)
.FUNC Random,0
;--------------------------------------------------------------
;
; FUNCTION Random: INTEGER;
;
; returns a signed 16 bit number, and updates unsigned 32 bit randSeed.
;
; recursion is randSeed := (randSeed * 16807) MOD 2147483647.
;
; See paper by Linus Schrage, A More Portable Fortran Random Number Generator
; ACM Trans Math Software Vol 5, No. 2, June 1979, Pages 132-138.
;
; Clobbers D0-D2, A0
;
;
; GET LO 16 BITS OF SEED AND FORM LO PRODUCT
; xalo := A * LoWord(seed)
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE #16807,D0 ;GET A = 7^5
MOVE D0,D2 ;GET A = 7^5
MULU RANDSEED+2(A0),D0 ;CALC LO PRODUCT = XALO
;
; FORM 31 HIGHEST BITS OF LO PRODUCT
; fhi:=HiWord(seed) * ORD4(a) + HiWord(xalo);
;
MOVE.L D0,D1 ;COPY xalo
CLR.W D1
SWAP D1 ;GET HiWord(xalo) as a long
MULU RANDSEED(A0),D2 ;MULT BY HiWord(seed)
ADD.L D1,D2 ;ADD LEFTLO = FHI
;
; GET OVERFLOW PAST 31ST BIT OF FULL PRODUCT
; k:=fhi DIV 32768;
;
MOVE.L D2,D1 ;COPY FHI
ADD.L D1,D1 ;CALC 2 TIMES FHI
CLR.W D1
SWAP D1 ;CALC FHI SHIFTED RIGHT 15 FOR K
;
; ASSEMBLE ALL THE PARTS AND PRE-SUBTRACT P
; seed:=((BitAnd(XALO,$0000FFFF) - P) + BitAnd(fhi,$00007FFF) * b16) + K;
;
AND.L #$0000FFFF,D0 ;GET LO WORD XALO
SUB.L #$7FFFFFFF,D0 ;SUBTRACT P = 2^31-1
AND.L #$00007FFF,D2 ;BitAnd(fhi,$00007FFF)
SWAP D2 ;TIMES 64K
ADD.L D1,D2 ;PLUS K
ADD.L D2,D0 ;CALC TOTAL
;
; IF seed < 0 THEN seed:=seed+p;
;
BPL.S UPDATE
ADD.L #$7FFFFFFF,D0
UPDATE MOVE.L D0,RANDSEED(A0) ;UPDATE SEED
CMP.W #$8000,D0 ;IS NUMBER -32768 ?
BNE.S NUMOK ;NO, CONTINUE
CLR D0 ;YES, RETURN ZERO INSTEAD
NUMOK MOVE.W D0,4(SP) ;RETURN LO WORD AS RESULT
RTS
.PROC ForeColor,1
.DEF BackColor,PortLong,ColorBit,PortWord
;--------------------------------------------------------------
;
; PROCEDURE ForeColor(color: LongInt);
;
MOVEQ #FGCOLOR,D0 ;GET OFFSET TO FGCOLOR
BRA.S PortLong ;INSTALL A LONG
;--------------------------------------------------------------
;
; PROCEDURE BackColor(color: LongInt);
;
BackColor
MOVEQ #BKCOLOR,D0 ;GET OFFSET TO FGCOLOR
;
; FALL THRU INTO PORTLONG
;
;-------------------------------------------------------
;
; PROCEDURE PortLong(long: LongInt);
; INSTALL A LONG INTO CURRENT GRAFPORT. ENTER WITH OFFSET IN D0
;
PortLong
MOVE.L (SP)+,A1 ;POP RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
MOVE.L (SP)+,0(A0,D0) ;INSTALL WORD INTO THEPORT
JMP (A1) ;AND RETURN
;--------------------------------------------------------------
;
; PROCEDURE ColorBit(whichBit: INTEGER);
;
ColorBit
MOVEQ #COLRBIT,D0 ;GET OFFSET TO COLRBIT
;FALL THRU INTO PORTWORD
;-------------------------------------------------------
;
; PROCEDURE PortWord(word: INTEGER);
; INSTALL A WORD INTO CURRENT GRAFPORT. ENTER WITH OFFSET IN D0
;
PortWord
MOVE.L (SP)+,A1 ;POP RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
MOVE.W (SP)+,0(A0,D0) ;INSTALL WORD INTO THEPORT
JMP (A1) ;AND RETURN
.PROC GetMaskTab,0
.DEF LeftMask,RightMask,BitMask,MaskTab
;----------------------------------------------------------
;
; ASSEMBLY LANGUAGE CALLABLE PROCEDURES LEFTMASK, RIGHTMASK, AND BITMASK:
;
; ENTER WITH COORDINATE IN D0, RETURNS WITH 16 BIT MASK IN D0
; NO OTHER REGISTERS ALTERED.
;
LEA MaskTab,A0 ;POINT TO MASK TABLE
RTS ;AND RETURN
LeftMask
AND #$F,D0 ;TREAT MOD 16
ADD D0,D0 ;DOUBLE FOR TABLE
MOVE MASKTAB+32(D0),D0 ;GET LEFTMASK
RTS
RIGHTMASK
AND #$F,D0 ;TREAT MOD 16
ADD D0,D0 ;DOUBLE FOR TABLE
MOVE MASKTAB(D0),D0 ;GET RIGHT MASK
RTS
BITMASK AND #$F,D0 ;TREAT MOD 16
ADD D0,D0 ;DOUBLE FOR TABLE
MOVE MASKTAB+64(D0),D0 ;GET BITMASK
RTS
MASKTAB .WORD $0000,$8000,$C000,$E000 ;TABLE OF 16 RIGHT MASKS
.WORD $F000,$F800,$FC00,$FE00
.WORD $FF00,$FF80,$FFC0,$FFE0
.WORD $FFF0,$FFF8,$FFFC,$FFFE
.WORD $FFFF,$7FFF,$3FFF,$1FFF ;TABLE OF 16 LEFT MASKS
.WORD $0FFF,$07FF,$03FF,$01FF
.WORD $00FF,$007F,$003F,$001F
.WORD $000F,$0007,$0003,$0001
.WORD $8000,$4000,$2000,$1000 ;TABLE OF 16 BIT MASKS
.WORD $0800,$0400,$0200,$0100
.WORD $0080,$0040,$0020,$0010
.WORD $0008,$0004,$0002,$0001
.PROC PatExpand,0
;----------------------------------------------------------
;
; EXPAND AN 8 BYTE PATTERN OUT TO 16 LONGS.
;
; CALLED ONLY FROM BITBLT,RGNBLT,DRAWLINE,DRAWARC.
;
; INPUTS: A0: POINTS TO 8 BYTE PATTERN
; A1: POINTS TO 16 LONGS OF DESTINATION
; A5: PASCAL GLOBAL PTR
; D2: HORIZONTAL GLOBAL-LOCAL OFFSET USED FOR PRE-ROTATE
; D7: -1 TO INVERT, ELSE 0
; patStretch AND PATALIGN
;
; OUTPUTS: 16 LONGS OF EXPANDED PATTERN
;
; CLOBBERS: D0,D1,D2,A0,A1
;
PARAMSIZE .EQU 0
TWOPAT .EQU -16 ;ROOM FOR TWO COPIES OF PAT
VARSIZE .EQU TWOPAT ;TOTAL BYTES OF LOCAL VARS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVE.L A4,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
;
; IF PATALIGN VERT NON-ZERO, COPY PAT TWICE AND REPLACE A0
;
MOVEQ #7,D0
AND PATALIGN(A4),D0 ;GET PATALIGN MOD 8
BEQ.S VERTOK ;SKIP IF ZERO
MOVE.L (A0),TWOPAT(A6) ;MAKE TWO COPIES OF PATTERN
MOVE.L (A0)+,TWOPAT+8(A6)
MOVE.L (A0),TWOPAT+4(A6)
MOVE.L (A0),TWOPAT+12(A6)
LEA TWOPAT(A6),A0
ADD D0,A0
VERTOK
ADD PATALIGN+H(A4),D2 ;ADJUST FOR PATALIGN HORIZ
MOVEQ #7,D1 ;INIT COUNT OF 8 BYTES
AND D1,D2 ;TREAT SHIFTCOUNT MOD 8
MOVE.L THEPORT(A4),A4 ;GET CURRENT GRAFPORT
MOVE patStretch(A4),D0 ;GET patStretch
CMP #2,D0 ;IS patStretch = 2 ?
BEQ.S DOUBLE ;YES, DOUBLE
CMP #-2,D0 ;IS PAT STRETCH = -2 ?
BEQ.S THIN ;YES, STRETCH THIN
;ANY OTHER, USE NORMAL
;---------------------------------------------------------
;
; NORMAL PATTERN. SIMPLY REPLICATE THE 8 BY 8 PATTERN.
;
NORMAL MOVE.B (A0)+,D0 ;GET A BYTE OF PATTERN
EOR.B D7,D0 ;INVERT IT IF MODE BIT 2
ROL.B D2,D0 ;ALIGN TO LOCAL COORDS
MOVE.B D0,(A1)+ ;PUT ONE BYTE
MOVE.B D0,(A1)+ ;PUT ANOTHER TO MAKE A WORD
MOVE.W -2(A1),(A1)+ ;STRETCH WORD OUT TO LONG
MOVE.L -4(A1),32-4(A1) ;DUPLICATE 8 SCANS LATER
DBRA D1,NORMAL ;LOOP ALL 8 INPUT BYTES
BRA.S DONE
;-----------------------------------------------------------
;
; STRETCHED BY TWO: DOUBLE EACH BIT HORIZONTALLY AND VERTICALLY
;
DOUBLE CLR D0 ;CLEAR OUT HI BYTE
DLOOP MOVE.B (A0)+,D0 ;GET A BYTE OF PATTERN
EOR.B D7,D0 ;INVERT IT IF MODE BIT 2
ROL.B D2,D0 ;ALIGN TO LOCAL COORDS
MOVE.B D0,-(SP) ;STASH FOR A WHILE
LSR.B #4,D0 ;GET HI NIBBLE
MOVE.B STRETCH(D0),(A1)+ ;PUT ONE BYTE
MOVEQ #$F,D0 ;MASK FOR LO NIBBLE
AND.B (SP)+,D0 ;GET THE LO NIBBLE
MOVE.B STRETCH(D0),(A1)+ ;PUT ANOTHER TO MAKE A WORD
MOVE.W -2(A1),(A1)+ ;STRETCH WORD OUT TO LONG
MOVE.L -4(A1),(A1)+ ;STRETCH LONG TO TWO LONGS
DBRA D1,DLOOP ;LOOP ALL 8 INPUT BYTES
BRA.S DONE
;-----------------------------------------------------------
;
; STRETCH BY TWO AND THIN OUT THE BITS. ADD EXTRA WHITE DOTS.
;
THIN CLR D0 ;CLEAR OUT HI BYTE
THINLP MOVE.B (A0)+,D0 ;GET A BYTE OF PATTERN
EOR.B D7,D0 ;INVERT IT IF MODE BIT 2
ROL.B D2,D0 ;ALIGN TO LOCAL COORDS
MOVE.B D0,-(SP) ;STASH FOR A WHILE
LSR.B #4,D0 ;GET HI NIBBLE
MOVE.B THINSTR(D0),(A1)+ ;PUT ONE BYTE
MOVEQ #$F,D0 ;MASK FOR LO NIBBLE
AND.B (SP)+,D0 ;GET THE LO NIBBLE
MOVE.B THINSTR(D0),(A1)+ ;PUT ANOTHER TO MAKE A WORD
MOVE.W -2(A1),(A1)+ ;STRETCH WORD OUT TO LONG
CLR.L (A1)+ ;STRETCH LONG TO TWO LONGS
DBRA D1,THINLP ;LOOP ALL 8 INPUT BYTES
DONE MOVE.L (SP)+,A4 ;RESTORE REG
UNLINK PARAMSIZE,'PATEXPAN'
;----------------------------------------------------------------
;
; BIT DOUBLING TABLE FOR 0..15 INPUT --> BYTE OUTPUT
;
STRETCH .BYTE $00,$03,$0C,$0F,$30,$33,$3C,$3F
.BYTE $C0,$C3,$CC,$CF,$F0,$F3,$FC,$FF
;
; TABLE FOR THIN DOUBLING.
;
THINSTR .BYTE $00,$01,$04,$05,$10,$11,$14,$15
.BYTE $40,$41,$44,$45,$50,$51,$54,$55
.PROC ColorMap,2
;----------------------------------------------------------------
;
; PROCEDURE ColorMap(mode: INTEGER, pat: Pattern);
;
; ADJUST INPUT MODE AND PATTERN TO ACCOMPLISH COLOR SEPARATION.
; Returns (altered) mode and pat on the stack where they were.
; PRESERVES ALL REGISTERS.
;
MOVEM.L D0-D3/A0,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L A0,D0 ;IS THEPORT NIL ?
BEQ.S COLOROK ;YES, LEAVE COLOR ALONE
BTST #0,D0 ;IS THEPORT ODD ?
BNE.S COLOROK ;YES, LEAVE COLOR ALONE
MOVE COLRBIT(A0),D2 ;GET COLOR BIT SELECT
BEQ.S COLOROK ;COLORBIT = 0 MEANS NO COLOR
MOVE 28(SP),D3 ;GET INPUT MODE
MOVEQ #3,D0 ;MASK FOR BOTTOM 2 BITS
AND D3,D0 ;GET 2 BITS OF MODE
BEQ.S COPY ;BR IF COPY MODE
;
; THE XOR MODES DEPEND ON NEITHER FOREGROUND OR BACKGROUND COLOR
;
CMP #2,D0 ;IS IT SOME KIND OF XOR ?
BEQ.S COLOROK ;YES, THEY DON'T CHANGE
BGT.S BICMODE ;BRANCH IF BIC
;ELSE MUST BE OR
;
; THE OR MODES DEPEND ONLY ON THE FOREGROUND COLOR
;
ORMODE MOVE.L FGCOLOR(A0),D1 ;GET FOREGROUND COLOR
SHARE BTST D2,D1 ;TEST FOREGROUND COLOR BIT
BNE.S COLOROK ;NO CHANGE IF FG TRUE
EOR #2,D3 ;ELSE INVERT MODE BIT 2
BRA.S NEWMODE ;UPDATE MODE AND QUIT
;
; THE BIC MODES DEPEND ONLY ON THE BACKGROUND COLOR
;
BICMODE MOVE.L BKCOLOR(A0),D1 ;GET BACKGROUND COLOR
NOT.L D1 ;INVERT IT
BRA SHARE ;AND SHARE CODE
;
; THE COPY MODES DEPEND ON BOTH FOREGOUND AND BACKGROUND
;
COPY MOVE.L FGCOLOR(A0),D0 ;GET FOREGROUND COLOR
MOVE.L BKCOLOR(A0),D1 ;GET BACKGROUND COLOR
BTST D2,D0 ;TEST FOREGROUND COLOR BIT
BEQ.S FORE0 ;BRANCH IF IT'S ZERO
FORE1 BTST D2,D1 ;TEST BACKGROUND COLOR BIT
BEQ.S COLOROK ;NO CHANGE IF BKGND FALSE
MOVEQ #8,D3 ;ELSE REPLACE MODE = PAT COPY
USEPAT MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
LEA BLACK(A0),A0 ;POINT TO BLACK PATTERN
MOVE.L A0,24(SP) ;REPLACE PATTERN WITH BLACK
BRA.S NEWMODE ;UPDATE MODE AND QUIT
FORE0 BTST D2,D1 ;TEST BACKGROUND COLOR BIT
BNE.S INVMODE ;IF BK TRUE, INVERT MODE
MOVEQ #12,D3 ;ELSE REPLACE MODE = NOTPAT COPY
BRA.S USEPAT ;AND PATTERN WITH BLACK
INVMODE EOR #4,D3 ;USE INVERSE OF MODE
NEWMODE MOVE D3,28(SP) ;CHANGE INPUT MODE
COLOROK MOVEM.L (SP)+,D0-D3/A0 ;RESTORE REGS
RTS ;AND RETURN
.FUNC GetPixel,2
.REF HideCursor,ShowCursor
;---------------------------------------------------------
;
; FUNCTION GetPixel(h,v: INTEGER): BOOLEAN;
;
; Returns TRUE if the pixel at (h,v) is set to black.
; h and v are in local coords of the current grafport.
;
; CLOBBERS A0,A1,D0,D1,D2
;
JSR HIDECURSOR ;GET RID OF CURSOR
MOVE.L (SP)+,D2 ;POP RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A1 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A1),A1 ;GET THEPORT
MOVE (SP)+,D0 ;GET VERT COORD
SUB PORTBITS+BOUNDS+TOP(A1),D0 ;CONVERT TO GLOBAL COORDS
MOVE (SP)+,D1 ;GET HORIZ COORD
SUB PORTBITS+BOUNDS+LEFT(A1),D1 ;CONVERT TO GLOBAL
MULU PORTBITS+ROWBYTES(A1),D0 ;CALC VERT * ROWBYTES
MOVE.L PORTBITS+BASEADDR(A1),A1 ;GET BASEADDR
ADD.L D0,A1 ;ADD VERTICAL OFFSET
MOVE D1,D0 ;COPY HORIZ
NOT D0 ;INVERT FOR BIT INDEX
LSR #3,D1 ;CONVERT DOTS TO BYTES
BTST D0,0(A1,D1) ;TEST ONE SCREEN BIT
SNE (SP) ;SET BOOLEAN RESULT
NEG.B (SP) ;MAKE $FF --> $01
MOVE.L D2,-(SP) ;PUSH RETURN ADDR
JMP SHOWCURSOR ;RESTORE CURSOR AND RETURN
.PROC StuffHex,2
;-------------------------------------------------------
;
; PROCEDURE STUFFHEX(THINGPTR: WORDPTR; S: STR255);
;
; CONVENIENCE ROUTINE TO STUFF HEX INTO ANY VARIABLE.
; BEWARE, NO RANGE-CHECKING.
;
MOVE.L 4(SP),A0 ;A0:=ADDR OF STRING
MOVE.L 8(SP),A1 ;A1:=THINGPTR
MOVE.L (SP),8(SP) ;CLEAN OFF STACK
ADD #8,SP ;POINT TO RETURN ADDR
MOVE.B (A0)+,D2 ;GET STRING LENGTH
AND #$00FE,D2 ;TRUNCATE LENGTH TO EVEN
BEQ.S ENDHEX ;QUIT IF LENGTH = 0
HEXLOOP BSR.S NEXTHEX ;GET HEX DIGIT AND CONVERT TO BINARY
MOVE.B D0,D1 ;SAVE MOST SIG DIGIT
BSR.S NEXTHEX ;GET HEX DIGIT AND CONVERT TO BINARY
LSL.B #4,D1 ;SHIFT MOST SIG INTO PLACE
ADD.B D0,D1 ;FILL IN LS NIBBLE
MOVE.B D1,(A1)+ ;STUFF BYTE INTO THING
SUB #2,D2 ;2 LESS CHARS TO GO
BNE.S HEXLOOP ;LOOP FOR STRING LENGTH
ENDHEX RTS ;RETURN TO PASCAL
;
; LOCAL ROUTINE TO GET NEXT HEX DIGIT AND CONVERT ASCII TO BINARY
;
NEXTHEX MOVE.B (A0)+,D0 ;GET HEX DIGIT FROM STRING
CMP.B #$39,D0 ;IS IT GTR THAN '9' ?
BLE.S SMALL ;NO, DO IT
ADD.B #9,D0 ;YES, ADD CORRECTION
SMALL AND.B #$F,D0 ;TREAT MOD 16, EVEN LOWER CASE OK
RTS
.PROC XorSlab
.REF MaskTab
;-----------------------------------------------------------
;
; LOCAL PROCEDURE XorSlab(bufAddr: Ptr; left,right: INTEGER);
;
; Enter with:
;
; A0: bufAddr
; D3: left coord
; D4: right coord
;
; Clobbers: A0,D0,D1,D3,D4,D5,D6
;
;
; GET LEFTMASK AND RIGHTMASK
;
MOVE.L A0,D1 ;save bufAddr
LEA MASKTAB,A0 ;point to mask table
MOVEQ #$F,D0 ;get mask for 4 lo bits
MOVE D3,D5 ;COPY LEFT COORD
AND D0,D5 ;CALC LEFT MOD 16
ADD D5,D5 ;DOUBLE FOR TABLE INDEX
MOVE 0(A0,D5),D5 ;GET MASK FROM TABLE
NOT D5 ;INVERT FOR LEFTMASK
MOVE D4,D6 ;COPY RIGHT COORD
AND D0,D6 ;TREAT RIGHT MOD 16
ADD D6,D6 ;DOUBLE FOR TABLE INDEX
MOVE 0(A0,D6),D6 ;GET RIGHTMASK IN D6
MOVE.L D1,A0 ;RESTORE SAVED bufAddr
;
; CALC LEFTWORD, BUFPTR, WORDCOUNT
;
ASR #4,D3 ;CONVERT DOTS TO WORDS
ADD D3,A0 ;ADD TO bufAddr
ADD D3,A0 ;TWICE FOR BYTE OFFSET
ASR #4,D4 ;CALC RIGHT DIV 16
SUB D3,D4 ;WORDCOUNT:=RIGHTWORD-LEFTWORD
BGT.S NOTIN1 ;BR IF NOT ALL IN ONE
;
; LEFT AND RIGHT ARE ALL IN ONE WORD
;
AND D5,D6 ;COMBINE LEFT AND RIGHT MASKS
EOR D6,(A0) ;XOR RIGHTMASK INTO BUFFER
RTS ;AND RETURN
;
; NOT ALL IN ONE WORD. DO LEFT, MIDDLE IF ANY, THEN RIGHT
;
NOTIN1 EOR D5,(A0)+ ;XOR LEFTMASK INTO BUFFER
BRA.S TEST ;SEE IF ANY FULL WORDS
INVLONG NOT.L (A0)+ ;INVERT 2 WHOLE WORDS
TEST SUBQ #2,D4 ;ANY FULL WORDS LEFT ?
BGT INVLONG ;YES, AT LEAST 2
BLT.S ENDWORD ;NO, FINISH UP LAST WITH MASK
NOT (A0)+ ;YES, DO LAST FULL WORD
ENDWORD EOR D6,(A0) ;XOR RIGHTMASK INTO BUFFER
RTS
.PROC DrawSlab,0
.DEF SlabMode,FastSlabMode
.REF MaskTab
;--------------------------------------------------------------
;
; LOCAL PROCEDURE DRAWSLAB
;
; INPUTS:
;
; D0: scratch A0: MASKTAB
; D1: left A1: DSTLEFT, clobbered
; D2: right A2: MASKBUF, clobbered
; D3: A3: MINRECT
; D4: A4: MODECASE
; D5: A5:
; D6: pattern A6:
; D7: A7: stack
;
; CLOBBERS: D0-D3,A1,A2
;
;
;
; CLIP LEFT AND RIGHT TO MINRECT:
;
CMP LEFT(A3),D1 ;IS LEFT < MINRECT.LEFT ?
BGE.S LEFTOK ;NO, CONTINUE
MOVE LEFT(A3),D1 ;YES, LEFT := MINRECT.LEFT
LEFTOK CMP RIGHT(A3),D2 ;IS RIGHT > MINRECT.RIGHT ?
BLE.S RIGHTOK ;NO, CONTINUE
MOVE RIGHT(A3),D2 ;YES, RIGHT := MINRECT.RIGHT
RIGHTOK CMP D2,D1 ;IS LEFT >= RIGHT ?
BGE.S DONESLAB ;YES, QUIT
;
; SET UP LEFTMASK AND RIGHTMASK: (A0 already points to MaskTab)
;
MOVEQ #$F,D3 ;get mask for 4 lo bits
MOVE D1,D0 ;COPY LEFT
AND D3,D1 ;TREAT LEFT MOD 16
ADD D1,D1 ;DOUBLE FOR TABLE
MOVE 32(A0,D1),D1 ;GET LEFTMASK IN D1
AND D2,D3 ;GET RIGHT MOD 16
ADD D3,D3 ;DOUBLE FOR TABLE
MOVE 0(A0,D3),D3 ;GET RIGHTMASK IN D3
;
; CALC WORDCOUNT, DSTPTR, MASKPTR, AND TAKE CASE JUMP
;
ASR #4,D2 ;CONVERT RIGHT TO WORDS
ASR #4,D0 ;CONVERT LEFT TO WORDS
SUB D0,D2 ;CALC WORD COUNT
ADD D0,D0 ;DOUBLE FOR BYTES
ADD D0,A1 ;OFFSET DSTPTR
ADD D0,A2 ;OFFSET MASKPTR
TST D2 ;SET Z-FLAG BASED ON WORDCOUNT
JMP (A4) ;TAKE MODECASE TO DRAW SLAB
DONESLAB RTS
;---------------------------------------------------------
;
; INTERFACE TO EACH SCAN LINE ROUTINE:
;
; ENTER WITH Z-FLAG SET IF ALL IN ONE WORD
;
; INPUTS: A1: DSTPTR
; A2: MASKPTR
; D1: LEFTMASK
; D2: WORDCNT
; D3: RIGHTMASK
; D6: PATTERN
;
; CLOBBERS: D0,D1,D2,A1,A2
;
;-------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST
;
END8 AND D3,D1 ;COMBINE RIGHT AND LEFT MASK
NEXT8 MOVE D6,D0 ;GET PATTERN DATA
AND (A2)+,D1 ;MERGE MASK AND CLIPRGN MASK
AND D1,D0 ;MASK PATTERN DATA
NOT D1 ;MAKE NOTMASK
AND (A1),D1 ;AND NOTMASK WITH OLD DST
OR D0,D1 ;FILL HOLE WITH PATTERN
MOVE D1,(A1)+ ;UPDATE DST
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
MASK8 BGT NEXT8 ;LOOP FOR ALL WORDS IN ROW
BEQ END8 ;DO LAST WORD WITH MASK
RTS
;-------------------------------------------------------
;
; MODE 9 OR 13: PATTERN OR DST --> DST
;
END9 AND D3,D1 ;COMBINE RIGHT AND LEFT MASK
NEXT9 AND D6,D1 ;GET PATTERN DATA
AND (A2)+,D1 ;MERGE MASK AND CLIPRGN MASK
OR D1,(A1)+ ;OR RESULT INTO DST
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
MASK9 BGT NEXT9 ;LOOP FOR ALL WORDS IN ROW
BEQ END9 ;DO LAST WORD WITH MASK
RTS
;-------------------------------------------------------
;
; MODE 10 OR 14: PATTERN XOR DST --> DST
;
END10 AND D3,D1 ;COMBINE RIGHT AND LEFT MASK
NEXT10 AND D6,D1 ;GET PATTERN DATA
AND (A2)+,D1 ;MERGE MASK AND CLIPRGN MASK
EOR D1,(A1)+ ;XOR RESULT INTO DST
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
MASK10 BGT NEXT10 ;LOOP FOR ALL WORDS IN ROW
BEQ END10 ;DO LAST WORD WITH MASK
RTS
;-------------------------------------------------------
;
; MODE 11 OR 15: PATTERN BIC DST --> DST
;
END11 AND D3,D1 ;COMBINE RIGHT AND LEFT MASK
NEXT11 AND D6,D1 ;GET PATTERN DATA
AND (A2)+,D1 ;MERGE MASK AND CLIPRGN MASK
NOT D1 ;INVERT FOR BIC
AND D1,(A1)+ ;BIC RESULT INTO DST
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
MASK11 BGT NEXT11 ;LOOP FOR ALL WORDS IN ROW
BEQ END11 ;DO LAST WORD WITH MASK
RTS
;--------------------------------------------
;
; PROCEDURE SlabMode
;
; INPUT: D2: MODE, CLOBBERED
; OUTPUT: A4: MODECASE
;
SlabMode
AND #$3,D2 ;GET LO 2 BITS OF MODE
LEA MODETAB,A4 ;POINT TO MODE TABLE
MOVE.B 0(A4,D2),D2 ;GET OFFSET FROM MODETAB
SUB D2,A4 ;GET CASE JUMP ADDRESS
RTS
MODETAB .BYTE MODETAB-MASK8
.BYTE MODETAB-MASK9
.BYTE MODETAB-MASK10
.BYTE MODETAB-MASK11
;---------------------------------------------------------------
;
; FAST LOOPS, OPTIMIZED FOR BLACK PATTERN AND RECTANGLE CLIPPED
;
; FAST BLACK SLAB:
;
FAST8 BEQ.S MERGE8 ;BR IF ALL IN ONE WORD
OR D1,(A1)+ ;OR LEFTMASK INTO DST
SUB #2,D2 ;ADJUST WORDCOUNT FOR DBRA
BLT.S LAST8 ;BR IF NO UNMASKED WORDS
MOVEQ #-1,D1 ;GET SOME BLACK
LOOP8 MOVE D1,(A1)+ ;WRITE A WORD OF BLACK
DBRA D2,LOOP8 ;LOOP ALL UNMASKED WORDS
MERGE8 AND D1,D3 ;COMBINE LEFTMASK AND RIGHTMASK
LAST8 OR D3,(A1)+ ;OR RIGHTMASK INTO DST
RTS ;AND RETURN
;
; FAST XOR SLAB:
;
FAST10 BEQ.S MERGE10 ;BR IF ALL IN ONE WORD
EOR D1,(A1)+ ;XOR LEFTMASK INTO DST
SUB #2,D2 ;ADJUST WORDCOUNT FOR DBRA
BLT.S LAST10 ;BR IF NO UNMASKED WORDS
LOOP10 NOT (A1)+ ;INVERT A WORD OF DST
DBRA D2,LOOP10 ;LOOP ALL UNMASKED WORDS
BRA.S LAST10 ;THEN FINISH UP LAST WITH MASK
MERGE10 AND D1,D3 ;COMBINE LEFTMASK AND RIGHTMASK
LAST10 EOR D3,(A1)+ ;XOR RIGHTMASK INTO DST
RTS ;AND RETURN
;
; FAST WHITE SLAB:
;
FAST11 BEQ.S MERGE11 ;BR IF ALL IN ONE WORD
NOT D1 ;FORM NOT LEFTMASK
AND D1,(A1)+ ;AND NOT LEFTMASK INTO DST
SUB #2,D2 ;ADJUST WORDCOUNT FOR DBRA
BLT.S LAST11 ;BR IF NO UNMASKED WORDS
LOOP11 CLR (A1)+ ;CLEAR A WORD OF DST
DBRA D2,LOOP11 ;LOOP ALL UNMASKED WORDS
BRA.S LAST11 ;THEN FINISH UP LAST WITH MASK
MERGE11 AND D1,D3 ;COMBINE LEFTMASK AND RIGHTMASK
LAST11 NOT D3 ;FORM NOT RIGHTMASK
AND D3,(A1)+ ;AND NOT RIGHTMASK INTO DST
RTS ;AND RETURN
;--------------------------------------------------------------------
;
; PROCEDURE FastSlabMode, Call when rect clipped and pattern black.
;
; INPUT: D2: MODE, CLOBBERED mode 0=black, 1=xor, 2=white
; OUTPUT: A4: MODECASE
;
FastSlabMode
AND #$3,D2 ;GET LO 2 BITS OF MODE
LEA FASTTAB,A4 ;POINT TO MODE TABLE
MOVE.B 0(A4,D2),D2 ;GET OFFSET FROM FASTTAB
SUB D2,A4 ;GET CASE JUMP ADDRESS
RTS
FASTTAB .BYTE FASTTAB-FAST8 ;BLACK
.BYTE FASTTAB-FAST10 ;XOR
.BYTE FASTTAB-FAST11 ;WHITE
.END