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

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

888 lines
25 KiB
Plaintext

;
; File: Util.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> 4/5/90 KON Add visRgnChanged call. For color machines it's in QDUtil.a.
; <1.1> 11/11/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <1.3> 10/12/88 CCH Changed Òm.GrafType.aÓ to ÒGrafType.m.aÓ.
; <1.2> 5/18/88 BBM Really fixed include statement
; <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 ÒUTIL.m.aÓ
; 1.1 CCH 11/11/1988 Fixed Header.
; 1.0 CCH 11/ 9/1988 Adding to EASE.
; OLD REVISIONS BELOW
; 1.3 CCH 10/12/1988 Changed Òm.GrafType.aÓ to ÒGrafType.m.aÓ.
; 1.2 BBM 5/18/88 Really fixed include statement
; 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'
;-------------------------------------------------------------
;
; --> UTIL.TEXT
;
; SMALL UTILITY ROUTINES USED BY QuickDraw.
;
VisRgnChanged PROC EXPORT ;<5Apr90 KON>
;-----------------------------------------------------------
;
; Procedure VisRgnChanged(thePort: GrafPort);
;
; This call will be needed for video windows so the mask plane
; for touchstone can be updated. Non-video QD simply returns.
;
move.l (a7)+,(a7)
rts
ENDPROC
BitNot FUNC EXPORT
;-----------------------------------------------------------
;
; 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
BitAnd FUNC EXPORT
EXPORT 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
BitTst FUNC EXPORT
EXPORT 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)
Random FUNC EXPORT
;--------------------------------------------------------------
;
; 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
ForeColor PROC EXPORT
EXPORT 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
GetMaskTab PROC EXPORT
EXPORT 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 DC.W $0000,$8000,$C000,$E000 ;TABLE OF 16 RIGHT MASKS
DC.W $F000,$F800,$FC00,$FE00
DC.W $FF00,$FF80,$FFC0,$FFE0
DC.W $FFF0,$FFF8,$FFFC,$FFFE
DC.W $FFFF,$7FFF,$3FFF,$1FFF ;TABLE OF 16 LEFT MASKS
DC.W $0FFF,$07FF,$03FF,$01FF
DC.W $00FF,$007F,$003F,$001F
DC.W $000F,$0007,$0003,$0001
DC.W $8000,$4000,$2000,$1000 ;TABLE OF 16 BIT MASKS
DC.W $0800,$0400,$0200,$0100
DC.W $0080,$0040,$0020,$0010
DC.W $0008,$0004,$0002,$0001
PatExpand PROC EXPORT
;----------------------------------------------------------
;
; 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 DC.B $00,$03,$0C,$0F,$30,$33,$3C,$3F
DC.B $C0,$C3,$CC,$CF,$F0,$F3,$FC,$FF
;
; TABLE FOR THIN DOUBLING.
;
THINSTR DC.B $00,$01,$04,$05,$10,$11,$14,$15
DC.B $40,$41,$44,$45,$50,$51,$54,$55
ColorMap PROC EXPORT
;----------------------------------------------------------------
;
; 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
BMI.S COLOROK ;COLORBIT NEG 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
GetPixel FUNC EXPORT
IMPORT 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
StuffHex PROC EXPORT
;-------------------------------------------------------
;
; 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
XorSlab PROC EXPORT
IMPORT 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
DrawSlab PROC EXPORT
EXPORT SlabMode,FastSlabMode
IMPORT 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 DC.B MODETAB-MASK8
DC.B MODETAB-MASK9
DC.B MODETAB-MASK10
DC.B 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 DC.B FASTTAB-FAST8 ;BLACK
DC.B FASTTAB-FAST10 ;XOR
DC.B FASTTAB-FAST11 ;WHITE
DC.B 0 ; even pad
END