initial import

This commit is contained in:
Jonathan Ragan-Kelley 2010-07-20 21:37:29 -07:00
commit 646aa270df
38 changed files with 19390 additions and 0 deletions

293
Angles.a Executable file
View File

@ -0,0 +1,293 @@
.INCLUDE GrafTypes.text
.FUNC AngleFromSlope,1
.DEF SlopeFromAngle
;-----------------------------------------------------
;
; FUNCTION AngleFromSlope(slope: Fixed): INTEGER;
;
; Scans slope table for angle and returns angle 0..180
;
MOVE.L 4(SP),D0 ;GET SLOPE
SMI D2 ;REMEMBER IF IT WAS NEGATIVE
BPL.S NOTNEG ;CONTINUE IF POSITIVE
NEG.L D0 ;ELSE MAKE SLOPE POS
NOTNEG SUB.L #500,D0 ;BIAS THE COMPARE
MOVE.L D0,4(SP)
LEA CONTINUE,A0 ;POINT TO TABLE OF SLOPES
MOVEQ #-1,D1 ;INIT ANGLE COUNT
SCAN ADD.W #1,D1
MOVE.W D1,D0
CLR.L -(SP)
BRA.S A2SLOPE
CONTINUE
MOVE.L 8(SP),D0 ;GET SLOPE
CMP.L (SP)+,D0 ;SCAN THRU SLOPE TABLE
BGT.S SCAN
MOVE #180,D0
SUB D1,D0 ;CALC 180-ANGLE = 90..180
TST.B D2 ;WAS DH POS ?
BPL.S DONE ;NO, RETURN 90..180
MOVE D1,D0 ;YES, RETURN 0..90
DONE MOVE.L (SP)+,(SP) ;STRIP PARAM
MOVE.W D0,4(SP) ;RETURN FUNCTION RESULT
RTS
;----------------------------------------------------------------
;
; FUNCTION SlopeFromAngle(angle: INTEGER): Fixed;
;
; calculate the fixed point slope of a line, DH/DV = -65536 * Tan(angle).
; Input angle is treated MOD 180.
;
SlopeFromAngle
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE (SP)+,D0 ;GET INTEGER ANGLE
EXT.L D0 ;SIGN EXTEND FOR DIVIDE
DIVS #180,D0 ;TREAT ANGLE MOD 180
SWAP D0 ;GET THE REMAINDER
TST D0 ;WAS IT NEGATIVE ?
BPL.S OK1 ;NO, CONTINUE
ADD #180,D0 ;YES, PUT IN RANGE 0..179
OK1 MOVE #$8000,(SP)
A2SLOPE CMP #90,D0
BLE.S OK2
CLR.W (SP)
SUB #180,D0
NEG D0
OK2 CMP #45,D0
BLT.S SHARE
ADD #1,(SP)
CMP #64,D0
BLT.S SHARE
MOVE.B SLOPE-91(D0),1(SP)
BPL.S SHARE
OR.B #$7F,(SP)
SHARE ADD D0,D0
MOVE.W SLOPE(D0),2(SP)
CHECK BCLR #7,(SP)
BEQ.S OK3
NEG.L (SP)
OK3 JMP (A0)
; .BYTE $01 ;45
; .BYTE $01
; .BYTE $01
; .BYTE $01
; .BYTE $01
; .BYTE $01 ;50
; .BYTE $01
; .BYTE $01
; .BYTE $01
; .BYTE $01
; .BYTE $01 ;55
; .BYTE $01
; .BYTE $01
; .BYTE $01
; .BYTE $01
; .BYTE $01 ;60
; .BYTE $01
; .BYTE $01
.BYTE $01
.BYTE $02
.BYTE $02 ;65
.BYTE $02
.BYTE $02
.BYTE $02
.BYTE $02
.BYTE $02 ;70
.BYTE $02
.BYTE $03
.BYTE $03
.BYTE $03
.BYTE $03 ;75
.BYTE $04
.BYTE $04
.BYTE $04
.BYTE $05
.BYTE $05 ;80
.BYTE $06
.BYTE $07
.BYTE $08
.BYTE $09
.BYTE $0B ;85
.BYTE $0E
.BYTE $13
.BYTE $1C
.BYTE $39
.BYTE $FF ;90
SLOPE
.WORD $0000 ;0
.WORD $0478
.WORD $08F1
.WORD $0D6B
.WORD $11E7
.WORD $1666 ;5
.WORD $1AE8
.WORD $1F6F
.WORD $23FA
.WORD $288C
.WORD $2D24 ;10
.WORD $31C3
.WORD $366A
.WORD $3B1A
.WORD $3FD4
.WORD $4498 ;15
.WORD $4968
.WORD $4E44
.WORD $532E
.WORD $5826
.WORD $5D2D ;20
.WORD $6245
.WORD $676E
.WORD $6CAA
.WORD $71FB
.WORD $7760 ;25
.WORD $7CDC
.WORD $8270
.WORD $881E
.WORD $8DE7
.WORD $93CD ;30
.WORD $99D2
.WORD $9FF7
.WORD $A640
.WORD $ACAD
.WORD $B341 ;35
.WORD $B9FF
.WORD $C0E9
.WORD $C802
.WORD $CF4E
.WORD $D6CF ;40
.WORD $DE8A
.WORD $E681
.WORD $EEB9
.WORD $F737
.WORD $0000 ;45
.WORD $0919
.WORD $1287
.WORD $1C51
.WORD $267F
.WORD $3117 ;50
.WORD $3C22
.WORD $47AA
.WORD $53B9
.WORD $605B
.WORD $6D9B ;55
.WORD $7B89
.WORD $8A35
.WORD $99AF
.WORD $AA0E
.WORD $BB68 ;60
.WORD $CDD6
.WORD $E177
.WORD $F66E
.WORD $0CE1
.WORD $24FE ;65
.WORD $3EFC
.WORD $5B19
.WORD $799F
.WORD $9AE7
.WORD $BF5B ;70
.WORD $E77A
.WORD $13E3
.WORD $4556
.WORD $7CC7
.WORD $BB68 ;75
.WORD $02C2
.WORD $54DB
.WORD $B462
.WORD $2501
.WORD $ABD9 ;80
.WORD $5051
.WORD $1D88
.WORD $24F3
.WORD $83AD
.WORD $6E17 ;85
.WORD $4CF5
.WORD $14BD
.WORD $A2D7
.WORD $4A30
.WORD $FFFF ;90
.PROC PtToAngle,3
.REF AngleFromSlope
;--------------------------------------------------------------
;
; PROCEDURE PtToAngle(r: Rect; pt: Point; VAR angle: INTEGER);
;
; Given a rectangle and a point, return the angle subtended by pt.
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 12 ;TOTAL BYTES OF PARAMS
RECT .EQU PARAMSIZE+8-4 ;ADDR OF RECT
PT .EQU RECT-4 ;POINT
ANGLE .EQU PT-4 ;ADDR OF INTEGER;
LINK A6,#0 ;NO LOCALS
MOVEM.L D6-D7/A4,-(SP) ;SAVE REGS
MOVE.L RECT(A6),A4 ;POINT TO RECT
MOVE BOTTOM(A4),D0
ADD TOP(A4),D0
ASR #1,D0 ;CENTER.V := (TOP+BOTTOM)/2
MOVE PT+V(A6),D1
SUB D0,D1 ;DV := PT.V - CENTER.V
MOVE RIGHT(A4),D0
ADD LEFT(A4),D0
ASR #1,D0 ;CENTER.H := (LEFT+RIGHT)/2
MOVE PT+H(A6),D7
SUB D0,D7 ;DH := PT.H - CENTER.H
BNE.S DHOK ;CONTINUE IF DH <> 0
TST D1 ;WAS DV > 0 ?
BLE.S ZERO ;NO, RETURN ANGLE = 0
MOVE #180,D0 ;YES, RETURN ANGLE = 180
BRA.S DONE
DHOK CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE D7,-(SP) ;PUSH DH
MOVE D1,-(SP) ;PUSH DV
_FixRatio ;CALC SLOPE := DH/DV
MOVE.L (SP)+,D6 ;GET SLOPE RESULT
CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE BOTTOM(A4),D0
SUB TOP(A4),D0
MOVE D0,-(SP) ;PUSH HEIGHT
MOVE RIGHT(A4),D0
SUB LEFT(A4),D0
MOVE D0,-(SP) ;PUSH WIDTH
_FixRatio ;CALC ASPECT := HT/WD
MOVE.L (SP)+,D0 ;GET ASPECT RESULT
CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE.L D6,-(SP) ;PUSH SLOPE
MOVE.L D0,-(SP) ;PUSH ASPECT
_FixMul ;CALC SLOPE*ASPECT
MOVE.L (SP)+,D0 ;GET RESULT SLOPE2
CLR.W -(SP) ;ROOM FOR FCN RESULT
MOVE.L D0,-(SP) ;PUSH SLOPE2
JSR AngleFromSlope ;SCAN FOR ARCTAN
MOVE (SP)+,D0 ;GET RESULT ANGLE
TST D7 ;WAS DH POSITIVE ?
BPL.S DONE ;YES, CONTINUE
ADD #180,D0 ;NO, ADD 180 TO ANG
CMP #360,D0 ;IS RESULT = 360 ?
BNE.S DONE ;NO, CONTINUE
ZERO CLR D0 ;YES, ANGLE := 0
DONE MOVE.L ANGLE(A6),A0 ;GET VAR ADDR
MOVE D0,(A0) ;STORE INTO ANGLE
MOVEM.L (SP)+,D6-D7/A4 ;RESTORE REGS
UNLINK PARAMSIZE,'PTTOANGL'
.END

164
Arcs.a Executable file
View File

@ -0,0 +1,164 @@
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
;
; * ***** *** ***
; * * * * * * * *
; * * * * * *
; * * ***** * ***
; ***** * * * *
; * * * * * * * *
; * * * * *** ***
;
; Procedures for drawing Arcs:
;
.PROC StdArc,4
.REF CheckPic,PutPicVerb,PutPicWord,PutPicRect
.REF PushVerb,DrawArc
;---------------------------------------------------------------
;
; PROCEDURE StdArc(verb: GrafVerb; r: Rect; startAngle,arcAngle: INTEGER);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE .EQU 10
VERB .EQU PARAMSIZE+8-2 ;GRAFVERB
RECT .EQU VERB-4 ;LONG, ADDR OF RECT
STARTANG .EQU RECT-2 ;WORD
ARCANG .EQU STARTANG-2 ;WORD
OVWD .EQU -2 ;WORD
OVHT .EQU OVWD-2 ;WORD
VARSIZE .EQU OVHT ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D4/D7/A3-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP)
JSR PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
MOVEQ #$60,D0 ;PUT ARCNOUN IN HI NIBBLE
ADD D7,D0 ;PUT VERB IN LO NIBBLE
MOVE.B D0,-(SP) ;PUSH OPCODE
MOVE.L RECT(A6),-(SP) ;PUSH ADDR OF RECT
JSR PutPicRect ;PUT OPCODE AND RECTANGLE
MOVE STARTANG(A6),-(SP)
JSR PutPicWord ;PUT STARTANGLE
MOVE ARCANG(A6),-(SP)
JSR PutPicWord ;PUT ARCANGLE
NOTPIC MOVE.L RECT(A6),A0 ;POINT TO RECT
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0
MOVE D0,OVWD(A6) ;OVWD := R.RIGHT - R.LEFT
MOVE BOTTOM(A0),D0
SUB TOP(A0),D0
MOVE D0,OVHT(A6) ;OVHT := R.BOTTOM - R.TOP
MOVE.L A0,-(SP) ;PUSH ADDR OF RECT
CLR.B -(SP) ;PUSH HOLLOW = FALSE
TST.B D7 ;IS VERB FRAME ?
BNE.S DOIT ;NO, CONTINUE
;
; Currently, FrameArc does not put inversion points to theRgn.
; If this changes, add test and call to PutArc here.
;
MOVE.B #1,(SP) ;REPLACE, PUSH HOLLOW = TRUE
DOIT MOVE.L OVHT(A6),-(SP) ;PUSH OVWD,OVHT
JSR PushVerb ;PUSH MODE AND PATTERN
MOVE STARTANG(A6),-(SP) ;PUSH STARTANGLE
MOVE ARCANG(A6),-(SP) ;PUSH ARCANGLE
; DrawArc(r,hollow,ovWd,ovHt,mode,pat,startAng,arcAng);
JSR DrawArc
MOVEM.L (SP)+,D4/D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDARC '
.PROC FrameArc,3
.DEF CallArc,PaintArc,EraseArc,InvertArc,FillArc
.REF STDARC
;-----------------------------------------------------
;
; PROCEDURE FrameArc(* r: Rect; startAngle,arcAngle: INTEGER *);
;
MOVEQ #FRAME,D0 ;VERB = FRAME
BRA.S CallArc ;SHARE COMMON CODE
;-----------------------------------------------------
;
; PROCEDURE PaintArc(* r: Rect; startAngle,arcAngle: INTEGER *);
;
PaintArc
MOVEQ #PAINT,D0 ;VERB = PAINT
BRA.S CallArc ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE EraseArc(* r: Rect; startAngle,arcAngle: INTEGER *);
;
EraseArc
MOVEQ #ERASE,D0 ;VERB = ERASE
BRA.S CallArc ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE InvertArc(* r: Rect; startAngle,arcAngle: INTEGER *);
;
InvertArc
MOVEQ #INVERT,D0 ;VERB = INVERT
BRA.S CallArc ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE FillArc(* r: Rect; startAngle,arcAngle: INTEGER; pat: Pattern *);
;
FillArc MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP ADDR OF PATTERN
MOVE.L A0,-(SP) ;PUT RETURN ADDR BACK
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA FILLPAT(A0),A0 ;POINT TO FILLPAT
MOVE.L (A1)+,(A0)+ ;COPY PAT INTO FILLPAT
MOVE.L (A1)+,(A0)+ ;ALL EIGHT BYTES
MOVEQ #FILL,D0 ;VERB = FILL
BRA.S CallArc ;SHARE COMMON CODE
;---------------------------------------------------------------
;
; PROCEDURE CallArc(r: Rect; startAngle,arcAngle: INTEGER);
;
; code shared by FrameArc, PaintArc, EraseArc, InvertArc, and FillArc.
; enter with verb in D0.
;
CallArc MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D1 ;POP BOTH ANGLES
MOVE.L (SP)+,A1 ;POP ADDR OF RECT
MOVE.B D0,-(SP) ;PUSH VERB
MOVE.L A1,-(SP) ;PUSH ADDR OF RECT
MOVE.L D1,-(SP) ;PUSH BOTH ANGLES
MOVE.L A0,-(SP) ;PUSH RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDARC,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L ARCPROC(A0),A0 ;NO, GET PROC PTR
USESTD JMP (A0) ;GO TO IT
.END

796
BitBlt.a Executable file
View File

@ -0,0 +1,796 @@
.INCLUDE GRAFTYPES.TEXT
;---------------------------------------------------------------
;
; --> BITBLT.TEXT
;
; Low-level bit boundary block transfer.
;
.PROC BITBLT,7
.REF LEFTMASK,RIGHTMASK,PATEXPAND
;--------------------------------------------------------------
;
; PROCEDURE BitBlt(srcBits,dstBits: BitMap;
; srcRect,dstRect: Rect;
; mode: INTEGER; pat: Pattern);
;
; TRANSFERS A RECTANGULAR BLOCK OF BITS WITH NO CLIPPING AT ALL.
; MODE SPECIFIES THE COMBINATION MODE AND WHETHER THE SOURCE SHOULD COME
; FROM THE SOURCE BITMAP OR FROM A REPEATING PATTERN.
;
; COPYRIGHT APPLE COMPUTER INC.
; WRITTEN BY BILL ATKINSON
;
; POSITION INDEPENDENT AND RE-ENTRANT, CLOBBERS ONLY A0.
;
; MODES: 0 SRC --> DST
; 1 SRC OR DST --> DST
; 2 SRC XOR DST --> DST
; 3 SRC BIC DST --> DST
;
; 4 (NOT SRC) --> DST
; 5 (NOT SRC) OR DST --> DST
; 6 (NOT SRC) XOR DST --> DST
; 7 (NOT SRC) BIC DST --> DST
;
; 8 PATTERN --> DST
; 9 PATTERN OR DST --> DST
; 10 PATTERN XOR DST --> DST
; 11 PATTERN BIC DST --> DST
;
; 12 (NOT PATTERN) --> DST
; 13 (NOT PATTERN) OR DST --> DST
; 14 (NOT PATTERN) XOR DST --> DST
; 15 (NOT PATTERN) BIC DST --> DST
;
;
;----------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 22 ;SIZE OF PARAMETERS
SRCBITS .EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
DSTBITS .EQU SRCBITS-4 ;LONG, ADDR OF BITMAP
SRCRECT .EQU DSTBITS-4 ;LONG, ADDR OF RECT
DSTRECT .EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE .EQU DSTRECT-2 ;WORD
PAT .EQU MODE-4 ;LONG, ADDR OF PATTERN
;----------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
EXPAT .EQU -64 ;16 LONGS
SRCV .EQU EXPAT-2 ;WORD
DSTV .EQU SRCV-2 ;WORD
SRCROW .EQU DSTV-2 ;WORD
DSTROW .EQU SRCROW-2 ;WORD
srcBump .EQU DSTROW-2 ;WORD
HEIGHT .EQU srcBump-2 ;WORD
WORDCNT .EQU HEIGHT-2 ;WORD
SAVEA5 .EQU WORDCNT-4 ;LONG
VARSIZE .EQU SAVEA5 ;SIZE OF LOCAL VARIABLES
;-------------------------------------------------------------------
;
; ENTER HERE. CALLER TAKES CARE OF CURSOR.
;
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARIABLES
MOVEM.L D3-D7/A2-A5,-(SP) ;SAVE REGS
MOVE.L A5,SAVEA5(A6) ;SAVE GLOBAL POINTER
;----------------------------------------------------------------------
;
; GET PARAMETER POINTERS IN REGISTERS
;
MOVE.L SRCRECT(A6),A2 ;A2 POINTS TO SRCRECT
MOVE.L DSTRECT(A6),A3 ;A3 POINTS TO DSTRECT
MOVE.L SRCBITS(A6),A4 ;A4 POINTS TO SRCBITS
MOVE.L DSTBITS(A6),A5 ;A5 POINTS TO DSTBITS
;-------------------------------------------------------------
;
; CALC HEIGHT OF DSTRECT. QUIT IF HEIGHT <= 0
;
MOVE BOTTOM(A3),D0 ;GET BOTTOM
SUB TOP(A3),D0 ;CALC HEIGHT
BLE GOHOME ;QUIT IF HEIGHT <= 0
MOVE D0,HEIGHT(A6) ;SAVE FOR LATER
;--------------------------------------------------------------
;
; SET UP FOR TOP TO BOTTOM, LEFT TO RIGHT
; GET SRC AND DST TOP AND ROWBYTES
;
MOVEQ #2,D3 ;BUMP:=2 (TRANSFER LEFT TO RIGHT)
MOVE TOP(A2),D0 ;GET SRC TOP
SUB BOUNDS+TOP(A4),D0 ;CONVERT SRC TOP TO GLOBAL
MOVE D0,SRCV(A6) ;SAVE FOR LATER
MOVE TOP(A3),D0 ;GET DST TOP
SUB BOUNDS+TOP(A5),D0 ;CONVERT DST TOP TO GLOBAL
MOVE D0,DSTV(A6) ;SAVE FOR LATER
MOVE ROWBYTES(A4),SRCROW(A6) ;SRCROW:=SRCBITS.ROWBYTES
MOVE ROWBYTES(A5),DSTROW(A6) ;DSTROW:=DSTBITS.ROWBYTES
;--------------------------------------------------------------------
;
; SET UP INVERT FLAG, IN CASE SRC OR PATTERN WILL BE INVERTED
;
CLR D7 ;SAY NOT INVERTED
MOVE MODE(A6),D0 ;GET TRANSFER MODE
BTST #2,D0 ;IS MODE AN INV. ONE ?
BEQ.S MODEOK ;NOT INVERTED, CONTINUE
NOT D7 ;INVERTED, PUT -1 IN INVERT REG
MODEOK BTST #3,D0 ;WILL WE USE PATTERN ?
BEQ.S DIREC ;NO, DON'T BOTHER TO SET UP
;------------------------------------------------------------
;
; PATTERN WILL BE USED. EXPAND 8 BYTE PATTERN TO 16 LONGS.
;
MOVE 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 POINTER
JSR PATEXPAND ;EXPAND 8 BYTES TO 16 LONGS
MOVE.L DSTBITS(A6),A5 ;RESTORE A5 TO DSTBITS
;------------------------------------------------------------
;
; SET UP (VERT * 4) MOD 64 AS PATTERN SELECTOR
;
MOVEQ #$F,D7 ;TREAT COORD MOD 16
AND TOP(A3),D7 ;GET DST TOP LOCAL COORD
LSL #2,D7 ;QUAD FOR LONG PATTERNS
MOVE.L EXPAT(A6,D7),D6 ;GET FIRST PATTERN DATA
BRA.S NOTSRC ;NOT USING SRC, SKIP OVER
;-----------------------------------------------------------
;
; SOURCE WILL BE USED, SO SET UP VERT AND HORIZ DIRECTIONS
; SUCH THAT SRC WON'T GET CLOBBERED TILL AFTER IT HAS BEEN USED
;
DIREC MOVE.L BASEADDR(A4),D0 ;GET SRC BASEADDR
CMP.L BASEADDR(A5),D0 ;ARE SRC AND DST ARRAYS THE SAME ?
BNE.S GETSRC ;NO, DONT WORRY ABOUT OVERLAP
MOVE SRCV(A6),D0 ;GET SRCV
CMP DSTV(A6),D0 ;IS SRCV > DSTV ?
BGT.S GETSRC ;YES, CONTINUE WITH TOP TO BOTTOM
BLT.S UPSIDE ;NO, DO UPSIDE DOWN
MOVE LEFT(A2),D0 ;SAME VERT, CHOOSE HORIZ DIRECTION
SUB BOUNDS+LEFT(A4),D0 ;CONVERT SRC LEFT TO GLOBAL
MOVE LEFT(A3),D1 ;GET DST LEFT
SUB BOUNDS+LEFT(A5),D1 ;CONVERT TO GLOBAL
CMP D1,D0 ;IS SRCLEFT < DSTLEFT ?
BGE.S GETSRC ;NO, DO LEFT TO RIGHT
NEG D3 ;YES, BUMP:=-2 (RIGHT TO LEFT)
BRA.S GETSRC ;CONTINUE
;----------------------------------------------------------
;
; DO UPSIDE DOWN TO AVOID CLOBBERING SRC
;
UPSIDE MOVE HEIGHT(A6),D0 ;GET HEIGHT
SUB #1,D0 ;CALC HEIGHT-1
ADD D0,SRCV(A6) ;SRCVERT:=SRCV+HEIGHT-1
ADD D0,DSTV(A6) ;DSTVERT:=DSTV+HEIGHT-1
NEG SRCROW(A6) ;SRCROW:=-SRCROW
NEG DSTROW(A6) ;DSTROW:=-DSTROW
;-----------------------------------------------------
;
; SET UP SHIFTCNT IN D6 (RELATIVE SHIFT BETWEEN SRC & DST)
;
GETSRC MOVE LEFT(A3),D6 ;GET DST LEFT
SUB BOUNDS+LEFT(A5),D6 ;CONVERT TO GLOBAL
MOVE LEFT(A2),D1 ;GET SRC LEFT
SUB BOUNDS+LEFT(A4),D1 ;CONVERT TO GLOBAL
SUB D1,D6 ;CALC DELTA HORIZ
AND #$F,D6 ;SHIFTCNT:=DELTA HORIZ MOD 16
;------------------------------------------------------------
;
; SET UP SRCLEFT IN A4, ADDR OF LEFTMOST SRC WORD
; (GOODBYE SRCBITS PTR)
;
MOVE SRCV(A6),D0 ;GET FIRST SRC VERT
MULU ROWBYTES(A4),D0 ;CALC SRC ROWBYTES * FIRST SRC VERT
MOVE.L BASEADDR(A4),A4 ;GET START OF SRC BITMAP
ADD.L D0,A4 ;ADD TO BITMAP START
ADD D6,D1 ;CALC SRCH+SHIFTCNT
ASR #3,D1 ;CONVERT BITS TO BYTE OFFSET
AND #$FFFE,D1 ;TRUNC TO WORD BOUNDARY
ADD D1,A4 ;LEAVE SRCLEFT IN A4
;------------------------------------------------------------
;
; SET UP DSTLEFT IN A5, ADDR OF LEFTMOST DST WORD
; (GOODBYE DSTBITS PTR)
;
NOTSRC MOVE LEFT(A3),D1 ;GET DST LEFT
SUB BOUNDS+LEFT(A5),D1 ;CONVERT TO GLOBAL
MOVE DSTV(A6),D0 ;GET FIRST DST VERT
MULU ROWBYTES(A5),D0 ;CALC DSTROW * FIRST DST VERT
MOVE.L BASEADDR(A5),A5 ;GET START OF DST BITMAP
ADD.L D0,A5 ;ADD DSTV*DSTROW
MOVE D1,D0 ;COPY DSTLEFT GLOBAL
ASR #4,D1 ;CONVERT FROM DOTS TO WORDS
ADD D1,D1 ;DOUBLE FOR BYTES
ADD D1,A5 ;LEAVE DSTLEFT IN A5
;-------------------------------------
;
; SET UP LEFTMASK IN D4
; (GOODBYE SRCRECT PTR)
;
MOVE D0,D1 ;SAVE DSTH
JSR LEFTMASK ;GET LEFTMASK
MOVE D0,D4 ;PUT IN D4
;-------------------------------------
;
; SET UP RIGHTMASK IN D5
; (GOODBYE DSTRECT PTR)
;
AND #$F,D1 ;TREAT DSTH MOD 16
MOVE RIGHT(A3),D0 ;GET DST RIGHT
SUB LEFT(A3),D0 ;CALC WIDTH
BLE GOHOME ;QUIT IF WIDTH <= 0
ADD D1,D0 ;CALC (DSTH MOD 16) + WIDTH
MOVE D0,D1 ;MAKE AN EXTRA COPY
JSR RIGHTMASK ;GET RIGHT MASK
MOVE D0,D5 ;SAVE RIGHTMASK IN D5
;------------------------------------------------
;
; CALC TOTAL NUMBER OF DST WORDS-1
;
ASR #4,D1 ;CALC ((DSTH MOD 16)+WIDTH) DIV 16
MOVE D1,WORDCNT(A6) ;SAVE AS WORDCNT
MOVE D1,D2 ;set up for below
;
; Set up srcBump and dstBump, assuming bumping to the right
;
ADD D1,D1 ;calc 2*wordCount
MOVE D1,D0 ;make a copy
ADD #2,D0 ;adjust for total bytesNeeded
;--------------------------------------------------------------------------
;
; IF DRAWING BACKWARDS FROM RIGHT, then adjust dstBump,
; ADJUST SRCADDR,DSTADDR TO FIRST WORD,
; AND SWAP LEFT AND RIGHT MASKS FOR FIRSTMASK AND LASTMASK.
;
MOVE D3,A0 ;put hBump (+-2) into A0
TST D3 ;ARE WE STARTING ON THE LEFT ?
BPL.S DIROK ;YES, CONTINUE
NEG D0 ;calc -1 * bytesNeeded
ADD D1,A5 ;ADJUST DSTADDR TO RIGHTMOST
ADD D1,A4 ;ADJUST SRCADDR TO RIGHTMOST
EXG D4,D5 ;FIRSTMASK=RIGHT,LASTMASK=LEFT
DIROK MOVE srcRow(A6),srcBump(A6)
SUB D0,srcBump(A6) ;srcBump := srcRow +- bytesBumped
MOVE dstRow(A6),A3
SUB D0,A3 ;dstBump := dstRow +- bytesBumped
;----------------------------------------------
;
; SET UP MODE CASE JUMP IN A1
;
GETMODE MOVE MODE(A6),D0 ;GET TRANSFER MODE
BNE.S NOTFAST ;BR IF NOT MODE 0
TST D6 ;IS SHIFTCNT 0 ?
BNE.S NOTFAST ;NO, CONTINUE
TST WORDCNT(A6) ;IS WORDCNT > 0 ?
BLE.S NOTFAST ;NO, CONTINUE
LEA SETUP0,A1 ;USE FAST COPY.
TST D3 ;ARE WE BUMPING LEFT TO RIGHT ?
BPL.S NEXTROW ;YES, ALL SET
LEA LEFT0,A1 ;NO, USE BACKWARDS LOOP
BRA.S NEXTROW
NOTFAST AND #$B,D0 ;TREAT MODE MOD 16 AND KILL INVERT BIT
MOVE D0,D1 ;MAKE A COPY
AND #3,D0 ;MASK FOR LOW BITS ONLY
ADD D0,D1 ;MAKE MODIFIED MODE * 2 FOR INDEX
TST D2 ;IS DST ALL IN ONE WORD ?
BNE.S DOMAIN ;NO, USE FIRST JUMP TABLE
ADD #16,D1 ;YES, USE SECOND JUMP TABLE
DOMAIN LEA MODETAB,A1 ;GET ADDRESS OF MODE TABLE
ADD 0(A1,D1),A1 ;POINT TO THIS MODE'S ROW LOOP
;---------------------------------------------------------
;
; OUTER LOOP: DO EACH SCAN LINE AND COME BACK TO NXTSRC OR NXTPAT.
; SOME MODES OPTIMIZE AND DO WHOLE OUTER LOOP AND COME BACK TO GOHOME.
;
NEXTROW MOVE HEIGHT(A6),D3 ;get height
SUB #1,D3 ;init DBRA rowcount
ROWLOOP MOVE D4,D1 ;MASK:=FIRSTMASK
MOVE WORDCNT(A6),D2 ;GET WORDCOUNT
JMP (A1) ;DO THIS ROW AND COME BACK
NXTSRC ADD srcBump(A6),A4 ;bump srcPtr to next row
ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW
DBRA D3,ROWLOOP ;loop for all srcRows
BRA.S GOHOME ;then quit
NXTPAT ADD #4,D7 ;BUMP PATTERN SELECTOR
AND #$3F,D7 ;MOD 64 FOR 16 LONG REPEAT
MOVE.L EXPAT(A6,D7),D6 ;GET PATTERN DATA FOR NEXT ROW
ADD A3,A5 ;BUMP DSTADDR TO NEXT ROW
DBRA D3,ROWLOOP ;loop for all srcRows
;then quit
GOHOME MOVEM.L (SP)+,D3-D7/A2-A5 ;RESTORE REGS
UNLINK PARAMSIZE,'BITBLT '
;---------------------------------------------------------------;
; ;
; INTERFACE TO EACH BITBLT SCANLINE LOOP: ;
; ;
; REGISTERS: A0: hBump (+-2) D0: scratch ;
; A1: MODE CASE JUMP D1: FIRSTMASK ;
; A2: used for loop jmp D2: WORDCNT ;
; A3: dstBump D3: height-1 ;
; A4: SRCPTR D4: FIRSTMASK ;
; A5: DSTPTR D5: LASTMASK ;
; A6: LOCALS D6: SHIFTCNT OR PATTERN ;
; A7: STACK PTR D7: INVERT OR PAT-SEL ;
; ;
;---------------------------------------------------------------;
MODETAB .WORD MAIN0-MODETAB ;JUMP TABLE USED IF DST WIDER THAN ONE WORD
.WORD MAIN1-MODETAB
.WORD MAIN2-MODETAB
.WORD MAIN3-MODETAB
.WORD SETUP8-MODETAB
.WORD MAIN9-MODETAB
.WORD SETUP10-MODETAB
.WORD MAIN11-MODETAB
.WORD END0-MODETAB ;JUMP TABLE USED IF DST FITS IN ONE WORD WIDE
.WORD END1-MODETAB
.WORD END2-MODETAB
.WORD END3-MODETAB
.WORD WORD8-MODETAB
.WORD END9-MODETAB
.WORD END10-MODETAB
.WORD END11-MODETAB
;------------------------------------------------------------
;
; OPTIMIZE RIGHT HORIZONTAL SCROLL IF NO SHIFT.
; ONLY IF MODE 0, BUMPING RIGHT TO LEFT, WORDCNT > 0, AND NO SHIFT.
;
LEFT0 MOVE (A4),D0 ;GET SRC FROM BITMAP
ADD A0,A4 ;BUMP LEFT
AND D1,D0 ;MASK FIRST WORD
NOT D1 ;MAKE NOTMASK
AND (A5),D1 ;GET DATA FROM DST
OR D1,D0 ;MERGE WITH SRC DATA
MOVE D0,(A5) ;PUT RESULT TO DST
ADD A0,A5 ;BUMP LEFT
MOVEQ #-1,D1 ;FLUSH MASK FOR END0
SUB #1,D2 ;DEC WORD COUNT
BEQ.S END0 ;BR IF NO UNMASKED WORDS
SUB A0,A4 ;GET READY FOR PRE-DECREMENT
SUB A0,A5 ;GET READY FOR PRE-DECREMENT
LSR #1,D2 ;HALVE WORDCOUNT FOR LONGCOUNT
BCC.S LONE0 ;BR IF EVEN # WORDS LEFT
MOVE -(A4),-(A5) ;ELSE MAKE EVEN BY DOING A WORD
SUB #1,D2 ;ADJUST LONGCOUNT
BRA.S LMORE0 ;SEE IF ANY LONGS LEFT TO DO
LTWO0 MOVE.L -(A4),-(A5) ;MOVE A LONG WORD
LONE0 MOVE.L -(A4),-(A5) ;MOVE ANOTHER LONG
SUB #2,D2 ;ANY UNMASKED LONGS LEFT IN ROW ?
LMORE0 BGT LTWO0 ;YES, AT LEAST 2 LONGS LEFT
BEQ LONE0 ;YES, FINISH UP LAST LONG
ADD A0,A4 ;RETURN TO NORMAL AFTER PRE-DECREMENT
ADD A0,A5 ;RETURN TO NORMAL AFTER PRE-DECREMENT
BRA.S END0 ;DO LAST WORD WITH MASK
;------------------------------------------------------------
;
; OPTIMIZE VERTICAL AND LEFT HORIZONTAL SCROLL IF SHIFT = 0.
; ONLY IF MODE 0, BUMPING LEFT TO RIGHT, WORDCNT > 0, AND NO SHIFT.
;
SETUP0 LEA FAST0,A1 ;only do setup once
LEA COPYBIG,A2 ;point to big copy
BRA CALCLP ;share loop calc
FAST0 MOVE (A4)+,D0 ;GET SRC FROM BITMAP
AND D1,D0 ;MASK FIRST WORD
NOT D1 ;MAKE NOTMASK
AND (A5),D1 ;GET DST DATA
OR D1,D0 ;MERGE WITH SRC DATA
MOVE D0,(A5)+ ;PUT RESULT TO DST
MOVEQ #-1,D1 ;FLUSH MASK FOR END0
SUB #1,D2 ;DEC WORD COUNT
BEQ.S END0 ;BR IF NO UNMASKED WORDS
JSR (A2) ;call unwound copy loop
MOVEQ #-1,D2 ;force finish up below
;-------------------------------------------------------
;
; MODE 0 OR 4: SRC --> DST
;
END0 AND D5,D1 ;MASK:=MASK AND LASTMASK
MAIN0 MOVE.L -2(A4),D0 ;GET SRC FROM BITMAP
ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT
LSR.L D6,D0 ;ALIGN TO DST
EOR D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND D1,D0 ;MASK SRC
NOT D1 ;FORM NOTMASK
AND (A5),D1 ;GET DST DATA
OR D1,D0 ;MERGE WITH SRC DATA
MOVE D0,(A5) ;PUT RESULT TO DST
ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
BGT MAIN0 ;BR IF UNMASKED WORDS LEFT
BEQ END0 ;DO LAST WORD WITH LASTMASK
BRA NXTSRC ;LOOP BACK FOR MORE
;----------------------------------------------------------
;
; Call copybig with wordcount in D2 (clobbered)
;
COPYBIG BCLR #0,D2 ;is wordcount even ?
BEQ.S @1 ;yes, continue
MOVE.W (A4)+,(A5)+ ;no, make it even
@1 SUB #32,D2 ;calc wordcount-32
BLE.S @2 ;continue if wordcount <= 32
BSR.S COPY32 ;else copy 32 words
BRA.S @1 ;and loop for more
@2 NEG D2 ;calc 32-wordcount
JMP COPY32(D2) ;jump into loop
COPY32 MOVE.L (A4)+,(A5)+ ;TABLE TO COPY 0..32 WORDS
MOVE.L (A4)+,(A5)+ ;wordCount = 30
MOVE.L (A4)+,(A5)+ ;wordCount = 28
MOVE.L (A4)+,(A5)+ ;wordCount = 26
MOVE.L (A4)+,(A5)+ ;wordCount = 24
MOVE.L (A4)+,(A5)+ ;wordCount = 22
MOVE.L (A4)+,(A5)+ ;wordCount = 20
MOVE.L (A4)+,(A5)+ ;wordCount = 18
MOVE.L (A4)+,(A5)+ ;wordCount = 16
MOVE.L (A4)+,(A5)+ ;wordCount = 14
MOVE.L (A4)+,(A5)+ ;wordCount = 12
MOVE.L (A4)+,(A5)+ ;wordCount = 10
MOVE.L (A4)+,(A5)+ ;wordCount = 8
MOVE.L (A4)+,(A5)+ ;wordCount = 6
MOVE.L (A4)+,(A5)+ ;wordCount = 4
MOVE.L (A4)+,(A5)+ ;wordCount = 2
COPY0 RTS ;wordCount = 0
COPY31 MOVE.L (A4)+,(A5)+ ;TABLE TO COPY 1..31 WORDS
MOVE.L (A4)+,(A5)+ ;wordCount = 29
MOVE.L (A4)+,(A5)+ ;wordCount = 27
MOVE.L (A4)+,(A5)+ ;wordCount = 25
MOVE.L (A4)+,(A5)+ ;wordCount = 23
MOVE.L (A4)+,(A5)+ ;wordCount = 21
MOVE.L (A4)+,(A5)+ ;wordCount = 19
MOVE.L (A4)+,(A5)+ ;wordCount = 17
MOVE.L (A4)+,(A5)+ ;wordCount = 15
MOVE.L (A4)+,(A5)+ ;wordCount = 13
MOVE.L (A4)+,(A5)+ ;wordCount = 11
MOVE.L (A4)+,(A5)+ ;wordCount = 9
MOVE.L (A4)+,(A5)+ ;wordCount = 7
MOVE.L (A4)+,(A5)+ ;wordCount = 5
MOVE.L (A4)+,(A5)+ ;wordCount = 3
COPY1 MOVE.W (A4)+,(A5)+ ;wordCount = 1
RTS
;-------------------------------------------------------
;
; MODE 1 OR 5: SRC OR DST --> DST
;
END1 AND D5,D1 ;MASK:=MASK AND LASTMASK
MAIN1 MOVE.L -2(A4),D0 ;GET SRC FROM BITMAP
ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT
LSR.L D6,D0 ;ALIGN TO DST
EOR D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND D1,D0 ;MASK SRC
OR D0,(A5) ;OR SRC INTO DST
ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
BGT MAIN1 ;LOOP TILL LAST WORD
BEQ END1 ;DO LAST WORD WITH LASTMASK
BRA NXTSRC ;LOOP BACK FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 2 OR 6: SRC XOR DST --> DST
;
END2 AND D5,D1 ;MASK:=MASK AND LASTMASK
MAIN2 MOVE.L -2(A4),D0 ;GET SRC FROM BITMAP
ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT
LSR.L D6,D0 ;ALIGN TO DST
EOR D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND D1,D0 ;MASK SRC
EOR D0,(A5) ;XOR SRC INTO DST
ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
BGT MAIN2 ;LOOP TILL LAST WORD
BEQ END2 ;DO LAST WORD WITH LASTMASK
BRA NXTSRC ;LOOP BACK FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 3 OR 7: SRC BIC DST --> DST
;
END3 AND D5,D1 ;MASK:=MASK AND LASTMASK
MAIN3 MOVE.L -2(A4),D0 ;GET SRC FROM BITMAP
ADD A0,A4 ;BUMP SRCPTR LEFT OR RIGHT
LSR.L D6,D0 ;ALIGN TO DST
EOR D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND D1,D0 ;MASK SRC
NOT D0 ;INVERT SRC
AND D0,(A5) ;BIT CLEAR SRC INTO DST
ADD A0,A5 ;BUMP DSTPTR LEFT OR RIGHT
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
BGT MAIN3 ;LOOP TILL LAST WORD
BEQ END3 ;DO LAST WORD WITH LASTMASK
BRA NXTSRC ;LOOP BACK FOR NEXT ROW
;-----------------------------------------------------------
;
; OPTIMIZE MODE 8 OR 12 IF DST FITS IN ONE WORD (VERT LINES ETC)
;
WORD8 AND D5,D1 ;COMBINE LEFT AND RIGHT MASKS
MOVE D1,D5 ;COPY COMBINED MASK
NOT D5 ;FORM NOTMASK
WORD8A AND D1,D6 ;MASK EXTRA PATTERN TO ZEROS
MOVE (A5),D0 ;GET DST DATA
AND D5,D0 ;AND WITH NOTMASK
OR D6,D0 ;MERGE WITH SRC DATA
MOVE D0,(A5)+ ;PUT RESULT TO DST
ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW
ADD #4,D7 ;BUMP PATTERN SELECTOR
AND #$3F,D7 ;MOD 64 FOR 16 LONG REPEAT
MOVE EXPAT(A6,D7),D6 ;GET PATTERN FOR NEXT ROW
DBRA D3,WORD8A ;LOOP ALL ROWS
BRA GOHOME
;-------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES)
;
SETUP8 LEA FAST8,A1 ;only do setup once
LEA FILLBIG,A2 ;point to big fill
CALCLP CMP #32,D2 ;is wordcnt > 32 ?
BGT.S @2 ;yes use fillbig
ADD #COPY0+1-COPYBIG,A2 ;no, point to even table
BTST #0,D2 ;will wordcount-1 be even ?
BNE.S @1 ;yes, use even table
ADD #COPY1+1-COPY0,A2 ;no, point to odd table
@1 SUB D2,A2 ;adjust loop jump
@2 JMP (A1) ;re-connect with shared code
FAST8 MOVE D6,D0 ;GET PATTERN DATA
AND D1,D0 ;MASK FIRST WORD
NOT D1 ;MAKE NOTMASK
AND (A5),D1 ;GET DST DATA
OR D1,D0 ;MERGE WITH PAT DATA
MOVE D0,(A5)+ ;PUT RESULT TO DST
SUB #1,D2 ;DEC WORD COUNT
BEQ.S END8 ;BR IF NO UNMASKED WORDS
JSR (A2) ;call unwound loop
END8 MOVE D5,D1 ;MASK:= RIGHTMASK
AND D1,D6 ;MASK PATTERN
NOT D1 ;MAKE NOTMASK
AND (A5),D1 ;GET DST DATA
OR D1,D6 ;MERGE WITH PAT DATA
MOVE D6,(A5)+ ;PUT RESULT TO DST
BRA NXTPAT ;LOOP BACK FOR NEXT ROW
;----------------------------------------------------------
;
; Call fillbig with wordcount in D2 (clobbered)
;
FILLBIG BCLR #0,D2 ;is wordcount even ?
BEQ.S @1 ;yes, continue
MOVE.W D6,(A5)+ ;no, make it even
@1 SUB #32,D2 ;calc wordcount-32
BLE.S @2 ;continue if wordcount <= 32
BSR.S FILL32 ;elsae fill 32 words
BRA.S @1 ;and loop for more
@2 NEG D2 ;calc 32-wordcount
JMP FILL32(D2) ;jump into loop
FILL32 MOVE.L D6,(A5)+ ;TABLE TO FILL 0..32 WORDS
MOVE.L D6,(A5)+ ;wordCount = 30
MOVE.L D6,(A5)+ ;wordCount = 28
MOVE.L D6,(A5)+ ;wordCount = 26
MOVE.L D6,(A5)+ ;wordCount = 24
MOVE.L D6,(A5)+ ;wordCount = 22
MOVE.L D6,(A5)+ ;wordCount = 20
MOVE.L D6,(A5)+ ;wordCount = 18
MOVE.L D6,(A5)+ ;wordCount = 16
MOVE.L D6,(A5)+ ;wordCount = 14
MOVE.L D6,(A5)+ ;wordCount = 12
MOVE.L D6,(A5)+ ;wordCount = 10
MOVE.L D6,(A5)+ ;wordCount = 8
MOVE.L D6,(A5)+ ;wordCount = 6
MOVE.L D6,(A5)+ ;wordCount = 4
MOVE.L D6,(A5)+ ;wordCount = 2
RTS ;wordCount = 0
FILL31 MOVE.L D6,(A5)+ ;TABLE TO FILL 1..31 WORDS
MOVE.L D6,(A5)+ ;wordCount = 29
MOVE.L D6,(A5)+ ;wordCount = 27
MOVE.L D6,(A5)+ ;wordCount = 25
MOVE.L D6,(A5)+ ;wordCount = 23
MOVE.L D6,(A5)+ ;wordCount = 21
MOVE.L D6,(A5)+ ;wordCount = 19
MOVE.L D6,(A5)+ ;wordCount = 17
MOVE.L D6,(A5)+ ;wordCount = 15
MOVE.L D6,(A5)+ ;wordCount = 13
MOVE.L D6,(A5)+ ;wordCount = 11
MOVE.L D6,(A5)+ ;wordCount = 9
MOVE.L D6,(A5)+ ;wordCount = 7
MOVE.L D6,(A5)+ ;wordCount = 5
MOVE.L D6,(A5)+ ;wordCount = 3
MOVE.W D6,(A5)+ ;wordCount = 1
RTS
;-------------------------------------------------------
;
; MODE 9 OR 13: PATTERN OR DST --> DST
;
END9 AND D5,D1 ;MASK:=MASK AND LASTMASK
MAIN9 MOVE D6,D0 ;GET PATTERN DATA
AND D1,D0 ;MASK PATTERN
OR D0,(A5)+ ;OR PATTERN INTO DST
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
BGT MAIN9 ;LOOP TILL LAST WORD
BEQ END9 ;DO LAST WORD WITH LASTMASK
BRA NXTPAT ;LOOP BACK FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 10 OR 14: PATTERN XOR DST --> DST (INVERTING AREAS, XOR LINES)
;
SETUP10 LEA FAST10,A1 ;only do setup once
LEA XORBIG,A2 ;point to big fill
BRA CALCLP ;share loop calc
FAST10 MOVE D6,D0 ;GET PATTERN DATA
AND D1,D0 ;MASK FIRST WORD
EOR D0,(A5)+ ;XOR PATTERN INTO DST
MOVEQ #-1,D1 ;FLUSH MASK FOR END10
SUB #1,D2 ;DEC WORD COUNT
BEQ.S END10 ;BR IF NO UNMASKED WORDS
JSR (A2) ;call unwound loop
MOVEQ #-1,D2 ;force finish up below
END10 AND D5,D1 ;MASK:=MASK AND LASTMASK
AND D1,D6 ;MASK PATTERN
EOR D6,(A5)+ ;XOR PATTERN DATA INTO DST
BRA NXTPAT ;LOOP BACK FOR NEXT ROW
;----------------------------------------------------------
;
; Call XORbig with wordcount in D2 (clobbered)
;
XORBIG BCLR #0,D2 ;is wordcount even ?
BEQ.S @1 ;yes, continue
EOR.W D6,(A5)+ ;no, make it even
@1 SUB #32,D2 ;calc wordcount-32
BLE.S @2 ;continue if wordcount <= 32
BSR.S XOR32 ;else XOR 32 words
BRA @1 ;and loop for more
@2 NEG D2 ;calc 32-wordcount
JMP XOR32(D2) ;jump into loop
XOR32 EOR.L D6,(A5)+ ;TABLE TO XOR 0..32 WORDS
EOR.L D6,(A5)+ ;wordCount = 30
EOR.L D6,(A5)+ ;wordCount = 28
EOR.L D6,(A5)+ ;wordCount = 26
EOR.L D6,(A5)+ ;wordCount = 24
EOR.L D6,(A5)+ ;wordCount = 22
EOR.L D6,(A5)+ ;wordCount = 20
EOR.L D6,(A5)+ ;wordCount = 18
EOR.L D6,(A5)+ ;wordCount = 16
EOR.L D6,(A5)+ ;wordCount = 14
EOR.L D6,(A5)+ ;wordCount = 12
EOR.L D6,(A5)+ ;wordCount = 10
EOR.L D6,(A5)+ ;wordCount = 8
EOR.L D6,(A5)+ ;wordCount = 6
EOR.L D6,(A5)+ ;wordCount = 4
EOR.L D6,(A5)+ ;wordCount = 2
RTS ;wordCount = 0
XOR31 EOR.L D6,(A5)+ ;TABLE TO XOR 1..31 WORDS
EOR.L D6,(A5)+ ;wordCount = 29
EOR.L D6,(A5)+ ;wordCount = 27
EOR.L D6,(A5)+ ;wordCount = 25
EOR.L D6,(A5)+ ;wordCount = 23
EOR.L D6,(A5)+ ;wordCount = 21
EOR.L D6,(A5)+ ;wordCount = 19
EOR.L D6,(A5)+ ;wordCount = 17
EOR.L D6,(A5)+ ;wordCount = 15
EOR.L D6,(A5)+ ;wordCount = 13
EOR.L D6,(A5)+ ;wordCount = 11
EOR.L D6,(A5)+ ;wordCount = 9
EOR.L D6,(A5)+ ;wordCount = 7
EOR.L D6,(A5)+ ;wordCount = 5
EOR.L D6,(A5)+ ;wordCount = 3
EOR.W D6,(A5)+ ;wordCount = 1
RTS
;-------------------------------------------------------
;
; MODE 11 OR 15: PATTERN BIC DST --> DST
;
END11 AND D5,D1 ;MASK:=MASK AND LASTMASK
MAIN11 MOVE D6,D0 ;GET PATTERN DATA
AND D1,D0 ;MASK PATTERN
NOT D0 ;INVERT PATTERN
AND D0,(A5)+ ;BIC PATTERN INTO DST
MOVEQ #-1,D1 ;FLUSH MASK
SUB #1,D2 ;DEC WORD COUNT
BGT MAIN11 ;LOOP TILL LAST WORD
BEQ END11 ;DO LAST WITH LASTMASK
BRA NXTPAT ;LOOP BACK FOR NEXT ROW
.ASCII 'CopyRight 1983 Apple Computer Inc.'
.END

1018
Bitmaps.a Executable file

File diff suppressed because it is too large Load Diff

3
COPYRIGHT.TXT Executable file
View File

@ -0,0 +1,3 @@
Copyright
This Material is Copyright © 1984 Apple Inc. and is made available only for non-commercial use.

1086
DrawArc.a Executable file

File diff suppressed because it is too large Load Diff

745
DrawLine.a Executable file
View File

@ -0,0 +1,745 @@
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------------
;
; --> DRAWLINE.TEXT
;
.PROC DrawLine
.REF RgnBlt,RSect,ShieldCursor,ShowCursor,TrimRect
.REF InitRgn,SeekRgn,PatExpand,ColorMap
.REF 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 = 0 ?
BEQ.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 .BYTE 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
_FixRatio ;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
_FixMul ;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 .WORD IGNORE-RECTJMP ;DO NOTHING IF BOTH RECT
.WORD A-RECTJMP
.WORD B-RECTJMP
.WORD 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

933
DrawText.a Executable file
View File

@ -0,0 +1,933 @@
.INCLUDE GRAFTYPES.TEXT
;--------------------------------------------------------------
;
; --> DRAWTEXT.TEXT
;
; QuickDraw Character Generator
;
; Completely reworked 29 Apr 85 by Bill Atkinson to get 50% speed up.
; Takes advantage of optional height table at end of font.
;
.PROC DrText,4
.REF RightMask,MaskTab,RSect,ShieldCursor,ShowCursor
.REF StdTxMeas,RectInRgn,MapRect,StretchBits,TrimRect
;------------------------------------------------------------
;
; PROCEDURE DrText(count: INTEGER; textAddr: Ptr; numer,denom: Point);
;
; DRAWS CHARACTERS INTO THE CURRENT PORT'S BITMAP.
; THE FONT AND ATTRIBUTES ARE GIVEN IN THE CURRENT PORT'S CHARSTYLE.
;
;-------------------------------------------
;
; KERNED STRIKE FONT FORMAT OFFSETS:
;
FORMAT .EQU 0 ;WORD
MINCHAR .EQU 2 ;WORD
MAXCHAR .EQU 4 ;WORD
MAXWD .EQU 6 ;WORD
FBBOX .EQU 8 ;WORD
FBBOY .EQU 10 ;WORD
FBBDX .EQU 12 ;WORD
FBBDY .EQU 14 ;WORD
LENGTH .EQU 16 ;WORD
ASCENT .EQU 18 ;WORD
DESCENT .EQU 20 ;WORD
XOFFSET .EQU 22 ;WORD
RASTER .EQU 24 ;WORD
;------------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 14 ;SIZE OF PARAMETERS
COUNT .EQU PARAMSIZE+8-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG
NUMER .EQU TEXTADDR-4 ;LONG, POINT
DENOM .EQU NUMER-4 ;LONG, POINT
;-----------------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
SAVESTK .EQU -4 ;LONG
TEXTRECT .EQU SAVESTK-8 ;RECT
TEXTR2 .EQU TEXTRECT-8 ;RECT
MINRECT .EQU TEXTR2-8 ;RECT
BUFEND .EQU MINRECT-4 ;LONG
BUFSTART .EQU BUFEND-4 ;LONG
BUFSIZE .EQU BUFSTART-2 ;WORD
BUFROW .EQU BUFSIZE-2 ;WORD
BUFLEFT .EQU BUFROW-2 ;WORD
BUF2START .EQU BUFLEFT-4 ;LONG
BUF2END .EQU BUF2START-4 ;LONG
HEIGHT .EQU BUF2END-2 ;WORD
SRCBITS .EQU HEIGHT-14 ;BITMAP
DSTBITS .EQU SRCBITS-14 ;BITMAP
FAKERGN .EQU DSTBITS-10 ;RECTANGULAR REGION
FAKEPTR .EQU FAKERGN-4 ;LONG, FAKE MASTER POINTER
SRCADDR .EQU FAKEPTR-4 ;LONG
SRCROW .EQU SRCADDR-2 ;WORD
FASTFLAG .EQU SRCROW-2 ;BYTE
PENLOC .EQU FASTFLAG-4 ;POINT
SRCPTR .EQU PENLOC-4 ;LONG
DSTPTR .EQU SRCPTR-4 ;LONG
STRETCH .EQU DSTPTR-2 ;BOOLEAN
FROMRECT .EQU STRETCH-8 ;RECT
TORECT .EQU FROMRECT-8 ;RECT
SRCRECT .EQU TORECT-8 ;RECT
DSTRECT .EQU SRCRECT-8 ;RECT
SPWIDTH .EQU DSTRECT-4 ;FIXED POINT
CHARLOC .EQU SPWIDTH-4 ;FIXED POINT
INFO .EQU CHARLOC-8 ;4 WORDS
HEIGHTAB .EQU INFO-4 ;LONG
WIDTAB .EQU HEIGHTAB-4 ;LONG
LOCTAB .EQU WIDTAB-4 ;LONG
TOPHT .EQU LOCTAB-2 ;word
HEIGHTFLAG .EQU TOPHT-2 ;byte
MAXMIN .EQU HEIGHTFLAG-2 ;word
MINCH .EQU MAXMIN-2 ;word
SAVEA5 .EQU MINCH-4 ;LONG
NUMER2 .EQU SAVEA5-4 ;Point
DENOM2 .EQU NUMER2-4 ;Point
VARSIZE .EQU DENOM2 ;SIZE OF VARIABLES
LINK A6,#VARSIZE ;ALLOCATE TEMP VARS
MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER WHERE STACK WAS
MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;GET CURRENT GRAFPORT
MOVE.L NUMER(A6),NUMER2(A6) ;SAVE ORIGINAL NUMER
MOVE.L DENOM(A6),DENOM2(A6) ;SAVE ORIGINAL DENOM
;
; Call StdTxMeas to swap font and measure width.
;
CLR -(SP) ;ROOM FOR FCN RESULT
MOVE COUNT(A6),-(SP) ;PUSH COUNT
BLE GOHOME ;QUIT IF COUNT <= 0
;STACK CLEANED UP BY SAVESTK
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
PEA NUMER(A6) ;PUSH VAR NUMER
PEA DENOM(A6) ;PUSH VAR DENOM
PEA INFO(A6) ;PUSH VAR INFO
JSR StdTxMeas ;MEASURE TEXT
MOVE (SP)+,D1 ;POP UNSCALED WIDTH RESULT
;
; StdTxMeas also stashes FMOutPtr in QD global FONTPTR,
; and unscaled fixed point text width inn FixTxWid.
;
MOVE.L FONTPTR(A4),A4 ;POINT TO FMOUTPUT
MOVE.L 2(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE FBBDY(A2),TOPHT(A6) ;INIT TOPHT IN CASE OLD FONT
BTST #0,1(A2) ;DOES FONT HAVE HEIGHT TABLE ?
SNE HEIGHTFLAG(A6) ;REMEMBER FOR LATER
;
; Setup textRect, the rectangle bounding the entire string.
;
MOVE.L PNLOC(A3),D2 ;GET PEN LOCATION
MOVE.L D2,PENLOC(A6) ;SAVE FOR LATER
MOVE.W D2,TEXTRECT+LEFT(A6) ;TEXTRECT.LEFT := PNLOC.H
ADD.W D1,D2 ;right := left + width
MOVEQ #7,D0 ;get mode mask
AND TXMODE(A3),D0 ;is txMode = srcCopy ?
BEQ.S NOSLOP ;yes, don't add slop
CMP #3,D0 ;is textMode > srcBic ?
BGT.S NOSLOP ;yes, don't add slop
ADD.W #32,D2 ;SLOP FOR ITALIC,BOLD,OVERSTRIKE
NOSLOP MOVE.W D2,TEXTRECT+RIGHT(A6) ;STORE IN TEXTRECT.RIGHT
SWAP D2 ;GET PNLOC.V
SUB ASCENT(A2),D2 ;SUBTRACT ASCENT
MOVE D2,TEXTRECT+TOP(A6) ;TEXTRECT.TOP := PNLOC.V - ASCENT
ADD FBBDY(A2),D2 ;ADD HEIGHT
MOVE D2,TEXTRECT+BOTTOM(A6) ;TEXTRECT.BOTTOM := TOP + HEIGHT
MOVE.L TEXTRECT(A6),TEXTR2(A6) ;MAKE AN EXTRA COPY
MOVE.L TEXTRECT+4(A6),TEXTR2+4(A6) ;OF TEXTRECT IN TEXTR2
;
; Check for stretching
;
MOVE.L NUMER(A6),D0 ;GET NUMERATOR
CMP.L DENOM(A6),D0 ;ARE WE STRETCHING ?
SNE STRETCH(A6) ;REMEMBER THE ANSWER
BEQ.S NOSTRCH ;CONTINUE IF NOT STRETCHING
;
; We will be stretching. Setup fromRect and toRect and map textR2.
;
MULU D0,D1 ;MULT WIDTH BY NUMER.H
DIVU DENOM+H(A6),D1 ;DIV BY DENOM.H
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,TORECT+TOPLEFT(A6) ;SET UP TORECT TOPLEFT
ADD.W NUMER+H(A6),D0 ;CALC PENLOC.H + NUMER.H
MOVE D0,TORECT+RIGHT(A6) ;SET UP TORECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD NUMER+V(A6),D0 ;CALC PENLOC.V + NUMER.V
MOVE D0,TORECT+BOTTOM(A6) ;SET UP TORECT BOTTOM
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,FROMRECT+TOPLEFT(A6) ;SET UP FROMRECT TOPLEFT
ADD.W DENOM+H(A6),D0 ;CALC PENLOC.H + DENOM.H
MOVE D0,FROMRECT+RIGHT(A6) ;SET UP FROMRECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD DENOM+V(A6),D0 ;CALC PENLOC.V + DENOM.V
MOVE D0,FROMRECT+BOTTOM(A6) ;SET UP FROMRECT BOTTOM
PEA TEXTR2(A6) ;PUSH TEXTR2
PEA FROMRECT(A6) ;PUSH FROMRECT
PEA TORECT(A6) ;PUSH TORECT
JSR MAPRECT ;MAP TEXTR2 (PRESERVES ALL REGS)
NOSTRCH ADD D1,PNLOC+H(A3) ;BUMP PEN BY (SCALED) TEXT WIDTH
;
; Quit if the pen is hidden
;
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT GOHOME ;YES, QUIT
;
; Calc minRect: the intersection of textRect, bitMap bounds,
; clipRgn and visRgn bounding boxes. Quit if no intersection.
;
PEA TEXTR2(A6) ;PUSH (MAPPED) TEXTRECT
PEA PORTBOUNDS(A3) ;PUSH BITMAP BOUNDS
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
MOVE #4,-(SP) ;PUSH NRECTS=4
PEA MINRECT(A6) ;PUSH DST ADDR
JSR RSECT ;CALC INTERSECTION
BEQ GOHOME ;QUIT IF NO INTERSECTION
;
; Set up srcAddr, srcRow, and height
;
LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVE.L A0,SRCADDR(A6) ;SAVE FOR LATER
MOVE RASTER(A2),D1 ;GET WORDS PER ROW IN FONT
ADD D1,D1 ;DOUBLE FOR BYTES PER ROW
MOVE D1,SRCROW(A6) ;REMEMBER FOR LATER
MOVE FBBDY(A2),HEIGHT(A6) ;SETUP HEIGHT FOR LATER
;
; Test for fast case:
; not stretched, no color mapping, txMode = srcOr,
; not bold, italic, underlined, outlined or shadowed,
; visRgn and clipRgn both rectangular.
;
TST.W 6(A4) ;TEST BOLD AND ITALIC
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
CMP #1,TXMODE(A3) ;IS TEXT MODE SRCOR ?
BNE NOTFAST ;NO, NOT FAST
TST.W 10(A4) ;TEST ULTHICK AND SHADOW
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
TST.B STRETCH(A6) ;IS TEXT STRETCHED ?
BNE NOTFAST ;YES, NOT FAST
MOVE COLRBIT(A3),D1 ;ARE WE COLOR MAPPING ?
BEQ.S NOCOLOR ;NO, CONTINUE
MOVE.L BKCOLOR(A3),D0 ;YES GET BACKGROUND COLOR
NOT.L D0 ;INVERT IT
AND.L FGCOLOR(A3),D0 ;AND WITH FOREGROUND COLOR
BTST D1,D0 ;IS THAT PLANE NORMAL ?
BEQ NOTFAST ;NO, NOT FAST
NOCOLOR MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
MOVEQ #10,D0
CMP RGNSIZE(A0),D0 ;IS CLIPRGN RECTANGULAR ?
BNE.S NOTFAST ;NO, NOT FAST
MOVE.L VISRGN(A3),A1 ;GET VISRGN HANDLE
MOVE.L (A1),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D0 ;IS VISRGN RECTANGULAR ?
BEQ.S FAST ;YES, TAKE FAST OPTIMIZATION
;
; All systems go except for VisRgn not rectangular.
; Check if visRgn sect minRect is rectangular.
; IF TrimRect(visRgn,minRect) THEN take the fast way.
;
MOVE.L A1,-(SP) ;PUSH VISRGN
PEA MINRECT(A6) ;PUSH MINRECT
JSR TRIMRECT ;CALL TRIMRECT
BLT GOHOME ;quit if intersection empty
BGT.S NOTFAST ;continue if non-rectangular
;
; Fast case, go directly to screen.
; If text is clipped vertically, then clear heightflag and update TOPHT
;
FAST ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
MOVE MINRECT+TOP(A6),D0 ;GET MINRECT.TOP
MOVE MINRECT+BOTTOM(A6),D1 ;GET MINRECT.BOTTOM
SUB TEXTRECT+TOP(A6),D0 ;was top clipped ?
BNE.S VCLIP ;yes, handle clip
CMP TEXTRECT+BOTTOM(A6),D1 ;was bottom clipped ?
BEQ.S VCLIPOK ;no, continue
VCLIP CLR.B HEIGHTFLAG(A6) ;can't use height table
MOVE.B D0,TOPHT(A6) ;use adjusted top
SUB MINRECT+TOP(A6),D1 ;calc clipped height
MOVE.B D1,TOPHT+1(A6) ;replace TOPHT
VCLIPOK MOVE TEXTRECT+TOP(A6),D0 ;GET DST TOP
SUB PORTBOUNDS+TOP(A3),D0 ;CONVERT TO GLOBAL COORDINATES
MULU PORTBITS+ROWBYTES(A3),D0 ;MULT BY ROWBYTES
ADD.L PORTBITS+BASEADDR(A3),D0 ;ADD START OF DST BITMAP
MOVE.L D0,BUFSTART(A6) ;SET UP BUFSTART FOR LATER
MOVE PORTBITS+ROWBYTES(A3),BUFROW(A6) ;SET UP BUFROW FOR LATER
MOVE PORTBOUNDS+LEFT(A3),BUFLEFT(A6) ;REMEMBER BUFLEFT
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L PORTBOUNDS+TOPLEFT(A3),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
JSR SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
BRA GETPTRS
;
; Slow case: Setup for an off-screen buffer.
;
; Calc bufLeft: (word-align to avoid shift)
;
NOTFAST CLR.B FASTFLAG(A6) ;NOT GOING DIRECTLY TO SCREEN
MOVE TEXTRECT+LEFT(A6),D0 ;GET TEXTRECT LEFT
SUB PORTBOUNDS+LEFT(A3),D0 ;CONVERT TO GLOBAL
AND #$FFF0,D0 ;TRUNC TO WORD BOUND
SUB #32,D0 ;32 DOT SLOP FOR SLANT & SHADOW
ADD PORTBOUNDS+LEFT(A3),D0 ;RETURN TO LOCAL COORDS
MOVE D0,BUFLEFT(A6) ;REMEMBER FOR LATER
;
; Calculate buffer size
;
MOVE TEXTRECT+RIGHT(A6),D1 ;BUFRIGHT := TEXTRECT RIGHT
SUB D0,D1 ;WIDTH:=BUFRIGHT-BUFLEFT
LSR #5,D1 ;CONVERT DOTS TO LONGS
ADD #2,D1 ;ROUND UP PLUS EXTRA LONG
MOVE HEIGHT(A6),D3 ;GET HEIGHT
MULU D1,D3 ;BUFSIZE:=HEIGHT*BUFROW LONGS
MOVE D3,BUFSIZE(A6) ;SAVE FOR LATER
LSL #2,D1 ;QUAD BUFROW FOR BYTES
MOVE D1,BUFROW(A6) ;SAVE FOR LATER
;
; Calculate total stack requirements for off-screen buffers.
;
MOVE.L D3,D2 ;GET BUFSIZE LONGS
TST.B 11(A4) ;ARE WE SHADOWING ?
BEQ @1 ;NO, CONTINUE
ADD.L D2,D2 ;YES, CALC 2*BUFSIZE
EXT.L D1 ;SIGN EXTEND BUFROW
ADD.L D1,D2 ;CALC TOTAL LONGS
@1 LSL.L #2,D2 ;CALC TOTAL STACK BYTES NEEDED
ADD.L #1024,D2 ;ADD 1 KBYTE SLOP
;
; If stack is too small to allocate buffer(s), then recursively call
; DrText with the left half and the right half of the text string.
;
_StackAvail ;Get StackAvail IN D0
CMP.L D0,D2 ;IS stackNeeded > stackAvail ?
BLE.S STACKOK ;NO, CONTINUE
MOVE.L PENLOC+H(A6),PNLOC+H(A3) ;RESTORE PNLOC TO ORIGINAL
MOVE COUNT(A6),D7 ;GET CHARACTER COUNT
LSR #1,D7 ;DIVIDE IN HALF
BEQ GOHOME ;GIVE UP IF COUNT WAS ONLY ONE
MOVE D7,-(SP) ;PUSH NEW COUNT
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
MOVE.L NUMER2(A6),-(SP) ;PUSH ORIGINAL NUMER
MOVE.L DENOM2(A6),-(SP) ;PUSH ORIGINAL DENOM
JSR DrText ;DRAW THE FIRST HALF
MOVE COUNT(A6),D0 ;GET ORIGINAL CHARACTER COUNT
SUB D7,D0 ;SUBTRACT CHARS ALREADY DONE
MOVE D0,-(SP) ;PUSH NEW COUNT
MOVE.L TEXTADDR(A6),A0 ;GET ORIGINAL TEXTADDR
ADD D7,A0 ;BUMP PAST CHARS ALREADY DONE
MOVE.L A0,-(SP) ;PUSH NEW TEXTADDR
MOVE.L NUMER2(A6),-(SP) ;PUSH ORIGINAL NUMER
MOVE.L DENOM2(A6),-(SP) ;PUSH ORIGINAL DENOM
JSR DrText ;DRAW THE SECOND HALF
BRA GOHOME ;AND QUIT !
;
; Allocate and clear an off-screen buffer
;
STACKOK SUB #1,D3 ;INIT DBRA LOOP COUNT
CLR.L -(SP) ;PAD BUFFER WITH AN EXTRA ZERO
MOVE.L SP,BUFEND(A6) ;REMEMBER WHERE BUFFER ENDS
CLRLOOP CLR.L -(SP)
DBRA D3,CLRLOOP ;ALLOCATE AND CLEAR BUFFER
MOVE.L SP,BUFSTART(A6) ;REMEMBER START OF BUFFER
CLR.L -(SP) ;PAD BUFFER WITH AN EXTRA ZERO
;
; Get pointers to location table, width table, and height table in font
;
GETPTRS LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVE FBBDY(A2),D0 ;GET HEIGHT OF FONT BITMAP
MULU SRCROW(A6),D0 ;CALC TOTAL SIZE OF STRIKE
ADD.L D0,A0 ;A1 := START OF LOC TABLE
MOVE.L A0,LOCTAB(A6) ;SAVE FOR LATER
CLR.L D0 ;get ready for unsigned word
MOVE LENGTH(A2),D0 ;HOW MANY WORDS IN STRIKE BODY
ADD.L D0,D0 ;DOUBLE FOR BYTECOUNT
LEA 16(A2,D0.L),A1 ;GET START OF WIDTH TABLE
MOVE.L A1,WIDTAB(A6) ;SAVE FOR LATER
MOVE MAXCHAR(A2),D0 ;GET MAXCHAR
MOVE MINCHAR(A2),D1 ;GET MINCHAR
MOVE D1,MINCH(A6) ;STASH MINCHAR FOR LATER
SUB D1,D0 ;CALC MAXCHAR-MINCHAR
MOVE D0,MAXMIN(A6) ;SAVE FOR LATER
ADD #3,D0 ;CALC MAXMIN+3
ADD D0,D0 ;CALC 2*(MAX-MIN+3)
BTST #1,1(A2) ;DOES FONT HAVE WIDTH TABLE ?
BEQ.S NOWID ;NO, CONTINUE
ADD D0,D0 ;YES, SKIP OVER WIDTH TABLE
NOWID LEA 0(A1,D0),A0 ;POINT TO HEIGHT TABLE
MOVE.L A0,HEIGHTAB(A6) ;SAVE FOR LATER
;
; Set up space width
;
MOVE.L widthPtr,A0 ;point to width table
MOVE.L 128(A0),SPWIDTH(A6) ;get width of the space char
;
; Setup misc stuff in registers for speed
;
MOVE BUFLEFT(A6),D1 ;GET BUFLEFT
MOVE PENLOC+H(A6),D0 ;GET PEN LOCATION
ADD FBBOX(A2),D0 ;ADJUST FOR KERNING
SUB D1,D0 ;MAKE CHARLOC RELATIVE TO BUFLEFT
MOVE.W D0,CHARLOC(A6) ;INIT INT PART OF CHARLOC
MOVE #$8000,CHARLOC+2(A6) ;SET FRACT PART TO ONE HALF
SUB D1,MINRECT+LEFT(A6) ;MAKE MINRECT.LEFT AND
SUB D1,MINRECT+RIGHT(A6) ;MINRECT.RIGHT BUFFER RELATIVE
MOVE.L TEXTADDR(A6),A1 ;GET TEXTPTR
BRA.S NEXTCH ;GO TO LOOP START
;---------------------------------------------------
;
; Here's the main character drawing loop:
;
SPACECH MOVE.L SPWIDTH(A6),D1 ;GET SPACE WIDTH
ADD.L D1,CHARLOC(A6) ;BUMP CHARLOC
SKIPCH SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BLE STRDONE ;QUIT IF CHARCOUNT <= 0
NEXTCH CLR D0 ;get ready for byte
MOVE.B (A1)+,D0 ;GET NEXT CHAR
CMP.B #32,D0 ;IS IT A SPACE ?
BEQ SPACECH ;YES, HANDLE IT
MOVE.L WidthPtr,A0 ;POINT TO WIDTH TABLE
MOVE D0,D4 ;COPY CHARACTER
LSL #2,D4 ;QUAD FOR TABLE OFFSET
MOVE.L 0(A0,D4),D4 ;GET FIXED POINT WIDTH
SUB MINCH(A6),D0 ;SUBTRACT SAVED MINCHAR
CMP MAXMIN(A6),D0 ;IS CH BETWEEN MINCHAR AND MAXCHAR ?
BLS.S OKCHAR ;YES, CONTINUE
MISSING MOVE MAXMIN(A6),D0 ;NO, USE MISSING SYMBOL
ADD #1,D0 ;WHICH IS ONE PAST MAXCHAR
ADD D0,D0 ;INDEX := 2*(MISSING-MINCHAR)
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
MOVE 0(A0,D0),D3 ;GET OFFSET AND WIDTH BYTES
BPL.S NOTMISS ;IS MISSING CHAR MISSING ?
BRA NEXTCH ;YES, SKIP THIS CHAR
OKCHAR ADD D0,D0 ;INDEX := 2*(ASCII-MINCHAR)
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
MOVE 0(A0,D0),D3 ;GET OFFSET AND WIDTH BYTES
BMI MISSING ;OFFSET NEG = MISSING CHAR
NOTMISS LSR #8,D3 ;GET OFFSET BYTE
ADD.W CHARLOC(A6),D3 ;DSTLEFT := CHARLOC.INT + OFFSET
ADD.L D4,CHARLOC(A6) ;ADD FIXED POINT WIDTH TO CHARLOC
MOVE.L LOCTAB(A6),A0 ;POINT TO LOCATION TABLE
MOVE 0(A0,D0),D1 ;GET SRCLEFT
MOVE 2(A0,D0),D2 ;GET SRCRIGHT
SUB D1,D2 ;CALC WIDTH OF BITS
BLE SKIPCH ;SKIP CHARBLT IF WIDTH <= 0
ADD D3,D2 ;DSTRIGHT := DSTLEFT + WIDTH
TST.B HEIGHTFLAG(A6) ;does font have height table ?
BEQ.S NOHEIGHT ;no, continue
MOVE.L HEIGHTAB(A6),A0 ;get height table
MOVE 0(A0,D0),TOPHT(A6) ;get this char's top and height
NOHEIGHT
;-----------------------------------------------------------------------
;
; Horizontal clip only if FastFlag: (else stretch,outline,shadow,italic die)
;
; skip if hidden on left, string done if hidden on right.
;
; at this point: D1: srcLeft
; D2: dstRight
; D3: dstLeft
;
TST.B FastFlag(A6) ;ARE WE GOING FAST ?
BEQ.S HORIZOK ;NO, DON'T CLIP
CMP MINRECT+LEFT(A6),D3 ;IS DSTLEFT < MINRECT.LEFT ?
BGE.S LEFTOK ;NO, CONTINUE
CMP MINRECT+LEFT(A6),D2 ;IS DSTRIGHT <= MINRECT.LEFT ?
BLE SKIPCH ;YES, SKIP THIS CHAR
TRIMLFT MOVE MINRECT+LEFT(A6),D0 ;NO, GET MINRECT.LEFT
SUB D3,D0 ;DISCARD:=MINRECT.LEFT-DSTLEFT
ADD D0,D1 ;SRCLEFT:=SRCLEFT+DISCARD
ADD D0,D3 ;DSTLEFT:=DSTLEFT+DISCARD
CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT > MINRECT.RIGHT ?
BLE.S HORIZOK ;NO, CONTINUE
BRA.S TRIMRT ;YES, TRIM RIGHT
LEFTOK CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT <= MINRECT.RIGHT ?
BLE.S HORIZOK ;YES, CONTINUE
CMP MINRECT+RIGHT(A6),D3 ;IS DSTLEFT >= MINRECT.RIGHT ?
BGE STRDONE ;YES, IGNORE REST OF STRING
TRIMRT MOVE MINRECT+RIGHT(A6),D2 ;NO, TRIM DSTRIGHT
HORIZOK
;--------------------------------------------------------------
;
; Inputs to local block CharBlt:
;
; srcAddr(A6)
; srcRow(A6)
; bufStart(A6) = dstAddr
; bufRow(A6) = dstRow
; D1 = srcLeft
; D2 = dstRight relative to buffer, > dstLeft
; D3 = dstLeft relative to buffer
; TOPHT(A6) top and height
;
; CLOBBERS: D0,D1,D2,D3,D4,D5,D6,D7,A0,A2,A3,A4,A5
; PRESERVES: A1,A6,A7
;
;
; Setup shift count in D5 (relative shift between src and dst)
;
MOVE D3,D5 ;COPY DSTLEFT
SUB D1,D5 ;SUB SRC LEFT
MOVEQ #$F,D0 ;get a 4 bit mask
AND D0,D5 ;SHIFTCNT:=DELTA HORIZ MOD 16
;
; Setup srcAddr in A4, address of leftmost word
;
MOVE.L SRCADDR(A6),A4 ;GET START OF SRC BITMAP
ADD D5,D1 ;CALC SRCLEFT+SHIFTCNT
ASR #4,D1 ;CONVERT FROM DOTS TO WORDS
ADD D1,D1 ;DOUBLE FOR BYTES
SUB #2,D1 ;BACK UP 1 WORD SINCE PICKING UP LONG
ADD D1,A4 ;LEAVE SRCPTR IN A4
;
; Setup dstPtr in A5, address of leftmost dst word
;
MOVE.L BUFSTART(A6),A5 ;GET START OF DST BITMAP
MOVE D3,D1 ;GET A COPY OF DSTLEFT
ASR #4,D1 ;CONVERT FROM DOTS TO WORDS
ADD D1,A5 ;ADD TO DSTPTR
ADD D1,A5 ;TWICE FOR BYTES
;
; Setup leftMask in D3 and rightMask in D4
;
LEA MaskTab,A0 ;point to mask table
AND D0,D3 ;get bottom 4 bits of dstLeft
ADD D3,D3 ;double for table index
MOVE 0(A0,D3),D3 ;get mask word from table
NOT D3 ;invert it for leftMask
MOVE D2,D6 ;copy dstRight
AND D0,D2 ;get bottom 4 bits of dstRight
ADD D2,D2 ;double for table index
MOVE 0(A0,D2),D4 ;get rightMask from table
;
; Get srcRow, dstRow, and char height into regs
;
MOVE SRCROW(A6),A2
MOVE BUFROW(A6),A3
MOVE.W #255,D7 ;GET -1 BYTE, CLEAR HI BYTE
ADD.B TOPHT+1(A6),D7 ;CALC HEIGHT-1 FOR DBRA LOOP
BMI SKIPCH ;OOPS HEIGHT WAS ZERO !
;
; Adjust srcPtr and dstPtr for charTop
;
CLR.W D0 ;get ready for byte
MOVE.B TOPHT(A6),D0 ;get char top
MOVE A2,D2 ;get srcRow in D-reg
MULU D0,D2 ;calc charTop * srcRow
ADD.L D2,A4 ;add to srcPtr
MOVE A3,D2 ;get dstRow in D-reg
MULU D0,D2 ;calc charTop * dstRow
ADD.L D2,A5 ;add to dstPtr
;
; Branch based on total number of dst words
;
ASR #4,D6 ;CALC (DSTRIGHT) DIV 16
SUB D1,D6 ;CALC TOTAL NUMBER OF WORDS-1
BEQ.S WORD1 ;BR IF DST ALL IN ONE WORD
SUB #1,D6
BEQ.S LONG1 ;BR IF DST ALL IN ONE LONG
ADD #1,D7 ;COMPENSATE FOR EXTRA DBRA
BRA.S WIDE1 ;DST WIDER THAN ONE LONG
;
; Slow loop only taken in wierd cases where dst wider than a long.
;
MAIN1 MOVE.L (A4),D0 ;GET SRC FROM BITMAP
ADD #2,A4 ;BUMP SRCPTR RIGHT
LSR.L D5,D0 ;ALIGN TO DST
AND D1,D0 ;MASK EXTRA TO ZEROS
OR D0,(A5)+ ;OR SRC INTO DST
MOVEQ #-1,D1 ;FLUSH MASK
DBRA D2,MAIN1 ;LOOP TILL LAST WORD
MOVE.L (A4),D0 ;GET SRC FROM BITMAP
LSR.L D5,D0 ;ALIGN TO DST
AND D4,D0 ;MASK WITH RIGHTMASK
OR D0,(A5) ;OR SRC INTO DST
MOVE.L SRCPTR(A6),A4 ;RESTORE SRCPTR TO LEFT
ADD A2,A4 ;BUMP TO NEXT ROW
MOVE.L DSTPTR(A6),A5 ;RESTORE DSTPTR TO LEFT
ADD A3,A5 ;BUMP DST TO NEXT ROW
WIDE1 MOVE.L A4,SRCPTR(A6) ;REMEMBER SRCPTR AT LEFT
MOVE.L A5,DSTPTR(A6) ;REMEMBER DSTPTR AT LEFT
MOVE D3,D1 ;MASK:=LEFTMASK
MOVE D6,D2 ;GET WORDCOUNT
DBRA D7,MAIN1 ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
BRA STRDONE ;QUIT IF CHARCOUNT <= 0
;
; Optimize if dst fits in one long. (30% of normal characters do)
;
LONG1 SUB #2,A3 ;ADJUST DSTEND FOR WORD BUMP
LONG1A MOVE.L (A4),D0 ;GET SRC DATA
LSR.L D5,D0 ;ALIGN TO DST
AND D3,D0 ;MASK EXTRA WITH LEFTMASK
OR D0,(A5)+ ;OR RESULT INTO DST
MOVE.L 2(A4),D0 ;GET SECOND WORD OF SRC
LSR.L D5,D0 ;ALIGN IT
AND D4,D0 ;MASK EXTRA WITH RIGHTMASK
OR D0,(A5) ;OR RESULT INTO DST
ADD A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,LONG1A ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
BRA STRDONE ;QUIT IF CHARCOUNT <= 0
;
; Optimize if dst fits in one word. (70% of normal characters do)
;
WORD1 AND D4,D3 ;COMBINE LEFT AND RIGHT MASKS
WORD1B MOVE.L (A4),D0 ;GET SRC DATA
LSR.L D5,D0 ;ALIGN TO DST
AND D3,D0 ;MASK EXTRA TO ZEROS
OR D0,(A5) ;OR RESULT INTO DST
ADD A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,WORD1B ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
STRDONE MOVE.L SAVEA5(A6),A5 ;RESTORE GLOBAL PTR
TST.B FASTFLAG(A6) ;WERE WE GOING DIRECT TO SCREEN ?
BEQ.S @1 ;NO, CONTINUE
JSR SHOWCURSOR ;YES, RESTORE CURSOR
BRA GOHOME ;AND QUIT
@1 MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A3 ;GET CURRENT GRAFPORT
MOVE.L FONTPTR(A0),A4 ;POINT TO FMOUTPUT
MOVE.L 2(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE CHARLOC(A6),D7 ;GET FINAL CHARLOC INT PART
SUB FBBOX(A2),D7 ;UN-ADJUST FROM KERNING
;
; Make buffer bold if necessary:
;
CKBOLD CLR D2 ;GET READY FOR BYTE
MOVE.B 6(A4),D2 ;GET NUMBER OF OVERSTRIKES
BRA.S NXTBOLD ;BOLD BUFFER IF ANY
BOLDIT MOVE.L BUFSTART(A6),A0 ;POINT TO START OF BUFFER
MOVE BUFSIZE(A6),D1 ;HOW MANY LONGS IN BUF
SUB D0,D0 ;CLEAR X-BIT
BOLDLP MOVE.L (A0),D0 ;GET ONE LONG
ROXR.L #1,D0 ;ROTATE RIGHT WITH EXTEND
OR.L D0,(A0)+ ;OR BACK INTO BUFFER
DBRA D1,BOLDLP ;LOOP ENTIRE BUFFER
NXTBOLD DBRA D2,BOLDIT ;LOOP FOR EACH OVERSTRIKE
;
; Slant the buffer if necessary:
; Work from bottom of buffer up, shifting each row right.
; Work right to left to avoid clobbering src.
;
CLR D2 ;GET READY FOR BYTE
MOVE.B 7(A4),D2 ;DO WE NEED ITALIC ?
BEQ.S CHECKUL ;NO, CONTINUE
MOVE.L BUFEND(A6),A1 ;DSTPTR:=END OF BUFFER
MOVE BUFROW(A6),D3 ;GET BUFFER ROWBYTES
SUB D3,A1 ;BACK UP DSTPTR TO END OF 2ND ROW
LSR #1,D3 ;WORDCNT:=ROWBYTES DIV 2
SUB #1,D3 ;WORDCOUNT-1 FOR DBRA LOOP
MOVE HEIGHT(A6),D6 ;INIT ROW COUNTER
CLR D4 ;INIT OFFSET
BRA.S DOSLANT ;GO TO LOOP START
NXTROW ADD D2,D4 ;OFFSET:=OFFSET+ITALIC
MOVE D4,D0 ;COPY OFFSET
LSR #4,D0 ;DELTA := OFFSET SCALED BY 16
MOVEQ #$F,D5
AND D0,D5 ;SHIFTCNT:=DELTA MOD 16
LSR #4,D0 ;DELWORD:=DELTA DIV 16
MOVE.L A1,A0 ;SRCPTR:=DSTPTR
SUB #4,A0 ;BACK UP ONE LONG
SUB D0,A0 ;SUBTRACT DELWORD
SUB D0,A0 ;TWICE BECAUSE WORDS
MOVE D3,D1 ;INIT LOOP TO WORDCNT
NXTWORD MOVE.L (A0),D0 ;GET A LONG OF SRC
SUB #2,A0 ;BUMP SRCPTR LEFT ONE WORD
LSR.L D5,D0 ;SHIFT SRC TO ALIGN WITH DST
MOVE D0,-(A1) ;STORE IN DST AND BUMP DSTPTR
DBRA D1,NXTWORD ;LOOP ALL WORDS THIS ROW
DOSLANT DBRA D6,NXTROW ;LOOP FOR ALL ROWS IN BUFFER
;
; Underline characters in buffer if necessary.
;
; Use characters in buffer to hide parts of the underline.
;
CHECKUL TST.B 10(A4) ;IS ULTHICK ZERO ?
BEQ NOTUL ;YES, CONTINUE
MOVE.L BUFSTART(A6),A0 ;POINT TO BUFFER START
MOVE BUFROW(A6),D1 ;GET BYTES PER ROW OF BUFFER
MOVE ASCENT(A2),D0 ;GET ASCENT
MOVE DESCENT(A2),D2 ;GET DESCENT
MULU D1,D0
ADD.L D0,A0 ;POINT TO BASELINE ROW
MOVE.L A0,A1
MOVE.L A0,A2
ADD D1,A1 ;POINT TO BASELINE+1
CMP #2,D2 ;IS DESCENT AT LEAST 2 ?
BLT.S NOTUL ;NO, SKIP UNDERLINE
BEQ.S ONLY2 ;ONLY USE 2 IF DESCENT=2
ADD D1,A2
ADD D1,A2 ;POINT TO BASELINE+2
ONLY2 SUB D1,SP ;ALLOCATE TEMP SCANBUF
MOVE.L A3,-(SP) ;SAVE GRAFPORT
LEA 4(SP),A3 ;POINT TO START OF TEMP
LSR #2,D1 ;CONVERT BYTES TO LONGS
SUB #1,D1 ;INIT DBRA LOOP COUNT
MOVE D1,D2 ;COPY LOOP COUNT
SUB D0,D0 ;CLEAR X-BIT
UL1 MOVE.L (A0)+,D0 ;GET FROM BASELINE
OR.L (A1)+,D0 ;OR WITH BASELINE+1
OR.L (A2)+,D0 ;OR WITH BASELINE+2
MOVE.L D0,(A3) ;PUT RESULT TO TEMP
ROXR.L #1,D0 ;SHIFT WITH CARRY
OR.L D0,(A3)+ ;OR INTO TEMP
DBRA D1,UL1 ;LOOP ALL LONGS IN ROW
MOVE.L A1,A0 ;COPY END PTR
SUB D0,D0 ;CLEAR X-BIT
UL2 MOVE.L -(A3),D0 ;GET FROM TEMP
ROXL.L #1,D0 ;SHIFT LEFT WITH CARRY
OR.L (A3),D0 ;OR WITH TEMP
NOT.L D0 ;INVERT
OR.L D0,-(A1) ;DRAW SOME UNDERLINE
DBRA D2,UL2 ;LOOP ALL LONGS IN ROW
MOVE.L (SP)+,A3 ;RESTORE GRAFPORT
;
; Trim right edge of underline. (left edge trimmed by StretchBits)
;
MOVE BUFROW(A6),D0 ;GET BYTES PER ROW OF BUFFER
LSL #3,D0 ;TIMES 8 FOR DOTS WIDE
SUB D7,D0 ;OVERSHOOT:=BUFRIGHT-LASTRIGHT
SUB #1,D0 ;BACK UP 1 SO MASK COMES OUT RIGHT
LSR #4,D0 ;CONVERT DOTS TO WORDCOUNT
BRA.S UL3 ;GO TO LOOP START
ULTRIM CLR -(A0) ;ERASE SOME UNDERLINE
UL3 DBRA D0,ULTRIM ;LOOP ALL FULL WORDS
ADD BUFLEFT(A6),D7 ;UNDO BUFFER RELATIVE
MOVE D7,D0 ;GET LAST RIGHT COORD
SUB PORTBOUNDS+LEFT(A3),D0 ;CONVERT TO GLOBAL COORDS
JSR RIGHTMASK ;COMPUTE A MASK
AND D0,-(A0) ;ERASE LAST PARTIAL WORD
;
; Setup fakeRgn, a dummy rectangular region
;
NOTUL MOVE #10,FAKERGN+RGNSIZE(A6) ;SIZE=10 BYTES FOR RECT RGN
MOVE.L PORTBOUNDS(A3),FAKERGN+RGNBBOX(A6)
MOVE.L PORTBOUNDS+4(A3),FAKERGN+RGNBBOX+4(A6)
LEA FAKERGN(A6),A0 ;GET ADDR OF FAKERGN
MOVE.L A0,FAKEPTR(A6) ;POINT FAKE MASTERPTR TO IT
;
; Setup bitMaps to transfer from buffer to screen.
;
; srcBits := buffer
;
LEA SRCBITS(A6),A0 ;POINT TO SRCBITS
MOVE.L BUFSTART(A6),(A0)+ ;SET UP BASEADDR
MOVE BUFROW(A6),(A0)+ ;SET UP ROWBYTES
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
MOVE BUFLEFT(A6),(A0)+ ;SET UP BOUNDS LEFT
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
;
; dstBits := portBits
;
LEA PORTBITS(A3),A2 ;POINT TO PORTBITS
LEA DSTBITS(A6),A0 ;POINT TO DSTBITS
MOVE.L (A2)+,(A0)+ ;COPY BASEADDR
MOVE (A2)+,(A0)+ ;COPY ROWBYTES
MOVE.L (A2)+,(A0)+ ;COPY BOUNDS.TOPLEFT
MOVE.L (A2)+,(A0)+ ;COPY BOUNDS.BOTRIGHT
;
; check if any shadowing:
;
CLR D3 ;GET READY FOR BYTE
MOVE.B 11(A4),D3 ;GET SHADOW COUNT
BEQ NOSHAD ;SKIP IF NO SHADOWING
;
; Shadowing will be used. Allocate buf2, 4 scans taller than BUF1.
; Clear out new 4 scanlines, and copy BUF1 into the rest.
;
MOVE BUFROW(A6),D0 ;GET 4 * NUMBER OF LONGS PER ROW
SUB #1,D0 ;INIT LOOP COUNTER
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
MOVE.L SP,BUF2END(A6) ;REMEMBER END OF BUF2
CLR2 CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLR2 ;CLEAR 4 SCANLINES WORTH
MOVE BUFSIZE(A6),D0 ;GET NUMBER OF LONGS IN BUF1
SUB #1,D0 ;INIT DBRA COUNTER
MOVE.L BUFEND(A6),A0 ;POINT TO END OF BUF1
COPYLP MOVE.L -(A0),-(SP) ;COPY FROM BUF1 TO NEW BUF2
DBRA D0,COPYLP ;COPY ALL OF BUF1
MOVE.L SP,BUF2START(A6) ;REMEMBER START OF BUF2
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
;
; Bold buf2 across to the right enough for shadow.
;
AND #3,D3 ;RESTRICT SHADOW COUNT TO 1..3
MOVE D3,D2 ;INIT BOLD COUNTER
ACROSS1 MOVE.L BUF2START(A6),A0 ;POINT TO START OF BUFFER2
MOVE BUFSIZE(A6),D1 ;INIT COUNT OF LONGS
SUB D0,D0 ;CLEAR X-BIT
ACROSS2 MOVE.L (A0),D0 ;GET A LONG FROM BUF2
ROXR.L #1,D0 ;SHIFT IT RIGHT EXTENDED
OR.L D0,(A0)+ ;OR IT BACK INTO BUFFER
DBRA D1,ACROSS2 ;LOOP FOR ALL LONGS
DBRA D2,ACROSS1 ;BOLD RIGHT 2,3, OR 4 TIMES
;
; Bold BUF2 down enough for shadow.
;
MOVE.L BUF2START(A6),A2 ;GET LIMIT POINTER
DOWN1 MOVE.L BUF2END(A6),A1 ;DSTPTR:=END OF BUF2
MOVE.L A1,A0
SUB SRCBITS+ROWBYTES(A6),A0 ;SRCPTR:=END - 1 SCANLINE
DOWN2 MOVE.L -(A0),D0 ;GET A LONG FROM LINE ABOVE
OR.L D0,-(A1) ;OR INTO THIS LINE
CMP.L A2,A0 ;IS SRCPTR <= BUF2START ?
BGT DOWN2 ;NO, LOOP ALL LONGS
DBRA D3,DOWN1 ;BOLD DOWN 2,3, OR 4 TIMES
;
; Alter srcBits to use BUF2
;
MOVE.L A2,SRCBITS+BASEADDR(A6) ;SRC BASEADDR:=BUF2START
ADD #4,SRCBITS+BOUNDS+BOTTOM(A6) ;4 SCANS TALLER
;
; Push params and call StretchBits to transfer shadow to screen
;
MOVE.L TEXTRECT(A6),SRCRECT(A6) ;SRCRECT := TEXTRECT
MOVE.L TEXTRECT+4(A6),SRCRECT+4(A6)
ADD #4,SRCRECT+BOTTOM(A6) ;PLUS 4 SCANS TALLER
MOVE.L SRCRECT(A6),DSTRECT(A6) ;DSTRECT := SRCRECT
MOVE.L SRCRECT+4(A6),DSTRECT+4(A6)
LEA DSTRECT+TOP(A6),A0 ;OFFSET BY (-1,-1)
SUB #1,(A0)+ ;TOP
SUB #1,(A0)+ ;LEFT
SUB #1,(A0)+ ;BOTTOM
SUB #1,(A0)+ ;RIGHT
TST.B STRETCH(A6)
BEQ.S @1
PEA DSTRECT(A6)
PEA FROMRECT(A6)
PEA TORECT(A6)
JSR MAPRECT ;THEN MAPPED FOR SCALING
@1
PEA SRCBITS(A6) ;PUSH SRCBITS
PEA DSTBITS(A6) ;PUSH DSTBITS
PEA SRCRECT(A6) ;PUSH SRCRECT
PEA DSTRECT(A6) ;PUSH DSTRECT
MOVEQ #7,D0 ;GET A 3-BIT MASK
AND TXMODE(A3),D0 ;GET TEXTMODE MOD 7
MOVE D0,-(SP) ;PUSH SHADOW MODE
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
JSR StretchBits ;TRANSFER BUFFER TO SCREEN
;
; restore altered srcBits
;
MOVE.L BUFSTART(A6),SRCBITS+BASEADDR(A6)
SUB #4,SRCBITS+BOUNDS+BOTTOM(A6)
;
; Push params and call StretchBits to transfer buffer to screen
;
NOSHAD PEA SRCBITS(A6) ;PUSH SRCBITS
PEA DSTBITS(A6) ;PUSH DSTBITS
PEA TEXTRECT(A6) ;PUSH SRCRECT = TEXTRECT
PEA TEXTR2(A6) ;PUSH DSTRECT = TEXTR2
MOVE TXMODE(A3),-(SP) ;PUSH TEXTMODE
TST.B 11(A4) ;ARE WE USING SHADOW ?
BEQ.S MODEOK ;NO, CONTINUE
MOVE #2,(SP) ;YES, USE XOR MODE
MODEOK AND #7,(SP) ;TREAT MODE MOD 8
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
JSR StretchBits ;TRANSFER BUFFER TO SCREEN
GOHOME MOVE.L SAVESTK(A6),SP ;STRIP BUFFER
MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'DRTEXT '
.END

45
FixMove.p Executable file
View File

@ -0,0 +1,45 @@
PROGRAM FixMove;
{ Assembler restrictions require procedure Move to assembled as MQVE. }
{ This program back patches the object file replacing 'MQVE' with 'MOVE' }
VAR f: FILE;
fileName: String[30];
buffer: PACKED ARRAY[0..1023] OF CHAR;
i,hitCount: INTEGER;
BEGIN
REPEAT
WRITE('file to patch:');
READLN(fileName);
RESET(f,fileName);
UNTIL IORESULT = 0;
i := BlockRead(f,buffer,2,0);
hitCount := 0;
FOR i := 0 TO 1020 DO
BEGIN
IF (buffer[i ] = 'M')
AND (buffer[i+1] = 'Q')
AND (buffer[i+2] = 'V')
AND (buffer[i+3] = 'E')
THEN
BEGIN
buffer[i+1] := 'O';
hitCount := hitCount + 1;
END;
END;
WRITE(hitCount:1,' matches found.');
IF hitCount = 0 THEN WRITELN(CHR(7))
ELSE
BEGIN
i := BlockWrite(f,buffer,2,0);
IF IORESULT <> 0 THEN WRITELN('Oops, trouble writing');
END;
CLOSE(f,lock);
END.

477
Graf3D.p Executable file
View File

@ -0,0 +1,477 @@
{$S Graf }
UNIT Graf3D;
{ three-dimensional graphics routines layered on top of QuickDraw }
INTERFACE
USES {$U obj:QuickDraw } QuickDraw;
CONST radConst=57.29578;
TYPE Point3D=RECORD
x: REAL;
y: REAL;
z: REAL;
END;
Point2D=RECORD
x: REAL;
y: REAL;
END;
XfMatrix = ARRAY[0..3,0..3] OF REAL;
Port3DPtr = ^Port3D;
Port3D = RECORD
GPort: GrafPtr;
viewRect: Rect;
xLeft,yTop,xRight,yBottom: REAL;
pen,penPrime,eye: Point3D;
hSize,vSize: REAL;
hCenter,vCenter: REAL;
xCotan,yCotan: REAL;
ident: BOOLEAN;
xForm: XfMatrix;
END;
VAR thePort3D: Port3DPtr;
PROCEDURE Open3DPort (port: Port3DPtr);
PROCEDURE SetPort3D (port: Port3DPtr);
PROCEDURE GetPort3D (VAR port: Port3DPtr);
PROCEDURE MoveTo2D(x,y: REAL); PROCEDURE MoveTo3D(x,y,z: REAL);
PROCEDURE LineTo2D(x,y: REAL); PROCEDURE LineTo3D(x,y,z: REAL);
PROCEDURE Move2D(dx,dy: REAL); PROCEDURE Move3D(dx,dy,dz: REAL);
PROCEDURE Line2D(dx,dy: REAL); PROCEDURE Line3D(dx,dy,dz: REAL);
PROCEDURE ViewPort (r: Rect);
PROCEDURE LookAt (left,top,right,bottom: REAL);
PROCEDURE ViewAngle (angle: REAL);
PROCEDURE Identity;
PROCEDURE Scale (xFactor,yFactor,zFactor: REAL);
PROCEDURE Translate (dx,dy,dz: REAL);
PROCEDURE Pitch (xAngle: REAL);
PROCEDURE Yaw (yAngle: REAL);
PROCEDURE Roll (zAngle: REAL);
PROCEDURE Skew (zAngle: REAL);
PROCEDURE TransForm (src: Point3D; VAR dst: Point3D);
FUNCTION Clip3D (src1,src2: Point3D; VAR dst1,dst2: POINT): BOOLEAN;
PROCEDURE SetPt3D (VAR pt3D: Point3D; x,y,z: REAL);
PROCEDURE SetPt2D (VAR pt2D: Point2D; x,y: REAL);
IMPLEMENTATION
PROCEDURE Open3DPort(* port: Port3DPtr *);
{ initialize all values in port^ to their defaults }
BEGIN
thePort3D:=port;
port^.GPort:=thePort;
ViewPort(thePort^.portRect);
WITH thePort^.portRect DO LookAt(left,top,right,bottom);
ViewAngle(0);
Identity;
MoveTo3D(0,0,0);
END;
PROCEDURE SetPort3D(* port: Port3DPtr *);
{ change to another Port3D }
BEGIN
thePort3D:=port;
SetPort(port^.GPort);
END;
PROCEDURE GetPort3D(* VAR port: Port3DPtr *);
{ inquire the current Port3D }
BEGIN
port:=thePort3D;
END;
PROCEDURE MoveTo3D(* x,y,z: REAL *);
{ Move from current position to x,y,z without drawing. }
VAR pt1,pt2: POINT;
oldPrime: Point3D;
BEGIN
WITH thePort3D^ DO
BEGIN
oldPrime:=penPrime;
pen.x:=x;
pen.y:=y;
pen.z:=z;
TransForm(pen,penPrime);
IF Clip3D(oldPrime,penPrime,pt1,pt2) THEN MoveTo(pt2.H,pt2.V);
END;
END;
PROCEDURE LineTo3D(* x,y,z: REAL *);
{ draw a 3-D line from current position to x,y,z. }
VAR oldPrime: Point3D;
pt1,pt2: POINT;
BEGIN
WITH thePort3D^ DO
BEGIN
oldPrime:=penPrime;
pen.x:=x;
pen.y:=y;
pen.z:=z;
TransForm(pen,penPrime);
IF Clip3D(oldPrime,penPrime,pt1,pt2) THEN
BEGIN
MoveTo(pt1.h,pt1.v);
LineTo(pt2.H,pt2.V);
END;
END;
END;
PROCEDURE Move3D(* dx,dy,dz: REAL *);
BEGIN
WITH thePort3D^ DO MoveTo3D(pen.x+dx,pen.y+dy,pen.z+dz);
END;
PROCEDURE Line3D(* dx,dy,dz: REAL *);
BEGIN
WITH thePort3D^ DO LineTo3D(pen.x+dx,pen.y+dy,pen.z+dz);
END;
PROCEDURE MoveTo2D(* x,y: REAL *);
BEGIN
MoveTo3D(x,y,thePort3D^.pen.z);
END;
PROCEDURE Move2D(* dx,dy: REAL *);
BEGIN
Move3D(dx,dy,0.0);
END;
PROCEDURE LineTo2D(* x,y: REAL *);
BEGIN
LineTo3D(x,y,thePort3D^.pen.z);
END;
PROCEDURE Line2D(* dx,dy: REAL *);
BEGIN
Line3D(dx,dy,0.0);
END;
PROCEDURE ViewLook;
{ re-calculate offsets and scales after LookAt or ViewPort }
BEGIN
WITH thePort3D^ DO
WITH viewRect DO
BEGIN
hSize:=(right-left)/2.0;
vSize:=(bottom-top)/(-2.0); { vert pos down, y pos up }
hCenter:=left + hSize;
vCenter:=top - vSize;
END;
END;
PROCEDURE ViewPort(* r: Rect *);
{ specify what portion of the folder to map onto }
BEGIN
thePort3D^.viewRect:=r;
ViewLook; { re-calculate scales and offsets }
END;
PROCEDURE LookAt(* left,top,right,bottom: REAL *);
{ specify the real number coordinates of the portRect }
BEGIN
WITH thePort3D^ DO
BEGIN
xLeft:=left;
xRight:=right;
yBottom:=bottom;
yTop:=top;
eye.x:=(left+right)/2.0;
eye.y:=(top+bottom)/2.0;
END;
ViewLook; { re-calculate scales and offsets }
END;
PROCEDURE ViewAngle(* angle: REAL *);
{ specify the horizontal angle subtended by the viewing pyramid }
BEGIN
WITH thePort3D^ DO
BEGIN
IF angle < 0.1 THEN angle:=0.1;
angle:=angle/(2.0*radConst); { halve angle & convert to rad }
xCotan:=COS(angle)/SIN(angle); { remember for perspective calc }
yCotan:=xCotan * (xRight-xLeft)/(yTop-yBottom);
eye.z:=xCotan * (xRight-xLeft)/2;
END;
END;
PROCEDURE TransForm(* src: Point3D; VAR dst: Point3D *);
{ use the current xForm matrix to transform }
{ a 3D source point into a 3D destination point. }
BEGIN
IF thePort3D^.ident THEN dst:=src
ELSE WITH thePort3D^ DO
BEGIN
dst.x:=src.x * xForm[0,0] + src.y * xForm[1,0]
+ src.z * xForm[2,0] + xForm[3,0];
dst.y:=src.x * xForm[0,1] + src.y * xForm[1,1]
+ src.z * xForm[2,1] + xForm[3,1];
dst.z:=src.x * xForm[0,2] + src.y * xForm[1,2]
+ src.z * xForm[2,2] + xForm[3,2];
END;
END;
FUNCTION Clip3D(* src1,src2: Point3D; VAR dst1,dst2: POINT *);
{ do full 3D clipping to viewing pyramid and return 2D }
{ screen coords in dst. Function value true if visible. }
LABEL 0;
TYPE Edge=(left,top,right,bottom);
OutCode=SET OF Edge;
VAR c,c1,c2: OutCode;
pt3D: Point3D;
t: REAL;
pt1,pt2: POINT;
PROCEDURE Code(pt3D: Point3D; VAR c: OutCode);
BEGIN
c:=[];
IF pt3D.x < -pt3D.z THEN c:=[left] ELSE IF pt3D.x > pt3D.z THEN c:=[right];
IF pt3D.y < -pt3D.z THEN c:=c+[bottom] ELSE IF pt3D.y > pt3D.z THEN c:=c+[top];
END;
BEGIN
Clip3D:=FALSE;
WITH thePort3D^ DO
BEGIN { convert both points into clipping coord system }
src1.x:=(src1.x - eye.x) * xCotan;
src1.y:=(src1.y - eye.y) * yCotan;
src1.z:=eye.z - src1.z;
src2.x:=(src2.x - eye.x) * xCotan;
src2.y:=(src2.y - eye.y) * yCotan;
src2.z:=eye.z - src2.z;
END;
Code(src1,c1); Code(src2,c2);
WHILE c1+c2 <> [] DO
BEGIN
IF c1*c2 <> [] THEN GOTO 0; { both out on same side }
c:=c1; IF c=[] THEN c:=c2;
IF left IN c THEN { calc intersect with left edge }
BEGIN
t:=(src1.z+src1.x) / ((src1.x-src2.x) - (src2.z-src1.z));
pt3D.z:=t*(src2.z-src1.z) + src1.z;
pt3D.x:=-pt3D.z;
pt3D.y:=t*(src2.y-src1.y) + src1.y;
END
ELSE IF right IN c THEN { calc intersect with right edge }
BEGIN
t:=(src1.z-src1.x) / ((src2.x-src1.x) - (src2.z-src1.z));
pt3D.z:=t*(src2.z-src1.z) + src1.z;
pt3D.x:=pt3D.z;
pt3D.y:=t*(src2.y-src1.y) + src1.y;
END
ELSE IF bottom IN c THEN { calc intersect with bottom edge }
BEGIN
t:=(src1.z+src1.y) / ((src1.y-src2.y) - (src2.z-src1.z));
pt3D.z:=t*(src2.z-src1.z) + src1.z;
pt3D.x:=t*(src2.x-src1.x) + src1.x;
pt3D.y:=-pt3D.z;
END
ELSE IF top IN c THEN { calc intersect with top edge }
BEGIN
t:=(src1.z-src1.y) / ((src2.y-src1.y) - (src2.z-src1.z));
pt3D.z:=t*(src2.z-src1.z) + src1.z;
pt3D.x:=t*(src2.x-src1.x) + src1.x;
pt3D.y:=pt3D.z;
END;
IF c=c1 THEN BEGIN src1:=pt3D; Code(src1,c1); END
ELSE BEGIN src2:=pt3D; Code(src2,c2); END;
END;
{ if we reach here, the line from src1 to src2 is visible }
Clip3D:=TRUE;
WITH thePort3D^ DO
WITH GPort^ DO
BEGIN { convert clip coords to screen coords }
dst1.H:=ROUND(hCenter + hSize * src1.x / src1.z);
dst1.V:=ROUND(vCenter + vSize * src1.y / src1.z);
dst2.H:=ROUND(hCenter + hSize * src2.x / src2.z);
dst2.V:=ROUND(vCenter + vSize * src2.y / src2.z);
END;
0: END;
PROCEDURE Identity;
{ reset the transform matrix to identity }
VAR ROW,COL: INTEGER;
BEGIN;
WITH thePort3D^ DO
BEGIN
FOR ROW:=0 TO 3 DO
FOR COL:=0 TO 3 DO
IF ROW=COL THEN xForm[ROW,COL]:=1.0
ELSE xForm[ROW,COL]:=0.0;
ident:=TRUE; { SET FLAG SO xForm CAN BE SKIPPED }
END;
END;
PROCEDURE Scale(* xFactor,yFactor,zFactor: REAL *);
{ change xForm matrix to provide scaling }
VAR ROW: INTEGER;
BEGIN
WITH thePort3D^ DO
BEGIN
ident:=FALSE;
FOR ROW:=0 TO 3 DO
BEGIN
xForm[ROW,0]:=xForm[ROW,0]*xFactor;
xForm[ROW,1]:=xForm[ROW,1]*yFactor;
xForm[ROW,2]:=xForm[ROW,2]*zFactor;
END;
END;
END;
PROCEDURE Translate(* dx,dy,dz: REAL *);
{ change xForm matrix to translate }
BEGIN
WITH thePort3D^ DO
BEGIN
ident:=FALSE;
xForm[3,0]:=xForm[3,0]+dx;
xForm[3,1]:=xForm[3,1]+dy;
xForm[3,2]:=xForm[3,2]+dz;
END;
END;
PROCEDURE Pitch(* xAngle: REAL *);
{ change xForm matrix to rotate xAngle degrees around x-Axis }
VAR si,co,TEMP: REAL;
BEGIN
xAngle:=xAngle/radConst; { convert degrees to rads }
si:=SIN(xAngle); co:=COS(xAngle);
WITH thePort3D^ DO
BEGIN
ident:=FALSE;
TEMP:=xForm[0,1]*co+xForm[0,2]*si;
xForm[0,2]:=xForm[0,2]*co-xForm[0,1]*si; xForm[0,1]:=TEMP;
TEMP:=xForm[1,1]*co+xForm[1,2]*si;
xForm[1,2]:=xForm[1,2]*co-xForm[1,1]*si; xForm[1,1]:=TEMP;
TEMP:=xForm[2,1]*co+xForm[2,2]*si;
xForm[2,2]:=xForm[2,2]*co-xForm[2,1]*si; xForm[2,1]:=TEMP;
TEMP:=xForm[3,1]*co+xForm[3,2]*si;
xForm[3,2]:=xForm[3,2]*co-xForm[3,1]*si; xForm[3,1]:=TEMP;
END;
END;
PROCEDURE Yaw(* yAngle: REAL *);
{ change xForm matrix to rotate yAngle degrees around y-Axis }
VAR si,co,TEMP: REAL;
BEGIN
yAngle:=yAngle/radConst; { convert degrees to rads }
si:=SIN(yAngle); co:=COS(yAngle);
WITH thePort3D^ DO
BEGIN
ident:=FALSE;
TEMP:=xForm[0,0]*co-xForm[0,2]*si;
xForm[0,2]:=xForm[0,0]*si+xForm[0,2]*co; xForm[0,0]:=TEMP;
TEMP:=xForm[1,0]*co-xForm[1,2]*si;
xForm[1,2]:=xForm[1,0]*si+xForm[1,2]*co; xForm[1,0]:=TEMP;
TEMP:=xForm[2,0]*co-xForm[2,2]*si;
xForm[2,2]:=xForm[2,0]*si+xForm[2,2]*co; xForm[2,0]:=TEMP;
TEMP:=xForm[3,0]*co-xForm[3,2]*si;
xForm[3,2]:=xForm[3,0]*si+xForm[3,2]*co; xForm[3,0]:=TEMP;
END;
END;
PROCEDURE Roll(* zAngle: REAL *);
{ change xForm matrix to rotate zAngle degrees around z-Axis }
VAR si,co,TEMP: REAL;
BEGIN
zAngle:=zAngle/radConst; { convert degrees to rads }
si:=SIN(zAngle); co:=COS(zAngle);
WITH thePort3D^ DO
BEGIN
ident:=FALSE;
TEMP:=xForm[0,0]*co+xForm[0,1]*si;
xForm[0,1]:=xForm[0,1]*co-xForm[0,0]*si; xForm[0,0]:=TEMP;
TEMP:=xForm[1,0]*co+xForm[1,1]*si;
xForm[1,1]:=xForm[1,1]*co-xForm[1,0]*si; xForm[1,0]:=TEMP;
TEMP:=xForm[2,0]*co+xForm[2,1]*si;
xForm[2,1]:=xForm[2,1]*co-xForm[2,0]*si; xForm[2,0]:=TEMP;
TEMP:=xForm[3,0]*co+xForm[3,1]*si;
xForm[3,1]:=xForm[3,1]*co-xForm[3,0]*si; xForm[3,0]:=TEMP;
END;
END;
PROCEDURE Skew(* zAngle: REAL *);
{ change xForm matrix to skew zAngle degrees around z-Axis }
{ x := (x + y*TAN(zAngle)) zAngle limited to +-90 degrees }
VAR co,TA: REAL;
COL: INTEGER;
BEGIN
zAngle:=zAngle/radConst; { convert degrees to rads }
co:= COS(zAngle);
IF ABS(co) > 1.0E-5 THEN
BEGIN
TA:= SIN(zAngle)/co;
WITH thePort3D^ DO
BEGIN
ident:=FALSE;
FOR COL:=0 TO 2 DO
xForm[1,COL]:=xForm[1,COL]+xForm[0,COL]*TA;
END;
END;
END;
PROCEDURE SetPt3D(* VAR pt3D: Point3D; x,y,z: REAL *);
BEGIN
pt3D.x:=x;
pt3D.y:=y;
pt3D.z:=z;
END;
PROCEDURE SetPt2D(* VAR pt2D: Point2D; x,y: REAL *);
BEGIN
pt2D.x:=x;
pt2D.y:=y;
END;
END. { of Unit }

507
GrafAsm.a Executable file
View File

@ -0,0 +1,507 @@
.INCLUDE GRAFTYPES.TEXT
;------------------------------------------------------------
;
; --> GRAFASM.TEXT
;
; Miscellaneous unclassified routines.
;
.PROC InitGraf,1
;--------------------------------------------------
;
; PROCEDURE InitGraf(globalPtr: Ptr);
;
;
PARAMSIZE .EQU 4
GLOBALPTR .EQU PARAMSIZE+8-4 ;LONG
LINK A6,#0 ;NO LOCALS
MOVE.L A4,-(SP) ;SAVE REG
MOVE.L GLOBALPTR(A6),A4 ;GET POINTER TO QUICKDRAW GLOBALS
MOVE.L A4,GRAFGLOBALS(A5) ;SAVE IN MAGIC LOCATION
;
; new addition 22 Apr 85
;
CLR.B $8F3 ; set lo-mem flag, QDExist
LEA lastGrafGlob(A4),A0 ;SET UP START POINTER
LEA thePort+4(A4),A1 ;SET UP LIMIT POINTER
CLRLP CLR.W (A0)+ ;CLEAR A WORD
CMPA.L A1,A0 ;CHECK LIMIT POINTER
BNE CLRLP ;CLEAR ALL GLOBALS
;QDSpareD..QDSpare3 = all zeros
;playIndex := 0
;fontPtr = Nil
;FixTxWid := 0.0
;patAlign := (0,0)
;polyMax := 0
;thePoly := Nil
;QDSpare0 := 0
;playPic := Nil
;rgnMax := 0
;rgnIndex := 0
;rgnBuf := Nil
LEA wideData(A4),A4
MOVE.L A4,D0 ;REMEMBER ADDR OF WIDEDATA
MOVE #10,(A4)+ ;wideData.rgnSize := 10
MOVE.L #$80018001,(A4)+ ;wideData.rgnBBox :=
MOVE.L #$7FFF7FFF,(A4)+ ;(-32767,-32767,32767,32767)
MOVE.L A4,D1 ;REMEMBER ADDR OF WIDEMASTER
MOVE.L D0,(A4)+ ;wideMaster := @wideData
MOVE.L D1,(A4)+ ;wideOpen := @wideMaster
MOVEQ #1,D0
MOVE.L D0,(A4)+ ;randSeed := 1
MOVE.L A4,-(SP) ;point to screenBits
_GetScrnBits ;fill in screenBits
ADD #14,A4 ;bump past screenBits
MOVEQ #26,D0 ;INIT LOOP COUNT
LEA CURDATA,A0 ;POINT TO CURSOR DATA
CRSRLP MOVE.L (A0)+,(A4)+ ;COPY A LONG INTO GLOBALS
DBRA D0,CRSRLP ;LOOP FOR 27 LONGS
;thePort := NIL
MOVE.L (SP)+,A4 ;RESTORE REG
UNLINK PARAMSIZE,'INITGRAF'
CURDATA .WORD $0000,$4000,$6000,$7000 ;ARROW.DATA
.WORD $7800,$7C00,$7E00,$7F00
.WORD $7F80,$7C00,$6C00,$4600
.WORD $0600,$0300,$0300,$0000
.WORD $C000,$E000,$F000,$F800 ;ARROW.MASK
.WORD $FC00,$FE00,$FF00,$FF80
.WORD $FFC0,$FFE0,$FE00,$EF00
.WORD $CF00,$8780,$0780,$0380
.WORD $0001,$0001 ;ARROW.HOTSPOT := (1,1)
.LONG $77DD77DD,$77DD77DD ;dkGray
.LONG $88228822,$88228822 ;ltGray
.LONG $AA55AA55,$AA55AA55 ;gray
.LONG $FFFFFFFF,$FFFFFFFF ;black
.LONG $00000000,$00000000 ;white
.PROC OpenPort,1
.REF NewRgn
;-------------------------------------------------------------
;
; PROCEDURE OpenPort(port: GrafPtr);
; { allocate clipRgn and visRgn, then call InitPort.
;
CLR.L -(SP) ;MAKE ROOM FOR FUNCTION RESULT
JSR NEWRGN ;ALLOCATE A NEW REGION
CLR.L -(SP) ;MAKE ROOM FOR FUNCTION RESULT
JSR NEWRGN ;ALLOCATE A SECOND NEW REGION
MOVE.L 12(SP),A0 ;POINT TO PORT
MOVE.L (SP)+,CLIPRGN(A0) ;INSTALL NEW REGION INTO CLIPRGN
MOVE.L (SP)+,VISRGN(A0) ;AND OTHER INTO VISRGN
;FALL THRU TO InitPort
.PROC InitPort,1
.REF RectRgn,CopyRgn
;-------------------------------------------------------------
;
; PROCEDURE InitPort(port: GrafPtr);
;
; { initialize all fields of an existing GrafPort }
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L 4(SP),A1 ;GET PORT PARAM
MOVE.L A1,THEPORT(A0) ;SetPort(port)
CLR.W (A1)+ ;DEVICE := 0
LEA SCREENBITS(A0),A0 ;POINT TO SCREENBITS
MOVE.L (A0)+,(A1)+ ;portBits := screenBits
MOVE.W (A0)+,(A1)+ ;COPY ROWBYTES
MOVE.L (A0),(A1)+ ;COPY TOPLEFT
MOVE.L 4(A0),(A1)+ ;COPY BOTRIGHT
MOVE.L (A0),(A1)+ ;portRect := screenBits.bounds
MOVE.L 4(A0),(A1)+ ;all 8 bytes
MOVE.L (A1)+,-(SP) ;visRgn := screenBits.bounds
MOVE.L A0,-(SP)
JSR RECTRGN
MOVE.L 4(SP),A1 ;GET PORT PARAM
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L WIDEOPEN(A0),-(SP) ;PUSH WIDE OPEN RGN
MOVE.L CLIPRGN(A1),-(SP) ;PUSH CLIPRGN
JSR COPYRGN ;SET TO WIDE OPEN
MOVE.L 4(SP),A1 ;GET PORT PARAM
LEA BKPAT(A1),A1
CLR.L (A1)+ ;bkPat := white
CLR.L (A1)+
MOVEQ #-1,D0
MOVE.L D0,(A1)+ ;fillPat := Black
MOVE.L D0,(A1)+
CLR.L (A1)+ ;pnLoc := (0,0)
MOVE.L #$00010001,(A1)+ ;pnSize := (1,1)
MOVE #8,(A1)+ ;pnMode := patCopy
MOVE.L D0,(A1)+ ;pnPat := black
MOVE.L D0,(A1)+
CLR.W (A1)+ ;pnVis := 0
CLR.L (A1)+ ;txFont, txFace := 0
MOVE #1,(A1)+ ;txMode := srcOr
CLR (A1)+ ;txSize := 0
CLR.L (A1)+ ;spExtra := 0.0
MOVE.L #blackColor,(A1)+ ;fgColor := blackColor
MOVE.L #whiteColor,(A1)+ ;bkColor := whiteColor
CLR.L (A1)+ ;colrBit,patStretch := 0
CLR.L (A1)+ ;picSave := Nil
CLR.L (A1)+ ;rgnSave := Nil
CLR.L (A1)+ ;polySave := Nil
CLR.L (A1)+ ;grafProcs := Nil
MOVE.L (SP)+,(SP) ;STRIP PARAM
RTS ;AND RETURN
.PROC ClosePort,1
;-------------------------------------------------------------
;
; PROCEDURE ClosePort(port: GrafPtr);
;
; { just disposes of clipRgn and visRgn }
;
MOVE.L 4(SP),A0 ;GET PORT
MOVE.L CLIPRGN(A0),A0 ;GET CLIPRGN HANDLE
_DisposHandle ;DISCARD IT
MOVE.L 4(SP),A0 ;GET PORT
MOVE.L VISRGN(A0),A0 ;GET VISRGN HANDLE
_DisposHandle ;DISCARD IT
MOVE.L (SP)+,(SP) ;STRIP PARAM
RTS ;AND RETURN
.PROC SetStdProcs,1
.REF StdText,StdLine,StdRect,StdRRect,StdOval,StdArc,StdPoly
.REF StdRgn,StdBits,StdComment,StdTxMeas,StdGetPic,StdPutPic
;-------------------------------------------------------------
;
; PROCEDURE SetStdProcs(VAR procs: QDProcs);
;
MOVE.L 4(SP),A1 ;GET ADDRESS OF PROC RECORD
LEA StdText,A0
MOVE.L A0,(A1)+
LEA StdLine,A0
MOVE.L A0,(A1)+
LEA StdRect,A0
MOVE.L A0,(A1)+
LEA StdRRect,A0
MOVE.L A0,(A1)+
LEA StdOval,A0
MOVE.L A0,(A1)+
LEA StdArc,A0
MOVE.L A0,(A1)+
LEA StdPoly,A0
MOVE.L A0,(A1)+
LEA StdRgn,A0
MOVE.L A0,(A1)+
LEA StdBits,A0
MOVE.L A0,(A1)+
LEA StdComment,A0
MOVE.L A0,(A1)+
LEA StdTxMeas,A0
MOVE.L A0,(A1)+
LEA StdGetPic,A0
MOVE.L A0,(A1)+
LEA StdPutPic,A0
MOVE.L A0,(A1)+
MOVE.L (SP)+,(SP) ;STRIP PARAM
RTS ;AND RETURN
.PROC LocalToGlobal,1
.DEF GlobalToLocal,AddPt,SubPt,SetPort,GetPort
;-------------------------------------------------------------
;
; PROCEDURE LocalToGlobal(VAR pt: Point);
;
; restores all registers.
;
MOVEM.L D0-D2/A0/A1,-(SP) ;SAVE REGS
MOVE.L #1,D2 ;INDICATE SUB
BRA.S SHARE
;-------------------------------------------------------------
;
; PROCEDURE GlobalToLocal(VAR pt: Point);
;
; restores all registers.
;
GlobalToLocal
MOVEM.L D0-D2/A0/A1,-(SP) ;SAVE REGS
MOVE.L #0,D2 ;INDICATE ADD
SHARE MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO CURRENT GRAFPORT
MOVE.L 24(SP),A1 ;POINT TO VAR PT
MOVE PORTBITS+BOUNDS+TOP(A0),D0 ;GET DV
MOVE PORTBITS+BOUNDS+LEFT(A0),D1 ;GET DH
BSR.S ADDSUB ;CONVERT TO LOCAL
MOVEM.L (SP)+,D0-D2/A0/A1 ;RESTORE REGS
BRA.S SHARE3 ;STRIP 4 BYTES AND RETURN
;
;
;
ADDSUB TST D2
BEQ.S JUSTADD
NEG D0
NEG D1
JUSTADD ADD D0,(A1)+
ADD D1,(A1)+
RTS
;-------------------------------------------------------------
;
; PROCEDURE AddPt(src: Point; VAR dst: Point);
; { add two points together, restores all regs }
;
AddPt MOVEM.L D0-D2/A1,-(SP) ;SAVE REGS
MOVE.L #0,D2 ;INDICATE ADD
BRA.S SHARE2
;-------------------------------------------------------------
;
; PROCEDURE SubPt(src: Point; VAR dst: Point);
; { subtract src Point from dst point, restores all regs }
;
SubPt MOVEM.L D0-D2/A1,-(SP) ;SAVE REGS
MOVE.L #1,D2 ;INDICATE SUB
SHARE2 MOVE.L 20(SP),A1 ;POINT TO DST
MOVE 24+V(SP),D0 ;GET SRC.V
MOVE 24+H(SP),D1 ;GET SRC.H
BSR.S ADDSUB
MOVEM.L (SP)+,D0-D2/A1 ;RESTORE REGS
MOVE.L (SP)+,(SP)
SHARE3 MOVE.L (SP)+,(SP)
RTS ;AND RETURN
;----------------------------------------------------------
;
; PROCEDURE SetPort(gp: GrafPtr);
; { switch the current port to a different GrafPort }
;
SetPort MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L 4(SP),THEPORT(A0) ;INSTALL INTO THEPORT
BRA.S SHARE3 ;STRIP 4 BYTES AND RETURN
;----------------------------------------------------------
;
; PROCEDURE GetPort(VAR gp: GrafPtr);
; { inquire the current GrafPort }
;
GetPort MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L 4(SP),A1 ;POINT TO VAR GP
MOVE.L THEPORT(A0),(A1) ;COPY FROM THEPORT
BRA.S SHARE3 ;STRIP 4 BYTES AND RETURN
.PROC GrafDevice,1
.REF PortWord
;----------------------------------------------------------
;
; PROCEDURE GrafDevice(device: INTEGER);
;
MOVEQ #DEVICE,D0 ;PUT PORT OFFSET IN D0
JMP PORTWORD ;INSTALL PARAM INTO THEPORT
.PROC SetPortBits,1
.DEF BackPat
;----------------------------------------------------------
;
; PROCEDURE SetPortBits(bm: BitMap);
; { re-direct output to a different BitMap }
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA PORTBITS(A0),A0 ;POINT TO PORTBITS
MOVE.L 4(SP),A1 ;POINT TO BITMAP
MOVE.L (A1)+,(A0)+ ;COPY BASEADDR
MOVE.W (A1)+,(A0)+ ;COPY ROWBYTES
SHARE MOVE.L (A1)+,(A0)+ ;COPY BOUNDS.TOPLEFT
MOVE.L (A1)+,(A0)+ ;COPY BOUNDS.BOTRIGHT
MOVE.L (SP)+,(SP) ;STRIP 4 BYTES
RTS ;AND RETURN
;----------------------------------------------------------
;
; PROCEDURE BackPat(pat: Pattern);
; { set the background pattern }
;
BackPat MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA BKPAT(A0),A0 ;POINT TO BKPAT
MOVE.L 4(SP),A1 ;GET ADDR OF PATTERN
BRA.S SHARE
.PROC PortSize,2
;----------------------------------------------------------
;
; PROCEDURE PortSize(width,height: INTEGER);
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE PORTRECT+LEFT(A0),D0 ;GET PORTRECT.LEFT
ADD 6(SP),D0 ;ADD WIDTH
MOVE D0,PORTRECT+RIGHT(A0) ;UPDATE PORTRECT.RIGHT
MOVE PORTRECT+TOP(A0),D0 ;GET PORTRECT.TOP
ADD 4(SP),D0 ;ADD HEIGHT
MOVE D0,PORTRECT+BOTTOM(A0) ;UPDATE PORTRECT.BOTTOM
MOVE.L (SP)+,(SP) ;STRIP 4 BYTES
RTS ;AND RETURN
.PROC MovePortTo,2
.DEF SetOrigin,ClipRect
.REF OffsetRgn,RectRgn
;----------------------------------------------------------
;
; PROCEDURE MovePortTo(leftGlobal,topGlobal: INTEGER);
; { move portRect to a different part of the bitmap }
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE PORTRECT+LEFT(A0),D0 ;GET PORTRECT.LEFT
SUB PORTBITS+BOUNDS+LEFT(A0),D0 ;CONVERT TO GLOBAL
SUB 6(SP),D0 ;SUB LEFTGLOBAL FOR DH
MOVE PORTRECT+TOP(A0),D1 ;GET PORTRECT.TOP
SUB PORTBITS+BOUNDS+TOP(A0),D1 ;CONVERT TO GLOBAL
SUB 4(SP),D1 ;SUB TOPGLOBAL FOR DV
MOVE.L (SP)+,(SP) ;STRIP 4 BYTES
OFSPORT LEA PORTBITS+BOUNDS(A0),A0 ;OFFSET PORTBITS.BOUNDS DH,DV
OFSRECT ADD D1,(A0)+ ;OFFSET TOP
ADD D0,(A0)+ ;OFFSET LEFT
ADD D1,(A0)+ ;OFFSET BOTTOM
ADD D0,(A0)+ ;OFFSET RIGHT
RTS ;AND RETURN
;----------------------------------------------------------
;
; PROCEDURE SetOrigin(h,v: INTEGER);
; { re-define the local coords by adjusting portBits.bounds, }
; { portRect, and visRgn }
;
SetOrigin
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L 4(SP),D0 ;GET V AND H BOTH
CMP.L PORTRECT+TOPLEFT(A0),D0 ;SAME AS ALREADY IN THEPORT ?
BEQ.S DONE ;YES, QUIT
MOVE 6(SP),D0 ;GET H
SUB PORTRECT+LEFT(A0),D0 ;DH:=H-PORTRECT.LEFT
MOVE 4(SP),D1 ;GET V
SUB PORTRECT+TOP(A0),D1 ;DV:=V-PORTRECT.TOP
MOVE.L VISRGN(A0),-(SP) ;PUSH PARMS FOR LATER
MOVE D0,-(SP)
MOVE D1,-(SP)
BSR.S OFSPORT ;OFFSET PORTBITS.BOUNDS
LEA PORTRECT-PORTBITS-BOUNDS-8(A0),A0 ;POINT A0 AT PORTRECT
BSR.S OFSRECT ;OFFSET PORTRECT
JSR OFFSETRGN
DONE MOVE.L (SP)+,(SP) ;STRIP 4 BYTES
RTS ;AND RETURN
;----------------------------------------------------------
;
; PROCEDURE ClipRect(r: Rect);
; { Make the current grafport's clipRgn match a given rectangle }
;
ClipRect
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L CLIPRGN(A0),-(SP) ;PUSH CLIPRGN
MOVE.L 8(SP),-(SP) ;PUCH ADDR OF RECT
JSR RECTRGN
BRA.S DONE
.PROC SetClip,1
.DEF GetClip
.REF CopyRgn
;----------------------------------------------------------
;
; PROCEDURE SetClip(rgn: RgnHandle);
;
; copy rgn into theport^.clipRgn
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A1 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A1),A1 ;GET CURRENT GRAFPORT
MOVE.L CLIPRGN(A1),-(SP) ;PUSH THEPORT^.CLIPRGN
BRA.S SHARE
;----------------------------------------------------------
;
; PROCEDURE GetClip(rgn: RgnHandle);
;
; copy from theport^.clipRgn into rgn.
;
GetClip
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;POP RGN HANDLE
MOVE.L GRAFGLOBALS(A5),A1 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A1),A1 ;GET CURRENT GRAFPORT
MOVE.L CLIPRGN(A1),-(SP) ;PUSH THEPORT^.CLIPRGN
MOVE.L D0,-(SP) ;PUSH RGN
SHARE MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
JMP COPYRGN ;AND GO TO COPYRGN
.PROC SetPt,3
;-------------------------------------------------------------
;
; PROCEDURE SetPt(VAR pt: Point; h,v: INTEGER);
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;POP H,V
MOVE.L (SP)+,A1 ;POP VAR ADDR OF PT
MOVE.L D0,(A1) ;STORE H,V INTO PT
JMP (A0) ;RETURN
.FUNC EqualPt,2
;----------------------------------------------------------
;
; FUNCTION EqualPt(pt1,pt2: Point): BOOLEAN;
;
; CLOBBERS D0,A0.
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D0 ;pop point1
CMP.L (SP)+,D0 ;is point2 = point1 ?
SEQ (SP) ;IF YES, SET TO TRUE
NEG.B (SP) ;CONVERT -1 TO 1
JMP (A0) ;RETURN
.END

375
GrafTypes.a Executable file
View File

@ -0,0 +1,375 @@
;-----------------------------------------------------------------
;
; --> GRAFTYPES.TEXT
;
; QUICKDRAW TYPE DECLARATIONS, USED BY ALL GRAPHICS ROUTINES
;
NIL .EQU 0 ;IMPLEMENTATION VALUE OF NIL
;-----------------------------------------------
;
; QuickDraw VERBS:
;
FRAME .EQU 0
PAINT .EQU 1
ERASE .EQU 2
INVERT .EQU 3
FILL .EQU 4
;-----------------------------------------------
;
; QuickDraw transfer MODES:
;
srcCopy .EQU 0
srcOr .EQU 1
srcXor .EQU 2
srcBic .EQU 3
notSrcCopy .EQU 4
notSrcOr .EQU 5
notSrcXor .EQU 6
notSrcBic .EQU 7
patCopy .EQU 8
patOr .EQU 9
patXor .EQU 10
patBic .EQU 11
notPatCopy .EQU 12
notPatOr .EQU 13
notPatXor .EQU 14
notPatBic .EQU 15
;-----------------------------------------------
;
; QuickDraw Color Separation:
;
normalBit .EQU 0 ;normal screen mapping
inverseBit .EQU 1 ;inverse screen mapping
redBit .EQU 4 ;RGB additive mapping
greenBit .EQU 3 ;for photos from screen
blueBit .EQU 2
cyanBit .EQU 8 ;CMYBk subtractive mapping
magentaBit .EQU 7 ;for ink jet printer
yellowBit .EQU 6
blackBit .EQU 5
blackColor .EQU 33
whiteColor .EQU 30
redColor .EQU 205
greenColor .EQU 341
blueColor .EQU 409
cyanColor .EQU 273
magentaColor .EQU 137
yellowColor .EQU 69
;-----------------------------------------------
;
; OFFSETS WITHIN A POINT:
;
V .EQU 0 ;WORD
H .EQU 2 ;WORD
;-----------------------------------------------
;
; OFFSETS WITHIN A RECT:
;
TOPLEFT .EQU 0 ;POINT
BOTRIGHT .EQU 4 ;POINT
TOP .EQU 0 ;INTEGER
LEFT .EQU 2 ;INTEGER
BOTTOM .EQU 4 ;INTEGER
RIGHT .EQU 6 ;INTEGER
;-----------------------------------------------
;
; OFFSETS WITHIN A BITMAP:
;
BASEADDR .EQU 0 ;LONG
ROWBYTES .EQU 4 ;WORD
BOUNDS .EQU 6 ;RECT
;-----------------------------------------------
;
; OFFSETS WITHIN A CURSOR:
;
DATA .EQU 0 ;16 WORDS
MASK .EQU 32 ;16 WORDS
HOTSPOT .EQU 64 ;POINT
;-----------------------------------------------
;
; OFFSETS WITHIN A POLYGON:
;
POLYSIZE .EQU 0 ;WORD, TOTAL BYTES
POLYBBOX .EQU 2 ;RECT
POLYPOINTS .EQU 10 ;ARRAY[0..0] OF Point
;-----------------------------------------------
;
; OFFSETS WITHIN A REGION:
;
RGNSIZE .EQU 0 ;WORD, TOTAL BYTES
RGNBBOX .EQU 2 ;RECT
RGNDATA .EQU 10 ;START OF RGN DATA
;-----------------------------------------------
;
; OFFSETS WITHIN A PICTURE:
;
PICSIZE .EQU 0 ;WORD, TOTAL BYTES
PICFRAME .EQU 2 ;RECT
PICDATA .EQU 10 ;START OF BYTE CODES
;-----------------------------------------------
;
; OFFSETS WITHIN QDProcs RECORD:
;
textProc .EQU 0 ;PROCPTR
lineProc .EQU textProc+4 ;PROCPTR
rectProc .EQU lineProc+4 ;PROCPTR
rRectProc .EQU rectProc+4 ;PROCPTR
ovalProc .EQU rRectProc+4 ;PROCPTR
arcProc .EQU ovalProc+4 ;PROCPTR
polyProc .EQU arcProc+4 ;PROCPTR
rgnProc .EQU polyProc+4 ;PROCPTR
bitsProc .EQU rgnProc+4 ;PROCPTR
commentProc .EQU bitsProc+4 ;PROCPTR
txMeasProc .EQU commentProc+4 ;PROCPTR
getPicProc .EQU txMeasProc+4 ;PROCPTR
putPicProc .EQU getPicProc+4 ;PROCPTR
;-----------------------------------------------
;
; OFFSETS WITHIN A GRAFPORT:
;
device .EQU 0 ;WORD
portBits .EQU device+2 ;BITMAP
portRect .EQU portBits+14 ;RECT
visRgn .EQU portRect+8 ;RGNPTR
clipRgn .EQU visRgn+4 ;RGNPTR
bkPat .EQU clipRgn+4 ;PATTERN
fillPat .EQU bkPat+8 ;PATTERN
pnLoc .EQU fillPat+8 ;POINT
pnSize .EQU pnLoc+4 ;POINT
pnMode .EQU pnSize+4 ;WORD
pnPat .EQU pnMode+2 ;PATTERN
pnVis .EQU pnPat+8 ;WORD
txFont .EQU pnVis+2 ;WORD
txFace .EQU txFont+2 ;WORD
txMode .EQU txFace+2 ;WORD
txSize .EQU txMode+2 ;WORD
spExtra .EQU txSize+2 ;Fixed Point
fgColor .EQU spExtra+4 ;LONG
bkColor .EQU fgColor+4 ;LONG
colrBit .EQU bkColor+4 ;WORD
patStretch .EQU colrBit+2 ;WORD
picSave .EQU patStretch+2 ;handle
rgnSave .EQU picSave+4 ;handle
polySave .EQU rgnSave+4 ;handle
grafProcs .EQU polySave+4 ;Pointer
PORTREC .EQU grafProcs+4 ;SIZE OF A GRAFPORT
PORTBOUNDS .EQU PORTBITS+BOUNDS
;-----------------------------------------------------
;
; OFFSETS IN A REGION STATE RECORD:
;
RGNPTR .EQU 0 ;LONG
DATAPTR .EQU RGNPTR+4 ;LONG
SCANBUF .EQU DATAPTR+4 ;LONG
SCANSIZE .EQU SCANBUF+4 ;WORD
THISV .EQU SCANSIZE+2 ;WORD
NEXTV .EQU THISV+2 ;WORD
MINH .EQU NEXTV+2 ;WORD
MAXH .EQU MINH+2 ;WORD
LEFTH .EQU MAXH+2 ;WORD
RGNREC .EQU LEFTH+2 ;SIZE OF A REGION RECORD
;-----------------------------------------------------
;
; Offsets in a PicSave record:
;
thePic .EQU 0 ;PICHANDLE
picMax .EQU thePic+4 ;LongInt
picIndex .EQU picMax+4 ;LongInt
picClipRgn .EQU picIndex+4 ;RgnHandle
picBkPat .EQU picClipRgn+4 ;Pattern
picTxFont .EQU picBkPat+8 ;WORD
picTxFace .EQU picTxFont+2 ;Style
picTxMode .EQU picTxFace+2 ;WORD
picTxSize .EQU picTxMode+2 ;WORD
picSpExtra .EQU picTxSize+2 ;Fixed Point
picTxNumer .EQU picSpExtra+4 ;Point
picTxDenom .EQU picTxNumer+4 ;Point
picTxLoc .EQU picTxDenom+4 ;Point
picPnLoc .EQU picTxLoc+4 ;Point
picPnSize .EQU picPnLoc+4 ;Point
picPnMode .EQU picPnSize+4 ;WORD
picPnPat .EQU picPnMode+2 ;Pattern
picFillPat .EQU picPnPat+8 ;Pattern
picTheRect .EQU picFillPat+8 ;Rect
picOvSize .EQU picTheRect+8 ;Point
picOrigin .EQU picOvSize+4 ;Point
picFgColor .EQU picOrigin+4 ;Long
picBkColor .EQU picFgColor+4 ;Long
picSaveRec .EQU picBkColor+4 ;total size in bytes
;-----------------------------------------------------
;
; QuickDraw GLOBAL VARIABLES:
;
; 52(A5) CONTAINS A POINTER TO THEPORT.
; ALL OTHER GLOBAL VARIABLES ARE EXPRESSED RELATIVE TO THEPORT.
;
GRAFGLOBALS .EQU 0 ;A5 OFFSET TO GLOBALPTR
;-----------------------------------------------------------
;
; QuickDraw PUBLIC GLOBAL VARIABLES:
;
thePort .EQU 0 ;GrafPtr
white .EQU thePort-8 ;Pattern
black .EQU white-8 ;Pattern
gray .EQU black-8 ;Pattern
ltGray .EQU gray-8 ;Pattern
dkGray .EQU ltGray-8 ;Pattern
arrow .EQU dkGray-68 ;Cursor
screenBits .EQU arrow-14 ;BitMap
randSeed .EQU screenBits-4 ;LONGINT
;------------------------------------------------------------
;
; QuickDraw private global variables:
;
wideOpen .EQU randSeed-4 ;RgnHandle
wideMaster .EQU wideOpen-4 ;RgnPtr
wideData .EQU wideMaster-10 ;Fake Region
rgnBuf .EQU wideData-4 ;PointsHandle
rgnIndex .EQU rgnBuf-2 ;INTEGER
rgnMax .EQU rgnIndex-2 ;INTEGER
playPic .EQU rgnMax-4 ;Long
QDSpare0 .EQU playPic-2 ;unused word
thePoly .EQU QDSpare0-4 ;POLYHANDLE
polyMax .EQU thePoly-2 ;INTEGER
patAlign .EQU polyMax-4 ;Point
fixTxWid .EQU patAlign-4 ;Fixed Point
fontPtr .EQU fixTxWid-4 ;long, ^FMOutput record
playIndex .EQU fontPtr-4 ;long
QDSpare3 .EQU playIndex-2 ;unused word
QDSpare4 .EQU QDSpare3-2 ;unused word
QDSpare5 .EQU QDSpare4-2 ;unused word
QDSpare6 .EQU QDSpare5-2 ;unused word
QDSpare7 .EQU QDSpare6-2 ;unused word
QDSpare8 .EQU QDSpare7-2 ;unused word
QDSpare9 .EQU QDSpare8-2 ;unused word
QDSpareA .EQU QDSpare9-2 ;unused word
QDSpareB .EQU QDSpareA-2 ;unused word
QDSpareC .EQU QDSpareB-2 ;unused word
QDSpareD .EQU QDSpareC-2 ;unused word
lastGrafGlob .EQU QDSpareD
grafSize .EQU 4-lastGrafGlob ;total size in bytes
.MACRO UNLINK
;--------------------------------------------------------------
;
; UNLINK A6, STRIP PARAMETERS, AND RETURN.
;
; FIRST PARAM IS NUMBER OF BYTES OF STACK BIAS.
;
UNLK A6 ;RELEASE LOCAL VARIABLES
.IF %1=0 ;NO PARAMETERS ?
RTS ;THEN JUST RTS
.ELSE
.IF %1=4 ;4 BYTES OF PARAMS ?
MOVE.L (SP)+,(SP) ;YES, STRIP AND ADJUST RET ADDR
RTS
.ELSE ;NOT 0 OR 4 BYTES OF PARAMS
MOVE.L (SP)+,A0 ;POP RETURN ADDR INTO A0
ADD #%1,SP ;STRIP PARAMETERS
JMP (A0) ;JUMP THRU A0 TO RETURN
.ENDC
.ENDC
.ENDM
;----------------------------------------------
;
; Trap Macros used by QuickDraw:
;
.MACRO _LongMul
.WORD $A867
.ENDM
.MACRO _FixMul
.WORD $A868
.ENDM
.MACRO _FixRatio
.WORD $A869
.ENDM
.MACRO _NewHandle
.WORD $A122
.ENDM
.MACRO _DisposHandle
.WORD $A023
.ENDM
.MACRO _SetHandleSize
.WORD $A024
.ENDM
.MACRO _GetHandleSize
.WORD $A025
.ENDM
.MACRO _HLock
.WORD $A029
.ENDM
.MACRO _HUnlock
.WORD $A02A
.ENDM
.MACRO _GetScrnBits
.WORD $A833 ;new trap number
.ENDM
.MACRO _StackAvail
MOVE.L SP,D0 ;copy stack pointer
SUB.L $114,D0 ;subtract HeapEnd for stack avail
.ENDM
.MACRO _SwapFont
MOVE.L $8E0,A0 ;get pointer to FMSwapFont
JSR (A0) ;call font manager
.ENDM

47
GrafUtil.p Executable file
View File

@ -0,0 +1,47 @@
UNIT GrafUtil;
INTERFACE
USES {$U obj:QuickDraw } QuickDraw;
TYPE Fixed = LongInt;
Int64Bit = RECORD
hiLong: LongInt;
loLong: LongInt;
END;
FUNCTION BitAnd (long1,long2: LongInt): LongInt;
FUNCTION BitOr (long1,long2: LongInt): LongInt;
FUNCTION BitXor (long1,long2: LongInt): LongInt;
FUNCTION BitNot (long: LongInt): LongInt;
FUNCTION BitShift (long: LongInt; count: INTEGER): LongInt;
FUNCTION BitTst (bytePtr: QDPtr; bitNum: LongInt): BOOLEAN;
PROCEDURE BitSet (bytePtr: QDPtr; bitNum: LongInt);
PROCEDURE BitClr (bytePtr: QDPtr; bitNum: LongInt);
PROCEDURE LongMul (a,b: LongInt; VAR dst: Int64Bit);
FUNCTION FixMul (a,b: Fixed): Fixed;
FUNCTION FixRatio (numer,denom: INTEGER): Fixed;
FUNCTION HiWord (x: Fixed): INTEGER;
FUNCTION LoWord (x: Fixed): INTEGER;
FUNCTION FixRound (x: Fixed): INTEGER;
IMPLEMENTATION
FUNCTION BitAnd; EXTERNAL;
FUNCTION BitOr; EXTERNAL;
FUNCTION BitXor; EXTERNAL;
FUNCTION BitNot; EXTERNAL;
FUNCTION BitShift; EXTERNAL;
FUNCTION BitTst; EXTERNAL;
PROCEDURE BitSet; EXTERNAL;
PROCEDURE BitClr; EXTERNAL;
PROCEDURE LongMul; EXTERNAL;
FUNCTION FixMul; EXTERNAL;
FUNCTION FixRatio; EXTERNAL;
FUNCTION HiWord; EXTERNAL;
FUNCTION LoWord; EXTERNAL;
FUNCTION FixRound; EXTERNAL;
END. { of unit }

122
LCursor.a Executable file
View File

@ -0,0 +1,122 @@
.INCLUDE GRAFTYPES.TEXT
;------------------------------------------------------------------
;
; --> LCURSOR.TEXT
;
; Links to MacIntosh Cursor routines.
;
; System Graphic Jump Vectors:
;
; Long pointers to system routine entry points.
;
GRAFBEGIN .EQU $800 ;GRAF GLOBAL AREA
JHIDECURSOR .EQU GRAFBEGIN
JSHOWCURSOR .EQU JHIDECURSOR+4
JSHIELDCURSOR .EQU JSHOWCURSOR+4
JSCRNADDR .EQU JSHIELDCURSOR+4 ;not used (see _GetScrnBits)
JSCRNSIZE .EQU JSCRNADDR+4 ;not used (see _GetScrnBits)
JINITCRSR .EQU JSCRNSIZE+4
JSETCRSR .EQU JINITCRSR+4
JCRSROBSCURE .EQU JSETCRSR+4
.PROC InitCursor,0
.REF SetCursor
;----------------------------------------------------------
;
; PROCEDURE InitCursor;
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
PEA ARROW(A0) ;PUSH ADDR OF ARROW
JSR SETCURSOR ;INSTALL ARROW CURSOR
MOVE.L JInitCrsr,A0 ;get lo mem pointer
JMP (A0) ;and call it
.PROC SetCursor,1
;---------------------------------------------------
;
; PROCEDURE SetCursor(crsr: Cursor);
;
MOVE.L 4(SP),A0 ;Point to Cursor
MOVE.L HOTSPOT+V(A0),-(SP) ;PUSH HOTX & HOTY
MOVE #16,-(SP) ;HEIGHT:=16
PEA DATA(A0) ;PUSH ADDR OF DATA
PEA MASK(A0) ;PUSH ADDR OF MASK
MOVE.L JSetCrsr,A0 ;get lo mem vector
JSR (A0) ;call vector
MOVE.L (SP)+,(SP) ;strip param
RTS ;and return
.PROC HideCursor,0
;---------------------------------------------------------
;
; PROCEDURE HideCursor;
;
; ALL REGS PRESERVED.
;
MOVE.L JHideCursor,-(SP) ;get lo mem vector
RTS ;and call it
.PROC ShowCursor,0
;---------------------------------------------------------
;
; PROCEDURE ShowCursor;
;
; ALL REGS PRESERVED.
;
MOVE.L JShowCursor,-(SP) ;get lo mem vector
RTS ;and call it
.PROC ShieldCursor,2
;---------------------------------------------------------
;
; PROCEDURE ShieldCursor(shieldRect: Rect; offset: Point);
;
; ALL REGS PRESERVED.
;
MOVEM.L D0-D3/A0-A1,-(SP) ;SAVE REGS
MOVE.L 32(SP),A0 ;POINT TO SHIELDRECT
MOVEM.W (A0)+,D0/D1/D2/D3 ;GET TOP ... RIGHT
LEA 28(SP),A1
SUB (A1),D0 ;TOP - OFFSET.V
SUB (A1)+,D2 ;BOTTOM - OFFSET.V
SUB (A1),D1 ;LEFT - OFFSET.H
SUB (A1),D3 ;RIGHT - OFFSET.H
MOVE D1,-(SP) ;PUSH GLOBAL LEFT
MOVE D0,-(SP) ;PUSH GLOBAL TOP
MOVE D3,-(SP) ;PUSH GLOBAL RIGHT
MOVE D2,-(SP) ;PUSH GLOBAL BOTTOM
MOVE.L JShieldCursor,A0 ;get lo mem vector
JSR (A0) ;and call it
MOVEM.L (SP)+,D0-D3/A0-A1 ;RESTORE REGS
MOVE.L (SP)+,(SP)
MOVE.L (SP)+,(SP) ;STRIP 8 BYTES
RTS ;AND RETURN
.PROC ObscureCursor,0
;---------------------------------------------------------
;
; PROCEDURE ObscureCursor;
;
; Hide the cursor image until the next time the mouse moves.
;
MOVE.L JCrsrObscure,A0 ;get lo mem vector
JMP (A0) ;and call it
.END

347
Lines.a Executable file
View File

@ -0,0 +1,347 @@
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------------
;
;
; * *** * * ***** ***
; * * * * * * *
; * * ** * * *
; * * * * * *** ***
; * * * ** * *
; * * * * * * *
; ***** *** * * ***** ***
;
;
;
; Line Drawing Rountines
;
.PROC StdLine,1
.REF CheckPic,PutPicVerb,PutPicByte,PutPicLong,DoLine
;---------------------------------------------------------------
;
; PROCEDURE StdLine(newPt: Point);
;
PARAMSIZE .EQU 4
NEWPT .EQU PARAMSIZE+8-4
LINK A6,#0 ;NO LOCAL VARS
MOVEM.L D5-D7/A3-A4,-(SP) ;SAVE REGS
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B #FRAME,-(SP) ;PUSH VERB
JSR PutPicVerb ;CHECK pnSize, pnMode, pnPat
;--------------------------------------------------------
;
; PUT ONE OF FOUR LINE OPCODES BASED ON NEWPT AND DH,DV.
;
; line 20, pnLoc(pt), newPt(pt)
; line from 21, newPt(pt)
; short line 22, pnLoc(pt), dh,dv(-128..127)
; short line from 23, dh,dv(-128..127)
;
MOVEQ #$20,D7 ;INIT OPCODE TO $20
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L PNLOC(A3),D0 ;GET CURRENT PNLOC
CMP.L PICPNLOC(A4),D0 ;IS LINE FROM LAST ENDPOINT ?
BNE.S NOTFROM ;NO, CONTINUE
ADDQ #1,D7 ;YES, SET BIT ZERO
NOTFROM MOVE NEWPT+H(A6),D6 ;GET NEWPT.H
SUB D0,D6 ;CALC DH = NEWPT.H - PNLOC.H
MOVE D6,D0 ;COPY DH
EXT.W D0
CMP.W D6,D0 ;IS DH -128..127 ?
BNE.S PUTOP ;NO, CONTINUE
MOVE NEWPT+V(A6),D5 ;GET NEWPT.V
SUB PNLOC+V(A3),D5 ;CALC DV = NEWPT.V - PNLOC.V
MOVE D5,D0 ;COPY DV
EXT.W D0
CMP.W D5,D0 ;IS DV -128..127 ?
BNE.S PUTOP ;NO, CONTINUE
ADDQ #2,D7 ;YES, SET BIT ONE IN OPCODE
PUTOP MOVE.B D7,-(SP)
JSR PutPicByte ;PUT ONE OF 4 LINE OPCODES
ROR #1,D7 ;DO WE NEED STARTPT ? (BIT 0)
BCS.S STARTOK ;NO, CONTINUE
MOVE.L PNLOC(A3),-(SP)
JSR PutPicLong ;YES, PUT STARTPT = PNLOC
STARTOK ROR #1,D7 ;IS LINE SHORT ? (BIT 1)
BCS.S DHDV ;YES, PUT DH,DV
MOVE.L NEWPT(A6),-(SP) ;NO, PUT LONG NEWPT
JSR PutPicLong ;PUT NEWPT TO THEPIC
BRA.S UPDATE
DHDV MOVE.B D6,-(SP) ;PUSH DH (-128..127)
JSR PutPicByte ;PUT TO THEPIC
MOVE.B D5,-(SP) ;PUSH DV (-128..127)
JSR PutPicByte ;PUT TO THEPIC
UPDATE MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L NEWPT(A6),PICPNLOC(A4) ;UPDATE PICTURE SAVING STATE
NOTPIC MOVE.L NEWPT(A6),-(SP) ;PUSH NEWPT
JSR DoLine ;DoLine(newPt);
MOVEM.L (SP)+,D5-D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDLINE '
.PROC LineTo,2
.REF StdLine
;----------------------------------------------------------
;
; PROCEDURE LineTo(h,v: INTEGER);
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDLINE,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L LINEPROC(A0),A0 ;NO, GET PROC PTR
USESTD JMP (A0) ;GO TO IT
.PROC Line,2
.REF LineTo
;----------------------------------------------------------
;
; PROCEDURE Line(dh,dv: INTEGER);
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE PNLOC+H(A0),D0 ;GET CURRENT PENLOC.H
ADD D0,6(SP) ;ADD TO DH
MOVE PNLOC+V(A0),D0 ;GET CURRENT PENLOC.V
ADD D0,4(SP) ;ADD TO DV
JMP LineTo ;LineTo(pnLoc.h+dh,pnLoc.v+dv);
.PROC MoveTo,2
;----------------------------------------------------------
;
; PROCEDURE MoveTo(h,v: INTEGER);
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A1 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A1),A1 ;POINT TO CURRENT GRAFPORT
MOVE.L (SP)+,PNLOC(A1) ;COPY POINT INTO PNLOC
JMP (A0) ;RETURN
.PROC MQVE,2
.DEF Moov
;----------------------------------------------------------
;
; PROCEDURE Move(dh,dv: INTEGER);
;
MOOV MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE (SP)+,D0 ;POP DV
MOVE (SP)+,D1 ;POP DH
MOVE.L GRAFGLOBALS(A5),A1 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A1),A1 ;GET CURRENT GRAFPORT
ADD D0,PNLOC+V(A1) ;ADD DV TO PNLOC.V
ADD D1,PNLOC+H(A1) ;ADD DH TO PNLOC.H
JMP (A0) ;RETURN
.PROC DoLine,1
.REF DrawLine,PutLine,SetSize
;----------------------------------------------------------
;
; PROCEDURE DoLine(newPt: Point);
;
; { called by StdLine and StdPoly frame }
;
MOVEM.L D6-D7/A3-A4,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT
MOVE.L 20(SP),D7 ;GET NEWPT
MOVE.L PNLOC(A3),D6 ;OLDPT := THEPORT^.PNLOC
;
; CHECK IF WE ARE SAVING FOR A POLYGON
;
TST.L POLYSAVE(A3) ;ARE WE SAVING FOR A POLYGON ?
BEQ.S NOTPOLY ;NO, CONTINUE
MOVE.L THEPOLY(A4),A1 ;YES, GET POLYHANDLE
MOVE.L (A1),A0 ;DE-REFERENCE IT
MOVE (A0),D0 ;GET CURRENT POLYSIZE
CMP #10,D0 ;IS THIS THE FIRST POINT ?
BNE.S FIRSTOK ;NO, CONTINUE
MOVE.L D6,0(A0,D0) ;YES, INSTALL FIRST := OLDPT
ADD #4,D0 ;BUMP INDEX
FIRSTOK MOVE.L D7,0(A0,D0) ;INSTALL NEWPT AT END
ADD #4,D0 ;BUMP INDEX
MOVE D0,(A0) ;UPDATE INDEX
CMP POLYMAX(A4),D0 ;TIME TO MAKE BIGGER ?
BLT.S SIZEOK ;NO, CONTINUE
ADD #256,POLYMAX(A4) ;YES, GROW IN CHUNKS
MOVE.L A1,-(SP) ;PUSH POLYHANDLE
MOVE POLYMAX(A4),-(SP) ;PUSH NEW SIZE
JSR SETSIZE ;MAKE THEPOLY BIGGER
SIZEOK BRA.S NOTRGN ;DONT SAVE FOR RGN TOO
;
; IF NOT POLY, THEN CHECK FOR RGNSAVE.
; IF RGNSAVE THEN PutLine(oldPt,newPt,rgnBuf,rgnIndex,rgnMax);
;
NOTPOLY TST.L RGNSAVE(A3) ;ARE WE SAVING FOR A REGION ?
BEQ.S NOTRGN
MOVE.L D6,-(SP) ;PUSH OLDPT
MOVE.L D7,-(SP) ;PUSH NEWPT
MOVE.L RGNBUF(A4),-(SP) ;PUSH RGNBUF
PEA RGNINDEX(A4) ;PUSH VAR RGNINDEX
PEA RGNMAX(A4) ;PUSH VAR RGNMAX
JSR PUTLINE ;ADD INVERSION PTS TO RGNBUF
NOTRGN MOVE.L D6,-(SP) ;PUSH OLDPT
MOVE.L D7,-(SP) ;PUSH NEWPT
JSR DRAWLINE ;DRAW THE LINE
MOVE.L D7,PNLOC(A3) ;UPDATE THEPORT^.PNLOC
MOVEM.L (SP)+,D6-D7/A3-A4 ;RESTORE REGS
MOVE.L (SP)+,(SP) ;STRIP PARAM
RTS ;AND RETURN
.PROC HidePen,0
.DEF ShowPen
;----------------------------------------------------------
;
; PROCEDURE HidePen;
;
MOVEQ #-1,D0
BRA.S SHARE
;----------------------------------------------------------
;
; PROCEDURE ShowPen;
;
ShowPen MOVEQ #1,D0
SHARE MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT PORT
ADD D0,PNVIS(A0) ;INCREMENT/DECREMENT PNVIS
RTS ;AND RETURN
.PROC GetPenState,1
.DEF SetPenState
;----------------------------------------------------------
;
; PROCEDURE GetPenState(VAR pnState: PenState);
; PROCEDURE SetPenState(pnState: PenState);
;
MOVEQ #1,D0 ;SET A FLAG
BRA.S SHARE ;AND SHARE CODE
SetPenState
CLR D0 ;CLEAR FLAG AND SHARE
SHARE MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA PNLOC(A0),A0 ;POINT TO PNLOC
MOVE.L 4(SP),A1 ;POINT TO VAR PNSTATE
TST D0 ;is this SET penstate ?
BNE.S NOTSET ;NO, CONTINUE
EXG A0,A1 ;YES, SWAP SRC AND DST
NOTSET MOVE.L (A0)+,(A1)+ ;COPY PNLOC FROM THEPORT
MOVE.L (A0)+,(A1)+ ;COPY PNSIZE FROM THEPORT
MOVE.W (A0)+,(A1)+ ;COPY PNMODE FROM THEPORT
MOVE.L (A0)+,(A1)+ ;COPY PNPAT FROM THEPORT
MOVE.L (A0)+,(A1)+ ;ALL 8 BYTES
MOVE.L (SP)+,(SP) ;STRIP 4 BYTES
RTS ;AND RETURN
.PROC GetPen,1
;----------------------------------------------------------
;
; PROCEDURE GetPen(VAR pt: Point);
; { inquire the current pen location }
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L 4(SP),A1 ;POINT TO VAR PT
MOVE.L PNLOC(A0),(A1) ;GET PNLOC FROM THEPORT
MOVE.L (SP)+,(SP) ;STRIP 4 BYTES
RTS ;AND RETURN
.PROC PenSize,2
;----------------------------------------------------------
;
; PROCEDURE PenSize(width,height: INTEGER);
; { set the pen width and height }
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L 4(SP),PNSIZE(A0) ;SET PEN WIDTH AND HEIGHT
MOVE.L (SP)+,(SP) ;STRIP 4 BYTES
RTS ;AND RETURN
.PROC PenMode,1
.REF PortWord
;----------------------------------------------------------
;
; PROCEDURE PenMode(mode: INTEGER);
; { set the transfer mode for line drawing }
;
MOVEQ #PNMODE,D0 ;PUT PORT OFFSET IN D0
JMP PORTWORD ;INSTALL PARAM INTO THEPORT
.PROC PenPat,1
;----------------------------------------------------------
;
; PROCEDURE PenPat(pat: Pattern);
; { set the pattern for line drawing }
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA PNPAT(A0),A0 ;POINT TO PNPAT
MOVE.L 4(SP),A1 ;POINT TO INPUT PATTERN
MOVE.L (A1)+,(A0)+ ;COPY PATTERN INTO THEPORT
MOVE.L (A1)+,(A0)+ ;ALL 8 BYTES
MOVE.L (SP)+,(SP) ;STRIP 4 BYTES
RTS ;AND RETURN
.PROC PenNormal,0
;----------------------------------------------------------
;
; PROCEDURE PenNormal;
; { restore all line drawing parameters to normal }
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L #$00010001,PNSIZE(A0) ;PEN SIZE:=1,1
MOVE #8,PNMODE(A0) ;PENMODE:=PATTERN COPY
MOVEQ #-1,D0
MOVE.L D0,PNPAT(A0) ;PNPAT:=BLACK
MOVE.L D0,PNPAT+4(A0)
RTS
.END

163
Ovals.a Executable file
View File

@ -0,0 +1,163 @@
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
;
; *** * * * * ***
; * * * * * * * * *
; * * * * * * * *
; * * * * * * * ***
; * * * * ***** * *
; * * * * * * * * *
; *** * * * ***** ***
;
;
;
.PROC StdOval,2
.REF CheckPic,PutPicVerb,PutPicRect
.REF PutOval,PushVerb,DrawArc
;---------------------------------------------------------------
;
; PROCEDURE StdOval(verb: GrafVerb; r: Rect);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE .EQU 6
VERB .EQU PARAMSIZE+8-2 ;GRAFVERB
RECT .EQU VERB-4 ;LONG, ADDR OF RECT
OVWD .EQU -2 ;WORD
OVHT .EQU OVWD-2 ;WORD
VARSIZE .EQU OVHT ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D7/A3-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP)
JSR PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
MOVEQ #$50,D0 ;PUT OVALNOUN IN HI NIBBLE
ADD D7,D0 ;PUT VERB IN LO NIBBLE
MOVE.B D0,-(SP) ;PUSH OPCODE
MOVE.L RECT(A6),-(SP) ;PUSH ADDR OF RECT
JSR PutPicRect ;PUT OPCODE AND RECTANGLE
NOTPIC MOVE.L RECT(A6),A0 ;POINT TO RECT
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0
MOVE D0,OVWD(A6) ;OVWD := R.RIGHT - R.LEFT
MOVE BOTTOM(A0),D0
SUB TOP(A0),D0
MOVE D0,OVHT(A6) ;OVHT := R.BOTTOM - R.TOP
MOVE.L A0,-(SP) ;PUSH ADDR OF RECT
TST.B D7 ;IS VERB FRAME ?
BNE.S NOTFR ;NO, CONTINUE
TST.L RGNSAVE(A3) ;YES, IS RGNSAVE TRUE ?
BEQ.S NOTRGN ;NO, CONTINUE
MOVE.L A0,-(SP) ;YES, PUSH ADDR OF RECT
MOVE.L OVHT(A6),-(SP) ;PUSH OVWD, OVHT
MOVE.L RGNBUF(A4),-(SP) ;PUSH RGNBUF
PEA RGNINDEX(A4) ;PUSH VAR RGNINDEX
PEA RGNMAX(A4) ;PUSH VAR RGNMAX
JSR PutOval ;ADD AN OVAL TO THERGN
NOTRGN MOVE.B #1,-(SP) ;PUSH HOLLOW = TRUE
BRA.S DOIT
NOTFR CLR.B -(SP) ;PUSH HOLLOW = FALSE
DOIT MOVE.L OVHT(A6),-(SP) ;PUSH OVWD,OVHT
JSR PushVerb ;PUSH MODE AND PATTERN
CLR -(SP) ;PUSH STARTANGLE = 0
MOVE #360,-(SP) ;PUSH ARCANGLE = 360
; DrawArc(r,hollow,ovWd,ovHt,mode,pat,startAng,arcAng);
JSR DrawArc
MOVEM.L (SP)+,D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDOVAL '
.PROC FrameOval,1
.DEF CallOval,PaintOval,EraseOval,InvertOval,FillOval
.REF StdOval
;-----------------------------------------------------
;
; PROCEDURE FrameOval(* r: Rect *);
;
MOVEQ #FRAME,D0 ;VERB = FRAME
BRA.S CallOval ;SHARE COMMON CODE
;-----------------------------------------------------
;
; PROCEDURE PaintOval(* r: Rect *);
;
PaintOval
MOVEQ #PAINT,D0 ;VERB = PAINT
BRA.S CallOval ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE EraseOval(* r: Rect *);
;
EraseOval
MOVEQ #ERASE,D0 ;VERB = ERASE
BRA.S CallOval ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE InvertOval(* r: Rect *);
;
InvertOval
MOVEQ #INVERT,D0 ;VERB = INVERT
BRA.S CallOval ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE FillOval(* r: Rect; pat: Pattern *);
;
FillOval
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP ADDR OF PATTERN
MOVE.L A0,-(SP) ;PUT RETURN ADDR BACK
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA FILLPAT(A0),A0 ;POINT TO FILLPAT
MOVE.L (A1)+,(A0)+ ;COPY PAT INTO FILLPAT
MOVE.L (A1)+,(A0)+ ;ALL EIGHT BYTES
MOVEQ #FILL,D0 ;VERB = FILL
BRA.S CallOval ;SHARE COMMON CODE
;---------------------------------------------------------------
;
; PROCEDURE CallOval(r: Rect);
;
; code shared by FrameOval, PaintOval, EraseOval, InvertOval, and FillOval.
; enter with verb in D0.
;
CallOval
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP ADDR OF RECT
MOVE.B D0,-(SP) ;PUSH VERB
MOVE.L A1,-(SP) ;PUSH ADDR OF RECT
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDOVAL,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L OVALPROC(A0),A0 ;NO, GET PROC PTR
USESTD JMP (A0) ;GO TO IT
.END

159
PackRgn.a Executable file
View File

@ -0,0 +1,159 @@
.INCLUDE GRAFTYPES.TEXT
.PROC PACKRGN,3
.REF SETSIZE
;-----------------------------------------------------------------
;
; PROCEDURE PackRgn(srcHandle: Handle; nPoints: INTEGER; dstRgn: RgnHandle);
;
; Converts a sorted array of inversion points into a region.
; Calls storage allocator to make more room and trim result to minimum size.
;
; OUTPUT IS IN THE FOLLOWING FORM:
;
; RGNSIZE
; RGNBBOX
; V H .. H 32767
; V H .. H 32767
; V=32767
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 10 ;TOTAL BYTES OF PARAMS
SRCHANDLE .EQU PARAMSIZE+8-4 ;LONG
NPOINTS .EQU SRCHANDLE-2 ;INTEGER
DSTRGN .EQU NPOINTS-4 ;LONG, HANDLE
;-------------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
BBOX .EQU -8 ;RECTANGLE
VARSIZE .EQU BBOX ;SIZE OF LOCAL VARIABLES
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARIABLES
MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS
MOVE.L SRCHANDLE(A6),A4 ;GET SRC HANDLE
MOVE.L DSTRGN(A6),A3 ;GET DST RGNHANDLE
MOVE NPOINTS(A6),D6 ;GET NUMBER OF POINTS
MOVE.L (A3),A1 ;DE-REFERENCE DSTRGN
MOVE RGNSIZE(A1),D5 ;GET CURRENT RGNSIZE
MOVE.L (A4),A0 ;DE-REFERENCE SRCHANDLE
;------------------------------------------------------------------------
;
; CHECK NPOINTS TO SPECIAL CASE EMPTY AND RECTANGULAR REGIONS.
;
MOVEQ #10,D7 ;INIT RGNSIZE TO EMPTY RGN SIZE
CLR.L BBOX+TOPLEFT(A6) ;INIT BOUNDING BOX TO EMPTY
CLR.L BBOX+BOTRIGHT(A6)
CMP #4,D6 ;HOW MANY POINTS IN SOURCE ?
BGT.S NOTRECT ;MORE THAN 4, NOT RECTANGULAR
BLT.S DONE ;LESS THAN 4, EMPTY REGION
MOVE.L 0(A0),BBOX+TOPLEFT(A6) ;GET TOPLEFT OF BOUNDING BOX
MOVE.L 12(A0),BBOX+BOTRIGHT(A6) ;GET BOTRIGHT OF BOUNDING BOX
BRA.S DONE ;INSTALL RGNSIZE AND BBOX AND QUIT
;------------------------------------------------------------------------
;
; MORE THAN FOUR POINTS, NON-RECTANGULAR. SCAN FOR BBOX LEFT AND RIGHT.
;
NOTRECT MOVE V(A0),BBOX+TOP(A6) ;BBOX TOP:=FIRST POINT.V
MOVE H(A0),D1 ;INIT MINH TO FIRST HORIZ
MOVE D1,D2 ;INIT MAXH TO FIRST HORIZ ALSO
MOVE D6,D3 ;GET NUMPER OF POINTS IN SRC
SCAN SUB #1,D3 ;ANY POINTS LEFT ?
BLT.S ENDSCAN ;NO, QUIT SCANNING
MOVE.L (A0)+,D0 ;YES, GET NEXT POINT
CMP.W D1,D0 ;IS PT.H < MINH ?
BGE.S LEFTOK ;NO, CONTINUE
MOVE D0,D1 ;YES, MINH:=PT.H
BRA SCAN ;LOOP FOR MORE
LEFTOK CMP.W D2,D0 ;IS PT.H > MAXH ?
BLE SCAN ;NO, GO FOR NEXT
MOVE D0,D2 ;YES, MAXH:=PT.H
BRA SCAN ;GO FOR NEXT
ENDSCAN MOVE D1,BBOX+LEFT(A6) ;BBOX LEFT:=MINH
MOVE D2,BBOX+RIGHT(A6) ;BBOX RIGHT:=MAXH
MOVE -4+V(A0),BBOX+BOTTOM(A6) ;BBOX BOTTOM:=LAST POINT.V
;----------------------------------------------------------------
;
; EXPAND DSTRGN TO HOLD WORST CASE = 12 + 4*NPOINTS bytes.
;
MOVEQ #3,D5
ADD D6,D5 ;GET NPOINTS + 3
LSL #2,D5 ;TIMES 4
MOVE.L A3,-(SP) ;PUSH DSTRGN
MOVE D5,-(SP) ;PUSH NEW BYTECOUNT
JSR SetSize ;MAKE IT THAT BIG
;----------------------------------------------------
;
; NEWLY DE-REFERENCE SRC AND DST HANDLES
;
MOVE.L (A4),A0 ;DE-REFERENCE SRC HANDLE
MOVE.L (A3),A1 ;DE-REFERENCE DSTRGN HANDLE
ADD D7,A1 ;SKIP OVER RGNSIZE & BBOX
SUB #1,D6 ;DBRA COUNT = NPOINTS - 1
MOVE (A0)+,D0 ;GET FIRST VERT COORD
MOVE #32767,D1
BRA.S START ;GO TO LOOP START
NEXTPT CMP (A0)+,D0 ;SAME VERT COORD ?
BEQ.S VSAME ;YES, CONTINUE
MOVE D1,(A1)+ ;PUT END OF ROW MARKER
MOVE -2(A0),D0 ;GET NEW VERT COORD
START MOVE D0,(A1)+ ;PUT VERT COORD
VSAME MOVE (A0)+,(A1)+ ;PUT HORIZ COORD
DBRA D6,NEXTPT ;LOOP FOR ALL POINTS
MOVE D1,(A1)+ ;PUT END OF ROW MARKER
MOVE D1,(A1)+ ;PUT FINAL VERT = 32767
MOVE.L (A3),A0 ;DE-REFERENCE DSTRGN HANDLE
SUB.L A0,A1 ;SUBTRACT FROM DSTPTR
MOVE.W A1,D7 ;TO COMPUTE RGNSIZE
;--------------------------------------------------------
;
; INSTALL RGNSIZE AND RGNBBOX.
;
DONE MOVE.L (A3),A0 ;DE-REFERENCE DSTRGN HANDLE
MOVE D7,(A0)+ ;INSTALL RGNSIZE
MOVE.L BBOX+TOPLEFT(A6),(A0)+ ;INSTALL BOUNDING BOX TOPLEFT
MOVE.L BBOX+BOTRIGHT(A6),(A0)+ ;AND BOTRIGHT
;--------------------------------------------------------
;
; TRIM DSTRGN TO EXACT SIZE IF IT ISN'T ALREADY.
;
CMP D7,D5 ;IS IT ALREADY THE RIGHT SIZE ?
BEQ.S SIZEOK ;YES, SKIP
MOVE.L A3,-(SP) ;PUSH DSTRGN HANDLE
MOVE D7,-(SP) ;PUSH NEW SIZE
JSR SETSIZE
;------------------------------------------------------
;
; CLEAN UP THE STACK AND GO HOME.
;
SIZEOK MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'PACKRGN '
.END

120
PicFormat.txt Executable file
View File

@ -0,0 +1,120 @@
QUICKDRAW INTERNAL PICTURE FORMAT:
OPCODE NAME ADDITIONAL PARAMS TOTAL BYTES
00 nop none 1
01 clipRgn region 1 + region
02 bkPat pattern 9
03 txFont font(word) 3
04 txFace face(byte) 2
05 txMode mode(word) 3
06 spExtra extra(fixed Point) 5
07 pnSize pnSize(point) 5
08 pnMode mode(word) 3
09 pnPat pattern 9
0A thePat pattern 9
0B ovSize point 5
0C origin dh(word),dv(word) 5
0D txSize size(word) 3
0E fgColor color(long) 4
0F bkColor color(long) 4
10 txRatio numer(pt), denom(pt) 9
11 picVersion version(byte) 2
20 line pnLoc(pt), newPt(pt) 9
21 line from newPt(pt) 5
22 short line pnLoc(pt), dh, dv(-128..127) 7
23 short line from dh, dv(-128..127) 3
28 long text: txLoc(pt), count(0..255), text 6 + text
29 DH text: dh(0..255), count(0..255), text 3 + text
2A DV text: dv(0..255), count(0..255), text 3 + text
2B DHDV text: dh,dv(0,..255), count(0..255), text 4 + text
30 frameRect rect 9
31 paintRect rect 9
32 eraseRect rect 9
33 invertRect rect 9
34 fillRect rect 9
38 frameSameRect 1
39 paintSameRect 1
3A eraseSameRect 1
3B invertSameRect 1
3C fillSameRect 1
40 frameRRect rect 9
41 paintRRect rect 9
42 eraseRRect rect 9
43 invertRRect rect 9
44 fillRRect rect 9
48 frameSameRRect 1
49 paintSameRRect 1
4A eraseSameRRect 1
4B invertSameRRect 1
4C fillSameRRect 1
50 frameOval rect 9
51 paintOval rect 9
52 eraseOval rect 9
53 invertOval rect 9
54 fillOval rect 9
58 frameSameOval 1
59 paintSameOval 1
5A eraseSameOval 1
5B invertSameOval 1
5C fillSameOval 1
60 frameArc rect 9
61 paintArc rect 9
62 eraseArc rect 9
63 invertArc rect 9
64 fillArc rect 9
68 frameSameArc 1
69 paintSameArc 1
6A eraseSameArc 1
6B invertSameArc 1
6C fillSameArc 1
70 framePoly poly 1 + poly
71 paintPoly poly 1 + poly
72 erasePoly poly 1 + poly
73 invertPoly poly 1 + poly
74 fillPoly poly 1 + poly
78 frameSamePoly (not implemented yet)
79 paintSamePoly (not implemented yet)
7A eraseSamePoly (not implemented yet)
7B invertSamePoly (not implemented yet)
7C fillSamePoly (not implemented yet)
80 frameRgn rgn 1 + region
81 paintRgn rgn 1 + region
82 eraseRgn rgn 1 + region
83 invertRgn rgn 1 + region
84 fillRgn rgn 1 + region
88 frameSameRgn (not implemented yet)
89 paintSameRgn (not implemented yet)
8A eraseSameRgn (not implemented yet)
8B invertSameRgn (not implemented yet)
8C fillSameRgn (not implemented yet)
90 BitsRect rowBytes, bounds, srcRect, dstRect, mode,
byteCount, unpacked bitData
91 BitsRgn rowBytes, bounds, srcRect, dstRect, mode,
maskRgn, byteCount, unpacked bitData
98 PackBitsRect rowBytes, bounds, srcRect, dstRect, mode
byteCount, packed bitData
99 PackBitsRgn rowBytes, bounds, srcRect, dstRect, mode
maskRgn, byteCount, packed bitData
A0 shortComment kind(word) 3
A1 longComment kind(word) size(word) data 5 + data
FF endOfPicture

1807
Pictures.a Executable file

File diff suppressed because it is too large Load Diff

417
Polygons.a Executable file
View File

@ -0,0 +1,417 @@
.INCLUDE GRAFTYPES.TEXT
;--------------------------------------------------------------
;
;
; **** *** * * * *** *** * * ***
; * * * * * * * * * * * * * * *
; * * * * * * * * * ** * *
; **** * * * * * ** * * * * * ***
; * * * * * * * * * * ** *
; * * * * * * * * * * * * *
; * *** ***** * *** *** * * ***
;
;
.PROC StdPoly,2
.REF CheckPic,PutPicVerb,DPutPicByte,PutPicRgn
.REF PushVerb,FrPoly,RSect,DrawPoly
;---------------------------------------------------------------
;
; PROCEDURE StdPoly(verb: GrafVerb; poly: PolyHandle);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 6
VERB .EQU PARAMSIZE+8-2 ;GRAFVERB
POLY .EQU VERB-4 ;LONG, PolyHandle
MINRECT .EQU -8 ;RECT
VARSIZE .EQU MINRECT ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D5-D7/A2-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP)
JSR PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
MOVEQ #$70,D0 ;PUT POLYNOUN IN HI NIBBLE
ADD D7,D0 ;PUT VERB IN LO NIBBLE
JSR DPutPicByte ;PUT OPCODE TO THEPIC
MOVE.L POLY(A6),-(SP) ;PUSH POLYHANDLE
JSR PutPicRgn ;TREAT SAME AS A REGION
NOTPIC MOVE.L POLY(A6),A2 ;GET POLYHANDLE
TST.B D7 ;IS VERB FRAME ?
BNE.S NOTFR ;NO, CONTINUE
MOVE.L A2,-(SP) ;PUSH POLYHANDLE
JSR FrPoly ;FrPoly(poly);
BRA.S GOHOME ;AND QUIT
NOTFR MOVE.L (A2),A0 ;DE-REFERANCE POLYHANDLE
PEA POLYBBOX(A0) ;PUSH POLYBBOX
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE HANDLE
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
MOVE #3,-(SP) ;PUSH NRECTS = 3
PEA MINRECT(A6) ;PUT RESULT IN MINRECT
JSR RSECT ;CALC INTERSECTION
BEQ.S GOHOME ;QUIT IF NO INTERSECT
MOVE.L A2,-(SP) ;PUSH POLYHANDLE
JSR PushVerb ;PUSH MODE AND PATTERN
JSR DrawPoly ;DrawPoly(poly,mode,pat);
GOHOME MOVEM.L (SP)+,D5-D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDPOLY '
.PROC FramePoly,1
.DEF CallPoly,PaintPoly,ErasePoly,InvertPoly,FillPoly
.REF StdPoly
;-----------------------------------------------------
;
; PROCEDURE FramePoly(* poly: PolyHandle *);
;
MOVEQ #FRAME,D0 ;VERB = FRAME
BRA.S CallPoly ;SHARE COMMON CODE
;-----------------------------------------------------
;
; PROCEDURE PaintPoly(* poly: PolyHandle *);
;
PaintPoly
MOVEQ #PAINT,D0 ;VERB = PAINT
BRA.S CallPoly ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE ErasePoly(* poly: PolyHandle *);
;
ErasePoly
MOVEQ #ERASE,D0 ;VERB = ERASE
BRA.S CallPoly ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE InvertPoly(* poly: PolyHandle *);
;
InvertPoly
MOVEQ #INVERT,D0 ;VERB = INVERT
BRA.S CallPoly ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE FillPoly(* poly: PolyHandle; pat: Pattern *);
;
FillPoly
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP ADDR OF PATTERN
MOVE.L A0,-(SP) ;PUT RETURN ADDR BACK
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA FILLPAT(A0),A0 ;POINT TO FILLPAT
MOVE.L (A1)+,(A0)+ ;COPY PAT INTO FILLPAT
MOVE.L (A1)+,(A0)+ ;ALL EIGHT BYTES
MOVEQ #FILL,D0 ;VERB = FILL
BRA.S CallPoly ;SHARE COMMON CODE
;---------------------------------------------------------------
;
; PROCEDURE CallPoly(poly: PolyHandle);
;
; code shared by FramePoly, PaintPoly, ErasePoly, InvertPoly, and FillPoly.
; enter with verb in D0.
;
CallPoly
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP POLY
MOVE.B D0,-(SP) ;PUSH VERB
MOVE.L A1,-(SP) ;PUSH POLY
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDPOLY,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L POLYPROC(A0),A0 ;NO, GET PROC PTR
USESTD JMP (A0) ;GO TO IT
.FUNC OpenPoly,0
.REF HidePen,NewHandle
;---------------------------------------------------------------
;
; FUNCTION OpenPoly: PolyHandle;
;
STARTSIZE .EQU 138 ;ENOUGH FOR 32 POINTS
JSR HidePen ;TURN OFF DRAWING
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
MOVE #STARTSIZE,-(SP) ;PUSH BYTE COUNT = STARTSIZE
JSR NEWHANDLE ;ALLOCATE NEWHANDLE
MOVE.L (SP)+,A1 ;POP RESULTING HANDLE
MOVE.L A1,4(SP) ;PUT HANDLE IN FCN RESULT
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L A1,THEPOLY(A0) ;REMEMBER HANDLE IN THEPOLY
MOVE #STARTSIZE,POLYMAX(A0) ;POLYMAX := STARTSIZE;
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVEQ #1,D0
MOVE.L D0,POLYSAVE(A0) ;POLYSAVE := TRUE
MOVE.L (A1),A1 ;DE-REFERENCE HANDLE
MOVE #10,(A1)+ ;INSTALL POLYSIZE = 10
CLR.L (A1)+ ;ZERO OUT POLYBBOX
CLR.L (A1)+
RTS ;RETURN
.PROC ClosePoly,0
.REF SetSize,ShowPen
;---------------------------------------------------------------
;
; PROCEDURE ClosePoly;
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
MOVEM.L D3-D7/A4,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A0 ;GET CURRENT GRAFPORT
CLR.L POLYSAVE(A0) ;POLYSAVE := FALSE
MOVE.L THEPOLY(A4),A4 ;GET THEPOLY HANDLE
MOVE.L (A4),A0 ;DE-REFERENCE THEPOLY
MOVE (A0)+,D7 ;GET POLYSIZE
CLR.L (A0)+ ;ZERO OUT POLYBBOX
CLR.L (A0)+
MOVE D7,D6
SUB #10,D6
LSR #2,D6 ;NPOINTS = (SIZE-10) DIV 4
BEQ.S EMPTY ;QUIT IF NO POINTS
;-----------------------------------------------------
;
; SCAN FOR BOUNDING BOX OF POLYGON
;
MOVE (A0)+,D1 ;TOP := FIRST POINT VERT
MOVE D1,D2 ;BOTTOM := FIRST POINT VERT
MOVE (A0)+,D3 ;LEFT := FIRST POINT HORIZ
MOVE D3,D4 ;RIGHT := FIRST POINT HORIZ
SUB #1,D6 ;DECREMENT POINT COUNT
BRA.S RIGHTOK ;GO TO LOOP START
NEXTPT MOVE (A0)+,D0 ;GET VERT COORD
CMP D1,D0 ;IS VERT < BBOX TOP ?
BGE.S TOPOK ;NO, CONTINUE
MOVE D0,D1 ;YES, UPDATE BBOX TOP
TOPOK CMP D2,D0 ;IS VERT > BBOX BOTTOM ?
BLE.S BOTOK ;NO, CONTINUE
MOVE D0,D2 ;YES, UPDATE BBOX BOTTOM
BOTOK MOVE (A0)+,D0 ;GET HORIZ COORD
CMP D3,D0 ;IS HORIZ < BBOX LEFT ?
BGE.S LEFTOK ;NO, CONTINUE
MOVE D0,D3 ;YES, UPDATE BBOX LEFT
LEFTOK CMP D4,D0 ;IS HORIZ > BBOX RIGHT ?
BLE.S RIGHTOK ;NO, CONTINUE
MOVE D0,D4 ;YES, UPDATE BBOX RIGHT
RIGHTOK DBRA D6,NEXTPT ;LOOP ALL POINTS
MOVE.L (A4),A0 ;DE-REFERENCE THEPOLY
LEA POLYBBOX(A0),A0 ;POINT TO POLYBBOX
MOVE D1,(A0)+ ;INSTALL BBOX TOP
MOVE D3,(A0)+ ;INSTALL BBOX LEFT
MOVE D2,(A0)+ ;INSTALL BBOX BOTTOM
MOVE D4,(A0)+ ;INSTALL BBOX RIGHT
;--------------------------------------------------------
;
; TRIM THEPOLY TO FINAL SIZE, SHOW PEN AND QUIT
;
EMPTY MOVE.L A4,-(SP) ;PUSH THEPOLY HANDLE
MOVE D7,-(SP) ;PUSH BYTECOUNT = POLYSIZE
JSR SETSIZE ;TRIM TO MINIMUM SIZE
JSR SHOWPEN ;RESTORE PNVIS
MOVEM.L (SP)+,D3-D7/A4 ;RESTORE REGS
RTS ;AND RETURN
.PROC KillPoly,1
;---------------------------------------------------
;
; PROCEDURE KillPoly(poly: PolyHandle);
;
MOVE.L (SP)+,A1 ;pop return addr
MOVE.L (SP)+,A0 ;pop handle
_DisposHandle ;discard it
JMP (A1) ;and return
.PROC OffsetPoly,3
;---------------------------------------------------
;
; PROCEDURE OffsetPoly(poly: PolyHandle; dh,dv: INTEGER);
;
MOVE.L (SP)+,A0 ;POP RETURN ADDRESS
MOVE (SP)+,D0 ;POP DV
MOVE (SP)+,D1 ;POP DH
MOVE.L (SP)+,A1 ;POP POLYHANDLE
MOVE.L (A1),A1 ;DE-REFERENCE POLYHANDLE
MOVE (A1)+,D2 ;GET POLYSIZE
SUB #2,D2 ;CALC TOTAL # POINTS, INCL BBOX
LSR #2,D2 ; # POINTS = (SIZE-2) DIV 4
SUB #1,D2 ;INIT DBRA COUNT
NEXTPT ADD D0,(A1)+ ;OFFSET VERT COORD
ADD D1,(A1)+ ;OFFSET HORIZ COORD
DBRA D2,NEXTPT ;LOOP FOR ALL POINTS
JMP (A0) ;AND RETURN
.PROC MapPoly,3
.REF MapPt,MapRect
;-------------------------------------------------------------
;
; PROCEDURE MapPoly(poly: PolyHandle; fromRect,toRect: Rect);
;
; A6 OFFSETS OF PARAMETERS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 12
POLY .EQU PARAMSIZE+8-4 ;LONG, RGNHANDLE
FROMRECT .EQU POLY-4 ;LONG, ADDR OF RECT
TORECT .EQU FROMRECT-4 ;LONG, ADDR OF RECT
LINK A6,#0 ;ALLOCATE STACK FRAME
MOVEM.L D7/A2-A4,-(SP) ;SAVE REGS
;
; QUIT FAST IF FROMRECT = TORECT
;
MOVE.L FROMRECT(A6),A2 ;POINT TO FROMRECT
MOVE.L TORECT(A6),A3 ;POINT TO TORECT
MOVE.L (A2),D0
CMP.L (A3),D0 ;IS TOPLEFT SAME ?
BNE.S NOTSAME ;NO, CONTINUE
MOVE.L 4(A2),D0
CMP.L 4(A3),D0 ;YES, IS BOTRIGHT SAME TOO ?
BEQ.S DONE ;IF SO, JUST QUIT
NOTSAME MOVE.L POLY(A6),A4 ;GET POLYHANDLE
MOVE.L (A4),A4 ;DE-REFERENCE POLYHANDLE
PEA POLYBBOX(A4) ;PUSH ADDR OF BBOX
MOVE.L A2,-(SP) ;PUSH FROMRECT
MOVE.L A3,-(SP) ;PUSH TORECT
JSR MAPRECT ;MAP POLYBBOX
MOVEQ #10,D0
MOVE POLYSIZE(A4),D7 ;GET POLYSIZE
SUB D0,D7
LSR #2,D7 ;NPOINTS = (POLYSIZE-10) DIV 4
ADD D0,A4 ;POINT TO FIRST POINT
BRA.S START ;GO TO LOOP START
NEXTPT MOVE.L A4,-(SP) ;PUSH ADDR OF POINT
MOVE.L A2,-(SP) ;PUSH FROMRECT
MOVE.L A3,-(SP) ;PUSH TORECT
JSR MAPPT ;MAP THIS POINT
ADD #4,A4 ;BUMP TO NEXT POINT
START DBRA D7,NEXTPT ;LOOP ALL POINTS IN POLY
DONE MOVEM.L (SP)+,D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'MAPPOLY '
.PROC FrPoly,1
.REF MoveTo,DoLine
;--------------------------------------------------------
;
; PROCEDURE FrPoly(poly: PolyHandle);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 4
POLY .EQU PARAMSIZE+8-4 ;LONG, POLYHANDLE
LINK A6,#0 ;ALLOCATE STACK FRAME
MOVEM.L D6-D7/A4,-(SP) ;SAVE REGS
MOVE.L POLY(A6),A4 ;GET POLYHANDLE
MOVE.L (A4),A0 ;DE-REFERENCE IT
MOVE (A0),D7 ;GET POLYSIZE
SUB #10,D7
LSR #2,D7 ;NPOINTS = (SIZE-10) DIV 4
BEQ.S DONE ;QUIT IF EMPTY POLYGON
MOVE.L 10(A0),-(SP) ;PUSH FIRST POINT
JSR MOVETO ;MOVETO(FIRST POINT)
MOVE.L #14,D6 ;INIT BYTE OFFSET
SUB #1,D7 ;DECREMENT COUNT
BRA.S START ;GOT TO LOOP START
NEXTPT MOVE.L (A4),A0 ;DE-REFERENCE POLYHANDLE
MOVE.L 0(A0,D6),-(SP) ;PUSH NEXT POINT
ADD #4,D6 ;BUMP BYTE OFFSET
JSR DOLINE ;DOLINE(PT)
START DBRA D7,NEXTPT ;LOOP FOR ALL POINTS
DONE MOVEM.L (SP)+,D6-D7/A4 ;RESTORE REGS
UNLINK PARAMSIZE,'FRPOLY '
.PROC DrawPoly,3
.REF OpenRgn,FrPoly,DoLine,NewRgn,CloseRgn,DrawRgn
;--------------------------------------------------------
;
; PROCEDURE DrawPoly(poly: PolyHandle; mode: INTEGER; VAR pat: Pattern);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 10
POLY .EQU PARAMSIZE+8-4 ;LONG, POLYHANDLE
MODE .EQU POLY-2 ;WORD
PAT .EQU MODE-4 ;LONG, ADDR OF PATTERN
LINK A6,#0 ;NO LOCAL VARS
MOVE.L A4,-(SP) ;SAVE REG
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT PORT
TST PNVIS(A0) ;IS PNVIS NEG ?
BMI.S DONE ;YES, QUIT
JSR OPENRGN ;OpenRgn
MOVE.L POLY(A6),-(SP)
JSR FRPOLY ;FrPoly(poly);
MOVE.L POLY(A6),A0
MOVE.L (A0),A0
MOVE.L 10(A0),-(SP) ;PUSH FIRST POINT
JSR DOLINE ;MAKE SURE IT CLOSES
CLR.L -(SP) ;ROOM FOR FCN RESULT
JSR NEWRGN ;ALLOCATE TEMPRGN
MOVE.L (SP),A4 ;PUT TEMPRGN IN A4
JSR CLOSERGN ;CLOSERGN(TEMPRGN)
MOVE.L A4,-(SP)
MOVE MODE(A6),-(SP)
MOVE.L PAT(A6),-(SP)
JSR DRAWRGN ;DrawRgn(tempRgn,mode,pat);
MOVE.L A4,A0 ;get tempRgn
_DisposHandle ;DISCARD IT
DONE MOVEM.L (SP)+,A4 ;RESTORE REG
UNLINK PARAMSIZE,'DRAWPOLY'
.END

205
PutLine.a Executable file
View File

@ -0,0 +1,205 @@
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
; --> PUTLINE.TEXT
;
; Decompose a line segment into a list of inversion points.
;
;
.PROC PUTLINE,5
.REF SETSIZE
;------------------------------------------------------------------
;
; PROCEDURE PutLine(pt1,pt2: Point; dst: Handle; VAR index,bufMax: INTEGER);
;
; INVERSION POINTS FOR A LINE SEGMENT
;
; SP OFFSETS OF PARAMETERS:
;
PARAMSIZE .EQU 20 ;TOTAL SIZE OF PARAMETERS
PT1 .EQU PARAMSIZE+4-4 ;LONG, POINT (VALUE)
PT2 .EQU PT1-4 ;LONG, POINT (VALUE)
BUF .EQU PT2-4 ;LONG, HANDLE
INDEX .EQU BUF-4 ;LONG, (VAR)
BUFMAX .EQU INDEX-4 ;LONG, (VAR)
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS, 8*4 ==> 32
;-----------------------------------------------------
;
; IF LINE IS VERTICAL, IGNORE IT.
;
MOVE PT1+H+32(SP),D2 ;GET 1ST POINT'S HORIZ
MOVE PT2+H+32(SP),D4 ;GET 2ND POINT'S HORIZ
CMP D2,D4 ;IS THIS A VERTICAL LINE ?
BEQ GOHOME ;YES, IGNORE IT
;------------------------------------------------------
;
; CALC BYTESNEEDED = 8 * ( Min(ABS(dh),ABS(dv)) + 1)
;
MOVE D2,D0 ;GET H1
SUB D4,D0 ;SUBTRACT H2
BPL.S DHPOS ;BR IF DH POS
NEG D0 ;ELSE TAKE ABSOLUTE VALUE
DHPOS MOVE PT1+V+32(SP),D1 ;GET V1
SUB PT2+V+32(SP),D1 ;SUBTRACT V2
BPL.S DVPOS ;BR IF DV POS
NEG D1 ;ELSE TAKE ABSOLUTE VALUE
DVPOS CMP D1,D0 ;IS DH <= DV ?
BLE.S DHLESS ;YES, CONTINUE
MOVE D1,D0 ;NO, PUT MIN(DH,DV) INTO D0
DHLESS ADD #1,D0 ;CALC MIN(DH,DV)+1
LSL #3,D0 ;TIMES EIGHT FOR BYTESNEEDED
MOVE.L BUF+32(SP),A3 ;GET DSTHANDLE
MOVE.L INDEX+32(SP),A4 ;POINT TO CURRENT INDEX
;-----------------------------------------------------
;
; GROW POINT BUFFER AS NECESSARY TO HOLD BYTESNEEDED
;
ADD (A4),D0 ;NEWSIZE := INDEX + BYTESNEEDED
MOVE.L BUFMAX+32(SP),A0 ;POINT TO BUFMAX
CMP (A0),D0 ;DO WE HAVE TO GROW DSTBUF ?
BLE.S NOGROW ;NO, CONTINUE
ADD #512,D0 ;GROW IN CHUNKS
MOVE D0,(A0) ;UPDATE NEW BUFMAX
MOVE.L A3,-(SP) ;PUSH DSTBUF HANDLE
MOVE D0,-(SP) ;PUSH NEW BUFMAX
JSR SETSIZE ;MAKE THE BUFFER BIGGER
MOVE PT1+H+32(SP),D2 ;RESTORE CLOBBERED REG
NOGROW
MOVE.L (A3),A3 ;DE-REFERENCE DSTHANDLE
ADD (A4),A3 ;ADD INDEX TO BUFPTR
;-----------------------------------------------------
;
; IF LINE IS HORIZONTAL, PUT ITS TWO ENDPOINTS
;
MOVE PT1+V+32(SP),D1 ;GET 1ST POINT'S VERT
MOVE PT2+V+32(SP),D3 ;GET 2ND POINT'S VERT
CMP D1,D3 ;IS THIS A HORIZONTAL LINE ?
BNE.S SLANTED ;NO, BRANCH
MOVE D1,(A3)+ ;PUT V1 VERT COORD
MOVE D2,(A3)+ ;PUT H1 HORIZ COORD
MOVE D3,(A3)+ ;PUT V2 VERT COORD
MOVE D4,(A3)+ ;PUT H2 HORIZ COORD
BRA.S DONE ;UPDATE INDEX AND QUIT
;------------------------------------------------------
;
; LINE IS SLANTED. DIVIDE IT INTO HORIZONTAL SLABS
; AND PUT THE TWO ENDPOINTS OF EACH SLAB.
;
; START BY SORTING POINTS VERTICALLY.
;
SLANTED BGT.S NOSWAP ;SKIP IF ALREADY IN ORDER
EXG D1,D3 ;SORT POINTS BY VERTICAL
EXG D2,D4 ;SWAP HORIZ TO MATCH
NOSWAP MOVE D1,D6 ;INIT V TO TOPV
;------------------------------------------------------------
;
; CALCULATE 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
_FixRatio ;CALC FIXED POINT SLOPE
MOVE.L (SP)+,D7 ;POP RESULT
;---------------------------------------------------------
;
; SET UP STARTING HORIZ FIXED POINT.
;
MOVE.W D2,D1
SWAP D1 ;HORIZ.INT := TOP HORIZ
MOVE.W #$8000,D1 ;HORIZ.FRACT := 1/2
;
; ADJUST HORIZ DEPENDING ON SIGN AND MAGNITUDE OF SLOPE
;
MOVE.L D7,D0 ;COPY SLOPE
ASR.L #1,D0 ;CALC SLOPE/2
ADD.L D0,D1 ;HORIZ := HORIZ + SLOPE/2
MOVE.L #$00010000,D0
TST.L D7 ;IS SLOPE NEG ?
BMI.S NEGSLOPE ;YES, CONTINUE
CMP.L D0,D7 ;IS SLOPE < ONE ?
BGE.S SLOPEOK ;NO, CONTINUE
ADD.L D7,D1 ;ADD SLOPE TO LEFTEDGE
BRA.S SLOPEOK ;CONTINUE
NEGSLOPE CMP.L #$FFFF0000,D7 ;IS SLOPE > -ONE ?
BGE.S SLOPEOK ;YES, CONTINUE
ADD.L D0,D1 ;YES, HORIZ := HORIZ + 1
SLOPEOK
;------------------------------------------------------
;
; FOR VERT:=TOPV TO BOTV-1 ADD SLOPE TO HORIZ AND PUT SLABS
;
MOVE D2,D5 ;H:=TOPH
LOOP SWAP D1 ;GET HORIZ.INT INTO D1 LOWER
CMP D1,D5 ;HAS HORIZ.INT CHANGED ?
BEQ.S NOCHNG ;NO, CONTINUE
MOVE D6,(A3)+ ;YES, PUT VERT COORD
MOVE D5,(A3)+ ;PUT OLD HORIZ COORD
MOVE.W D1,D5 ;OLDH := HORIZ.INT
MOVE D6,(A3)+ ;PUT VERT COORD
MOVE D5,(A3)+ ;PUT NEW HORIZ COORD
NOCHNG SWAP D1 ;PUTBACK HORIZ.INT INTO D1 UPPER
ADD #1,D6 ;VERT:=VERT+1
ADD.L D7,D1 ;ADD SLOPE TO HORIZ
CMP D6,D3 ;IS VERT AT BOTTOM VERT YET ?
BNE LOOP ;NO, GO FOR MORE
;-------------------------------------------------
;
; FINISH UP LAST SLAB
;
CMP D4,D5 ;IS OLDH = BOTTOM H ?
BEQ.S DONE ;YES, CONTINUE
MOVE D6,(A3)+ ;NO, PUT VERT COORD
MOVE D5,(A3)+ ;PUT HORIZ COORD
MOVE D6,(A3)+ ;PUT VERT COORD
MOVE D4,(A3)+ ;PUT BOTTOM H COORD
;---------------------------------------------------
;
; UPDATE INDEX TO REFLECT POINTS ADDED.
;
DONE MOVE.L BUF+32(SP),A0 ;GET DSTHANDLE
SUB.L (A0),A3 ;INDEX := BUFPTR-BUFSTART
MOVE A3,(A4) ;UPDATE INDEX
GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
MOVE.L (SP)+,A0
ADD.W #PARAMSIZE,A7
JMP (A0)
.END

249
PutOval.a Executable file
View File

@ -0,0 +1,249 @@
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
; --> PUTOVAL.TEXT
;
; Routine to add the inversion points for an oval to a region.
;
;------------------------------------------------------
;
; OFFSETS IN AN OVAL STATE RECORD:
;
OVALTOP .EQU 0 ;INTEGER
OVALBOT .EQU OVALTOP+2 ;INTEGER
OVALY .EQU OVALBOT+2 ;INTEGER
RSQYSQ .EQU OVALY+2 ;LONGINT
SQUARE .EQU RSQYSQ+4 ;64 BIT LONGFIX
ODDNUM .EQU SQUARE+8 ;64 BIT LONGFIX
ODDBUMP .EQU ODDNUM+8 ;64 BIT LONGFIX
LEFTEDGE .EQU ODDBUMP+8 ;32 BIT FIXED POINT
RIGHTEDGE .EQU LEFTEDGE+4 ;32 BIT FIXED POINT
ONEHALF .EQU RIGHTEDGE+4 ;32 BIT FIXED POINT
OVALSIZE .EQU ONEHALF+4 ;SIZE OF AN OVALREC
.PROC PUTOVAL,6
.REF INITOVAL,BUMPOVAL,SETSIZE
;----------------------------------------------------------------
;
; PROCEDURE PutOval(dstRect: Rect; ovalWidth,ovalHeight: INTEGER;
; bufHandle: Handle; VAR index,size: INTEGER);
;
; Create region inversion points for an oval or roundRect.
;
;------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 20 ;TOTAL SIZE OF PARAMETERS
DSTRECT .EQU PARAMSIZE+8-4 ;ADDR OF RECT
OVALWIDTH .EQU DSTRECT-2 ;INTEGER
OVALHEIGHT .EQU OVALWIDTH-2 ;INTEGER
BUFHANDLE .EQU OVALHEIGHT-4 ;LONG, HANDLE
INDEX .EQU BUFHANDLE-4 ;LONG, VAR
SIZE .EQU INDEX-4 ;LONG, VAR
;------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
OVAL .EQU -OVALSIZE ;OVAL RECORD
SKIPTOP .EQU OVAL-2 ;WORD
SKIPBOT .EQU SKIPTOP-2 ;WORD
OLDLEFT .EQU SKIPBOT-2 ;WORD
OLDRIGHT .EQU OLDLEFT-2 ;WORD
VARSIZE .EQU OLDRIGHT ;SIZE OF LOCAL VARIABLES
ENTRY LINK A6,#VARSIZE ;ALLOCATE LOCAL VARS
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGS
;---------------------------------------------------------------
;
; INIT AN OVAL RECORD
;
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
LEA OVAL(A6),A1 ;POINT TO OVAL RECORD
MOVE OVALWIDTH(A6),D2 ;GET OVALWIDTH
MOVE OVALHEIGHT(A6),D1 ;GET OVALHEIGHT
JSR INITOVAL ;INIT OVAL RECORD
MOVE.W OVAL+LEFTEDGE(A6),OLDLEFT(A6)
MOVE.W OVAL+RIGHTEDGE(A6),OLDRIGHT(A6)
MOVE OVALHEIGHT(A6),D0 ;GET OVALHEIGHT
ASR #1,D0 ;CALC OVAL HEIGHT DIV 2
ADD OVAL+OVALTOP(A6),D0 ;ADD OVAL TOP
MOVE D0,SKIPTOP(A6) ;SAVE SKIPTOP
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
ADD BOTTOM(A0),D0 ;ADD BOTTOM
SUB TOP(A0),D0 ;SUBTRACT TOP
SUB OVALHEIGHT(A6),D0 ;SUBTRACT OVALHEIGHT
MOVE D0,SKIPBOT(A6) ;SAVE SKIPBOT
;-----------------------------------------------------------------
;
; GET BUF HANDLE, DE-REFERENCE IT, AND ADD INDEX
;
MOVE.L BUFHANDLE(A6),A3 ;GET HANDLE
MOVE.L (A3),A3 ;DE-REFERENCE IT
MOVE.L A3,A2 ;REMEMBER BUFSTART FOR LATER
MOVE.L INDEX(A6),A0 ;GET ADDR OF INDEX
ADD (A0),A3 ;ADD INDEX TO BUFPTR
;----------------------------------------------------------
;
; BUFLIMIT := BUFSTART + BUFSIZE
;
MOVE.L A2,A1 ;GET BUFSTART
MOVE.L SIZE(A6),A0 ;GET ADDR OF SIZE
ADD (A0),A1 ;LEAVE BUFLIMIT IN A1
;------------------------------------------------
;
; PUT THE TOP EDGE
;
MOVE OVAL+OVALTOP(A6),D6 ;START VERT:= OVAL TOP
MOVE OLDLEFT(A6),D5
JSR PUTPT ;PUTPOINT (OLDLEFT,VERT)
MOVE OLDRIGHT(A6),D5
JSR PUTPT ;PUTPOINT (OLDRIGHT,VERT)
;-----------------------------------------------------
;
; FOR EACH VERTICAL, BUMP LEFTEDGE AND RIGHTEDGE.
; IF THEY DIFFER FROM OLDLEFT AND OLDRIGHT, PUT INVERSION
; POINTS FOR THE DIFFERENCES
;
NXTVERT CMP SKIPTOP(A6),D6 ;IS VERT < SKIPTOP ?
BLT.S YESBUMP ;YES, BUMP OVAL RECORD
CMP SKIPBOT(A6),D6 ;IS VERT >= SKIPBOT ?
BLT.S RIGHTOK ;NO, SKIP BUMPING
YESBUMP MOVEM.L D6/A1-A3,-(SP) ;PRESERVE REGS
LEA OVAL(A6),A3 ;POINT TO OVAL RECORD
MOVE D6,D0 ;GET CURRENT VERT
JSR BUMPOVAL ;BUMP IT TO NEXT SCANLINE
MOVEM.L (SP)+,D6/A1-A3 ;RESTORE REGS
; CHECK LEFT EDGE AND PUT TWO INVERSION POINTS IF IT HAS CHANGED
MOVE.W OVAL+LEFTEDGE(A6),D5 ;GET LEFTEDGE.INT
CMP OLDLEFT(A6),D5 ;SAME AS OLDLEFT ?
BEQ.S LEFTOK ;YES, CONTINUE
JSR PUTPT ;PUTPOINT (NEWLEFT,VERT)
MOVE OLDLEFT(A6),D5
JSR PUTPT ;PUTPOINT(OLDLEFT,VERT)
MOVE OVAL+LEFTEDGE(A6),OLDLEFT(A6) ;UPDATE OLDLEFT
; CHECK RIGHT EDGE AND PUT TWO INVERSION POINTS IF IT HAS CHANGED
LEFTOK MOVE.W OVAL+RIGHTEDGE(A6),D5 ;GET RIGHTEDGE.INT
CMP OLDRIGHT(A6),D5 ;SAME AS OLDRIGHT ?
BEQ.S RIGHTOK ;YES, CONTINUE
JSR PUTPT ;PUTPOINT (NEWRIGHT,VERT)
MOVE OLDRIGHT(A6),D5
JSR PUTPT ;PUTPOINT(OLDRIGHT,VERT)
MOVE OVAL+RIGHTEDGE(A6),OLDRIGHT(A6) ;UPDATE OLDRIGHT
RIGHTOK ADD #1,D6 ;BUMP CURRENT VERT
CMP OVAL+OVALBOT(A6),D6 ;DONE WITH THE OVAL ?
BLT NXTVERT ;LOOP FOR ALL VERTICALS
;------------------------------------------------
;
; PUT THE BOTTOM EDGE
;
MOVE OLDLEFT(A6),D5
JSR PUTPT ;PUTPOINT (OLDLEFT,VERT)
MOVE OLDRIGHT(A6),D5
JSR PUTPT ;PUTPOINT (OLDRIGHT,VERT)
;----------------------------------------------------
;
; UPDATE INDEX TO REFLECT POINTS ADDED, CLEAN UP STACK AND GO HOME.
;
SUB.L A2,A3 ;CALC BUFPTR-BUFSTART
MOVE.L INDEX(A6),A0 ;GET VAR ADDR OF INDEX
MOVE A3,(A0) ;UPDATE INDEX
MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'PUTOVAL '
;-----------------------------------------------------------------------
;
; Local routine to Append a point to the end of the saved points buffer,
; extending buffer if necessary. If pt is a duplicate of the last pt,
; cancel both instead.
;
; INPUTS: D5: HORIZ COORD
; D6: VERT COORD
; A1: BUFLIMIT GETS EXPANDED AND RELOCATED
; A2: BUFSTART GETS RELOCATED
; A3: BUFPTR GETS BUMPED AND RELOCATED
;
; ALTERS: A1,A2,A3, VAR SIZE
;
PUTPT CMP.L A1,A3 ;IS BUFPTR < BUFLIMIT ?
BLT.S SIZEOK ;YES, CONTINUE
;---------------------------------------------------------------------
;
; BUFFER IS FULL, CALL STORAGE ALLOCATOR TO MAKE ROOM FOR 256 MORE POINTS.
; UPDATE BUFPTR, BUFSTART, BUFLIMIT, AND BUFSIZE AFTER RELOCATION.
;
SUB.L A2,A3 ;MAKE BUFPTR RELATIVE
SUB.L A2,A1 ;MAKE BUFLIMIT RELATIVE
ADD #1024,A1 ;MAKE BUFLIMIT BIGGER
MOVEM.L D0-D7/A0-A3,-(SP) ;SAVE REGS
MOVE.L SIZE(A6),A0 ;GET ADDR OF SIZE
MOVE A1,(A0) ;UPDATE BUFFER SIZE
MOVE.L BUFHANDLE(A6),-(SP) ;PUSH HANDLE PARAM
MOVE A1,-(SP) ;PUSH NEW SIZE
JSR SETSIZE ;MAKE THE BUFFER BIGGER
MOVEM.L (SP)+,D0-D7/A0-A3 ;RESTORE REGS
MOVE.L BUFHANDLE(A6),A2 ;GET BUF HANDLE
MOVE.L (A2),A2 ;GET NEW BUFSTART
ADD.L A2,A3 ;MAKE BUFPTR UN-RELATIVE
ADD.L A2,A1 ;MAKE BUFLIMIT UN-RELATIVE
;-------------------------------------------------------------------
;
; ADD NEW POINT TO THE SAVE BUFFER UNLESS IT MATCHED THE PREVIOUS PT.
; DELETE DUPLICATE POINTS SINCE THEY WILL CANCEL EACH OTHER ANYWAY.
;
SIZEOK CMP.L A2,A3 ;IS BUFPTR=STARTPTR ?
BEQ.S APPEND ;BR IF FIRST POINT
CMP -4+H(A3),D5 ;IS PREVIOUS HORIZ SAME ?
BNE.S APPEND ;NO, APPEND NEW POINT
CMP -4+V(A3),D6 ;YES, IS PREVIOUS VERT SAME TOO ?
BNE.S APPEND ;NO, APPEND NEW POINT
SUB #4,A3 ;YES, DELETE OLD INSTEAD
RTS
APPEND MOVE D6,(A3)+ ;PUT VERT COORD
MOVE D5,(A3)+ ;PUT HORIZ COORD
RTS
.END

79
PutRgn.a Executable file
View File

@ -0,0 +1,79 @@
.INCLUDE GRAFTYPES.TEXT
.PROC PUTRGN,4
.REF SETSIZE
;----------------------------------------------------------------
;
; PROCEDURE PutRgn(Rgn: RgnHandle; bufHandle: Handle; VAR index,size: INTEGER);
;
; Expands a region out to an array of inversion points.
;
;------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 16 ;TOTAL SIZE OF PARAMETERS
RGNHANDLE .EQU PARAMSIZE+8-4 ;LONG,RGNHANDLE
BUFHANDLE .EQU RGNHANDLE-4 ;LONG, HANDLE
INDEX .EQU BUFHANDLE-4 ;LONG, VAR
SIZE .EQU INDEX-4 ;LONG, VAR
LINK A6,#0 ;NO LOCAL VARS
MOVEM.L D7/A2-A4,-(SP) ;SAVE REGS
;-------------------------------------------------------
;
; EXPAND BUF TO FIT WORST CASE BYTESNEEDED = RGNSIZE * 2
;
MOVE.L BUFHANDLE(A6),A4 ;GET BUFHANDLE
MOVE.L RGNHANDLE(A6),A3 ;GET RGNHANDLE
MOVE.L INDEX(A6),A2 ;POINT TO CURRENT INDEX
MOVE.L (A3),A0 ;DE-REFERENCE RGN
MOVE (A0),D7 ;GET RGNSIZE
ADD D7,D7 ;TIMES 2
ADD (A2),D7 ;ADD CURRENT INDEX
MOVE.L SIZE(A6),A1 ;POINT TO SIZE
CMP (A1),D7 ;IS REQUIRED > CURRENT SIZE ?
BLE.S NOGROW ;NO, CONTINUE
ADD #256,D7 ;GROW IN CHUNKS
MOVE D7,(A1) ;UPDATE CURRENT SIZE
MOVE.L A4,-(SP) ;PUSH BUFHANDLE
MOVE D7,-(SP) ;PUSH NEW SIZE
JSR SETSIZE ;MAKE ROOM IN BUF
MOVE.L (A3),A0 ;RE-DEREFERENCE RGNHANDLE
MOVE.L INDEX(A6),A2 ;GET ADDR OF INDEX AGAIN
NOGROW MOVE.L (A4),A1 ;DE-REFERENCE BUFHANDLE
ADD (A2),A1 ;ADD INDEX TO BUFPTR
CMP #10,RGNSIZE(A0) ;IS REGION RECTANGULAR ?
BNE.S NOTRECT ;NO, CONTINUE
ADD #2,A0 ;YES, POINT TO BBOX TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY TOPLEFT
MOVE.L (A0)+,(A1)+ ;COPY BOTRIGHT
BRA.S DONE ;UPDATE INDEX AND QUIT
NOTRECT LEA RGNDATA(A0),A0 ;POINT TO TOP VERT IN RGN
NXTVERT MOVE.L (A0)+,D7 ;GET VERT AND HORIZ COORDS
NXTHOR MOVE.L D7,(A1)+ ;PUT LEFT POINT TO DST
MOVE (A0)+,D7 ;GET HORIZ COORD
MOVE.L D7,(A1)+ ;PUT RIGHT POINT TO DST
MOVE (A0)+,D7 ;GET NEXT HORIZ COORD
CMP #32767,D7 ;END OF SCAN FLAG ?
BNE NXTHOR ;NO, GO FOR MORE
CMP #32767,(A0) ;END OF REGION ?
BNE NXTVERT ;NO, LOOP FOR MORE
DONE SUB.L (A4),A1 ;CALC DSTPTR - DSTSTART
MOVE A1,(A2) ;UPDATE VAR INDEX
GOHOME MOVEM.L (SP)+,D7/A2-A4 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'PUTRGN '
.END

1028
QDPatch.a Executable file

File diff suppressed because it is too large Load Diff

418
QuickDraw.p Executable file
View File

@ -0,0 +1,418 @@
UNIT QuickDraw;
{ Copyright 1983 Apple Computer Inc. }
{ Written by Bill Atkinson }
INTERFACE
CONST srcCopy = 0; { the 16 transfer modes }
srcOr = 1;
srcXor = 2;
srcBic = 3;
notSrcCopy = 4;
notSrcOr = 5;
notSrcXor = 6;
notSrcBic = 7;
patCopy = 8;
patOr = 9;
patXor = 10;
patBic = 11;
notPatCopy = 12;
notPatOr = 13;
notPatXor = 14;
notPatBic = 15;
{ QuickDraw color separation constants }
normalBit = 0; { normal screen mapping }
inverseBit = 1; { inverse screen mapping }
redBit = 4; { RGB additive mapping }
greenBit = 3;
blueBit = 2;
cyanBit = 8; { CMYBk subtractive mapping }
magentaBit = 7;
yellowBit = 6;
blackBit = 5;
blackColor = 33; { colors expressed in these mappings }
whiteColor = 30;
redColor = 205;
greenColor = 341;
blueColor = 409;
cyanColor = 273;
magentaColor = 137;
yellowColor = 69;
picLParen = 0; { standard picture comments }
picRParen = 1;
TYPE QDByte = -128..127;
QDPtr = ^QDByte; { blind pointer }
QDHandle = ^QDPtr; { blind handle }
Str255 = String[255];
Pattern = PACKED ARRAY[0..7] OF 0..255;
Bits16 = ARRAY[0..15] OF INTEGER;
VHSelect = (v,h);
GrafVerb = (frame,paint,erase,invert,fill);
StyleItem = (bold,italic,underline,outline,shadow,condense,extend);
Style = SET OF StyleItem;
FontInfo = RECORD
ascent: INTEGER;
descent: INTEGER;
widMax: INTEGER;
leading: INTEGER;
END;
Point = RECORD CASE INTEGER OF
0: (v: INTEGER;
h: INTEGER);
1: (vh: ARRAY[VHSelect] OF INTEGER);
END;
Rect = RECORD CASE INTEGER OF
0: (top: INTEGER;
left: INTEGER;
bottom: INTEGER;
right: INTEGER);
1: (topLeft: Point;
botRight: Point);
END;
BitMap = RECORD
baseAddr: QDPtr;
rowBytes: INTEGER;
bounds: Rect;
END;
Cursor = RECORD
data: Bits16;
mask: Bits16;
hotSpot: Point;
END;
PenState = RECORD
pnLoc: Point;
pnSize: Point;
pnMode: INTEGER;
pnPat: Pattern;
END;
PolyHandle = ^PolyPtr;
PolyPtr = ^Polygon;
Polygon = RECORD
polySize: INTEGER;
polyBBox: Rect;
polyPoints: ARRAY[0..0] OF Point;
END;
RgnHandle = ^RgnPtr;
RgnPtr = ^Region;
Region = RECORD
rgnSize: INTEGER; { rgnSize = 10 for rectangular }
rgnBBox: Rect;
{ plus more data if not rectangular }
END;
PicHandle = ^PicPtr;
PicPtr = ^Picture;
Picture = RECORD
picSize: INTEGER;
picFrame: Rect;
{ plus byte codes for picture content }
END;
QDProcsPtr = ^QDProcs;
QDProcs = RECORD
textProc: QDPtr;
lineProc: QDPtr;
rectProc: QDPtr;
rRectProc: QDPtr;
ovalProc: QDPtr;
arcProc: QDPtr;
polyProc: QDPtr;
rgnProc: QDPtr;
bitsProc: QDPtr;
commentProc: QDPtr;
txMeasProc: QDPtr;
getPicProc: QDPtr;
putPicProc: QDPtr;
END;
GrafPtr = ^GrafPort;
GrafPort = RECORD
device: INTEGER;
portBits: BitMap;
portRect: Rect;
visRgn: RgnHandle;
clipRgn: RgnHandle;
bkPat: Pattern;
fillPat: Pattern;
pnLoc: Point;
pnSize: Point;
pnMode: INTEGER;
pnPat: Pattern;
pnVis: INTEGER;
txFont: INTEGER;
txFace: Style;
txMode: INTEGER;
txSize: INTEGER;
spExtra: LongInt;
fgColor: LongInt;
bkColor: LongInt;
colrBit: INTEGER;
patStretch: INTEGER;
picSave: QDHandle;
rgnSave: QDHandle;
polySave: QDHandle;
grafProcs: QDProcsPtr;
END;
VAR thePort: GrafPtr;
white: Pattern;
black: Pattern;
gray: Pattern;
ltGray: Pattern;
dkGray: Pattern;
arrow: Cursor;
screenBits: BitMap;
randSeed: LongInt;
{ GrafPort Routines }
PROCEDURE InitGraf (globalPtr: QDPtr);
PROCEDURE OpenPort (port: GrafPtr);
PROCEDURE InitPort (port: GrafPtr);
PROCEDURE ClosePort (port: GrafPtr);
PROCEDURE SetPort (port: GrafPtr);
PROCEDURE GetPort (VAR port: GrafPtr);
PROCEDURE GrafDevice (device: INTEGER);
PROCEDURE SetPortBits(bm: BitMap);
PROCEDURE PortSize (width,height: INTEGER);
PROCEDURE MovePortTo (leftGlobal,topGlobal: INTEGER);
PROCEDURE SetOrigin (h,v: INTEGER);
PROCEDURE SetClip (rgn: RgnHandle);
PROCEDURE GetClip (rgn: RgnHandle);
PROCEDURE ClipRect (r: Rect);
PROCEDURE BackPat (pat: Pattern);
{ Cursor Routines }
PROCEDURE InitCursor;
PROCEDURE SetCursor(crsr: Cursor);
PROCEDURE HideCursor;
PROCEDURE ShowCursor;
PROCEDURE ObscureCursor;
{ Line Routines }
PROCEDURE HidePen;
PROCEDURE ShowPen;
PROCEDURE GetPen (VAR pt: Point);
PROCEDURE GetPenState(VAR pnState: PenState);
PROCEDURE SetPenState(pnState: PenState);
PROCEDURE PenSize (width,height: INTEGER);
PROCEDURE PenMode (mode: INTEGER);
PROCEDURE PenPat (pat: Pattern);
PROCEDURE PenNormal;
PROCEDURE MoveTo (h,v: INTEGER);
PROCEDURE Move (dh,dv: INTEGER);
PROCEDURE LineTo (h,v: INTEGER);
PROCEDURE Line (dh,dv: INTEGER);
{ Text Routines }
PROCEDURE TextFont (font: INTEGER);
PROCEDURE TextFace (face: Style);
PROCEDURE TextMode (mode: INTEGER);
PROCEDURE TextSize (size: INTEGER);
PROCEDURE SpaceExtra (extra: LongInt);
PROCEDURE DrawChar (ch: char);
PROCEDURE DrawString (s: Str255);
PROCEDURE DrawText (textBuf: QDPtr; firstByte,byteCount: INTEGER);
FUNCTION CharWidth (ch: CHAR): INTEGER;
FUNCTION StringWidth (s: Str255): INTEGER;
FUNCTION TextWidth (textBuf: QDPtr; firstByte,byteCount: INTEGER): INTEGER;
PROCEDURE GetFontInfo (VAR info: FontInfo);
{ Point Calculations }
PROCEDURE AddPt (src: Point; VAR dst: Point);
PROCEDURE SubPt (src: Point; VAR dst: Point);
PROCEDURE SetPt (VAR pt: Point; h,v: INTEGER);
FUNCTION EqualPt (pt1,pt2: Point): BOOLEAN;
PROCEDURE ScalePt (VAR pt: Point; fromRect,toRect: Rect);
PROCEDURE MapPt (VAR pt: Point; fromRect,toRect: Rect);
PROCEDURE LocalToGlobal (VAR pt: Point);
PROCEDURE GlobalToLocal (VAR pt: Point);
{ Rectangle Calculations }
PROCEDURE SetRect (VAR r: Rect; left,top,right,bottom: INTEGER);
FUNCTION EqualRect (rect1,rect2: Rect): BOOLEAN;
FUNCTION EmptyRect (r: Rect): BOOLEAN;
PROCEDURE OffsetRect (VAR r: Rect; dh,dv: INTEGER);
PROCEDURE MapRect (VAR r: Rect; fromRect,toRect: Rect);
PROCEDURE InsetRect (VAR r: Rect; dh,dv: INTEGER);
FUNCTION SectRect (src1,src2: Rect; VAR dstRect: Rect): BOOLEAN;
PROCEDURE UnionRect (src1,src2: Rect; VAR dstRect: Rect);
FUNCTION PtInRect (pt: Point; r: Rect): BOOLEAN;
PROCEDURE Pt2Rect (pt1,pt2: Point; VAR dstRect: Rect);
{ Graphical Operations on Rectangles }
PROCEDURE FrameRect (r: Rect);
PROCEDURE PaintRect (r: Rect);
PROCEDURE EraseRect (r: Rect);
PROCEDURE InvertRect (r: Rect);
PROCEDURE FillRect (r: Rect; pat: Pattern);
{ RoundRect Routines }
PROCEDURE FrameRoundRect (r: Rect; ovWd,ovHt: INTEGER);
PROCEDURE PaintRoundRect (r: Rect; ovWd,ovHt: INTEGER);
PROCEDURE EraseRoundRect (r: Rect; ovWd,ovHt: INTEGER);
PROCEDURE InvertRoundRect (r: Rect; ovWd,ovHt: INTEGER);
PROCEDURE FillRoundRect (r: Rect; ovWd,ovHt: INTEGER; pat: Pattern);
{ Oval Routines }
PROCEDURE FrameOval (r: Rect);
PROCEDURE PaintOval (r: Rect);
PROCEDURE EraseOval (r: Rect);
PROCEDURE InvertOval (r: Rect);
PROCEDURE FillOval (r: Rect; pat: Pattern);
{ Arc Routines }
PROCEDURE FrameArc (r: Rect; startAngle,arcAngle: INTEGER);
PROCEDURE PaintArc (r: Rect; startAngle,arcAngle: INTEGER);
PROCEDURE EraseArc (r: Rect; startAngle,arcAngle: INTEGER);
PROCEDURE InvertArc (r: Rect; startAngle,arcAngle: INTEGER);
PROCEDURE FillArc (r: Rect; startAngle,arcAngle: INTEGER; pat: Pattern);
PROCEDURE PtToAngle (r: Rect; pt: Point; VAR angle: INTEGER);
{ Polygon Routines }
FUNCTION OpenPoly: PolyHandle;
PROCEDURE ClosePoly;
PROCEDURE KillPoly (poly: PolyHandle);
PROCEDURE OffsetPoly (poly: PolyHandle; dh,dv: INTEGER);
PROCEDURE MapPoly (poly: PolyHandle; fromRect,toRect: Rect);
PROCEDURE FramePoly (poly: PolyHandle);
PROCEDURE PaintPoly (poly: PolyHandle);
PROCEDURE ErasePoly (poly: PolyHandle);
PROCEDURE InvertPoly (poly: PolyHandle);
PROCEDURE FillPoly (poly: PolyHandle; pat: Pattern);
{ Region Calculations }
FUNCTION NewRgn: RgnHandle;
PROCEDURE DisposeRgn(rgn: RgnHandle);
PROCEDURE CopyRgn (srcRgn,dstRgn: RgnHandle);
PROCEDURE SetEmptyRgn(rgn: RgnHandle);
PROCEDURE SetRectRgn(rgn: RgnHandle; left,top,right,bottom: INTEGER);
PROCEDURE RectRgn (rgn: RgnHandle; r: Rect);
PROCEDURE OpenRgn;
PROCEDURE CloseRgn (dstRgn: RgnHandle);
PROCEDURE OffsetRgn (rgn: RgnHandle; dh,dv: INTEGER);
PROCEDURE MapRgn (rgn: RgnHandle; fromRect,toRect: Rect);
PROCEDURE InsetRgn (rgn: RgnHandle; dh,dv: INTEGER);
PROCEDURE SectRgn (srcRgnA,srcRgnB,dstRgn: RgnHandle);
PROCEDURE UnionRgn (srcRgnA,srcRgnB,dstRgn: RgnHandle);
PROCEDURE DiffRgn (srcRgnA,srcRgnB,dstRgn: RgnHandle);
PROCEDURE XorRgn (srcRgnA,srcRgnB,dstRgn: RgnHandle);
FUNCTION EqualRgn (rgnA,rgnB: RgnHandle): BOOLEAN;
FUNCTION EmptyRgn (rgn: RgnHandle): BOOLEAN;
FUNCTION PtInRgn (pt: Point; rgn: RgnHandle): BOOLEAN;
FUNCTION RectInRgn (r: Rect; rgn: RgnHandle): BOOLEAN;
{ Graphical Operations on Regions }
PROCEDURE FrameRgn (rgn: RgnHandle);
PROCEDURE PaintRgn (rgn: RgnHandle);
PROCEDURE EraseRgn (rgn: RgnHandle);
PROCEDURE InvertRgn (rgn: RgnHandle);
PROCEDURE FillRgn (rgn: RgnHandle; pat: Pattern);
{ Graphical Operations on BitMaps }
PROCEDURE ScrollRect(dstRect: Rect; dh,dv: INTEGER; updateRgn: rgnHandle);
PROCEDURE CopyBits (srcBits,dstBits: BitMap;
srcRect,dstRect: Rect;
mode: INTEGER;
maskRgn: RgnHandle);
{ Picture Routines }
FUNCTION OpenPicture(picFrame: Rect): PicHandle;
PROCEDURE ClosePicture;
PROCEDURE DrawPicture(myPicture: PicHandle; dstRect: Rect);
PROCEDURE PicComment(kind,dataSize: INTEGER; dataHandle: QDHandle);
PROCEDURE KillPicture(myPicture: PicHandle);
{ The Bottleneck Interface: }
PROCEDURE SetStdProcs(VAR procs: QDProcs);
PROCEDURE StdText (count: INTEGER; textAddr: QDPtr; numer,denom: Point);
PROCEDURE StdLine (newPt: Point);
PROCEDURE StdRect (verb: GrafVerb; r: Rect);
PROCEDURE StdRRect (verb: GrafVerb; r: Rect; ovWd,ovHt: INTEGER);
PROCEDURE StdOval (verb: GrafVerb; r: Rect);
PROCEDURE StdArc (verb: GrafVerb; r: Rect; startAngle,arcAngle: INTEGER);
PROCEDURE StdPoly (verb: GrafVerb; poly: PolyHandle);
PROCEDURE StdRgn (verb: GrafVerb; rgn: RgnHandle);
PROCEDURE StdBits (VAR srcBits: BitMap; VAR srcRect,dstRect: Rect;
mode: INTEGER; maskRgn: RgnHandle);
PROCEDURE StdComment (kind,dataSize: INTEGER; dataHandle: QDHandle);
FUNCTION StdTxMeas (count: INTEGER; textAddr: QDPtr;
VAR numer,denom: Point; VAR info: FontInfo): INTEGER;
PROCEDURE StdGetPic (dataPtr: QDPtr; byteCount: INTEGER);
PROCEDURE StdPutPic (dataPtr: QDPtr; byteCount: INTEGER);
{ Misc Utility Routines }
FUNCTION GetPixel (h,v: INTEGER): BOOLEAN;
FUNCTION Random: INTEGER;
PROCEDURE StuffHex (thingptr: QDPtr; s:Str255);
PROCEDURE ForeColor (color: LongInt);
PROCEDURE BackColor (color: LongInt);
PROCEDURE ColorBit (whichBit: INTEGER);
IMPLEMENTATION
{$I QuickDraw2.text }

267
QuickDraw2.p Executable file
View File

@ -0,0 +1,267 @@
{ QuickDraw2.text: Implementation part of QuickDraw }
{$S Graf }
TYPE FMOutPtr = ^FMOutRec;
FMOutrec = PACKED RECORD
errNum: INTEGER; { used only for GrafError }
fontHandle: QDHandle; { handle to font }
bold: 0..255; { how much to smear horiz }
italic: 0..255; { how much to shear }
ulOffset: 0..255; { pixels below baseline }
ulShadow: 0..255; { how big is the halo }
ulThick: 0..255; { how thick is the underline }
shadow: 0..255; { 0,1,2,or 3 only }
extra: -128..127; { extra white dots each char }
ascent: 0..255; { ascent measure for font }
descent: 0..255; { descent measure for font }
widMax: 0..255; { width of widest char }
leading: -128..127; { leading between lines }
unused: 0..255;
numer: Point; { use this modified scale to }
denom: Point; { draw or measure text with }
END;
VAR wideOpen: RgnHandle; { a dummy rectangular region, read-only }
wideMaster: RgnPtr;
wideData: Region;
rgnBuf: QDHandle; { point saving buffer for OpenRgn }
rgnIndex: INTEGER; { current bytes used in rgnBuf }
rgnMax: INTEGER; { max bytes allocated so far to rgnBuf }
playPic: PicHandle; { used by StdGetPic }
QDSpare0: INTEGER; { unused word }
thePoly: PolyHandle; { the current polygon being defined }
polyMax: INTEGER; { max bytes allocated so far to thePoly }
patAlign: Point; { to align pattern during DrawPicture }
fixTxWid: Fixed; { Fixed Point width from StdTxMeas. }
fontPtr: FMOutPtr; { the last font used, used by DrawText }
playIndex: LongInt; { used by StdGetPic during DrawPicture }
QDSpare3: INTEGER; { unused word }
QDSpare4: INTEGER; { unused word }
QDSpare5: INTEGER; { unused word }
QDSpare6: INTEGER; { unused word }
QDSpare7: INTEGER; { unused word }
QDSpare8: INTEGER; { unused word }
QDSpare9: INTEGER; { unused word }
QDSpareA: INTEGER; { unused word }
QDSpareB: INTEGER; { unused word }
QDSpareC: INTEGER; { unused word }
QDSpareD: INTEGER; { unused word }
{ grafPort routines }
PROCEDURE InitGraf; EXTERNAL;
PROCEDURE OpenPort; EXTERNAL;
PROCEDURE InitPort; EXTERNAL;
PROCEDURE ClosePort; EXTERNAL;
PROCEDURE GrafDevice; EXTERNAL;
PROCEDURE SetPort; EXTERNAL;
PROCEDURE GetPort; EXTERNAL;
PROCEDURE SetPortBits; EXTERNAL;
PROCEDURE PortSize; EXTERNAL;
PROCEDURE MovePortTo; EXTERNAL;
PROCEDURE SetOrigin; EXTERNAL;
PROCEDURE SetClip; EXTERNAL;
PROCEDURE GetClip; EXTERNAL;
PROCEDURE ClipRect; EXTERNAL;
PROCEDURE BackPat; EXTERNAL;
{ cursor routines }
PROCEDURE InitCursor; EXTERNAL;
PROCEDURE SetCursor; EXTERNAL;
PROCEDURE HideCursor; EXTERNAL;
PROCEDURE ShowCursor; EXTERNAL;
PROCEDURE ObscureCursor; EXTERNAL;
{ text routines }
PROCEDURE TextFont; EXTERNAL;
PROCEDURE TextFace; EXTERNAL;
PROCEDURE TextMode; EXTERNAL;
PROCEDURE TextSize; EXTERNAL;
PROCEDURE SpaceExtra; EXTERNAL;
PROCEDURE DrawChar; EXTERNAL;
PROCEDURE DrawString; EXTERNAL;
PROCEDURE DrawText; EXTERNAL;
FUNCTION CharWidth; EXTERNAL;
FUNCTION StringWidth; EXTERNAL;
FUNCTION TextWidth; EXTERNAL;
PROCEDURE GetFontInfo; EXTERNAL;
{ line routines }
PROCEDURE HidePen; EXTERNAL;
PROCEDURE ShowPen; EXTERNAL;
PROCEDURE GetPen; EXTERNAL;
PROCEDURE GetPenState; EXTERNAL;
PROCEDURE SetPenState; EXTERNAL;
PROCEDURE PenSize; EXTERNAL;
PROCEDURE PenMode; EXTERNAL;
PROCEDURE PenPat; EXTERNAL;
PROCEDURE PenNormal; EXTERNAL;
PROCEDURE MoveTo; EXTERNAL;
PROCEDURE Move; EXTERNAL;
PROCEDURE LineTo; EXTERNAL;
PROCEDURE Line; EXTERNAL;
{ rectangle calculations }
PROCEDURE SetRect; EXTERNAL;
FUNCTION EqualRect; EXTERNAL;
FUNCTION EmptyRect; EXTERNAL;
PROCEDURE OffsetRect; EXTERNAL;
PROCEDURE MapRect; EXTERNAL;
PROCEDURE InsetRect; EXTERNAL;
FUNCTION SectRect; EXTERNAL;
PROCEDURE UnionRect; EXTERNAL;
FUNCTION PtInRect; EXTERNAL;
PROCEDURE Pt2Rect; EXTERNAL;
{ graphical operations on rectangles }
PROCEDURE FrameRect; EXTERNAL;
PROCEDURE PaintRect; EXTERNAL;
PROCEDURE EraseRect; EXTERNAL;
PROCEDURE InvertRect; EXTERNAL;
PROCEDURE FillRect; EXTERNAL;
{ graphical operations on RoundRects }
PROCEDURE FrameRoundRect; EXTERNAL;
PROCEDURE PaintRoundRect; EXTERNAL;
PROCEDURE EraseRoundRect; EXTERNAL;
PROCEDURE InvertRoundRect; EXTERNAL;
PROCEDURE FillRoundRect; EXTERNAL;
{ graphical operations on Ovals }
PROCEDURE FrameOval; EXTERNAL;
PROCEDURE PaintOval; EXTERNAL;
PROCEDURE EraseOval; EXTERNAL;
PROCEDURE InvertOval; EXTERNAL;
PROCEDURE FillOval; EXTERNAL;
{ Arc routines }
PROCEDURE FrameArc; EXTERNAL;
PROCEDURE PaintArc; EXTERNAL;
PROCEDURE EraseArc; EXTERNAL;
PROCEDURE InvertArc; EXTERNAL;
PROCEDURE FillArc; EXTERNAL;
PROCEDURE PtToAngle; EXTERNAL;
{ polygon routines }
FUNCTION OpenPoly; EXTERNAL;
PROCEDURE ClosePoly; EXTERNAL;
PROCEDURE KillPoly; EXTERNAL;
PROCEDURE OffsetPoly; EXTERNAL;
PROCEDURE MapPoly; EXTERNAL;
PROCEDURE FramePoly; EXTERNAL;
PROCEDURE PaintPoly; EXTERNAL;
PROCEDURE ErasePoly; EXTERNAL;
PROCEDURE InvertPoly; EXTERNAL;
PROCEDURE FillPoly; EXTERNAL;
{ region calculations }
FUNCTION NewRgn; EXTERNAL;
PROCEDURE DisposeRgn; EXTERNAL;
PROCEDURE OpenRgn; EXTERNAL;
PROCEDURE CloseRgn; EXTERNAL;
PROCEDURE OffsetRgn; EXTERNAL;
PROCEDURE MapRgn; EXTERNAL;
PROCEDURE InsetRgn; EXTERNAL;
PROCEDURE SectRgn; EXTERNAL;
PROCEDURE CopyRgn; EXTERNAL;
PROCEDURE SetEmptyRgn; EXTERNAL;
PROCEDURE SetRectRgn; EXTERNAL;
PROCEDURE RectRgn; EXTERNAL;
PROCEDURE UnionRgn; EXTERNAL;
PROCEDURE DiffRgn; EXTERNAL;
PROCEDURE XorRgn; EXTERNAL;
FUNCTION EqualRgn; EXTERNAL;
FUNCTION EmptyRgn; EXTERNAL;
FUNCTION PtInRgn; EXTERNAL;
FUNCTION RectInRgn; EXTERNAL;
{ graphical operations on Regions }
PROCEDURE FrameRgn; EXTERNAL;
PROCEDURE PaintRgn; EXTERNAL;
PROCEDURE EraseRgn; EXTERNAL;
PROCEDURE InvertRgn; EXTERNAL;
PROCEDURE FillRgn; EXTERNAL;
{ BitMap routines }
PROCEDURE CopyBits; EXTERNAL;
PROCEDURE ScrollRect; EXTERNAL;
{ Picture routines }
FUNCTION OpenPicture; EXTERNAL;
PROCEDURE ClosePicture; EXTERNAL;
PROCEDURE KillPicture; EXTERNAL;
PROCEDURE DrawPicture; EXTERNAL;
PROCEDURE PicComment; EXTERNAL;
{ BottleNeck routines }
PROCEDURE StdText; EXTERNAL;
PROCEDURE StdLine; EXTERNAL;
PROCEDURE StdRect; EXTERNAL;
PROCEDURE StdRRect; EXTERNAL;
PROCEDURE StdOval; EXTERNAL;
PROCEDURE StdArc; EXTERNAL;
PROCEDURE StdPoly; EXTERNAL;
PROCEDURE StdRgn; EXTERNAL;
PROCEDURE StdBits; EXTERNAL;
PROCEDURE StdComment; EXTERNAL;
FUNCTION StdTxMeas; EXTERNAL;
PROCEDURE StdGetPic; EXTERNAL;
PROCEDURE StdPutPic; EXTERNAL;
{ misc utility routines }
FUNCTION GetPixel; EXTERNAL;
FUNCTION Random; EXTERNAL;
PROCEDURE AddPt; EXTERNAL;
PROCEDURE SubPt; EXTERNAL;
PROCEDURE SetPt; EXTERNAL;
FUNCTION EqualPt; EXTERNAL;
PROCEDURE StuffHex; EXTERNAL;
PROCEDURE LocalToGlobal; EXTERNAL;
PROCEDURE GlobalToLocal; EXTERNAL;
PROCEDURE ScalePt; EXTERNAL;
PROCEDURE MapPt; EXTERNAL;
PROCEDURE ForeColor; EXTERNAL;
PROCEDURE BackColor; EXTERNAL;
PROCEDURE ColorBit; EXTERNAL;
PROCEDURE SetStdProcs; EXTERNAL;
END. { of UNIT }

145
QuickGlue.a Executable file
View File

@ -0,0 +1,145 @@
; File: QuickGlue.TEXT
;------------------------------------------------------------------
;
; QuickDraw/Mac OS Interface
;
; written by Andy Hertzfeld 16-Sept-82
;
; (c) 1982 by Apple Computer, Inc. All rights reserved.
;
; QuickGlue is the QuickDraw/Mac OS interface. It is linked with QuickDraw and
; defines all of the externals required by QuickDraw except those of the
; font manager. All of these are very short and simple (memory manager traps or
; jumps through the graphics jump table).
;
; Modification History
;
; 16-Nov-82 AJH Made font manager interface go through graphics jump table
; 09-Feb-83 AJH Added LockHandle, UnLockHandle
; 17-Aug-83 SC Made all cursor jumps preserve A0
; 22-Apr-85 LAK Removed RInitGraf (coordinated with Bill clearing
; QDExist flag in InitGraf).
;------------------------------------------------------------------
.INCLUDE tlasm-SysTlQk.Sym
;
; Here is a subset of Unit Storage (the ones needed by
; QuickDraw), implemented by trapping to the Mac OS.
;
;
; FUNCTION NewHandle(byteCount: INTEGER): Ptr;
;
.FUNC NewHandle,1
;
MOVEQ #0,D0 ;clear out high part
MOVE.L (SP)+,A1 ;get return address
MOVE.W (SP)+,D0 ;get the byte count
_NEWHANDLE ;ask OS to do request
BNE.S MemFull ;if memory full, deep shit!
MOVE.L A0,(SP) ;return result handle on stack
JMP (A1) ;return to caller
; handle the memory full error by deep-shitting
MemFull
MOVEQ #DSMemFullErr,D0
_SysError
.WORD $A9FF ;invoke debugger just in case it comes back
;
; PROCEDURE SetSize(h: Handle; newSize: INTEGER);
;
.DEF SetSize
;
SetSize
MOVEQ #0,D0 ;clear out high part
MOVE.L (SP)+,A1 ;get return address
MOVE.W (SP)+,D0 ;get the new size
MOVE.L (SP)+,A0 ;get the handle
_SETHANDLESIZE ;let OS do it
BNE.S MemFull ;if out of memory, deepShit
JMP (A1) ;return to caller
;
; PROCEDURE DisposeHandle(h: Handle);
;
.PROC DisposeHandle,2
;
MOVE.L (SP)+,A1 ;get return address
MOVE.L (SP)+,A0 ;get parameter
_DISPOSHANDLE ;let OS do work
JMP (A1) ;return to caller
;
; PROCEDURE LockHandle(h: Handle);
;
.PROC LockHandle
MOVE.L 4(SP),A0
BSET #7,(A0)
MOVE.L (SP)+,(SP)
RTS
;
; PROCEDURE UnLockHandle(h: handle);
;
.PROC UnlockHandle
MOVE.L 4(SP),A0
BCLR #7,(A0)
MOVE.L (SP)+,(SP)
RTS
;
; Following is the QuickDraw cursor interface, implemented by accessing
; system routines through the graphics jump table
;
.PROC CursorDisplay,0
;
MOVE.L JShowCursor,-(SP)
RTS
;
.PROC CursorHide,0
;
MOVE.L JHideCursor,-(SP)
RTS
;
.PROC CursorImage,0
;
MOVE.L JSetCrsr,-(SP)
RTS
;
.PROC CursorInit,0
;
MOVE.L JInitCrsr,-(SP)
RTS
;
.PROC CursorObscure,0
;
MOVE.L JCrsrObscure,-(SP)
RTS
;
.PROC CursorShield,0
;
MOVE.L JShieldCursor,-(SP)
RTS
;
.PROC ScreenAdress,0
;
MOVE.L JScrnAddr,-(SP)
RTS
;
.PROC ScreenSize,0
;
MOVE.L JScrnSize,-(SP)
RTS
;
.PROC FMSwapFont,0
MOVE.L JSwapFont,-(SP)
RTS
.END

177
RRects.a Executable file
View File

@ -0,0 +1,177 @@
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
;
; **** **** ***** *** ***** ***
; * * * * * * * * * *
; * * * * * * * *
; **** **** *** * * ***
; * * * * * * * *
; * * * * * * * * * *
; * * * * ***** *** * ***
;
;
; procedures for operating on RoundRects.
;
;
.PROC StdRRect,4
.REF CheckPic,DPutPicByte,PutPicVerb,PutPicLong,PutPicRect
.REF PutOval,PushVerb,DrawArc
;---------------------------------------------------------------
;
; PROCEDURE StdRRect(verb: GrafVerb; r: Rect; ovWd,ovHt: INTEGER);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE .EQU 10
VERB .EQU PARAMSIZE+8-2 ;GRAFVERB
RECT .EQU VERB-4 ;LONG, ADDR OF RECT
OVWD .EQU RECT-2 ;WORD
OVHT .EQU OVWD-2 ;WORD
LINK A6,#0 ;NO LOCALS
MOVEM.L D7/A3-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP) ;PUSH VERB
JSR PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
;
; CHECK FOR NEW OVAL SIZE
;
MOVE.L PICSAVE(A3),A0 ;GET PICSAVE HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE PICSAVE
MOVE.L OVHT(A6),D0 ;GET OVWD AND OVHT
CMP.L PICOVSIZE(A0),D0 ;SAME AS CURRENT OVAL SIZE ?
BEQ.S OVALOK ;YES, CONTINUE
MOVE.L D0,PICOVSIZE(A0) ;NO, UPDATE STATE VARIABLE
MOVE.L D0,-(SP) ;PUSH OVSIZE FOR PutPicLong CALL
MOVEQ #$0B,D0
JSR DPutPicByte ;PUT OVSIZE OPCODE
JSR PutPicLong ;PUT NEW OVAL SIZE DATA
OVALOK MOVEQ #$40,D0 ;PUT RRECT NOUN IN HI NIBBLE
ADD D7,D0 ;PUT VERB IN LO NIBBLE
MOVE.B D0,-(SP) ;PUSH OPCODE
MOVE.L RECT(A6),-(SP) ;PUSH ADDR OF RECT
JSR PutPicRect ;PUT OPCODE AND RECTANGLE
NOTPIC MOVE.L RECT(A6),-(SP) ;PUSH ADDR OF RECT
CLR.B -(SP) ;PUSH HOLLOW = FALSE
TST.B D7 ;IS VERB FRAME ?
BNE.S DOIT ;NO, CONTINUE
TST.L RGNSAVE(A3) ;YES, IS RGNSAVE TRUE ?
BEQ.S NOTRGN ;NO, CONTINUE
MOVE.L RECT(A6),-(SP) ;YES, PUSH ADDR OF RECT
MOVE.L OVHT(A6),-(SP) ;PUSH OVWD, OVHT
MOVE.L RGNBUF(A4),-(SP) ;PUSH RGNBUF
PEA RGNINDEX(A4) ;PUSH VAR RGNINDEX
PEA RGNMAX(A4) ;PUSH VAR RGNMAX
JSR PutOval ;ADD AN OVAL TO THERGN
NOTRGN MOVE.B #1,(SP) ;REPLACE, PUSH HOLLOW = TRUE
DOIT MOVE.L OVHT(A6),-(SP) ;PUSH OVWD,OVHT
JSR PushVerb ;PUSH MODE AND PATTERN
CLR -(SP) ;PUSH STARTANGLE = 0
MOVE #360,-(SP) ;PUSH ARCANGLE = 360
; DrawArc(r,hollow,ovWd,ovHt,mode,pat,startAng,arcAng);
JSR DrawArc
MOVEM.L (SP)+,D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDRRECT'
.PROC FrameRoundRect,3
.DEF CallRRect,PaintRoundRect,EraseRoundRect
.DEF InvertRoundRect,FillRoundRect
.REF StdRRect
;--------------------------------------------------------
;
; PROCEDURE FrameRoundRect(* r: Rect; ovWd,ovHt: INTEGER *);
;
MOVEQ #FRAME,D0 ;VERB = FRAME
BRA.S CallRRect ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE PaintRoundRect(* r: Rect; ovWd,ovHt: INTEGER *);
;
PaintRoundRect
MOVEQ #PAINT,D0 ;VERB = PAINT
BRA.S CallRRect ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE EraseRoundRect(* r: Rect; ovWd,ovHt: INTEGER *);
;
EraseRoundRect
MOVEQ #ERASE,D0 ;VERB = ERASE
BRA.S CallRRect ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE InvertRoundRect(* r: Rect; ovWd,ovHt: INTEGER *);
;
InvertRoundRect
MOVEQ #INVERT,D0 ;VERB = INVERT
BRA.S CallRRect ;SHARE COMMON CODE
;--------------------------------------------------------
;
; PROCEDURE FillRoundRect(r: Rect; ovWd,ovHt: INTEGER; pat: Pattern);
;
FillRoundRect
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP ADDR OF PATTERN
MOVE.L A0,-(SP) ;PUT RETURN ADDR BACK
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA FILLPAT(A0),A0 ;POINT TO FILLPAT
MOVE.L (A1)+,(A0)+ ;COPY PAT INTO FILLPAT
MOVE.L (A1)+,(A0)+ ;ALL EIGHT BYTES
MOVEQ #FILL,D0 ;VERB = FILL
BRA.S CallRRect ;SHARE COMMON CODE
;---------------------------------------------------------------
;
; PROCEDURE CallRRect(r: Rect; ovWd,ovHt: INTEGER);
;
; code shared by FrameRoundRect, PaintRoundRect, EraseRoundRect,
; InvertRoundRect, and FillRoundRect.
; enter with verb in D0.
;
CallRRect
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D1 ;POP ovWd and ovHt
MOVE.L (SP)+,A1 ;POP ADDR OF RECT
MOVE.B D0,-(SP) ;PUSH VERB
MOVE.L A1,-(SP) ;PUSH ADDR OF RECT
MOVE.L D1,-(SP) ;PUSH ovWd and ovHt
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDRRECT,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L RRECTPROC(A0),A0 ;NO, GET PROC PTR
USESTD JMP (A0) ;GO TO IT
.END

675
Rects.a Executable file
View File

@ -0,0 +1,675 @@
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
;
; **** ***** *** ***** ***
; * * * * * * * *
; * * * * * *
; **** *** * * ***
; * * * * * *
; * * * * * * * *
; * * ***** *** * ***
;
;
;
; Procedures for operating on rectangles.
;
.PROC StdRect,2
.REF CheckPic,PutPicVerb,PutPicRect
.REF PutRect,FrRect,PushVerb,DrawRect
;---------------------------------------------------------------
;
; PROCEDURE StdRect(verb: GrafVerb; r: Rect);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE .EQU 6
VERB .EQU PARAMSIZE+8-2 ;GRAFVERB
RECT .EQU VERB-4 ;LONG, ADDR OF RECT
LINK A6,#0 ;NO LOCALS
MOVEM.L D7/A3-A4,-(SP) ;SAVE REGS
MOVE.B VERB(A6),D7 ;GET VERB
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE.S NOTPIC ;BRANCH IF NOT PICSAVE
MOVE.B D7,-(SP) ;PUSH VERB
JSR PutPicVerb ;PUT ADDIONAL PARAMS TO THEPIC
MOVEQ #$30,D0 ;GET RECTNOUN IN HI NIBBLE
ADD D7,D0 ;PUT VERB IN LO NIBBLE
MOVE.B D0,-(SP) ;PUSH OPCODE
MOVE.L RECT(A6),-(SP) ;PUSH ADDR OF RECT
JSR PutPicRect ;PUT OPCODE AND RECTANGLE
NOTPIC MOVE.L RECT(A6),-(SP) ;PUSH RECT FOR FrRect or DrawRect
TST.B D7 ;IS VERB FRAME ?
BNE.S NOTFR ;NO, CONTINUE
TST.L RGNSAVE(A3) ;YES, IS RGNSAVE TRUE ?
BEQ.S NOTRGN ;NO, CONTINUE
MOVE.L RECT(A6),-(SP) ;YES, PUSH ADDR OF RECT
MOVE.L RGNBUF(A4),-(SP) ;PUSH RGNBUF
PEA RGNINDEX(A4) ;PUSH VAR RGNINDEX
PEA RGNMAX(A4) ;PUSH VAR RGNMAX
JSR PutRect ;ADD A RECT TO THERGN
NOTRGN JSR FrRect ;FrRect(rect)
BRA.S GOHOME
NOTFR JSR PushVerb ;PUSH MODE AND PATTERN
JSR DRAWRECT ;DrawRect(rect,mode,pat);
GOHOME MOVEM.L (SP)+,D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDRECT '
.PROC PushVerb
;----------------------------------------------------------
;
; PUSH A MODE AND A PATTERN, BASED ON VERB
; ENTER WITH VERB IN D7, GRAFGLOBALS IN A4, THEPORT IN A3.
;
; CLOBBERS A0.
;
; frame: pnMode, pnPat
; paint: pnMode, pnPat
; erase: patCopy, bkPat
; invert: patXor, black
; fill: patCopy, fillPat
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE #8,-(SP) ;PUSH MODE = PATCOPY (IE. DEFAULT)
CMP.B #1,D7 ;CASE ON VERB
BLE.S PAINT1
CMP.B #3,D7
BLT.S ERASE1
BEQ.S INVERT1
FILL1 PEA FILLPAT(A3) ;PUSH PAT := FILLPAT
BRA.S DONE
ERASE1 PEA BKPAT(A3) ;PUSH PAT = BKPAT
BRA.S DONE
INVERT1 ADD.W #2,(SP) ;ADJUST, PUSH MODE = PATXOR
PEA BLACK(A4) ;PUSH PAT = BLACK
BRA.S DONE
PAINT1 MOVE PNMODE(A3),(SP) ;REPLACE, PUSH MODE = PNMODE
PEA PNPAT(A3) ;PUSH PAT = PNPAT
DONE JMP (A0) ;RETURN TO CALLER
.PROC FillRect,2
.DEF CallRect,FrameRect,PaintRect,EraseRect,InvertRect
.REF StdRect
;----------------------------------------------------------
;
; PROCEDURE FillRect(r: Rect; pat: Pattern);
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP ADDR OF PATTERN
MOVE.L A0,-(SP) ;PUT RETURN ADDR BACK
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
LEA FILLPAT(A0),A0 ;POINT TO FILLPAT
MOVE.L (A1)+,(A0)+ ;COPY PAT INTO FILLPAT
MOVE.L (A1)+,(A0)+ ;ALL EIGHT BYTES
MOVEQ #FILL,D0 ;VERB = FILL
BRA.S CallRect ;SHARE COMMON CODE
;----------------------------------------------------------
;
; PROCEDURE FrameRect(r: Rect);
;
FrameRect
MOVEQ #FRAME,D0 ;VERB = FRAME
BRA.S CallRect ;SHARE COMMON CODE
;----------------------------------------------------------
;
; PROCEDURE PaintRect(r: Rect);
;
PaintRect
MOVEQ #PAINT,D0 ;VERB = PAINT
BRA.S CallRect ;SHARE COMMON CODE
;----------------------------------------------------------
;
; PROCEDURE EraseRect(r: Rect);
;
EraseRect
MOVEQ #ERASE,D0 ;VERB = ERASE
BRA.S CallRect ;SHARE COMMON CODE
;----------------------------------------------------------
;
; PROCEDURE InvertRect(r: Rect);
;
InvertRect
MOVEQ #INVERT,D0 ;VERB = INVERT
BRA.S CallRect ;SHARE COMMON CODE
;---------------------------------------------------------------
;
; PROCEDURE CallRect(r: Rect);
;
; code shared by FrameRect, PaintRect, EraseRect, InvertRect, and FillRect.
; enter with verb in D0.
;
CallRect
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP ADDR OF RECT
MOVE.B D0,-(SP) ;PUSH VERB
MOVE.L A1,-(SP) ;PUSH ADDR OF RECT
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDRECT,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L RECTPROC(A0),A0 ;NO, GET PROC PTR
USESTD JMP (A0) ;GO TO IT
.PROC DrawRect,3
.REF RgnBlt
;----------------------------------------------------------
;
; PROCEDURE DrawRect(r: Rect; mode: INTEGER; pat: Pattern);
;
; Rectangle is given in local coordinates.
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 10 ;TOTAL BYTES OF PARAMS
DSTRECT .EQU PARAMSIZE+8-4 ;LONG, ADDR OF RECT
MODE .EQU DSTRECT-2 ;WORD
PAT .EQU MODE-4 ;LONG, ADDR OF PAT
LINK A6,#0 ;NO LOCAL VARS
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A1 ;GET CURRENT GRAFPORT
TST PNVIS(A1) ;IS PNVIS >= 0 ?
BLT.S GOHOME ;NO, QUIT
PEA PORTBITS(A1) ;PUSH SRCBITS = DSTBITS
MOVE.L (SP),-(SP) ;PUSH DSTBITS
MOVE.L DSTRECT(A6),-(SP) ;PUSH SRCRECT = DSTRECT
MOVE.L (SP),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L PAT(A6),-(SP) ;PUSH ADDR OF PATTERN
MOVE.L CLIPRGN(A1),-(SP) ;PUSH CLIPRGN
MOVE.L VISRGN(A1),-(SP) ;PUSH VISRGN
MOVE.L WIDEOPEN(A0),-(SP) ;PUSH WIDE OPEN
JSR RGNBLT ;CALL RGNBLT
GOHOME UNLINK PARAMSIZE,'DRAWRECT'
.PROC FrRect,1
.REF RgnBlt
;----------------------------------------------------------
;
; PROCEDURE FrRect(r: Rect);
; Draws an outline inside a rect.
;
; A6 OFFSETS OF PARAMETERS AND LOCALS AFTER LINK:
;
DSTRECT .EQU 8 ;LONG, ADDR OF RECT
H1 .EQU -2 ;WORD
H2 .EQU H1-2 ;WORD
H3 .EQU H2-2 ;WORD
H4 .EQU H3-4 ;WORD
V1 .EQU H4-2 ;WORD
V2 .EQU V1-2 ;WORD
V3 .EQU V2-2 ;WORD
V4 .EQU V3-4 ;WORD
TEMPRECT .EQU V4-8 ;RECT
VARSIZE .EQU TEMPRECT ;TOTAL SIZE OF LOCALS
LINK A6,#VARSIZE ;SET UP STACK FRAME
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
TST PNVIS(A0) ;IS PNVIS NEGATIVE ?
BLT GOHOME ;YES, DON'T DRAW AT ALL
MOVE.L DSTRECT(A6),A1 ;POINT TO INPUT RECT
MOVE.L (A1)+,TEMPRECT+TOPLEFT(A6) ;COPY INPUT RECT
MOVE.L (A1)+,TEMPRECT+BOTRIGHT(A6)
;
; Now set up h1,h2,h3,h4 and v1,v2,v3,v4
;
LEA TEMPRECT(A6),A1 ;POINT TO COPIED RECT
MOVE PNSIZE+H(A0),D2 ;GET PEN WIDTH
MOVE LEFT(A1),D0
MOVE D0,H1(A6) ;H1:=LEFT
ADD D2,D0
MOVE D0,H2(A6) ;H2:=LEFT+PENWIDTH
MOVE RIGHT(A1),D1
MOVE D1,H4(A6) ;H4:=RIGHT
SUB D2,D1
MOVE D1,H3(A6) ;H3:=RIGHT-PENWIDTH
CMP D1,D0 ;IS H2 >= H3 ?
BGE.S @1 ;YES, FILL IT IN SOLID
MOVE PNSIZE+V(A0),D2 ;GET PEN HEIGHT
MOVE TOP(A1),D0
MOVE D0,V1(A6) ;V1:=TOP
ADD D2,D0
MOVE D0,V2(A6) ;V2:=TOP+PENHEIGHT
MOVE BOTTOM(A1),D1
MOVE D1,V4(A6) ;V4:=BOTTOM
SUB D2,D1
MOVE D1,V3(A6) ;V3:=BOTTOM-PENHEIGHT
CMP D1,D0 ;IS V2 >= V3 ?
BGE.S @1 ;YES, FILL IT IN SOLID
;
; PEN IS NOT SO BIG AS TO FILL IN SOLID. BREAK RECT INTO 4 EDGES.
;
MOVE H1(A6),TEMPRECT+LEFT(A6)
MOVE H3(A6),TEMPRECT+RIGHT(A6)
MOVE V1(A6),TEMPRECT+TOP(A6)
MOVE V2(A6),TEMPRECT+BOTTOM(A6)
BSR.S DORECT ;PAINT TOP EDGE
MOVE H3(A6),TEMPRECT+LEFT(A6)
MOVE H4(A6),TEMPRECT+RIGHT(A6)
MOVE V3(A6),TEMPRECT+BOTTOM(A6)
BSR.S DORECT ;PAINT RIGHT EDGE
MOVE H2(A6),TEMPRECT+LEFT(A6)
MOVE V3(A6),TEMPRECT+TOP(A6)
MOVE V4(A6),TEMPRECT+BOTTOM(A6)
BSR.S DORECT ;PAINT BOTTOM EDGE
MOVE H1(A6),TEMPRECT+LEFT(A6)
MOVE H2(A6),TEMPRECT+RIGHT(A6)
MOVE V2(A6),TEMPRECT+TOP(A6)
@1 BRA.S FILLED ;PAINT LEFT EDGE
;--------------------------------------------------------
;
; LOCAL ROUTINE TO PAINT TEMPRECT, GIVEN IN LOCAL COORDS
;
DORECT MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO LISAGRAF GLOBALS
MOVE.L THEPORT(A0),A1 ;POINT TO CURRENT GRAFPORT
PEA PORTBITS(A1) ;PUSH SRCBITS = DSTBITS
MOVE.L (SP),-(SP) ;PUSH DSTBITS
PEA TEMPRECT(A6) ;PUSH SRCRECT = DSTRECT
MOVE.L (SP),-(SP) ;PUSH DSTRECT, LOCAL COORDS
MOVE PNMODE(A1),-(SP) ;PUSH PEN MODE
PEA PNPAT(A1) ;PUSH ADDR OF PEN PATTERN
MOVE.L CLIPRGN(A1),-(SP) ;PUSH CLIPRGN
MOVE.L VISRGN(A1),-(SP) ;PUSH VISRGN
MOVE.L WIDEOPEN(A0),-(SP) ;PUSH WIDE OPEN
JSR RGNBLT ;CALL RGNBLT
RTS
FILLED BSR DORECT ;FILL TEMPRECT SOLID
GOHOME UNLINK 4,'FRRECT '
.PROC SetRect,5
;----------------------------------------------------------
;
; PROCEDURE SetRect(VAR r: Rect; left,top,right,bottom: INTEGER);
; { assign 4 integers into a rectangle }
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L (SP)+,D1 ;POP BOTRIGHT POINT
MOVE.L (SP)+,D0 ;POP TOPLEFT POINT
MOVE.L (SP)+,A1 ;POP ADDR OF RECT
MOVE.L D0,(A1)+ ;INSTALL TOPLEFT
MOVE.L D1,(A1)+ ;INSTALL BOTRIGHT
JMP (A0) ;RETURN
.FUNC EqualRect,2
;----------------------------------------------------------
;
; FUNCTION EqualRect(rect1,rect2: Rect): BOOLEAN;
;
; CLOBBERS D0,A0,A1.
;
MOVE.L (SP)+,D0 ;POP RETURN ADDR
MOVE.L (SP)+,A1 ;POP ADDR OF RECT2
MOVE.L (SP)+,A0 ;POP ADDR OF RECT1
CMPM.L (A0)+,(A1)+ ;IS TOPLEFT SAME ?
BNE.S FALSE ;NO, RETURN FALSE
CMPM.L (A0)+,(A1)+ ;YES, IS BOTRIGHT SAME TOO ?
BNE.S FALSE ;NO, RETURN FALSE
MOVE.B #1,(SP) ;YES, RETURN TRUE
BRA.S DONE ;AND QUIT
FALSE CLR.B (SP) ;RETURN FALSE
DONE MOVE.L D0,-(SP) ;PUSH RETURN ADDR
RTS ;AND RETURN
.FUNC EmptyRect,1
;----------------------------------------------------------
;
; FUNCTION EmptyRect(r: Rect): BOOLEAN;
;
; CLOBBERS D0,D1,A0,A1.
;
MOVE.L (SP)+,A1 ;POP RETURN ADDR
MOVE.L (SP)+,A0 ;POP ADDR OF RECT
MOVE (A0)+,D0 ;GET TOP
MOVE (A0)+,D1 ;GET LEFT
CMP (A0)+,D0 ;IS TOP >= BOTTOM ?
BGE.S EMPTY ;YES, RETURN TRUE
CMP (A0)+,D1 ;IS LEFT >= RIGHT ?
BGE.S EMPTY ;YES, RETURN TRUE
CLR.B (SP) ;NOT EMPTY, RETURN FALSE
BRA.S DONE ;AND QUIT
EMPTY MOVE.B #1,(SP) ;RETURN TRUE
DONE JMP (A1) ;RETURN
.PROC OffsetRect,3
;----------------------------------------------------------
;
; PROCEDURE OffsetRect(VAR r: Rect; dh,dv: INTEGER);
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE (SP)+,D1 ;POP DV
MOVE (SP)+,D0 ;POP DH
MOVE.L (SP)+,A1 ;POP ADDR OF RECT
ADD D1,(A1)+ ;TOP:=TOP+DV
ADD D0,(A1)+ ;LEFT:=LEFT+DH
ADD D1,(A1)+ ;BOTTOM:=BOTTOM+DV
ADD D0,(A1)+ ;RIGHT:=RIGHT+DH
JMP (A0) ;RETURN
.PROC InsetRect,3
;----------------------------------------------------------
;
; PROCEDURE InsetRect(VAR r: Rect; dh,dv: INTEGER);
; { inset a rectangle on all 4 sides }
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE (SP)+,D1 ;POP DV
MOVE (SP)+,D0 ;POP DH
MOVE.L (SP)+,A1 ;POP ADDR OF RECT
ADD D1,(A1)+ ;ADD DV TO TOP
ADD D0,(A1)+ ;ADD DH TO LEFT
SUB D1,(A1)+ ;SUBTRACT DV FROM BOTTOM
SUB D0,(A1)+ ;SUBTRACT DH FROM RIGHT
DONE JMP (A0) ;RETURN
.FUNC SectRect,3
.DEF RSect
;---------------------------------------------------------
;
; FUNCTION SectRect(srcA,srcB: Rect; VAR dstC: Rect): BOOLEAN;
;
; Returns TRUE and intersection in dst,
; else FALSE and dst = 0,0,0,0.
; Dst may also be used as one of the inputs
;
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 12 ;SIZE OF PARAMETERS
RESULT .EQU PARAMSIZE+8 ;BOOLEAN RESULT
SRCA .EQU RESULT-4 ;LONG, ADDR OF RECTANGLE
SRCB .EQU SRCA-4 ;LONG, ADDR OF RECTANGLE
DST .EQU SRCB-4 ;LONG, ADDR OF RECTANGLE
LINK A6,#0 ;NO LOCAL VARS
MOVE.L SRCA(A6),-(SP) ;PUSH SRCA POINTER
MOVE.L SRCB(A6),-(SP) ;PUSH SRCB POINTER
MOVE #2,-(SP) ;PUSH NRECTS=2
MOVE.L DST(A6),-(SP) ;PUSH DST POINTER
BSR.S RSECT ;CALC INTERSECTION
SNE RESULT(A6) ;STORE BOOLEAN RESULT
NEG.B RESULT(A6) ;CONVERT $FF TO $01
NOTEMPTY UNLINK PARAMSIZE,'SECTRECT'
;---------------------------------------------------
;
; ASSEMBLY CALLABLE ROUTINE TO COMPUTE THE INTERSECTION OF
; ANY NUMBER OF RECTANGLES.
;
; INPUTS: PUSH ADDRESSES OF EACH INPUT RECTANGLE (LONGS)
; PUSH # OF RECTANGLES (WORD)
; PUSH ADDRESS OF OUTPUT RECTANGLE (LONG)
;
; RETURNS DST=(0,0,0,0) AND Z-FLAG SET IF NO INTERSECTION
;
; CLOBBERS: D0,A0
;
RSECT LINK A6,#0
MOVEM.L D1-D4/A1,-(SP) ;SAVE REGS
LEA 12(A6),A1 ;POINT TO NRECTS
MOVE (A1)+,D0 ;GET NRECTS COUNT
BLE.S EMPTY ;EMPTY IF NRECTS <= 0
MOVE.L (A1)+,A0 ;POINT TO FIRST RECT
MOVEM.W (A0)+,D1/D2/D3/D4 ;GET TOP, LEFT, BOT, RIGHT
SUB #1,D0 ;DECREMENT RECT COUNT
BRA.S RTOK ;CHECK THIS RECT AND LOOP
NEXTRECT MOVE.L (A1)+,A0 ;POINT TO NEXT RECT
CMP (A0)+,D1 ;IS TOP < NEXT TOP ?
BGE.S TOPOK ;NO, CONTINUE
MOVE -2(A0),D1 ;YES, TOP:=NEXT TOP
TOPOK CMP (A0)+,D2 ;IS LEFT < NEXT LEFT ?
BGE.S LEFTOK ;NO, CONTINUE
MOVE -2(A0),D2 ;YES, LEFT:=NEXT LEFT
LEFTOK CMP (A0)+,D3 ;IS BOTTOM > NEXT BOT ?
BLE.S BOTOK ;NO, CONTINUE
MOVE -2(A0),D3 ;YES, BOTTOM:=NEXT BOT
BOTOK CMP (A0)+,D4 ;IS RIGHT > NEXT RIGHT ?
BLE.S RTOK ;NO, CONTINUE
MOVE -2(A0),D4 ;YES, RIGHT:=NEXT RIGHT
RTOK CMP D1,D3 ;IS BOTTOM <= TOP ?
BLE.S EMPTY ;YES, EMPTY
CMP D2,D4 ;IS RIGHT <= LEFT ?
BLE.S EMPTY ;YES, EMPTY
DBRA D0,NEXTRECT ;LOOP FOR ALL RECTANGLES
BRA.S DONE
EMPTY CLR D1 ;ALL EMPTY RECTS ARE (0,0,0,0)
CLR D2
CLR D3
CLR D4
DONE MOVE.L 8(A6),A0 ;GET DST ADDR
MOVE D1,(A0)+ ;STORE DST TOP
MOVE D2,(A0)+ ;DST LEFT
MOVE D3,(A0)+ ;DST BOT
MOVE D4,(A0)+ ;DST RIGHT
MOVE 12(A6),D0 ;GET NRECTS COUNT AGAIN
LSL #2,D0 ;TIMES 4 BYTES PER RECTANGLE
ADD #6,D0 ;PLUS 6 BYTES FOR NRECTS AND DSTPTR
CMP D1,D3 ;SET Z-FLAG IF EMPTY RECT
MOVEM.L (SP)+,D1-D4/A1 ;RESTORE REGS
UNLK A6 ;RELEASE STATIC FRAME PTR
MOVE.L (SP)+,A0 ;POP RETURN ADDR
ADD D0,SP ;STRIP VARIABLE NUMBER OF PARAMS
JMP (A0) ;RETURN WITH Z-FLAG IF EMPTY
.PROC UnionRect,3
.DEF Pt2Rect
;----------------------------------------------------------
;
; PROCEDURE UnionRect(* src1,src2: Rect; VAR dst: Rect *);
;
; { compute smallest rectangle containing both input rectangles }
; { works correctly even if one of the sources is the destination }
;
MOVE.L 12(SP),A0 ;GET ADDR OF SRC1
MOVE.L 8(SP),A1 ;GET ADDR OF SRC2
MOVE (A0)+,D0 ;TOP:=TOP1
CMP (A1)+,D0 ;IS TOP2 < TOP ?
BLE.S TOPOK ;NO, CONTINUE
MOVE -2(A1),D0 ;YES, TOP:=TOP2
TOPOK SWAP D0 ;PUT TOP IN HI WORD
MOVE (A0)+,D0 ;LEFT:=LEFT1
CMP (A1)+,D0 ;IS LEFT2 < LEFT ?
BLE.S LEFTOK ;NO, CONTINUE
MOVE -2(A1),D0 ;YES, LEFT:=LEFT2
LEFTOK MOVE (A0)+,D1 ;BOTTOM:=BOTTOM1
CMP (A1)+,D1 ;IS BOTTOM2 > BOTTOM ?
BGE.S BOTOK ;NO, CONTINUE
MOVE -2(A1),D1 ;YES, BOTTOM:=BOTTOM2
BOTOK SWAP D1 ;PUT BOTTOM IN HI WORD
MOVE (A0)+,D1 ;RIGHT:=RIGHT1
CMP (A1)+,D1 ;IS RIGHT2 > RIGHT1 ?
BGE.S RIGHTOK ;NO, CONTINUE
MOVE -2(A1),D1 ;YES, RIGHT:=RIGHT2
RIGHTOK MOVE.L 4(SP),A0 ;POINT TO DST RECT
MOVE.L D0,(A0)+ ;INSTALL TOPLEFT
MOVE.L D1,(A0)+ ;INSTALL BOTRIGHT
BRA.S SHARE ;STRIP 3 PARAMETERS AND RETURN
;----------------------------------------------------------
;
; PROCEDURE Pt2Rect(* pt1,pt2: Point; VAR dst: Rect *);
;
; { make a rectangle from two points }
;
Pt2Rect MOVE.L 4(SP),A0 ;POINT TO DST RECT
MOVE 14(SP),D0 ;GET H1
MOVE 10(SP),D1 ;GET H2
CMP D0,D1 ;IS H2 < H1 ?
BGE.S HOK ;NO, CONTINUE
EXG D0,D1 ;YES, SWAP THEM
HOK MOVE D0,LEFT(A0) ;INSTALL DST LEFT = MIN(H1,H2)
MOVE D1,RIGHT(A0) ;INSTALL DST RIGHT = MAX(H1,H2)
MOVE 12(SP),D0 ;GET V1
MOVE 8(SP),D1 ;GET V2
CMP D0,D1 ;IS V2 < V1 ?
BGE.S VOK ;NO, CONTINUE
EXG D0,D1 ;YES, SWAP THEM
VOK MOVE D0,TOP(A0) ;INSTALL DST TOP = MIN(V1,V2)
MOVE D1,BOTTOM(A0) ;INSTALL DST BOTTOM = MAX(V1,V2)
SHARE MOVE.L (SP)+,A0 ;POP RETURN ADDR
ADD #12,SP ;STRIP 3 PARAMETERS
JMP (A0) ;AND RETURN
.FUNC PtInRect,2
;------------------------------------------------------------
;
; FUNCTION PtInRect(pt: Point; r: Rect): BOOLEAN;
;
; Returns TRUE if point is within the rectangle.
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 8 ;SIZE OF PARAMETERS
RESULT .EQU PARAMSIZE+8 ;A6 OFFSETS AFTER LINK
PT .EQU RESULT-4 ;POINT, VALUE
R .EQU PT-4 ;LONG, ADDR OF RECTANGLE
LINK A6,#0 ;NO LOCAL VARS
MOVE.L R(A6),A0 ;GET RECT PTR
MOVE PT+H(A6),D0 ;GET HORIZ COORD
MOVE PT+V(A6),D1 ;GET VERT COORD
CLR.B RESULT(A6) ;INIT BOOLEAN TO FALSE
CMP (A0)+,D1 ;IS PT.V < TOP ?
BLT.S FALSE ;YES, QUIT
CMP (A0)+,D0 ;IS PT.H < LEFT ?
BLT.S FALSE ;YES, QUIT
CMP (A0)+,D1 ;IS PT.V >= BOTTOM ?
BGE.S FALSE ;YES, QUIT
CMP (A0)+,D0 ;IS PT.H >= RIGHT ?
BGE.S FALSE ;YES, QUIT
ADDQ.B #1,RESULT(A6) ;RETURN BOOLEAN TRUE
FALSE UNLINK PARAMSIZE,'PTINRECT'
.PROC PutRect,4
.REF SetSize
;----------------------------------------------------------------
;
; PROCEDURE PutRect(r: Rect; bufHandle: Handle; VAR index,size: INTEGER);
;
; Puts the four inversion points of a rectangle
;
; Clobbers D0,A0,A1
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 16 ;TOTAL SIZE OF PARAMETERS
RECT .EQU PARAMSIZE+8-4 ;LONG, ADDR OF RECT
BUFHANDLE .EQU RECT-4 ;LONG, HANDLE
INDEX .EQU BUFHANDLE-4 ;LONG, ADDR OF INTEGER
SIZE .EQU INDEX-4 ;LONG, ADDR OF INTEGER
LINK A6,#0 ;NO LOCAL VARIABLES
;------------------------------------------------------------
;
; IS THERE ROOM FOR FOUR NEW POINTS IN THE POINT BUFFER ?
;
MOVE.L INDEX(A6),A0 ;POINT TO INDEX
MOVE.L SIZE(A6),A1 ;POINT TO SIZE
MOVEQ #16,D0
ADD (A0),D0 ;GET CURRENT INDEX + 16
CMP (A1),D0 ;IS NEW INDEX > SIZE ?
BLE.S SIZEOK ;NO, CONTINUE
;-------------------------------------------------------------
;
; NO, GROW THE POINT BUFFER ENOUGH FOR 256 MORE POINTS
;
ADD #1024,(A1) ;ADD 1024 TO SIZE
MOVEM.L D3/A2,-(SP) ;SAVE REGS
MOVE.L BUFHANDLE(A6),-(SP) ;PUSH HANDLE PARAM
MOVE (A1),-(SP) ;PUSH NEW SIZE
JSR SETSIZE ;MAKE THE BUFFER BIGGER
MOVEM.L (SP)+,D3/A2 ;RESTORE REGS
MOVE.L INDEX(A6),A0 ;POINT TO INDEX AGAIN
;------------------------------------------------------------
;
; NOW INSTALL THE 4 NEW INVERSION POINTS
;
SIZEOK MOVE.L BUFHANDLE(A6),A1 ;GET BUFHANDLE
MOVE.L (A1),A1 ;DE-REFERENCE HANDLE
ADD (A0),A1 ;ADD INDEX FOR POINTER
ADD #16,(A0) ;BUMP INDEX
MOVE.L RECT(A6),A0 ;POINT TO RECTANGLE
MOVE.L TOPLEFT(A0),(A1)+ ;PUT TOPLEFT POINT
MOVE TOP(A0),(A1)+ ;PUT TOP-RIGHT POINT
MOVE RIGHT(A0),(A1)+
MOVE BOTTOM(A0),(A1)+ ;PUT BOTTOM-LEFT POINT
MOVE LEFT(A0),(A1)+
MOVE.L BOTRIGHT(A0),(A1)+ ;PUT BOTRIGHT POINT
UNLINK PARAMSIZE,'PUTRECT '
.END

1170
Regions.a Executable file

File diff suppressed because it is too large Load Diff

825
RgnBlt.a Executable file
View File

@ -0,0 +1,825 @@
.INCLUDE GRAFTYPES.TEXT
;------------------------------------------------------------------
;
; --> RGNBLT.TEXT
;
; Low level block transfer clipped to an arbitrary region.
;
.PROC RgnBlt,9
.REF BitBlt,RSect,ShieldCursor,ShowCursor
.REF SeekRgn,PatExpand,ColorMap,InitRgn,TrimRect
;--------------------------------------------------------------
;
; PROCEDURE RgnBlt(srcBits,dstBits: BitMap;
; srcRect,dstRect: Rect;
; mode: INTEGER; pat: Pattern;
; rgnA,rgnB,rgnC: RgnHandle);
;
; TRANSFERS A RECTANGULAR BLOCK OF BITS CLIPPED TO THE DESTINATION
; BITMAP'S BOUNDS AND TO THE INTERSECTION OF THREE REGIONS.
; MODE SPECIFIES THE TRANSFER MODE AND WHETHER THE SOURCE SHOULD COME
; FROM THE SOURCE BITMAP OR FROM A REPEATING PATTERN.
;
; COPYRIGHT APPLE COMPUTER INC.
; DESIGNED AND WRITTEN BY BILL ATKINSON
;
; THIS CODE IS POSITION INDEPENDENT, RE-ENTRANT, AND READ-ONLY.
; CLOBBERS ONLY A0.
;
; MODES: 0 SRC --> DST
; 1 SRC OR DST --> DST
; 2 SRC XOR DST --> DST
; 3 SRC BIC DST --> DST
;
; 4 (NOT SRC) --> DST
; 5 (NOT SRC) OR DST --> DST
; 6 (NOT SRC) XOR DST --> DST
; 7 (NOT SRC) BIC DST --> DST
;
; 8 PATTERN --> DST
; 9 PATTERN OR DST --> DST
; 10 PATTERN XOR DST --> DST
; 11 PATTERN BIC DST --> DST
;
; 12 (NOT PATTERN) --> DST
; 13 (NOT PATTERN) OR DST --> DST
; 14 (NOT PATTERN) XOR DST --> DST
; 15 (NOT PATTERN) BIC DST --> DST
;
;
;----------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 34 ;SIZE OF PARAMETERS
SRCBITS .EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
DSTBITS .EQU SRCBITS-4 ;LONG, ADDR OF BITMAP
SRCRECT .EQU DSTBITS-4 ;LONG, ADDR OF RECT
DSTRECT .EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE .EQU DSTRECT-2 ;WORD
PAT .EQU MODE-4 ;LONG, ADDR OF PATTERN
RGNA .EQU PAT-4 ;LONG, RGNHANDLE
RGNB .EQU RGNA-4 ;LONG, RGNHANDLE
RGNC .EQU RGNB-4 ;LONG, RGNHANDLE
;-------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
EXPAT .EQU -64 ;16 LONGS
MINRECT .EQU EXPAT-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
SRCADDR .EQU BUFSIZE-4 ;LONG
DSTADDR .EQU SRCADDR-4 ;LONG
SRCROW .EQU DSTADDR-4 ;LONG
DSTROW .EQU SRCROW-4 ;LONG
VERT .EQU DSTROW-2 ;WORD
MODECASE .EQU VERT-4 ;LONG
SAVEA5 .EQU MODECASE-4 ;LONG
FIRSTV .EQU SAVEA5-2 ;WORD
LASTV .EQU FIRSTV-2 ;WORD
VBUMP .EQU LASTV-2 ;WORD, MUST BE ABOVE HBUMP
HBUMP .EQU VBUMP-2 ;WORD
SRCRECT2 .EQU HBUMP-8 ;RECT
MASKADDR .EQU SRCRECT2-4 ;LONG
VARSIZE .EQU MASKADDR ;SIZE OF LOCAL VARIABLES
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARIABLES
MOVEM.L D3-D7/A2-A5,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER
MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR
;----------------------------------------------------------------
;
; ADJUST MODE AND PATTERN IF COLOR FILTERING.
;
MOVE MODE(A6),-(SP) ;YES, PUSH INPUT MODE
MOVE.L PAT(A6),-(SP) ;PUSH ADDR OF INPUT PATTERN
JSR COLORMAP ;ALTER BY THECOLOR, THEFILTER
MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN
MOVE (SP)+,MODE(A6) ;GET (ALTERED) MODE
;------------------------------------------------------
;
; GET THREE REGION HANDLES AND DE-REFERENCE THEM.
;
MOVE.L RGNA(A6),A1 ;GET RGNHANDLE
MOVE.L (A1),A1 ;DE-REFERENCE IT
MOVE.L RGNB(A6),A2 ;GET RGNHANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE.L RGNC(A6),A3 ;GET RGNHANDLE
MOVE.L (A3),A3 ;DE-REFERENCE IT
;-------------------------------------------------------------------
;
; CALC MINRECT, THE INTERSECTION OF DSTRECT, DSTBITS.BOUNDS,
; AND 3 REGION BOUNDING BOXES. QUIT IF THE INTERSECTION IS EMPTY.
;
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE.L DSTBITS(A6),A4 ;A4 POINTS TO DSTBITS
PEA BOUNDS(A4) ;PUSH DSTBITS.BOUNDS
PEA RGNBBOX(A1) ;PUSH RGNA BBOX
PEA RGNBBOX(A2) ;PUSH RGNB BBOX
PEA RGNBBOX(A3) ;PUSH RGNC BBOX
MOVE #5,-(SP) ;PUSH NRECTS=5
PEA MINRECT(A6) ;PUSH WHERE TO PUT RESULT
JSR RSECT ;CALC INTERSECTION
BEQ GOHOME ;QUIT IF EMPTY
;----------------------------------------------------
;
; HIDE THE CURSOR IF IT INTERSECTS MINRECT
;
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L BOUNDS+TOPLEFT(A4),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
JSR SHIELDCURSOR ;REMOVE CURSOR IF INTERSECT
;----------------------------------------------------
;
; ARE ALL THREE REGIONS RECTANGULAR ?
;
CMP #10,RGNSIZE(A1) ;IS RGNA RECTANGULAR ?
BNE.S NOTRECT ;NO, CONTINUE
CMP #10,RGNSIZE(A3) ;IS RGN3 RECTANGULAR ?
BNE.S NOTRECT ;NO, CONTINUE
CMP #10,RGNSIZE(A2) ;IS RGN2 RECTANGULAR ?
BEQ.S OKRECT ;NO, CONTINUE
;
; If only rgnB (visRgn) is non-rectangular, then check if
; its intersection with minrect would be rectangular.
; IF TrimRect(rgnB,minRect) then take the fast way.
;
MOVE.L RGNB(A6),-(SP) ;push rgnHandle
PEA minRect(A6) ;push addr of minRect
JSR TrimRect ;call trimRect
BLT DONE ;quit if intersection empty
BGT.S NOTRECT ;continue if non-rectangular
;--------------------------------------------------------------
;
; SINCE ALL THREE REGIONS ARE RECTANGULAR, WE WILL USE BITBLT.
; FIRST CLIP SRCRECT TO MATCH MINRECT. (COPY SRCRECT SINCE IT'S NOT VAR)
;
OKRECT MOVE.L SRCRECT(A6),A2 ;POINT TO SRC RECT
LEA SRCRECT2(A6),A0 ;POINT TO LOCAL COPY OF SRCRECT
MOVE.L DSTRECT(A6),A3 ;POINT TO DSTRECT
MOVE MINRECT+TOP(A6),D0 ;GET MINRECT TOP
SUB TOP(A3),D0 ;CONVERT FROM DST COORDS
ADD TOP(A2),D0 ;TO SRC COORDS
MOVE D0,TOP(A0) ;PUT CLIPPED SRC TOP INTO COPY
MOVE MINRECT+LEFT(A6),D0 ;GET MINRECT LEFT
SUB LEFT(A3),D0 ;CONVERT FROM DST COORDS
ADD LEFT(A2),D0 ;TO SRC COORDS
MOVE D0,LEFT(A0) ;PUT CLIPPED SRC LEFT INTO COPY
;----------------------------------------------------
;
; PUSH PARAMETERS AND CALL BITBLT
;
MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS
MOVE.L A4,-(SP) ;PUSH DSTBITS
MOVE.L A0,-(SP) ;PUSH SRCRECT COPY
PEA MINRECT(A6) ;PUSH DST = MINRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L PAT(A6),-(SP) ;PUSH PATTERN
JSR BITBLT ;CALL BITBLT
BRA DONE ;RESTORE CURSOR AND QUIT
;-----------------------------------
;
; CALC BUFLEFT AND BUFSIZE
;
NOTRECT MOVE MINRECT+LEFT(A6),D1 ;GET MINRECT LEFT
SUB BOUNDS+LEFT(A4),D1 ;CONVERT TO GLOBAL COORDS
AND #$FFF0,D1 ;TRUNC TO MULT OF 16
ADD BOUNDS+LEFT(A4),D1 ;CONVERT BACK TO LOCAL
MOVE D1,BUFLEFT(A6) ;SAVE AS BUFLEFT
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
SUB D1,D0 ;CALC WIDTH IN DOTS
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
DBRA D0,CLRMASK ;LOOP TILL DONE
MOVE.L SP,MASKBUF(A6); ;REMEMBER WHERE MASKBUF IS
;-------------------------------------------------------------------
;
; INIT STATE RECORDS VERT0 AND VERT1 IN CASE RECTANGULAR
;
MOVE #32767,D0
MOVE D0,STATEA+NEXTV(A6)
MOVE D0,STATEB+NEXTV(A6)
MOVE D0,STATEC+NEXTV(A6)
NEG D0
MOVE D0,STATEA+THISV(A6)
MOVE D0,STATEB+THISV(A6)
MOVE D0,STATEC+THISV(A6)
;----------------------------------------------------------------------
;
; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION
;
CLR D5 ;INIT ALL RGNS RECT
MOVE.L RGNA(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP #10,RGNSIZE(A0) ;IS RGNA RECTANGULAR ?
BEQ.S ARECT ;YES, SKIP IT
ADD #2,D5 ;NO, SET UP FLAG
LEA STATEA(A6),A1 ;POINT TO STATE RECORD A
BSR.S INITONE ;INIT STATE, ALLOC BUFFER
ARECT
MOVE.L RGNB(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP #10,RGNSIZE(A0) ;IS RGNB RECTANGULAR ?
BEQ.S BRECT ;YES, SKIP IT
ADD #4,D5 ;NO, BUMP FLAG
LEA STATEB(A6),A1 ;POINT TO STATE RECORD B
BSR.S INITONE ;INIT STATE, ALLOC BUFFER
BRECT
MOVE.L RGNC(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP #10,RGNSIZE(A0) ;IS RGNC RECTANGULAR ?
BEQ.S CRECT ;YES, SKIP IT
ADD #8,D5 ;NO, BUMP FLAG
LEA STATEC(A6),A1 ;POINT TO STATE RECORD C
PEA CRECT ;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
CRECT
;---------------------------------------------------------------------
;
; IF ONLY ONE REGION IS NON-RECTANGULAR, PLAY IT BACK DIRECTLY
; INTO THE MASK BUFFER.
;
MOVE.L MASKBUF(A6),D7
MOVE D5,RECTFLAG(A6)
CMP #2,D5 ;IS RGNA THE ONLY NON-RECT ?
BNE.S AOK ;NO, CONTINUE
MOVE.L D7,STATEA+SCANBUF(A6) ;YES, PLAY DIRECTLY INTO MASK
BRA.S COK
AOK CMP #4,D5 ;IS RGNB THE ONLY NON-RECT ?
BNE.S BOK
MOVE.L D7,STATEB+SCANBUF(A6)
BRA.S COK
BOK CMP #8,D5 ;IS RGNC THE ONLY NON-RECT ?
BNE.S COK
MOVE.L D7,STATEC+SCANBUF(A6)
COK
;----------------------------------------------------------
;
; ASSUME WE WILL BE DRAWING DOWNWARD AND TO RIGHT.
;
MOVE MINRECT+TOP(A6),FIRSTV(A6) ;FIRSTV:=MINRECT TOP
MOVE MINRECT+BOTTOM(A6),LASTV(A6) ;LASTV:=MINRECT BOTTOM
MOVE.L #$00040001,HBUMP(A6) ;HBUMP:=4 BYTES, VBUMP:=1 SCAN
MOVE ROWBYTES(A4),D0
EXT.L D0
MOVE.L D0,DSTROW(A6) ;DSTROW:=+ROWBYTES
MOVE.L D7,MASKADDR(A6) ;MASKADDR:=MASKBUF
;---------------------------------------
;
; SET UP INVERT FLAG IN D7 TO REFLECT MODE BIT 2
;
CLR.L D7 ;SAY NOT INVERTED
MOVE MODE(A6),D2 ;GET TRANSFER MODE
BMI DONE ;QUIT IF MODE NEGATIVE
BCLR #2,D2 ;TEST AND CLR INVERT BIT
BEQ.S SETMODE ;SKIP IF NOT INVERTED
NOT.L D7 ;INVERTED; D7 GETS ALL 1'S
;--------------------------------------------------
;
; CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES
;
SETMODE AND #$F,D2 ;TREAT MODE MOD 16
MOVEQ #3,D0
AND D2,D0 ;GET BOTTOM 2 BITS OF MODE
ADD D0,D2 ;MODIFY MODE FOR INDEX
LEA MODETAB,A0 ;POINT TO MODE TABLE
ADD 0(A0,D2),A0 ;GET CASE JUMP ADDRESS
MOVE.L A0,MODECASE(A6) ;SAVE FOR LATER
BTST #3,D2 ;WILL PATTERN BE USED ?
BEQ.S USESRC ;NO, USE SOURCE INSTEAD
;------------------------------------------------------------------
;
; PATTERN WILL BE USED. EXPAND 8 BYTE PATTERN TO 16 LONGS
;
MOVE BOUNDS+LEFT(A4),D2 ;GET GLOBAL-LOCAL OFFSET
MOVE.L PAT(A6),A0 ;POINT TO BYTE WIDE PATTERN
LEA EXPAT(A6),A1 ;POINT TO EXPANDED PATTERN
JSR PATEXPAND ;EXPAND 8 BYTES TO 16 LONGS
;-------------------------------------------------
;
; SET UP (VERT * 4) MOD 64 AS PATTERN SELECTOR
;
MOVEQ #$F,D7 ;TREAT COORD MOD 16
AND MINRECT+TOP(A6),D7 ;GET TOP VERT COORD
LSL #2,D7 ;QUAD FOR 4 BYTE PATTERNS
MOVE.L EXPAT(A6,D7),D6 ;GET FIRST PATTERN DATA
BRA GETDST ;SKIP OVER SRC STUFF
;--------------------------------------------------------------
;
; SRC WILL BE USED. CHECK FOR OVERLAP AND CHOOSE DIRECTION SO
; THAT SRC WONT GET CLOBBERED BEFORE IT IS USED.
;
USESRC MOVE.L DSTRECT(A6),A1 ;POINT TO DSTRECT
MOVE.L SRCRECT(A6),A2 ;POINT TO SRCRECT
MOVE.L SRCBITS(A6),A3 ;POINT TO SRCBITS
MOVE ROWBYTES(A3),D0
EXT.L D0
MOVE.L D0,SRCROW(A6) ;SRCROW:=+ROWBYTES
MOVE.L BASEADDR(A3),D0 ;GET SRC BASEADDR
CMP.L BASEADDR(A4),D0 ;ARE SRC AND DST SAME BITMAP ?
BNE.S SRCOK ;NO, DON'T WORRY ABOUT OVERLAP
MOVE TOP(A1),D0 ;GET DST TOP
SUB BOUNDS+TOP(A4),D0 ;CONVERT TO GLOBAL
MOVE TOP(A2),D1 ;GET SRC TOP
SUB BOUNDS+TOP(A3),D1 ;CONVERT TO GLOBAL
SUB D1,D0 ;CALC DV:=DSTTOP-SRCTOP
BLT.S SRCOK ;EVERYTHING FINE IF SCROLLING UP
BGT.S UPSIDE ;UPSIDE DOWN IF SCROLLING DOWN
;------------------------------------------------------------
;
; DV=0. IF DH > 0 THEN WE MUST TRANSFER BACKWARDS FROM RIGHT.
;
MOVE LEFT(A1),D0 ;GET DST LEFT
SUB BOUNDS+LEFT(A4),D0 ;CONVERT TO GLOBAL
MOVE LEFT(A2),D1 ;GET SRC LEFT
SUB BOUNDS+LEFT(A3),D1 ;CONVERT TO GLOBAL
SUB D1,D0 ;DH := DSTLEFT-SRCLEFT
BLE.S SRCOK ;IF DH <= 0, WE'RE FINE
NEG HBUMP(A6) ;ELSE BUMP TOWARD LEFT
BRA.S SRCOK ;CONTINUE
;------------------------------------------------------------
;
; DV IS POSITIVE, WE MUST TRANSFER UPSIDE-DOWN FROM BOTTOM.
;
UPSIDE NEG VBUMP(A6) ;VBUMP:=-1, BUMP UPWARD
NEG.L SRCROW(A6) ;SRCROW:=-SRC ROWBYTES
NEG.L DSTROW(A6) ;DSTROW:=-DST ROWBYTES
MOVE MINRECT+BOTTOM(A6),FIRSTV(A6)
SUB #1,FIRSTV(A6) ;FIRSTV:=BOTTOM-1
MOVE MINRECT+TOP(A6),LASTV(A6)
SUB #1,LASTV(A6) ;LASTV:=TOP-1
;----------------------------------------------
;
; CALC SHIFTCNT
;
SRCOK MOVE LEFT(A1),D6 ;GET DST LEFT LOCAL COORDS
SUB BOUNDS+LEFT(A4),D6 ;CONVERT TO GLOBAL
MOVE LEFT(A2),D1 ;GET SRC LEFT LOCAL COORDS
SUB BOUNDS+LEFT(A3),D1 ;CONVERT TO GLOBAL
SUB D1,D6 ;CALC DELTA HORIZ GLOBAL
AND #$F,D6 ;MOD 16 FOR SHIFTCNT
;------------------------------------
;
; CALC STARTING SRCADDR
;
MOVE FIRSTV(A6),D0 ;GET FIRST DST VERTICAL
SUB TOP(A1),D0 ;SUBTRACT DSTRECT TOP
ADD TOP(A2),D0 ;ADD SRCRECT TOP
SUB BOUNDS+TOP(A3),D0 ;CONVERT SRCV TO GLOBAL
MULU ROWBYTES(A3),D0 ;MULT BY SRC ROWBYTES
MOVE.L BASEADDR(A3),A0 ;GET START OF BITMAP
ADD.L D0,A0 ;ADD OFFSET TO BASEADDR
MOVE MINRECT+LEFT(A6),D0 ;GET DST LEFT
SUB LEFT(A1),D0 ;CONVERT FROM DST COORDS
ADD LEFT(A2),D0 ;TO SRC COORDS
SUB BOUNDS+LEFT(A3),D0 ;CONVERT TO GLOBAL SRC
ADD D6,D0 ;ADD SHIFTCNT
LSR #4,D0 ;CONVERT DOTS TO WORDS
ADD D0,D0 ;DOUBLE FOR BYTES
ADD D0,A0 ;ADD HORIZ OFFSET
MOVE.L A0,SRCADDR(A6) ;SAVE AS SRCADDR
;------------------------------------
;
; CALC STARTING DSTADDR
;
GETDST MOVE FIRSTV(A6),D0 ;GET FIRST DST VERT
SUB BOUNDS+TOP(A4),D0 ;CONVERT TO GLOBAL
MULU ROWBYTES(A4),D0 ;MULT BY ROWBYTES
MOVE.L BASEADDR(A4),A0 ;GET START OF BITMAP
ADD.L D0,A0 ;ADD VERTICAL OFFSET
MOVE MINRECT+LEFT(A6),D0 ;GET DST LEFT
SUB BOUNDS+LEFT(A4),D0 ;CONVERT TO GLOBAL
LSR #4,D0 ;CONVERT DOTS TO WORDS
ADD D0,D0 ;DOUBLE FOR BYTES
ADD D0,A0 ;ADD HORIZ OFFSET
MOVE.L A0,DSTADDR(A6) ;SAVE AS DSTADDR
;------------------------------------------------------------------------
;
; ADJUST SRCADDR,DSTADDR,MASKADDR IF WE ARE BUMPING BACKWARDS FROM RIGHT
;
TST HBUMP(A6) ;BUMPING BACKWARD ?
BPL.S HBUMPOK ;NO, CONTINUE
MOVE BUFSIZE(A6),D0 ;GET BUFFER SIZE
ASL #2,D0 ;QUAD FOR # BYTES
EXT.L D0 ;CLEAR HI WORD
ADD.L D0,DSTADDR(A6) ;ADJUST DSTADDR
ADD.L D0,SRCADDR(A6) ;ADJUST SRCADDR
ADD.L D0,MASKADDR(A6) ;ADJUST MASKADDR
HBUMPOK
MOVE FIRSTV(A6),VERT(A6) ;INIT CURRENT VERTICAL
;-------------------------------------------------------
;
; MAKE MASK BUFFER CURRENT FOR THIS VERTICAL.
; THEN SET UP AND DRAW CURRENT SCANLINE.
;
NXTMASK JSR SEEKMASK ;MAKE MASK BUFFER CURRENT
MOVE.L SRCADDR(A6),A3 ;INIT SRCPTR
MOVE.L DSTADDR(A6),A5 ;INIT DSTPTR FOR ROW
MOVE.L MASKADDR(A6),A4 ;INIT MASKPTR FOR ROW
MOVE BUFSIZE(A6),D2 ;INIT COUNT OF LONGS
MOVE.L MODECASE(A6),A2 ;GET MODE CASE JUMP
JMP (A2) ;TAKE MODE JUMP
NEXTSRC MOVE.L SRCROW(A6),D0 ;GET SRC ROWBYTES
ADD.L D0,SRCADDR(A6) ;BUMP SRC TO NEXT ROW
BRA.S BUMPV ;CONTINUE WITH NEXT ROW
NEXTPAT ADD #4,D7 ;BUMP PATTERN SELECTOR
AND #$3F,D7 ;MOD 64 FOR 16 LONG REPEAT
MOVE.L EXPAT(A6,D7),D6 ;GET PATTERN FOR NEXT ROW
;-----------------------------------------------------
;
; BUMP DESTINATION VERTICALLY AND LOOP FOR ALL ROWS
;
BUMPV MOVE.L DSTROW(A6),D0 ;GET DST ROWBYTES
ADD.L D0,DSTADDR(A6) ;BUMP DST TO NEXT ROW
NODRAW MOVE VERT(A6),D0 ;GET CURRENT VERT
ADD VBUMP(A6),D0 ;BUMP UP OR DOWN A SCAN LINE
MOVE D0,VERT(A6) ;UPDATE CURRENT VERT
CMP LASTV(A6),D0 ;ARE WE AT THE LAST SCAN LINE ?
BNE NXTMASK ;NO, LOOP FOR ALL SCAN LINES
;-----------------------------------------------------------------
;
; ENTIRE RGNBLT COMPLETE. RESTORE REGS AND STACK AND GO HOME.
;
DONE MOVE.L SAVEA5(A6),A5 ;GET GLOBAL POINTER
JSR SHOWCURSOR ;RESTORE CURSOR
GOHOME MOVE.L SAVESTK(A6),SP ;STRIP VARIABLE SIZED BUFFER
MOVEM.L (SP)+,D3-D7/A2-A5 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'RGNBLT '
;-----------------------------------------------------------------
;
; LOCAL ROUTINE TO UPDATE MASK BUFFER TO CURRENT VERTICAL COORD.
;
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 .WORD SEEKOK-RECTJMP
.WORD A-RECTJMP
.WORD B-RECTJMP
.WORD AB-RECTJMP
.WORD C-RECTJMP
.WORD AC-RECTJMP
.WORD BC-RECTJMP
.WORD ABC-RECTJMP
;--------------------------------------------------------------------
;
; ONLY REGION A IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
;
A LEA STATEA(A6),A1
BRA.S JMPSEEK
;--------------------------------------------------------------------
;
; ONLY REGION B IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
;
B LEA STATEB(A6),A1
BRA.S JMPSEEK
;--------------------------------------------------------------------
;
; ONLY REGION C IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
;
C LEA STATEC(A6),A1
JMPSEEK MOVE.L MASKBUF(A6),SCANBUF(A1) ;PLAY DIRECTLY INTO MASKBUF
JMP SEEKRGN
;-------------------------------------------------------------------
;
; REGIONS A AND B ARE NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
AB LEA STATEA(A6),A1
JSR SEEKRGN
MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED
LEA STATEB(A6),A1
JSR SEEKRGN
OR (SP)+,D1 ;HAS EITHER RGN CHANGED ?
BEQ.S SEEKOK ;NO, WE'RE DONE
MOVE.L STATEA+SCANBUF(A6),A0
MOVE.L STATEB+SCANBUF(A6),A1
BRA.S CPY2BUF
;-------------------------------------------------------------------
;
; REGIONS A AND C ARE NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
AC LEA STATEA(A6),A1
JSR SEEKRGN
MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED
LEA STATEC(A6),A1
JSR SEEKRGN
OR (SP)+,D1 ;HAS EITHER RGN CHANGED ?
BEQ.S SEEKOK ;NO, WE'RE DONE
MOVE.L STATEA+SCANBUF(A6),A0
MOVE.L STATEC+SCANBUF(A6),A1
BRA.S CPY2BUF
;-------------------------------------------------------------------
;
; REGIONS B AND C ARE NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
BC LEA STATEB(A6),A1
JSR SEEKRGN
MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED
LEA STATEC(A6),A1
JSR SEEKRGN
OR (SP)+,D1 ;HAS EITHER RGN CHANGED ?
BEQ.S SEEKOK ;NO, WE'RE DONE
MOVE.L STATEB+SCANBUF(A6),A0
MOVE.L STATEC+SCANBUF(A6),A1
CPY2BUF MOVE.L MASKBUF(A6),A2
MOVE BUFSIZE(A6),D1
BCLOOP MOVE.L (A0)+,D0
AND.L (A1)+,D0
MOVE.L D0,(A2)+
DBRA D1,BCLOOP
SEEKOK RTS ;ALL 3 ARE RECT, DO NOTHING
;-------------------------------------------------------------------
;
; REGIONS A, B AND C ARE ALL NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
ABC LEA STATEA(A6),A1
JSR SEEKRGN
MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED
LEA STATEB(A6),A1
JSR SEEKRGN
OR D1,(SP) ;REMEMBER IF RGN CHANGED
LEA STATEC(A6),A1
JSR SEEKRGN
OR (SP)+,D1 ;HAS EITHER RGN CHANGED ?
BEQ.S ABCDONE ;NO, WE'RE DONE
MOVE.L STATEA+SCANBUF(A6),A0
MOVE.L STATEB+SCANBUF(A6),A1
MOVE.L STATEC+SCANBUF(A6),A2
MOVE.L MASKBUF(A6),A3
MOVE BUFSIZE(A6),D1
ABCLOOP MOVE.L (A0)+,D0
AND.L (A1)+,D0
AND.L (A2)+,D0
MOVE.L D0,(A3)+
DBRA D1,ABCLOOP
ABCDONE RTS
;---------------------------------------------------------------;
; ;
; INTERFACE TO EACH OF THE RGNBLT SCANLINE LOOPS: ;
; ;
; REGISTERS: A0: D0: ;
; A1: D1: ;
; A2: D2: LONGCNT ;
; A3: SRCPTR D3: ;
; A4: MASKPTR D4: ;
; A5: DSTPTR D5: ;
; A6: D6: SHIFTCNT OR PATTERN ;
; A7: D7: INVERT OR PAT-SEL ;
; ;
;---------------------------------------------------------------;
MODETAB .WORD MASK0-MODETAB
.WORD MASK1-MODETAB
.WORD MASK2-MODETAB
.WORD MASK3-MODETAB
.WORD MASK8-MODETAB
.WORD MASK9-MODETAB
.WORD MASK10-MODETAB
.WORD MASK11-MODETAB
;-------------------------------------------------------
;
; MODE 0 OR 4: SRC --> DST
;
MASK0 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP
LSR.L D6,D0 ;ALIGN TO DST
SWAP D0 ;PUT INTO HI HALF OF D0
MOVE.L (A3),D1 ;GET SRC FROM BITMAP
ADD HBUMP(A6),A3 ;BUMP 4 BYTES RIGHT OR LEFT
LSR.L D6,D1 ;ALIGN TO DST
MOVE D1,D0 ;ASSEMBLE ONE LONG
EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET
MOVE.L (A4),D1 ;GET MASK
ADD HBUMP(A6),A4 ;BUMP 4 BYTES RIGHT OR LEFT
AND.L D1,D0 ;MASK SRC
NOT.L D1 ;FORM NOTMASK
AND.L (A5),D1 ;GET DST DATA
OR.L D1,D0 ;MERGE WITH SRC DATA
MOVE.L D0,(A5) ;PUT RESULT IN DST
ADD HBUMP(A6),A5 ;BUMP 4 BYTES RIGHT OR LEFT
DBRA D2,MASK0 ;LOOP ALL LONGS THIS ROW
BRA NEXTSRC ;GO FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 1 OR 5: SRC OR DST --> DST
;
MASK1 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP
LSR.L D6,D0 ;ALIGN TO DST
SWAP D0 ;PUT INTO HI HALF OF D0
MOVE.L (A3),D1 ;GET SRC FROM BITMAP
ADD HBUMP(A6),A3 ;BUMP 4 BYTES RIGHT OR LEFT
LSR.L D6,D1 ;ALIGN TO DST
MOVE D1,D0 ;ASSEMBLE ONE LONG
EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND.L (A4),D0 ;AND WITH MASK
ADD HBUMP(A6),A4 ;BUMP 4 BYTES RIGHT OR LEFT
OR.L D0,(A5) ;OR RESULT INTO DST
ADD HBUMP(A6),A5 ;BUMP 4 BYTES RIGHT OR LEFT
DBRA D2,MASK1 ;LOOP ALL LONGS THIS ROW
BRA NEXTSRC ;LOOP FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 2 OR 6: SRC XOR DST --> DST
;
MASK2 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP
LSR.L D6,D0 ;ALIGN TO DST
SWAP D0 ;PUT INTO HI HALF OF D0
MOVE.L (A3),D1 ;GET SRC FROM BITMAP
ADD HBUMP(A6),A3 ;BUMP 4 BYTES RIGHT OR LEFT
LSR.L D6,D1 ;ALIGN TO DST
MOVE D1,D0 ;ASSEMBLE ONE LONG
EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND.L (A4),D0 ;AND WITH MASK
ADD HBUMP(A6),A4 ;BUMP 4 BYTES RIGHT OR LEFT
EOR.L D0,(A5) ;XOR RESULT INTO DST
ADD HBUMP(A6),A5 ;BUMP 4 BYTES RIGHT OR LEFT
DBRA D2,MASK2 ;LOOP ALL LONGS THIS ROW
BRA NEXTSRC ;LOOP FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 3 OR 7: SRC BIC DST --> DST
;
MASK3 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP
LSR.L D6,D0 ;ALIGN TO DST
SWAP D0 ;PUT INTO HI HALF OF D0
MOVE.L (A3),D1 ;GET SRC FROM BITMAP
ADD HBUMP(A6),A3 ;BUMP 4 BYTES RIGHT OR LEFT
LSR.L D6,D1 ;ALIGN TO DST
MOVE D1,D0 ;ASSEMBLE ONE LONG
EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND.L (A4),D0 ;AND WITH MASK
ADD HBUMP(A6),A4 ;BUMP 4 BYTES RIGHT OR LEFT
NOT.L D0 ;INVERT FOR BIC
AND.L D0,(A5) ;BIC RESULT INTO DST
ADD HBUMP(A6),A5 ;BUMP 4 BYTES RIGHT OR LEFT
DBRA D2,MASK3 ;LOOP ALL LONGS THIS ROW
BRA NEXTSRC ;LOOP FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 8 OR 12: PATTERN --> DST (FILLING AREAS, DRAWING LINES)
;
MASK8 MOVE.L D6,D0 ;GET PATTERN DATA
MOVE.L (A4)+,D1 ;GET MASK
AND.L D1,D0 ;MASK PATTERN DATA
NOT.L D1 ;MAKE NOTMASK
AND.L (A5),D1 ;GET DST DATA
OR.L D1,D0 ;MERGE WITH PAT DATA
MOVE.L D0,(A5)+ ;PUT RESULT TO DST
DBRA D2,MASK8 ;LOOP ALL LONGS THIS ROW
BRA NEXTPAT ;LOOP BACK FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 9 OR 13: PATTERN OR DST --> DST
;
MASK9 MOVE.L D6,D0 ;GET PATTERN DATA
AND.L (A4)+,D0 ;MASK PATTERN DATA
OR.L D0,(A5)+ ;OR RESULT INTO DST
DBRA D2,MASK9 ;LOOP ALL LONGS THIS ROW
BRA NEXTPAT ;LOOP BACK FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 10 OR 14: PATTERN XOR DST --> DST (INVERTING AREAS, XOR LINES)
;
MASK10 MOVE.L D6,D0 ;GET PATTERN DATA
AND.L (A4)+,D0 ;MASK PATTERN DATA
EOR.L D0,(A5)+ ;XOR RESULT INTO DST
DBRA D2,MASK10 ;LOOP ALL LONGS THIS ROW
BRA NEXTPAT ;LOOP BACK FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 11 OR 15: PATTERN BIC DST --> DST
;
MASK11 MOVE.L D6,D0 ;GET PATTERN DATA
AND.L (A4)+,D0 ;MASK PATTERN DATA
NOT.L D0 ;INVERT FOR BIC
AND.L D0,(A5)+ ;BIC RESULT INTO DST
DBRA D2,MASK11 ;LOOP ALL LONGS THIS ROW
BRA NEXTPAT ;LOOP BACK FOR NEXT ROW
.END

444
RgnOp.a Executable file
View File

@ -0,0 +1,444 @@
.INCLUDE GRAFTYPES.TEXT
.FUNC RgnOp,7
.REF SectScan,DiffScan,UnionScan,XorScan,InsetScan,SetSize
;-------------------------------------------------------------------
;
; FUNCTION RgnOp(rgnA,rgnB: RgnHandle;
; bufHandle: Handle;
; maxBytes: INTEGER;
; op,dh: INTEGER;
; okGrow: BOOLEAN): INTEGER;
;
; Computes the intersection, difference, union, or XOR of two regions,
; or the horizontal inset of one region, and stores the result as an
; unpacked array of sorted inversion points in bufHandle. Returns the
; number of points as the function value. BufHandle will be grown only
; if more space is needed needed and okGrow is true.
;
; OP = 0: SECT
; 2: DIFF A-B
; 4: UNION
; 6: XOR
; 8: HORIZ INSET
;
;
; A6 OFFSETS OF PARAMETERS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 20 ;TOTAL # BYTES
RESULT .EQU PARAMSIZE+8 ;INTEGER, FUNCTION RESULT
RGNA .EQU RESULT-4 ;LONG, RGNHANDLE
RGNB .EQU RGNA-4 ;LONG, RGNHANDLE
BUFHANDLE .EQU RGNB-4 ;LONG, HANDLE TO POINT BUFFER
MAXBYTES .EQU BUFHANDLE-2 ;WORD
OP .EQU MAXBYTES-2 ;WORD
DH .EQU OP-2 ;WORD
OKGROW .EQU DH-2 ;BOOLEAN
SCAN1 .EQU -4 ;long
SCAN2 .EQU SCAN1-4 ;long
SCAN3 .EQU SCAN2-4 ;long
SCAN4 .EQU SCAN3-4 ;long
SCAN5 .EQU SCAN4-4 ;long
NEXTA .EQU SCAN5-2 ;WORD
NEXTB .EQU NEXTA-2 ;WORD
VERT .EQU NEXTB-2 ;WORD
BUFPTR .EQU VERT-4 ;LONG, ^POINT
BUFLIMIT .EQU BUFPTR-4 ;LONG
FAKEB .EQU BUFLIMIT-18 ;18 BYTE FAKE RGN DATA
MASTERB .EQU FAKEB-4 ;LONG
FAKEA .EQU MASTERB-18 ;18 BYTE FAKE RGN DATA
MASTERA .EQU FAKEA-4 ;LONG
CASEJMP .EQU MASTERA-4 ;LONG
SAVESTK .EQU CASEJMP-4 ;LONG
VARSIZE .EQU SAVESTK ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK PTR
;------------------------------------------------------------
;
; DE-REFERENCE RGNA AND RGNB AND OFFSET TO FIRST RGNDATA.
; IF EITHER IS RECTANGULAR, REPLACE IT WITH AN EXPANDED ONE.
;
LEA MASTERA(A6),A2 ;POINT TO FAKE AREA
LEA RGNA(A6),A0 ;POINT TO RGNA HANDLE
BSR EXPAND ;DE-REFERENCE AND EXPAND
MOVE.L A0,A3 ;SAVE RGNA DATA PTR IN A3
LEA RGNB(A6),A0 ;POINT TO RGNB HANDLE
BSR EXPAND ;DE-REFERENCE AND EXPAND
MOVE.L A0,A4 ;SAVE RGNB DATA PTR IN A4
;-----------------------------------------------------------
;
; SET UP A CASE JUMP BASED ON OP
;
LEA SECTSCAN,A0
MOVE OP(A6),D0
BEQ.S CASEOK ;BR IF OP = SECT
LEA DIFFSCAN,A0
SUB #2,D0
BEQ.S CASEOK ;BR IF OP = DIFF
LEA UNIONSCAN,A0
SUB #2,D0
BEQ.S CASEOK ;BR IF OP = UNION
LEA XORSCAN,A0
SUB #2,D0
BEQ.S CASEOK ;BR IF OP = XOR
LEA INSETSCAN,A0 ;ELSE OP = INSET
CASEOK MOVE.L A0,CASEJMP(A6) ;SAVE FOR LATER
;-----------------------------------------------------------------
;
; Calc bufSize based on StackAvail and allocate 5 scan buffers
;
_StackAvail ;get stack avail in D0.L
SUB.L #1024,D0 ;subtract slop factor
CMP.L #200,D0 ;is result < 200 bytes ?
BGE.S STKOK1 ;no, continue
MOVE #40,D0 ;yes, make bufSize = 40 bytes
BRA.S ALLOC ;and continue
STKOK1 DIVS #5,D0 ;no, divide for 5 buffers
BVC.S STKOK2 ;overflow ?
MOVE #30000,D0 ;yes, use 30K bytes
STKOK2 BCLR #0,D0 ;make bufSize even
ALLOC SUB D0,SP ;allocate one buffer
MOVE.L SP,SCAN1(A6) ;remember buffer pointer
SUB D0,SP ;allocate one buffer
MOVE.L SP,SCAN2(A6) ;remember buffer pointer
SUB D0,SP ;allocate one buffer
MOVE.L SP,SCAN3(A6) ;remember buffer pointer
SUB D0,SP ;allocate one buffer
MOVE.L SP,SCAN4(A6) ;remember buffer pointer
SUB D0,SP ;allocate one buffer
MOVE.L SP,SCAN5(A6) ;remember buffer pointer
;-----------------------------------------------------------
;
; INIT ASSORTED POINTERS
;
MOVE.L BUFHANDLE(A6),A0 ;GET BUFHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
MOVE.L A0,BUFPTR(A6) ;BUFPTR := BUFSTART
AND #$FFF8,MAXBYTES(A6) ;TRUNCATE TO A MULT OF 8 BYTES
ADD MAXBYTES(A6),A0
MOVE.L A0,BUFLIMIT(A6) ;BUFLIMIT:=BUFSTART+MAXBYTES
MOVE.L SCAN1(A6),A0
MOVE.L A0,D4 ;SCANA := @SCAN1
MOVE #32767,D0
MOVE D0,(A0) ;INIT SCANA TO EMPTY
MOVE.L SCAN2(A6),A0
MOVE.L A0,D5 ;SCANB := @SCAN2
MOVE D0,(A0) ;INIT SCANB TO EMPTY
MOVE.L SCAN3(A6),A0
MOVE.L A0,D6 ;SCANC := @SCAN3
MOVE D0,(A0) ;INIT SCANC TO EMPTY
MOVE.L SCAN4(A6),A0
MOVE.L A0,D7 ;TEMPSCAN := @SCAN4
MOVE (A3)+,NEXTA(A6) ;NEXTA := FIRST VERT IN A
MOVE (A4)+,NEXTB(A6) ;NEXTB := FIRST VERT IN B
CMP #8,OP(A6) ;IS OP = INSET ?
BNE.S NXTVERT ;NO, CONTINUE
MOVE D0,NEXTB(A6) ;YES, NEXTB := 32767
NXTVERT MOVE NEXTA(A6),D0 ;GET NEXT VERT IN A
CMP NEXTB(A6),D0 ;WHICH COMES FIRST ?
BEQ.S BOTH ;SAME, UPDATE BOTH RGNS
BGT.S UPDATEB ;B, UPDATE RGNB ONLY
BSR.S UPDATEA ;A, UPDATE RGNA ONLY
BRA.S CALC ;CALC NEW C-SCAN
UPDATEA MOVE NEXTA(A6),VERT(A6) ;VERT := NEXTA
MOVE.L A3,A0 ;SRCA := PTRA
MOVE.L D4,A1 ;SRCB := SCANA
MOVE.L D7,A2 ;DSTC := TEMPSCAN
JSR XORSCAN ;XORSCAN(PTRA,SCANA,TEMPSCAN)
MOVE.L A0,A3 ;BUMP PTRA TO END OF SCAN
MOVE (A3)+,NEXTA(A6) ;NEXTA := NEXT VERT
EXG D4,D7 ;SWAP SCANA AND TEMPSCAN
RTS ;RETURN TO LOCAL CALLER
BOTH CMP #32767,D0 ;ARE BOTH VERTICALS 32767 ?
BEQ DONE ;YES, WE'RE ALL FINISHED
BSR.S UPDATEA ;UPDATE RGNA
UPDATEB MOVE NEXTB(A6),VERT(A6) ;VERT := NEXTB
MOVE.L A4,A0 ;SRCA := PTRB
MOVE.L D5,A1 ;SRCB := SCANB
MOVE.L D7,A2 ;DSTC := TEMPSCAN
JSR XORSCAN ;XORSCAN(PTRB,SCANB,TEMPSCAN)
MOVE.L A0,A4 ;BUMP PTRB TO END OF SCAN
MOVE (A4)+,NEXTB(A6) ;NEXTB := NEXT VERT
EXG D7,D5 ;SWAP SCANB AND TEMPSCAN
;---------------------------------------------------------
;
; CALCULATE SECT, DIFF, UNION, XOR, OR INSET INTO SCANC
;
CALC MOVE.L D4,A0 ;POINT TO SCANA
MOVE.L D5,A1 ;POINT TO SCANB
MOVE.L D7,A2 ;POINT TO TEMPSCAN
MOVE DH(A6),D2 ;GET DH IN CASE INSET
PEA CHANGES ;PUSH RETURN ADDR
MOVE.L CASEJMP(A6),-(SP) ;PUSH CASE JUMP
RTS ;DO CASE JSR
;-------------------------------------------------------------
;
; FIND ANY CHANGES NOT IN PREVIOUS SCANC, THEN UPDATE SCANC
;
CHANGES MOVE.L D7,A0 ;GET TEMPSCAN
MOVE.L D6,A1 ;GET SCANC
MOVE.L SCAN5(A6),A2 ;GET OUTPUT SCAN
JSR XORSCAN ;XorScan(tempScan,scanC,@SCAN5);
EXG D7,D6 ;SWAP TEMPSCAN AND SCANC
MOVE.L SCAN5(A6),A0 ;POINT TO OUTPUT SCAN
MOVE.L BUFPTR(A6),A1 ;POINT TO DST POINT BUFFER
MOVE.L BUFLIMIT(A6),A2 ;GET BUFLIMIT
MOVE.L VERT(A6),D0 ;GET VERT COORD IN HI WORD
BRA.S OUTTEST ;GO TO LOOP START
OUTLOOP MOVE.W (A0)+,D0 ;GET LEFT HORIZ COORD
MOVE.L D0,(A1)+ ;PUT LEFT POINT
MOVE.W (A0)+,D0 ;GET RIGHT HORIZ COORD
MOVE.L D0,(A1)+ ;PUT RIGHT POINT
OUTTEST CMP.L A2,A1 ;IS BUFPTR >= BUFLIMIT ?
BLO.S SIZEOK ;NO, CONTINUE
;-----------------------------------------------------------
;
; THE POINT BUFFER IS FULL, GROW IT IF OKGROW IS TRUE
;
TST.B OKGROW(A6) ;ARE WE ALLOWED TO GROW ?
BEQ ABORT ;NO, ABORT RGNOP
MOVE.L A0,D1 ;YES, SAVE OUTPUT SCAN PTR
MOVE.L RGNA(A6),A0 ;GET RGNA MASTER
SUB.L (A0),A3 ;MAKE RGNA PTR RELATIVE
MOVE.L RGNB(A6),A0 ;GET RGNB MASTER
SUB.L (A0),A4 ;MAKE RGNB PTR RELATIVE
MOVE.L BUFHANDLE(A6),A0 ;GET BUFHANDLE
SUB.L (A0),A1 ;MAKE BUFPTR RELATIVE
SUB.L (A0),A2 ;MAKE BUFLIMIT RELATIVE, = SIZE
ADD #256,A2 ;BUMP BUFLIMIT 256 BYTES
MOVEM.L D0-D2/A0-A2,-(SP) ;SAVE REGS
MOVE.L A0,-(SP) ;PUSH BUFHANDLE
MOVE.W A2,-(SP) ;PUSH NEW BYTECOUNT
JSR SETSIZE ;GROW POINT BUFFER
MOVEM.L (SP)+,D0-D2/A0-A2 ;RESTORE REGS
MOVE.L RGNA(A6),A0 ;GET RGNA MASTER
ADD.L (A0),A3 ;MAKE RGNA UN-RELATIVE
MOVE.L RGNB(A6),A0 ;GET RGNB MASTER
ADD.L (A0),A4 ;MAKE RGNB UN-RELATIVE
MOVE.L BUFHANDLE(A6),A0 ;GET BUFHANDLE
ADD.L (A0),A1 ;MAKE BUFPTR UN-RELATIVE
ADD.L (A0),A2 ;MAKE BUFLIMIT UN-RELATIVE
MOVE.L A2,BUFLIMIT(A6) ;UPDATE BUFLIMIT
MOVE.L D1,A0 ;RESTORE OUTPUT SCAN PTR
SIZEOK CMP #32767,(A0) ;END OF SCAN MARKER ?
BNE OUTLOOP ;NO, GO FOR MORE
MOVE.L A1,BUFPTR(A6) ;UPDATE BUFPTR
BRA NXTVERT ;LOOP FOR NEXT VERT
;------------------------------------------------------------------------
;
; LOCAL ROUTINE TO EXPAND A RECTANGULAR REGION TO ITS INVERSION POINTS.
; ENTER WITH ADDR OF RGNHANDLE IN A0, ADDR OF FAKE MASTER IN A2.
; RETURNS IN A0 DE-REFERENCED POINTER BUMPED TO FIRST RGNDATA,
; AND A2 BUMPED TO NEXT AVAILABLE FAKE MASTER.
;
EXPAND MOVE.L (A0),A1 ;GET RGNHANDLE
MOVE.L (A1),A1 ;DE-REFERENCE HANDLE
CMP #10,RGNSIZE(A1) ;IS REGION RECTANGULAR ?
BNE.S NOTRECT ;NO, DON'T EXPAND IT
MOVE.L A2,(A0) ;POINT HANDLE TO FAKE MASTER
LEA -6(A2),A0 ;POINT 10 BYTES BEFORE DATA
MOVE.L A0,(A2)+ ;FILL IN FAKE MASTER
MOVE.L RGNBBOX+TOPLEFT(A1),(A2)+ ;PUT TOP V AND LEFT H
MOVE RGNBBOX+RIGHT(A1),(A2)+ ;PUT RIGHT HORIZ
MOVE #32767,D0
MOVE D0,(A2)+ ;PUT HORIZ TERMINATOR
MOVE RGNBBOX+BOTTOM(A1),(A2)+ ;PUT BOTTOM VERT
MOVE RGNBBOX+LEFT(A1),(A2)+ ;PUT LEFT HORIZ
MOVE RGNBBOX+RIGHT(A1),(A2)+ ;PUT RIGHT HORIZ
MOVE D0,(A2)+ ;PUT HORIZ TERMINATOR
MOVE D0,(A2)+ ;PUT VERT TERMINATOR
MOVE.L A0,A1 ;PUT FAKE RGNPTR IN A1
NOTRECT LEA RGNDATA(A1),A0 ;OFFSET TO FIRST REGION DATA
RTS ;AND RETURN
ABORT MOVE.L A1,BUFPTR(A6) ;UPDATE BUFPTR
DONE MOVE.L BUFPTR(A6),D0 ;GET BUFPTR
MOVE.L BUFHANDLE(A6),A0 ;GET BUFHANDLE
SUB.L (A0),D0 ;BYTES USED = BUFPTR - BUFSTART
LSR #2,D0 ;DIV BY 4 FOR NPOINTS
MOVE D0,RESULT(A6) ;RETURN NPOINTS
MOVE.L SAVESTK(A6),SP ;STRIP SCAN BUFFERS
MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'RGNOP '
.PROC SectScan,3
.DEF DiffScan,UnionScan
;---------------------------------------------------------
;
; PROCEDURE SectScan(srcA,srcB,dstC: ScanPtr);
;
; Calculate the intersection, difference, or union of two inversion scans.
;
; Each input scan is a sorted array of integers terminated by 32767.
; The output scan contains the inversion coordinates for the result.
;
; INPUTS: A0 SRCA
; A1 SRCB
; A2 DSTC
;
; CLOBBERS D0-D3, A0-A2
;
SECT CLR D2 ;RESET ASTATE OFF
CLR D3 ;RESET BSTATE OFF
BRA.S SHARE ;SHARE CODE
DIFFSCAN CLR D2 ;RESET ASTATE OFF
BRA.S UNION2 ;SHARE CODE
UNIONSCAN MOVEQ #-1,D2 ;SET ASTATE ON
UNION2 MOVEQ #-1,D3 ;SET BSTATE ON
SHARE MOVE (A0)+,D0 ;GET NEXTA
MOVE (A1)+,D1 ;GET NEXTB
NEXT CMP D1,D0 ;IS NEXTA < NEXT B ?
BLT.S ALESS ;YES, BRANCH
BGT.S BLESS ;BR IF NEXTB IS LESS
EQUAL CMP #32767,D0 ;ARE WE AT THE END ?
BEQ.S DONE ;YES, QUIT
CMP D3,D2 ;ARE ASTATE AND BSTATE SAME ?
BNE.S SKIP0 ;NO, SKIP
MOVE D0,(A2)+ ;YES, PUT CHANGE
SKIP0 MOVE (A0)+,D0 ;GET NEW NEXTA
NOT D2 ;TOGGLE ASTATE
MOVE (A1)+,D1 ;GET NEW NEXTB
NOT D3 ;TOGGLE BSTATE
BRA NEXT ;LOOP FOR MORE
ALESS TST D3 ;TEST BSTATE
BEQ.S SKIP1 ;SKIP IF NOT TRUE
MOVE D0,(A2)+ ;PUT NEXTA
SKIP1 MOVE (A0)+,D0 ;GET NEW NEXTA
NOT D2 ;AND TOGGLE ASTATE
BRA NEXT ;LOOP FOR MORE
BLESS TST D2 ;TEST ASTATE
BEQ.S SKIP2 ;SKIP IF NOT TRUE
MOVE D1,(A2)+ ;PUT NEXTB
SKIP2 MOVE (A1)+,D1 ;GET NEW NEXTB
NOT D3 ;AND TOGGLE BSTATE
BRA NEXT ;LOOP FOR MORE
DONE MOVE #32767,(A2)+ ;PUT END MARKER INTO DST
RTS
.PROC InsetScan,3
.DEF XorScan
;---------------------------------------------------------
;
; PROCEDURE InsetScan(src,dst: ScanPtr; dh: INTEGER);
;
; Horizontally inset an inversion scan by dh;
;
; The input scan is a sorted array of integers terminated by 32767.
; The output scan contains the inversion coordinates for the inset.
;
; INPUTS: A0 SRC
; A2 DST
; D2 DH
;
; CLOBBERS D0-D1/A0-A2
;
TST D2 ;IS DH NEG ?
BLT.S OUTSET ;YES, OUTSET
;---------------------------------------------------------------
;
; GET EACH PAIR OF COORDS, INSET THEM, AND CANCEL IF THEY CROSS.
;
INSET CMP #32767,(A0) ;CHECK FOR TERMINATOR
BEQ.S DONE ;QUIT WHEN FOUND
MOVE (A0)+,D0 ;GET LEFT COORD
MOVE (A0)+,D1 ;GET RIGHT COORD
ADD.W D2,D0 ;ADD DH TO LEFT
SUB.W D2,D1 ;SUB DH FROM RIGHT
CMP D1,D0 ;IS LEFT >= RIGHT ?
BGE.S INSET ;YES, SKIP BOTH
MOVE D0,(A2)+ ;PUT LEFT COORD TO DST
MOVE D1,(A2)+ ;PUT RIGHT COORD TO DST
BRA.S INSET ;LOOP ENTIRE SCAN
;------------------------------------------------------------------
;
; GET EACH PAIR OF COORDS, OUTSET THEM, AND CANCEL IF THEY CROSS.
;
OUTSET MOVE #-32767,A1 ;OLDRIGHT := -32767
BRA.S START ;GO TO LOOP START
OUTLOOP MOVE (A0)+,D0 ;GET LEFT COORD
MOVE (A0)+,D1 ;GET RIGHT COORD
ADD D2,D0 ;ADD DH TO LEFT
SUB D2,D1 ;SUB DH FROM RIGHT
CMP A1,D0 ;IS LEFT <= OLDRIGHT ?
BGT.S OUTOK ;NO, CONTINUE
SUB #2,A2 ;YES, OVER-WRITE PREVIOUS RIGHT
BRA.S OUTOK2 ;AND CONTINUE
OUTOK MOVE D0,(A2)+ ;PUT LEFT COORD
OUTOK2 MOVE D1,(A2)+ ;PUT RIGHT COORD
MOVE D1,A1 ;OLDRIGHT := RIGHT
START CMP #32767,(A0) ;CHECK FOR TERMINATOR
BNE OUTLOOP ;AND LOOP ENTIRE SCAN
DONE MOVE #32767,(A2)+ ;PUT TERMINATOR
RTS
;--------------------------------------------------------------
;
; LOCAL PROCEDURE XorScan(srcA,srcB,dstC: ScanPtr);
;
; Form the exclusive-or of two inversion scans.
;
; Each input scan is a sorted array of integers terminated by 32767.
; The output scan conatins all input coordinates from each, but
; with duplicate pairs cancelled. It also is terminated by 32767.
;
; INPUTS: A0 SRCA
; A1 SRCB
; A2 DSTC
;
; CLOBBERS D0-D1, A0-A2
;
EQUAL CMP #32767,D0 ;ALL DONE ?
BEQ.S DONE ;YES, QUIT
XorScan MOVE (A0)+,D0 ;GET NEXT A
MOVE (A1)+,D1 ;GET NEXT B
NEXT CMP D1,D0 ;WHICH IS LESS, A OR B ?
BEQ.S EQUAL ;THE SAME, SO CANCEL
BLT.S ALESS ;A IS LESS
BLESS MOVE D1,(A2)+ ;PUT B TO DST
MOVE (A1)+,D1 ;GET NEXT B
BRA.S NEXT ;LOOP FOR MORE
ALESS MOVE D0,(A2)+ ;PUT A TO DST
MOVE (A0)+,D0 ;GET NEXT A
BRA.S NEXT ;LOOP FOR MORE
.END

192
SeekRgn.a Executable file
View File

@ -0,0 +1,192 @@
.INCLUDE GRAFTYPES.TEXT
;------------------------------------------------------------------
;
; --> SEEKRGN.TEXT
;
; Routines to play back a region into a scanline buffer.
;
;
.PROC INITRGN,0
;------------------------------------------------------
;
; INPUTS: A0: RGNPTR
; A1: STATE RECORD
; D0: MINH
; D1: MAXH
; D2: BUFLEFT
;
; OUTPUTS: ALL FIELDS OF STATE RECORD,
; SCANBUF ALLOCATED ON STACK
;
; CLOBBERS: D0,D1,A0
;
MOVE D0,MINH(A1) ;INSTALL MINH
MOVE D1,MAXH(A1) ;INSTALL MAXH
MOVE D2,LEFTH(A1) ;INSTALL LEFTH
MOVE.L A0,RGNPTR(A1) ;INSTALL RGNPTR
MOVE #-32767,THISV(A1) ;THISV := -32767
MOVE RGNBBOX+TOP(A0),NEXTV(A1) ;NEXTV := RGN BBOX TOP
LEA RGNDATA(A0),A0 ;POINT TO FIRST DATA
MOVE.L A0,DATAPTR(A1) ;INIT DATAPTR
MOVE.L (SP)+,A0 ;POP RETURN ADDR
SUB D2,D1 ;CALC BUFFER WIDTH IN DOTS
LSR #5,D1 ;DIV BY 32 FOR #LONGS-1
MOVE D1,SCANSIZE(A1) ;SAVE SCANSIZE FOR LATER
CLRLOOP CLR.L -(SP) ;ALLOCATE AND CLEAR BUFFER
DBRA D1,CLRLOOP
MOVE.L SP,SCANBUF(A1) ;REMEMBER BUFFER START
JMP (A0) ;RETURN
.PROC SEEKRGN,0
.REF MaskTab
;------------------------------------------------------------------
;
; SeekRgn(rgnState,vert);
;
; ROUTINE TO PLAY BACK A REGION FORWARD OR BACKWARD UNTIL ITS SCAN
; BUFFER CONTAINS THE BITMAP FOR THE GIVEN VERTICAL COORDINATE.
;
; INPUTS: A1 POINTS TO A REGION STATE RECORD
; DO CONTAINS THE DESIRED VERTICAL COORD
;
; OUTPUTS: UPDATES THISV, NEXTV, DATAPTR, AND SCANBUF^ OF STATE RECORD
; D1-->1 IF CHANGE, 0 IF NO CHANGE. (Z-FLAG SET IF NO CHANGE)
;
; CLOBBERS: A0,D1.
;
;----------------------------------------------------
;
; RETURN QUICKLY IF SCANBUF IS ALREADY CURRENT.
;
CMP NEXTV(A1),D0 ;IS DESIRED VERT >= NEXTV ?
BGE.S DOWN ;YES, BUMP DOWNWARD
CMP THISV(A1),D0 ;IS DESIRED VERT < CURRENT VERT ?
BLT.S UP ;YES, BUMP UPWARD
CLR D1 ;ELSE REPORT NO CHANGES
RTS ;AND RETURN
;-----------------------------------------------------
;
; TO MOVE UPWARDS, JUST RESET TO START AND MOVE DOWN.
;
UP MOVE.L SCANBUF(A1),A0 ;POINT TO SCANBUF
MOVE SCANSIZE(A1),D1 ;GET BUFFER SIZE
CLRLP CLR.L (A0)+ ;CLEAR A LONG
DBRA D1,CLRLP ;LOOP ENTIRE SCANBUF
MOVE.L RGNPTR(A1),A0 ;GET RGNPTR
MOVE RGNBBOX+TOP(A0),NEXTV(A1) ;NEXTV := TOP VERT
MOVE #-32767,THISV(A1) ;RESET THISV TO -32767
LEA RGNDATA(A0),A0 ;POINT TO START OF REGION DATA
MOVE.L A0,DATAPTR(A1) ;RESET DATAPTR
CMP NEXTV(A1),D0 ;IS DESIRED VERT >= NEXTV ?
BLT DONE ;NO, QUIT
;------------------------------------------------------
;
; WHILE DESIRED VERT >= NEXTV DO BUMP DOWN.
;
DOWN MOVEM.L D0-D6/A2-A3,-(SP) ;SAVE REGS
MOVE D0,D2 ;SAVE VERT
MOVE.L DATAPTR(A1),A2 ;POINT TO VERT COORD
DOWN1 MOVE (A2)+,THISV(A1) ;UPDATE CURRENT VERT
;-------------------------------------------------
;
; GET LEFT AND RIGHT HORIZ COORDS
; AND TRIM AGAINST MINH AND MAXH
;
NEXTHOR MOVE (A2)+,D3 ;GET LEFT COORD
CMP #32767,D3 ;IS IT A TERMINATOR ?
BEQ.S DONE1 ;YES, QUIT
MOVE (A2)+,D4 ;GET RIGHT COORD
CMP MINH(A1),D4 ;IS RIGHT <= MINH ?
BLE NEXTHOR ;YES, IGNORE ON LEFT
CMP MAXH(A1),D3 ;IS LEFT >= MAXH ?
BGE NEXTHOR ;YES, IGNORE ON RIGHT
CMP MINH(A1),D3 ;IS LEFT < MINH ?
BGE.S LOK ;NO, CONTINUE
MOVE MINH(A1),D3 ;YES, TRIM LEFT
LOK CMP MAXH(A1),D4 ;IS RIGHT > MAXH ?
BLE.S ROK ;NO, CONTINUE
MOVE MAXH(A1),D4 ;YES, TRIM RIGHT
ROK SUB LEFTH(A1),D3 ;MAKE COORDS REL TO BUFFER
SUB LEFTH(A1),D4
;------------------------------------------
;
; GET LEFTMASK AND RIGHTMASK
;
LEA MASKTAB,A0 ;POINT TO MASK TABLE
MOVEQ #$F,D0 ;GET MASK FOR LO 4 BITS
MOVE D3,D5 ;COPY LEFT COORD
AND D0,D5 ;CALC LEFT MOD 16
ADD D5,D5 ;DOUBLE FOR INDEX
MOVE 0(A0,D5),D5 ;GET MASK FROM TABLE
NOT D5 ;INVERT FOR LEFTMASK
MOVE D4,D6 ;COPY RIGHT COORD
AND D0,D6 ;CALC RIGHT MOD 16
ADD D6,D6 ;DOUBLE FOR INDEX
MOVE 0(A0,D6),D6 ;GET RIGHTMASK IN D6
;------------------------------------------
;
; CALC LEFTWORD, BUFPTR, WORDCOUNT
;
LSR #4,D3 ;CONVERT DOTS TO WORDS
MOVE.L SCANBUF(A1),A3 ;COPY BUFSTART
ADD D3,A3
ADD D3,A3 ;INIT BUFPTR TO LEFTWORD
LSR #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,(A3) ;XOR COMBINATION INTO BUFFER
BRA NEXTHOR ;GO FOR MORE DH'S THIS SCAN
;------------------------------------------
;
; NOT ALL IN ONE WORD. DO LEFT, MIDDLE IF ANY, THEN RIGHT
;
NOTIN1 EOR D5,(A3)+ ;XOR LEFTMASK INTO BUFFER
BRA.S TEST ;SEE IF ANY FULL WORDS
INVLONG NOT.L (A3)+ ;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 (A3)+ ;YES, DO LAST FULL WORD
ENDWORD EOR D6,(A3) ;XOR RIGHTMASK INTO BUFFER
BRA NEXTHOR ;GO FOR MORE DH'S THIS SCAN
DONE1 MOVE.L A2,DATAPTR(A1) ;UPDATE DATAPTR
MOVE (A2),NEXTV(A1) ;UPDATE NEXT VERT
CMP NEXTV(A1),D2 ;IS DESIRED VERT >= NEXTV ?
BGE DOWN1 ;YES, BUMP DOWN SOME MORE
MOVEM.L (SP)+,D0-D6/A2-A3 ;RESTORE REGS
DONE MOVEQ #1,D1 ;REPORT SCANLINE CHANGED
RTS ;AND RETURN
.END

180
SortPoints.a Executable file
View File

@ -0,0 +1,180 @@
.INCLUDE GRAFTYPES.TEXT
;------------------------------------------------------------------
;
; --> SORTPOINTS.TEXT
;
; Routines to sort inversion points and cull duplicates.
;
.PROC SortPoints
;-------------------------------------------------------------
;
; PROCEDURE SortPoints(ptBuf: PointsPtr; ptCount: INTEGER);
;
; PERFORMS A NON-RECURSIVE QUICKSORT ON AN ARRAY OF POINTS
; TO PUT THEM IN INCREASING VERT.HORIZ ORDER.
;
; RE-WROTE 5 SEPT 83 TO CUT DOWN WORST CASE STACK USAGE
;
; See Algorithms + Data Structures = Programs, p.80
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 6
PTBUF .EQU PARAMSIZE+8-4 ;LONG
PTCOUNT .EQU PTBUF-2 ;WORD
LINK A6,#0 ;NO LOCAL VARIABLES
MOVEM.L D3-D4/A2-A4,-(SP) ;SAVE REGS
MOVE.L PTBUF(A6),A3 ;LEFTPTR:=START OF PT ARRAY
MOVE A3,D3
AND #3,D3 ;SET UP LOBITS FOR SORT
CLR.L D0
MOVE PTCOUNT(A6),D0 ;GET PTCOUNT
BLE.S GOHOME ;DO NOTHING IF NO POINTS
LSL.L #2,D0 ;QUAD PTCOUNT FOR BYTES
MOVE.L A3,A4
ADD.L D0,A4 ;ADD TO DSTSTART
SUB #4,A4 ;RIGHTPTR:=DSTEND-4
MOVE.L SP,D4 ;REMEMBER STACK MARKER
MOVEM.L A3/A4,-(SP) ;PUSH LEFTPTR AND RIGHTPTR
POPNXT MOVEM.L (SP)+,A3/A4 ;POP LEFTPTR AND RIGHTPTR
SPLIT MOVE.L A3,A1 ;IPTR := LEFTPTR
MOVE.L A4,A2 ;JPTR := RIGHTPTR
;
; CALC MIDPTR AND MIDPT
;
MOVE.L A3,D0 ;ADD LEFTPTR
ADD.L A4,D0 ;AND RIGHTPTR
ROXR.L #1,D0 ;THEN DIVIDE BY 2 FOR MIDPTR
AND #$FFFC,D0 ;TRUNC TO MULTIPLE OF 4 BYTES
OR D3,D0 ;OR IN LOBITS FOR POINT BOUNDARY
MOVE.L D0,A0 ;GET MIDPTR INTO A-REG
MOVE H(A0),D1 ;GET MIDPT.H
MOVE V(A0),D2 ;AND MIDPT.V
SCAN
;
; WHILE IPTR^ < MIDPT DO BUMP IPTR TO RIGHT
;
BRA.S TWO ;GO TO LOOP START
ONE ADD #4,A1 ;BUMP IPTR TO RIGHT
TWO CMP V(A1),D2 ;IS MIDPT.V > IPTR^.V ?
BGT ONE ;YES, BUMP SOME MORE
BLT.S THREE ;BR IF DONE WITH IPTR.
CMP H(A1),D1 ;IF SAME VERT, LOOK AT HORIZ
BGT ONE ;KEEP BUMPING IF MIDPT.H > IPTR^.H
THREE
;
; WHILE JPTR^ > MIDPT DO BUMP JPTR TO LEFT
;
BRA.S FIVE ;GO TO LOOP START
FOUR SUB #4,A2 ;BUMP JPTR TO LEFT
FIVE CMP V(A2),D2 ;IS MIDPT.V < JPTR^.V ?
BLT FOUR ;YES, BUMP SOME MORE
BGT.S SIX ;BR IF DONE BUMPING JPTR
CMP H(A2),D1 ;IF SAME VERT, LOOK AT HORIZ
BLT FOUR ;KEEP BUMPING IF MIDPT.H < JPTR^.H
SIX
;
; if IPtr <= JPtr then swap IPtr^ and JPtr^, and bump both pointers
;
CMP.L A2,A1 ;IS IPTR > JPTR ?
BGT.S NOSWAP ;YES, ALL DONE
MOVE.L (A1),D0
MOVE.L (A2),(A1)
MOVE.L D0,(A2) ;SWAP POINTS
ADD #4,A1 ;BUMP IPTR TO RIGHT
SUB #4,A2 ;BUMP JPTR TO LEFT
;
; repeat until this partitioning is complete, IPtr > JPtr
;
NOSWAP CMPA.L A2,A1 ;IS IPTR > JPTR ?
BLS SCAN ;NO, LOOP AGAIN
;
; IF i < right then stack request to sort right partition
;
CMPA.L A4,A1 ;IS IPTR < RIGHTPTR ?
BHS.S RIGHTOK ;YES, CONTINUE
MOVEM.L A1/A4,-(SP) ;NO, PUSH IPTR,RIGHTPTR
RIGHTOK MOVE.L A2,A4 ;RIGHTPTR := JPTR
CMPA.L A4,A3 ;IS LEFTPTR >= RIGHTPTR ?
BLO SPLIT ;NO, PARTITION AGAIN
CMPA.L D4,SP ;IS STACK EMPTY YET ?
BNE POPNXT ;NO, LOOP FOR MORE
GOHOME MOVEM.L (SP)+,D3-D4/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'SORTPOIN'
.PROC CullPoints,2
;-------------------------------------------------------------
;
; PROCEDURE CullPoints(ptBuf: PointsPtr; VAR ptCount: INTEGER);
;
; CANCEL ANY DUPLICATE PAIRS OF POINTS IN AN ARRAY OF POINTS.
;
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 8
PTBUF .EQU PARAMSIZE+8-4 ;LONG
PTCOUNT .EQU PTBUF-4 ;LONG, VAR
LINK A6,#0 ;NO LOCAL VARIABLES
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGS
MOVE.L PTCOUNT(A6),A0 ;GET VAR ADDR OF PTCOUNT
MOVE (A0),D0 ;GET PTCOUNT
BLE GOHOME ;DO NOTHING IF NO POINTS
MOVE.L PTBUF(A6),A1 ;SRCPTR:=START PTR
MOVE.L A1,A3 ;COPY START
EXT.L D0 ;CLEAR HI WORD
LSL.L #2,D0 ;QUAD PTCOUNT FOR BYTES
ADD.L D0,A3 ;ADD TO START
SUB #4,A3 ;LAST POINT IS AT END-4
MOVE.L A1,D5 ;SAVE START FOR LATER
MOVE.L A1,A2 ;DSTPTR:=START
BRA.S WHILE1 ;GO TO LOOP START
DELETE ADD #4,A1 ;SKIP OVER BOTH SRC POINTS
BRA.S WHILE1 ;GO TO LOOP START
MORE1 MOVE.L (A1)+,D0 ;GET CURRENT SRC POINT
CMP.L (A1),D0 ;IS IT SAME AS NEXT ?
BEQ DELETE ;YES, DELETE BOTH
MOVE.L D0,(A2)+ ;NO, COPY TO DST
WHILE1 CMP.L A3,A1 ;IS SRCPTR < LASTPTR ?
BLT.S MORE1 ;YES, GO FOR MORE
BGT.S DONE
MOVE.L (A1)+,(A2)+ ;FINISH UP LAST POINT
DONE MOVE.L A2,D0 ;GET DST PTR
SUB.L D5,D0 ;SUBTRACT START PTR
LSR #2,D0 ;DIV BY 4 FOR PTCOUNT
MOVE.L PTCOUNT(A6),A0 ;GET VAR ADDR
MOVE D0,(A0) ;UPDATE PTCOUNT TO REFLECT DELETIONS
GOHOME MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGS
UNLINK PARAMSIZE,'CULLPOIN'
.END

1164
Stretch.a Executable file

File diff suppressed because it is too large Load Diff

971
TestGraf.p Executable file
View File

@ -0,0 +1,971 @@
PROGRAM TestGraf;
{ Quick Checkout for QuickDraw }
USES {$U obj:QuickDraw } QuickDraw,
{$U obj:QDSupport } QDSupport,
{$U obj:GrafUtil } GrafUtil;
LABEL 1;
CONST heapSize = $10000; { 64k bytes }
TYPE IconData = ARRAY[0..95] OF INTEGER;
VAR heapStart: QDPtr;
heapLimit: QDPtr;
port1: GrafPtr;
tempRect: Rect;
myPoly: PolyHandle;
myRgn: RgnHandle;
myPattern: Pattern;
myPicture: PicHandle;
bigPicture: PicHandle;
icons: ARRAY[0..5] OF IconData;
i,errNum: INTEGER;
numerArray: ARRAY[0..30] OF INTEGER;
denomArray: ARRAY[0..30] OF INTEGER;
srcRect: Rect;
dstRect: Rect;
ch: CHAR;
FUNCTION HeapError(hz: QDPtr; bytesNeeded: INTEGER): INTEGER;
{ this function will be called if the heapZone runs out of space }
BEGIN
WRITELN('The heap is full. User Croak !! ');
Halt;
END;
PROCEDURE InitIcons;
{ Manually stuff some icons. Normally we would read them from a file }
BEGIN
{ Lisa }
StuffHex(@icons[0, 0],'000000000000000000000000000000000000001FFFFFFFFC');
StuffHex(@icons[0,12],'00600000000601800000000B0600000000130FFFFFFFFFA3');
StuffHex(@icons[0,24],'18000000004311FFFFF00023120000080F231200000BF923');
StuffHex(@icons[0,36],'120000080F23120000080023120000080023120000080F23');
StuffHex(@icons[0,48],'1200000BF923120000080F2312000008002311FFFFF00023');
StuffHex(@icons[0,60],'08000000004307FFFFFFFFA30100000000260FFFFFFFFE2C');
StuffHex(@icons[0,72],'18000000013832AAAAA8A9F0655555515380C2AAAA82A580');
StuffHex(@icons[0,84],'800000000980FFFFFFFFF300800000001600FFFFFFFFFC00');
{ Printer }
StuffHex(@icons[1, 0],'000000000000000000000000000000000000000000000000');
StuffHex(@icons[1,12],'00000000000000007FFFFF00000080000280000111514440');
StuffHex(@icons[1,24],'0002000008400004454510400004000017C00004A5151000');
StuffHex(@icons[1,36],'0004000010000004A54510000004000017FE00F4A5151003');
StuffHex(@icons[1,48],'0184000013870327FFFFF10F06400000021B0CFFFFFFFC37');
StuffHex(@icons[1,60],'18000000006B3000000000D77FFFFFFFFFABC00000000356');
StuffHex(@icons[1,72],'8000000001AC87F000000158841000CCC1B087F000CCC160');
StuffHex(@icons[1,84],'8000000001C0C000000003807FFFFFFFFF0007800001E000');
{ Trash Can }
StuffHex(@icons[2, 0],'000001FC000000000E0600000000300300000000C0918000');
StuffHex(@icons[2,12],'00013849800000026C4980000004C0930000000861260000');
StuffHex(@icons[2,24],'0010064FE0000031199830000020E6301800002418E00800');
StuffHex(@icons[2,36],'0033E3801C0000180E002C00000FF801CC0000047FFE0C00');
StuffHex(@icons[2,48],'000500004C000005259A4C000005250A4C00000525FA4C00');
StuffHex(@icons[2,60],'000524024C00000524924C00600524924C0090E524924C7C');
StuffHex(@icons[2,72],'932524924C82A44524924D01C88524924CF10C4524924C09');
StuffHex(@icons[2,84],'0784249258E70003049233100000E000E40800001FFFC3F0');
{ tray }
StuffHex(@icons[3, 0],'000000000000000000000000000000000000000000000000');
StuffHex(@icons[3,12],'0000000000000000000000000000000000000007FFFFFFF0');
StuffHex(@icons[3,24],'000E00000018001A00000038003600000078006A000000D8');
StuffHex(@icons[3,36],'00D7FFFFFFB801AC000003580358000006B807FC000FFD58');
StuffHex(@icons[3,48],'040600180AB80403FFF00D58040000000AB8040000000D58');
StuffHex(@icons[3,60],'040000000AB807FFFFFFFD5806AC00000AB8055800000D58');
StuffHex(@icons[3,72],'06B000000AB807FC000FFD70040600180AE00403FFF00DC0');
StuffHex(@icons[3,84],'040000000B80040000000F00040000000E0007FFFFFFFC00');
{ File Cabinet }
StuffHex(@icons[4, 0],'0007FFFFFC00000800000C00001000001C00002000003400');
StuffHex(@icons[4,12],'004000006C0000FFFFFFD40000800000AC0000BFFFFED400');
StuffHex(@icons[4,24],'00A00002AC0000A07F02D40000A04102AC0000A07F02D400');
StuffHex(@icons[4,36],'00A00002AC0000A08082D40000A0FF82AC0000A00002D400');
StuffHex(@icons[4,48],'00A00002AC0000BFFFFED40000800000AC0000BFFFFED400');
StuffHex(@icons[4,60],'00A00002AC0000A07F02D40000A04102AC0000A07F02D400');
StuffHex(@icons[4,72],'00A00002AC0000A08082D40000A0FF82AC0000A00002D800');
StuffHex(@icons[4,84],'00A00002B00000BFFFFEE00000800000C00000FFFFFF8000');
{ drawer }
StuffHex(@icons[5, 0],'000000000000000000000000000000000000000000000000');
StuffHex(@icons[5,12],'000000000000000000000000000000000000000000000000');
StuffHex(@icons[5,24],'000000000000000000000000000000000000000000000000');
StuffHex(@icons[5,36],'00000000000000000000000000000000000000001FFFFFF0');
StuffHex(@icons[5,48],'0000380000300000680000700000D80000D0003FFFFFF1B0');
StuffHex(@icons[5,60],'0020000013500020000016B000201FE01D50002010201AB0');
StuffHex(@icons[5,72],'00201FE01560002000001AC0002000001580002020101B00');
StuffHex(@icons[5,84],'00203FF01600002000001C00002000001800003FFFFFF000');
END;
PROCEDURE DrawIcon(whichIcon,h,v: INTEGER);
VAR srcBits: BitMap;
srcRect,dstRect: Rect;
BEGIN
srcBits.baseAddr:=@icons[whichIcon];
srcBits.rowBytes:=6;
SetRect(srcBits.bounds,0,0,48,32);
srcRect:=srcBits.bounds;
dstRect:=srcRect;
OffsetRect(dstRect,h,v);
CopyBits(srcBits,thePort^.portBits,srcRect,dstRect,srcOr,Nil);
END;
PROCEDURE DrawStuff;
VAR i: INTEGER;
tempRect: Rect;
srcRect: Rect;
dstRect: Rect;
dataPtr: QDPtr;
tempStr: Str255;
BEGIN
BackColor(whiteColor);
ForeColor(blackColor);
{ test comments }
PicComment(100,0,Nil);
tempStr := 'Hello Test';
dataPtr := @tempStr;
PicComment(200,11,@dataPtr);
tempRect := thePort^.portRect;
ClipRect(tempRect);
EraseRoundRect(tempRect,30,20);
FrameRoundRect(tempRect,30,20);
{ draw two horizontal lines across the top }
MoveTo(0,18);
LineTo(719,18);
MoveTo(0,20);
LineTo(719,20);
{ draw divider lines }
MoveTo(0,134);
LineTo(719,134);
MoveTo(0,248);
LineTo(719,248);
MoveTo(240,21);
LineTo(240,363);
MoveTo(480,21);
LineTo(480,363);
{ draw title }
TextFont(0);
MoveTo(210,14);
DrawString('Look what you can draw with QuickDraw');
{--------- draw text samples --------- }
ForeColor(redColor);
MoveTo(80,34); DrawString('Red');
ForeColor(greenColor);
TextFace([bold]);
MoveTo(70,55); DrawString('Green');
ForeColor(blueColor);
TextFace([italic]);
MoveTo(70,70); DrawString('Blue');
ForeColor(cyanColor);
TextFace([underline]);
MoveTo(70,85); DrawString('Cyan');
ForeColor(magentaColor);
TextFace([outline]);
MoveTo(70,100); DrawString('Magenta');
ForeColor(yellowColor);
TextFace([shadow]);
MoveTo(70,115); DrawString('Yellow');
TextFace([]); { restore to normal }
{ --------- draw line samples --------- }
ForeColor(blackColor);
MoveTo(330,34); DrawString('Lines');
ForeColor(redColor);
MoveTo(280,25); Line(160,40);
ForeColor(greenColor);
PenSize(3,2);
MoveTo(280,35); Line(160,40);
ForeColor(blueColor);
PenSize(6,4);
MoveTo(280,46); Line(160,40);
ForeColor(cyanColor);
PenSize(12,8);
PenPat(gray);
MoveTo(280,61); Line(160,40);
ForeColor(magentaColor);
PenSize(15,10);
PenPat(myPattern);
MoveTo(280,80); Line(160,40);
PenNormal;
{ --------- draw rectangle samples --------- }
ForeColor(blackColor);
MoveTo(560,34); DrawString('Rectangles');
ForeColor(redColor);
SetRect(tempRect,510,40,570,70);
FrameRect(tempRect);
ForeColor(greenColor);
OffsetRect(tempRect,25,15);
PenSize(3,2);
EraseRect(tempRect);
FrameRect(tempRect);
ForeColor(blueColor);
OffsetRect(tempRect,25,15);
PaintRect(tempRect);
ForeColor(cyanColor);
OffsetRect(tempRect,25,15);
PenNormal;
FillRect(tempRect,gray);
FrameRect(tempRect);
ForeColor(magentaColor);
OffsetRect(tempRect,25,15);
FillRect(tempRect,myPattern);
FrameRect(tempRect);
{ --------- draw roundRect samples --------- }
ForeColor(blackColor);
MoveTo(70,148); DrawString('RoundRects');
ForeColor(redColor);
SetRect(tempRect,30,150,90,180);
FrameRoundRect(tempRect,30,20);
ForeColor(greenColor);
OffsetRect(tempRect,25,15);
PenSize(3,2);
EraseRoundRect(tempRect,30,20);
FrameRoundRect(tempRect,30,20);
ForeColor(blueColor);
OffsetRect(tempRect,25,15);
PaintRoundRect(tempRect,30,20);
ForeColor(cyanColor);
OffsetRect(tempRect,25,15);
PenNormal;
FillRoundRect(tempRect,30,20,gray);
FrameRoundRect(tempRect,30,20);
ForeColor(magentaColor);
OffsetRect(tempRect,25,15);
FillRoundRect(tempRect,30,20,myPattern);
FrameRoundRect(tempRect,30,20);
{ --------- draw bitmap samples --------- }
ForeColor(blackColor);
MoveTo(320,148); DrawString('BitMaps');
ForeColor(redColor);
DrawIcon(0,266,156);
ForeColor(greenColor);
DrawIcon(1,336,156);
ForeColor(blueColor);
DrawIcon(2,406,156);
ForeColor(cyanColor);
DrawIcon(3,266,196);
ForeColor(magentaColor);
DrawIcon(4,336,196);
ForeColor(yellowColor);
DrawIcon(5,406,196);
{ --------- draw ARC samples --------- }
ForeColor(blackColor);
MoveTo(570,148); DrawString('Arcs');
SetRect(tempRect,520,153,655,243);
ForeColor(redColor);
FillArc(tempRect,135,65,dkGray);
ForeColor(greenColor);
FillArc(tempRect,200,130,myPattern);
ForeColor(blueColor);
FillArc(tempRect,330,75,gray);
ForeColor(cyanColor);
FrameArc(tempRect,135,270);
OffsetRect(tempRect,20,0);
ForeColor(magentaColor);
PaintArc(tempRect,45,90);
{ --------- draw polygon samples --------- }
ForeColor(blackColor);
MoveTo(80,262); DrawString('Polygons');
myPoly:=OpenPoly;
MoveTo(30,290);
LineTo(30,280);
LineTo(50,265);
LineTo(90,265);
LineTo(80,280);
LineTo(95,290);
LineTo(30,290);
ClosePoly; { end of definition }
ForeColor(redColor);
FramePoly(myPoly);
ForeColor(greenColor);
OffsetPoly(myPoly,25,15);
PenSize(3,2);
ErasePoly(myPoly);
FramePoly(myPoly);
ForeColor(blueColor);
OffsetPoly(myPoly,25,15);
PaintPoly(myPoly);
ForeColor(cyanColor);
OffsetPoly(myPoly,25,15);
PenNormal;
FillPoly(myPoly,gray);
FramePoly(myPoly);
ForeColor(magentaColor);
OffsetPoly(myPoly,25,15);
FillPoly(myPoly,myPattern);
FramePoly(myPoly);
KillPoly(myPoly);
(*
{ --------- draw region samples --------- }
ForeColor(blackColor);
MoveTo(80,262); DrawString('Regions');
myRgn := NewRgn;
OpenRgn;
MoveTo(30,290);
LineTo(30,280);
LineTo(50,265);
LineTo(90,265);
LineTo(80,280);
LineTo(95,290);
LineTo(30,290);
CloseRgn(myRgn); { end of definition }
ForeColor(redColor);
FrameRgn(myRgn);
ForeColor(greenColor);
OffsetRgn(myRgn,25,15);
PenSize(3,2);
EraseRgn(myRgn);
FrameRgn(myRgn);
ForeColor(blueColor);
OffsetRgn(myRgn,25,15);
PaintRgn(myRgn);
ForeColor(cyanColor);
OffsetRgn(myRgn,25,15);
PenNormal;
FillRgn(myRgn,gray);
FrameRgn(myRgn);
ForeColor(magentaColor);
OffsetRgn(myRgn,25,15);
FillRgn(myRgn,myPattern);
FrameRgn(myRgn);
DisposeRgn(myRgn);
*)
{ --------- demonstrate region clipping --------- }
ForeColor(blackColor);
MoveTo(320,262); DrawString('Regions');
myRgn:=NewRgn;
OpenRgn;
ShowPen;
ForeColor(yellowColor);
SetRect(tempRect,260,270,460,350);
FrameRoundRect(tempRect,24,16);
MoveTo(275,335); { define triangular hole }
LineTo(325,285);
LineTo(375,335);
LineTo(275,335);
SetRect(tempRect,365,277,445,325); { oval hole }
FrameOval(tempRect);
HidePen;
CloseRgn(myRgn); { end of definition }
SetClip(myRgn);
BackColor(blueColor);
ForeColor(greenColor);
FOR i:=0 TO 6 DO { draw stuff inside the clip region }
BEGIN
MoveTo(260,280+12*i);
DrawString('Arbitrary Clipping Regions');
END;
BackColor(whiteColor);
ClipRect(thePort^.portRect);
DisposeRgn(myRgn);
{ --------- draw oval samples --------- }
ForeColor(blackColor);
MoveTo(580,262); DrawString('Ovals');
ForeColor(redColor);
SetRect(tempRect,510,264,570,294);
FrameOval(tempRect);
ForeColor(greenColor);
OffsetRect(tempRect,25,15);
PenSize(3,2);
EraseOval(tempRect);
FrameOval(tempRect);
ForeColor(blueColor);
OffsetRect(tempRect,25,15);
PaintOval(tempRect);
ForeColor(cyanColor);
OffsetRect(tempRect,25,15);
PenNormal;
FillOval(tempRect,gray);
FrameOval(tempRect);
ForeColor(magentaColor);
OffsetRect(tempRect,25,15);
FillOval(tempRect,myPattern);
FrameOval(tempRect);
BackColor(whiteColor);
ForeColor(blackColor);
{ test large CopyBits }
SetRect(srcRect,0,0,200,100);
SetRect(dstRect,50,50,250,150);
CopyBits(thePort^.portBits,thePort^.portBits,srcRect,dstRect,0,Nil);
END; { DrawStuff }
PROCEDURE InitScales;
{ initialize an array of common scale factors }
BEGIN
numerArray[ 0] := 1; denomArray[ 0] := 8;
numerArray[ 1] := 1; denomArray[ 1] := 4;
numerArray[ 2] := 1; denomArray[ 2] := 3;
numerArray[ 3] := 3; denomArray[ 3] := 8;
numerArray[ 4] := 1; denomArray[ 4] := 2;
numerArray[ 5] := 2; denomArray[ 5] := 3;
numerArray[ 6] := 3; denomArray[ 6] := 4;
numerArray[ 7] := 1; denomArray[ 7] := 1;
numerArray[ 8] := 4; denomArray[ 8] := 3;
numerArray[ 9] := 3; denomArray[ 9] := 2;
numerArray[10] := 2; denomArray[10] := 1;
numerArray[11] := 3; denomArray[11] := 1;
numerArray[12] := 4; denomArray[12] := 1;
numerArray[13] := 6; denomArray[13] := 1;
numerArray[14] := 8; denomArray[14] := 1;
numerArray[15] := 16; denomArray[15] := 1;
numerArray[16] := 24; denomArray[16] := 1;
numerArray[17] := 32; denomArray[17] := 1;
numerArray[18] := 40; denomArray[18] := 1;
numerArray[19] := 48; denomArray[19] := 1;
numerArray[20] := 56; denomArray[20] := 1;
numerArray[21] := 64; denomArray[21] := 1;
END;
PROCEDURE SetScale(numer,denom: LongInt);
BEGIN
WITH dstRect DO
BEGIN
left := 360 - (360 * numer) DIV denom;
right := 360 + (360 * numer) DIV denom;
top := 182 - (182 * numer) DIV denom;
bottom:= 182 + (182 * numer) DIV denom;
END;
END;
PROCEDURE DumpPicture(myPicture: PicHandle);
LABEL 1;
VAR ch: CHAR;
i,byteCount: INTEGER;
count,total: INTEGER;
picPtr: QDPtr;
opCode,hiNibble,loNibble: INTEGER;
sameFlag: BOOLEAN;
srcBits: BitMap;
FUNCTION GetWord: INTEGER;
VAR word: INTEGER;
BEGIN
word := BitAnd(picPtr^,$FF);
picPtr := Pointer(ORD(picPtr)+1);
word := BitShift(word,+8) + BitAnd(picPtr^,$FF);
picPtr := Pointer(ORD(picPtr)+1);
GetWord := word;
END;
FUNCTION GetSByte: INTEGER;
BEGIN
GetSByte := picPtr^;
picPtr := Pointer(ORD(picPtr)+1);
END;
FUNCTION GetUByte: INTEGER;
BEGIN
GetUByte := BitAnd(picPtr^,$FF);
picPtr := Pointer(ORD(picPtr)+1);
END;
FUNCTION GetLong: LongInt;
VAR long: LongInt;
BEGIN
long := BitAnd(picPtr^,$FF);
picPtr := Pointer(ORD(picPtr)+1);
long := BitShift(long,+8) + BitAnd(picPtr^,$FF);
picPtr := Pointer(ORD(picPtr)+1);
long := BitShift(long,+8) + BitAnd(picPtr^,$FF);
picPtr := Pointer(ORD(picPtr)+1);
long := BitShift(long,+8) + BitAnd(picPtr^,$FF);
picPtr := Pointer(ORD(picPtr)+1);
GetLong := long;
END;
BEGIN
WRITELN;
WRITELN('picSize = ',myPicture^^.picSize,' bytes');
WITH myPicture^^.picFrame DO
WRITELN('picFrame = (',left:1,',',top:1,',',right:1,',',bottom:1,')');
picPtr := Pointer(ORD(myPicture^) + 10);
1: opCode := GetSByte;
WRITELN;
IF opCode = -1 THEN EXIT(DumpPicture);
loNibble := BitAnd(opCode,$F);
hiNibble := BitShift(BitAnd(opCode,$F0),-4);
IF hiNibble = 0 THEN
BEGIN
CASE loNibble OF
1: BEGIN
WRITE('Set clipRgn ');
byteCount := GetWord;
WRITE('rgnSize = ',byteCount);
picPtr := Pointer(ORD(picPtr) + byteCount - 2);
END;
2: BEGIN
WRITE('Set bkPat');
picPtr := Pointer(ORD(picPtr) + 8);
END;
3: BEGIN
WRITE('Set txFont ',GetWord);
END;
4: BEGIN
WRITE('Set txFace ',GetUByte);
END;
5: BEGIN
WRITE('Set txMode ',GetWord);
END;
6: BEGIN
WRITE('Set spExtra ',GetWord);
END;
7: BEGIN
WRITE('Set pnSize ',GetWord,GetWord);
END;
8: BEGIN
WRITE('Set pnMode ',GetWord);
END;
9: BEGIN
WRITE('Set pnPat');
picPtr := Pointer(ORD(picPtr) + 8);
END;
10: BEGIN
WRITE('Set thePat');
picPtr := Pointer(ORD(picPtr) + 8);
END;
11: BEGIN
WRITE('Set ovalSize ',GetWord,GetWord);
END;
12: BEGIN
WRITE('Set Origin ',GetWord,GetWord);
END;
13: BEGIN
WRITE('Set txSize ',GetWord);
END;
14: BEGIN
WRITE('Set ForeColor ',GetLong);
END;
15: BEGIN
WRITE('Set BackColor ',GetLong);
END;
END; { case }
GOTO 1;
END; { if hiNibble = 0 }
IF hiNibble = 1 THEN
BEGIN
CASE loNibble OF
0: BEGIN
WRITE('txNumer,txDenom = ',GetWord,GetWord,GetWord,GetWord);
END;
1: BEGIN
WRITE('picVersion = ',GetUByte);
END;
OTHERWISE WRITE('OOPS ! OPCODE WAS ',opCode);
END; { case }
GOTO 1;
END; { if hiNibble = 1 }
IF hiNibble = 2 THEN
BEGIN { text or line }
CASE loNibble OF
0: WRITE('Line from ',GetWord,GetWord,' to ',GetWord,GetWord);
1: WRITE('Line to ',GetWord,GetWord);
2: WRITE('Line from ',GetWord,GetWord, ' dh,dv = ',GetSByte,GetSByte);
3: WRITE('Line dh,dv = ',GetSByte,GetSByte);
8,9,10,11:
BEGIN { text }
CASE loNibble OF
8: WRITE('LongText at ',GetWord,GetWord,' ');
9: WRITE('DH Text, dh = ',GetUByte,' ');
10: WRITE('DV Text, dv = ',GetUByte,' ');
11: WRITE('DHDV Text, dh,dv = ',GetUByte,GetUByte,' ');
END;
byteCount := GetUByte;
FOR i:= 1 to byteCount DO WRITE(CHR(GetUByte));
END;
END; { case loNibble }
GOTO 1;
END;
IF hiNibble = 9 THEN WITH srcBits, bounds DO
BEGIN
sameFlag := FALSE; { not packed }
IF BitAnd(loNibble,$8) <> 0 THEN
BEGIN
sameFlag := TRUE; { packed }
loNibble := BitAnd(loNibble,$7);
WRITE('Pack');
END;
IF loNibble = 0
THEN WRITELN('BitsRect: ') ELSE WRITELN('BitsRgn: ');
rowBytes := GetWord;
top := GetWord;
left := GetWord;
bottom := GetWord;
right := GetWord;
WRITELN(' rowBytes = ',rowBytes);
WRITELN(' bounds = ',top,left,bottom,right);
WRITELN(' srcRect = ',GetWord,GetWord,GetWord,GetWord);
WRITELN(' dstRect = ',GetWord,GetWord,GetWord,GetWord);
WRITELN(' mode = ',GetWord);
IF loNibble <> 0 THEN
BEGIN
byteCount := GetWord;
WRITELN(' maskRgn rgnSize = ',byteCount);
picPtr := Pointer(ORD(picPtr) + byteCount-2);
END;
byteCount := rowBytes*(bottom-top);
IF sameFlag THEN
BEGIN
total := 0;
FOR i := top TO bottom - 1 DO
BEGIN
count := GetUByte;
total := total + count;
picPtr := Pointer(ORD(picPtr) + count);
END;
WRITELN(' ',byteCount:1,' bytes compressed to ',total);
END
ELSE
BEGIN
WRITELN(' Uncompressed bytes = ',byteCount);
picPtr := Pointer(ORD(picPtr) + byteCount);
END;
GOTO 1;
END;
IF hiNibble = 10 THEN
BEGIN
IF loNibble = 0 THEN
BEGIN
WRITE('Short Comment ',GetWord);
GOTO 1;
END;
WRITE('Long Comment ',GetWord);
byteCount := GetWord;
picPtr := Pointer(ORD(picPtr) + byteCount);
GOTO 1;
END;
IF hiNibble > 10 THEN
BEGIN
WRITE('OOPS, hiNibble > 10 ! opcode was ',opCode);
READLN;
GOTO 1;
END;
{ hi nibble is 3..8 }
sameFlag := FALSE;
IF BitAnd(loNibble,$8) <> 0 THEN
BEGIN
sameFlag := TRUE;
loNibble := BitAnd(loNibble,$7);
END;
CASE loNibble OF
0: WRITE('Frame');
1: WRITE('Paint');
2: WRITE('Erase');
3: WRITE('Invert');
4: WRITE('Fill');
END;
IF sameFlag THEN WRITE('Same');
CASE hiNibble OF
3: BEGIN
WRITE('Rect');
IF NOT sameFlag THEN WRITE(GetWord,GetWord,GetWord,GetWord);
END;
4: BEGIN
WRITE('RRect');
IF NOT sameFlag THEN WRITE(GetWord,GetWord,GetWord,GetWord);
END;
5: BEGIN
WRITE('Oval');
IF NOT sameFlag THEN WRITE(GetWord,GetWord,GetWord,GetWord);
END;
6: BEGIN
WRITE('Arc');
IF NOT sameFlag THEN WRITE(GetWord,GetWord,GetWord,GetWord);
WRITE(GetWord,GetWord);
END;
7: BEGIN
WRITE('Poly');
byteCount := GetWord;
WRITE(' polySize = ',byteCount);
picPtr := Pointer(ORD(picPtr) + byteCount-2);
END;
8: BEGIN
WRITE('Rgn');
byteCount := GetWord;
WRITE(' rgnSize = ',byteCount);
picPtr := Pointer(ORD(picPtr) + byteCount-2);
END;
END;
GOTO 1;
END;
BEGIN { main program }
WRITE('Press return '); READLN;
NEW(heapStart);
heapLimit:=Pointer(ORD(heapStart)+heapSize);
RELEASE(heapLimit); { forward release to allocate }
InitHeap(heapStart,heapLimit,@heapError);
InitGraf(@thePort);
InitCursor;
HideCursor;
FMInit(errNum);
IF errNum <> 0 THEN
BEGIN
WRITELN('FMInit says errNum=',errNum);
HALT;
END;
StuffHex(@myPattern,'8040200002040800');
InitIcons;
InitScales;
NEW(port1);
OpenPort(port1);
PaintRect(thePort^.portRect);
DrawStuff;
READLN;
myPicture := OpenPicture(thePort^.portRect);
DrawStuff;
ClosePicture;
WRITELN('picSize = ',myPicture^^.picSize:1);
READLN;
DrawPicture(myPicture,thePort^.portRect);
WRITE('Dump ?'); READ(ch); WRITELN;
IF ch IN ['Y','y'] THEN
BEGIN
DumpPicture(myPicture);
READLN;
END;
WRITE('ABOUT TO make bigPicture '); READLN;
bigPicture := OpenPicture(thePort^.portRect);
DrawPicture(myPicture,thePort^.portRect);
tempRect := thePort^.portRect;
InsetRect(tempRect,100,50);
DrawPicture(myPicture,tempRect);
InsetRect(tempRect,100,50);
DrawPicture(myPicture,tempRect);
ClosePicture;
WRITELN('big picSize = ',bigPicture^^.picSize:1);
READLN;
DrawPicture(bigPicture,thePort^.portRect);
WRITE('Dump Big ?'); READ(ch); WRITELN;
IF ch IN ['Y','y'] THEN
BEGIN
DumpPicture(bigPicture);
READLN;
END;
KillPicture(bigPicture);
WRITE('ABOUT TO DO NORMAL from picture '); READLN;
ColorBit(normalBit);
DrawPicture(myPicture,thePort^.portRect);
WRITE('ABOUT TO DO INVERSE from picture '); READLN;
ColorBit(inverseBit);
DrawPicture(myPicture,thePort^.portRect);
WRITE('ABOUT TO DO CYAN from picture '); READLN;
ColorBit(cyanBit);
DrawPicture(myPicture,thePort^.portRect);
WRITE('ABOUT TO DO MAGENTA from picture '); READLN;
ColorBit(magentaBit);
DrawPicture(myPicture,thePort^.portRect);
WRITE('ABOUT TO DO YELLOW from picture '); READLN;
ColorBit(yellowBit);
DrawPicture(myPicture,thePort^.portRect);
WRITE('ABOUT TO DO BLACK from picture'); READLN;
ColorBit(blackBit);
DrawPicture(myPicture,thePort^.portRect);
ColorBit(normalBit);
READLN;
PaintRect(thePort^.portRect);
REPEAT
FOR i:=0 to 15 DO
BEGIN
SetScale(numerArray[i],denomArray[i]);
DrawPicture(myPicture,dstRect);
IF MouseButton THEN GOTO 1;
END;
FOR i:=14 DOWNTO 1 DO
BEGIN
SetScale(numerArray[i],denomArray[i]);
DrawPicture(myPicture,dstRect);
IF MouseButton THEN GOTO 1;
END;
UNTIL FALSE;
1: ShowCursor;
SetRect(myPicture^^.picFrame,0,0,200,100);
REPEAT UNTIL NOT MouseButton;
REPEAT
REPEAT UNTIL MouseButton;
GetMouse(dstRect.topLeft);
REPEAT UNTIL NOT MouseButton;
GetMouse(dstRect.botRight);
ClipRect(thePort^.portRect);
PaintRect(thePort^.portRect);
DrawPicture(myPicture,dstRect);
IF MouseButton THEN EXIT(TestGraf);
UNTIL FALSE;
KillPicture(myPicture);
END.

740
Text.a Executable file
View File

@ -0,0 +1,740 @@
.INCLUDE GRAFTYPES.TEXT
;---------------------------------------------------------
;
;
; ***** ***** * * *****
; * * * * *
; * * * * *
; * *** * *
; * * * * *
; * * * * *
; * ***** * * *
;
;
; Routines for measuring and drawing Text.
;
;-------------------------------------------
;
; KERNED STRIKE FONT FORMAT OFFSETS:
;
FORMAT .EQU 0 ;WORD
MINCHAR .EQU 2 ;WORD
MAXCHAR .EQU 4 ;WORD
MAXWD .EQU 6 ;WORD
FBBOX .EQU 8 ;WORD
FBBOY .EQU 10 ;WORD
FBBDX .EQU 12 ;WORD
FBBDY .EQU 14 ;WORD
LENGTH .EQU 16 ;WORD
ASCENT .EQU 18 ;WORD
DESCENT .EQU 20 ;WORD
XOFFSET .EQU 22 ;WORD
RASTER .EQU 24 ;WORD
.PROC StdText,4
.REF CheckPic,DPutPicByte,PutPicData,PutPicWord,PutPicLong
.REF DrText
;--------------------------------------------------------------------------
;
; PROCEDURE StdText(count: INTEGER; textAddr: Ptr; numer,denom: Point);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 14
COUNT .EQU PARAMSIZE+8-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG
NUMER .EQU TEXTADDR-4 ;POINT
DENOM .EQU NUMER-4 ;POINT
TXLOC .EQU -4 ;POINT
VARSIZE .EQU TXLOC ;TOTAL LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D5-D7/A3-A4,-(SP) ;SAVE REGS
TXTLOOP MOVE COUNT(A6),D6 ;GET CHARACTER COUNT
BLE GOHOME ;QUIT IF COUNT <= 0
CMP #255,D6 ;is count > 255 ?
BLE.S COUNTOK ;no, continue
MOVE #255,D6 ;yes, pin at 255
COUNTOK JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE NOTPIC
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
;
; CHECK TXFONT
;
MOVE TXFONT(A3),D7 ;GET THEPORT^.TXFONT
CMP PICTXFONT(A4),D7 ;HAS IT CHANGED ?
BEQ.S FONTOK ;NO, CONTINUE
MOVEQ #3,D0 ;YES, PUSH TXFONT PARAM OPCODE
JSR DPutPicByte ;PUT OPCODE
MOVE D7,-(SP)
JSR PutPicWord ;PUT TXFONT PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE D7,PICTXFONT(A4) ;UPDATE CURRENT STATE
;
; CHECK TXFACE
;
FONTOK MOVE.B TXFACE(A3),D7 ;GET THEPORT^.TXFACE
CMP.B PICTXFACE(A4),D7 ;HAS IT CHANGED ?
BEQ.S FACEOK ;NO, CONTINUE
MOVEQ #4,D0 ;YES, PUSH TXFACE PARAM OPCODE
JSR DPutPicByte ;PUT OPCODE
MOVE.B D7,D0
JSR DPutPicByte ;PUT TXFACE PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.B D7,PICTXFACE(A4) ;UPDATE CURRENT STATE
;
; CHECK TXMODE
;
FACEOK MOVE TXMODE(A3),D7 ;GET THEPORT^.TXMODE
CMP PICTXMODE(A4),D7 ;HAS IT CHANGED ?
BEQ.S MODEOK ;NO, CONTINUE
MOVEQ #5,D0 ;YES, PUSH TXMODE PARAM OPCODE
JSR DPutPicByte ;PUT OPCODE
MOVE D7,-(SP)
JSR PutPicWord ;PUT TXMODE PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE D7,PICTXMODE(A4) ;UPDATE CURRENT STATE
;
; CHECK TXSIZE
;
MODEOK MOVE TXSIZE(A3),D7 ;GET THEPORT^.TXSIZE
CMP PICTXSIZE(A4),D7 ;HAS IT CHANGED ?
BEQ.S SIZEOK ;NO, CONTINUE
MOVEQ #$0D,D0 ;YES, PUSH TXSIZE PARAM OPCODE
BSR.S JDPutPicByte ;PUT OPCODE
MOVE D7,-(SP)
JSR PutPicWord ;PUT TXSIZE PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE D7,PICTXSIZE(A4) ;UPDATE CURRENT STATE
;
; CHECK SPEXTRA
;
SIZEOK MOVE.L SPEXTRA(A3),D7 ;GET THEPORT^.SPEXTRA
CMP.L PICSPEXTRA(A4),D7 ;HAS IT CHANGED ?
BEQ.S SPOK ;NO, CONTINUE
MOVEQ #6,D0 ;YES, PUSH SPEXTRA PARAM OPCODE
BSR.S JDPutPicByte ;PUT OPCODE
MOVE.L D7,-(SP)
BSR.S JPutPicLong ;PUT SPEXTRA PARAM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L D7,PICSPEXTRA(A4) ;UPDATE CURRENT STATE
;
; CHECK NUMER, DENOM
;
SPOK MOVE.L NUMER(A6),D7 ;GET NUMER
MOVE.L DENOM(A6),D5 ;GET DENOM
CMP.L PICTXNUMER(A4),D7 ;HAS IT CHANGED ?
BNE.S NOTSAME ;YES, RECORD CHANGE
CMP.L PICTXDENOM(A4),D5 ;HAS IT CHANGED ?
BEQ.S NUMEROK ;NO, CONTINUE
NOTSAME MOVEQ #$10,D0 ;YES, PUSH TXRATIO OPCODE
BSR.S JDPutPicByte ;PUT OPCODE
MOVE.L D7,-(SP)
BSR.S JPutPicLong ;PUT NUMER
MOVE.L D5,-(SP)
BSR.S JPutPicLong ;PUT DENOM
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L D7,PICTXNUMER(A4) ;UPDATE CURRENT STATE
MOVE.L D5,PICTXDENOM(A4) ;UPDATE CURRENT STATE
NUMEROK
;-------------------------------------------------------------
;
; USE DH AND DV TO CHOOSE ONE OF FOUR TEXT OPCODES.
;
MOVE.L PNLOC(A3),D5 ;GET CURRENT PNLOC
SUB.L PICTXLOC(A4),D5 ;CALC DV.DH
MOVE.L D5,D0 ;COPY DV.DH
AND.L #$FF00FF00,D0 ;ARE DH AND DV BOTH 0..255 ?
BEQ.S SHORT ;YES, USE SHORT FORM
MOVEQ #$28,D0
BSR.S JDPutPicByte ;NO, PUT LONGTEXT OPCODE
MOVE.L PNLOC(A3),-(SP)
BSR.S JPutPicLong ;PUT PNLOC 4 BYTES
BRA.S TEXT2 ;AND CONTINUE
JDPutPicByte
JMP DPutPicByte
JPutPicLong
JMP PutPicLong
SHORT MOVE.L D5,D0 ;YES, COPY DV.DH
AND.L #$00FF0000,D0 ;IS DV = 0 ?
BNE.S DV ;NO, CONTINUE
MOVEQ #$29,D0
BSR.S JDPutPicByte ;YES, PUT DHTEXT OPCODE
BRA.S SHARE2 ;SHARE COMMON CODE
DV TST.B D5 ;IS DH = 0 ?
BNE.S DHDV ;NO, CONTINUE
MOVEQ #$2A,D0
BSR.S JDPutPicByte ;YES, PUT DVTEXT OPCODE
BRA.S SHARE1 ;SHARE COMMON CODE
DHDV MOVEQ #$2B,D0
BSR.S JDPutPicByte ;PUT DHDVTEXT OPCODE
MOVE.B D5,D0
BSR.S JDPutPicByte ;PUT DH 0..255 TO PIC
SHARE1 SWAP D5 ;PUT DV IN LO WORD
SHARE2 MOVE.B D5,D0
BSR.S JDPutPicByte ;PUT DH OR DV 0..255 TO PIC
TEXT2 MOVE.B D6,D0
BSR.S JDPutPicByte ;PUT COUNT BYTE TO PIC
MOVE.L TEXTADDR(A6),-(SP) ;PUSH ADDR OF TEXT
MOVE D6,-(SP) ;PUSH COUNT
JSR PutPicData ;PUT TEXT DATA
MOVE.L PICSAVE(A3),A4 ;GET PICSAVE HANDLE
MOVE.L (A4),A4 ;DE-REFERENCE PICSAVE
MOVE.L PNLOC(A3),PICTXLOC(A4) ;UPDATE PICTXLOC STATE
;
; DrText(count,textAddr,numer,denom);
;
NOTPIC MOVE D6,-(SP) ;PUSH COUNT
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
MOVE.L NUMER(A6),-(SP) ;PUSH NUMER
MOVE.L DENOM(A6),-(SP) ;PUSH DENOM
JSR DrText ;DRAW THE TEXT
SUB D6,COUNT(A6) ;was count > 255 ?
BLE.S GOHOME ;no, quit
MOVE.L TEXTADDR(A6),A0 ;yes, get old textaddr
ADD D6,A0 ;offset for characters done
MOVE.L A0,TEXTADDR(A6) ;update textAddr
BRA TXTLOOP ;and loop for more
GOHOME MOVEM.L (SP)+,D5-D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDTEXT '
.PROC CallText,2
.REF STDTEXT
;---------------------------------------------------------------
;
; PROCEDURE CallText(count: INTEGER; textAddr: Ptr);
;
MOVE.L (SP)+,A0 ;POP RETURN ADDR
MOVE.L #$00010001,-(SP) ;PUSH NUMER = (1,1)
MOVE.L (SP),-(SP) ;PUSH DENOM = (1,1)
MOVE.L A0,-(SP) ;RESTORE RETURN ADDR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDTEXT,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L TEXTPROC(A0),A0 ;NO, GET PROC PTR
USESTD JMP (A0) ;GO TO IT
.PROC TextFace,1
.DEF DrawChar,CharWidth
.REF CallText,TextWidth
;-------------------------------------------------------
;
; PROCEDURE TextFace(face: Style);
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
MOVE.B 5(SP),TXFACE(A0) ;INSTALL TXFACE
BRA.S SHARE ;STRIP PARAM AND RETURN
;----------------------------------------------------
;
; PROCEDURE DrawChar(ch: CHAR);
;
DrawChar
MOVE #1,-(SP) ;PUSH COUNT=1
PEA 7(SP) ;PUSH TEXTADDR
JSR CallText ;CALL TEXT ROUTINE
BRA.S SHARE ;STRIP PARAM AND RETURN
;---------------------------------------------
;
; FUNCTION CharWidth(ch: CHAR): INTEGER;
;
CharWidth
CLR -(SP) ;ROOM FOR FCN RESULT
MOVE.L SP,-(SP) ;PUSH TEXTBUF
MOVE.L #$00010007,-(SP) ;PUSH OFFSET = 7 & COUNT = 1
JSR TEXTWIDTH
MOVE (SP)+,6(SP) ;MOVE UP RESULT
SHARE MOVE.L (SP)+,A0 ;POP RETURN ADDR
ADD #2,SP ;STRIP CHAR PARAM
JMP (A0) ;AND RETURN
.PROC TextFont,1
.DEF TextSize
.DEF TextMode
.REF PortWord
;-------------------------------------------------------
;
; PROCEDURE TextFont(font: INTEGER);
;
MOVEQ #TXFONT,D0 ;PUT PORT OFFSET IN D0
BRA.S SHARE
;-------------------------------------------------------
;
; PROCEDURE TextMode(mode: INTEGER);
;
TextMode
MOVEQ #TXMODE,D0 ;PUT PORT OFFSET IN D0
BRA.S SHARE
;-------------------------------------------------------
;
; PROCEDURE TextSize(mode: INTEGER);
;
TextSize
MOVEQ #TXSIZE,D0 ;PUT PORT OFFSET IN D0
SHARE JMP PORTWORD ;INSTALL PARAM INTO THEPORT
.PROC SpaceExtra,1
.DEF DrawString,DrawText
.REF CallText
;-------------------------------------------------------
;
; PROCEDURE SpaceExtra(extra: LongInt);
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QuickDraw GLOBALS
MOVE.L THEPORT(A0),A0 ;POINT TO THEPORT
MOVE.L 4(SP),SPEXTRA(A0) ;INSTALL FIXED POINT SPEXTRA
BRA.S SHARE
;----------------------------------------------------
;
; PROCEDURE DrawString(s: Str255);
;
DrawString
MOVE.L 4(SP),A0 ;POINT TO STRING
CLR D0 ;GET READY FOR BYTE
MOVE.B (A0)+,D0 ;GET STRING LENGTH
MOVE D0,-(SP) ;PUSH COUNT
MOVE.L A0,-(SP) ;PUSH TEXTADDR
JSR CallText ;CALL TEXT ROUTINE
BRA.S SHARE
;----------------------------------------------------
;
; PROCEDURE DrawText(textBuf: WordPtr; start,count: INTEGER);
;
DrawText
MOVE.L 8(SP),A0 ;POINT TO TEXTBUF
ADD 6(SP),A0 ;ADD STARTING OFFSET
MOVE 4(SP),-(SP) ;PUSH COUNT
MOVE.L A0,-(SP) ;PUSH TEXTADDR
JSR CallText ;CALL TEXT ROUTINE
MOVE.L (SP)+,(SP)
SHARE MOVE.L (SP)+,(SP) ;STRIP PARAMS
RTS ;AND RETURN
.FUNC StringWidth,1
.REF TextWidth
;---------------------------------------------
;
; FUNCTION StringWidth(s: Str255): INTEGER;
;
MOVE.L (SP)+,A1 ;POP RETURN ADDR
MOVE.L (SP)+,A0 ;POP ADDR OF STRING
CLR D0
MOVE.B (A0)+,D0 ;GET UNSIGNED BYTE
MOVE.L A0,-(SP) ;PUSH TEXTADDR
CLR -(SP) ;FIRSTBYTE := 0
MOVE D0,-(SP) ;PUSH BYTECOUNT
MOVE.L A1,-(SP) ;PUT BACK RETURN ADDR
;
; FALL THRU INTO TEXTWIDTH
;
.FUNC TextWidth,3
.REF StdTxMeas
;------------------------------------------
;
; FUNCTION TEXTWIDTH(TEXTBUF: WordPtr; firstbyte,byteCount: INTEGER): INTEGER;
;
PARAMSIZE .EQU 8
RESULT .EQU PARAMSIZE+8
TEXTBUF .EQU RESULT-4 ;LONG
FIRSTBYTE .EQU TEXTBUF-2 ;WORD
BYTECOUNT .EQU FIRSTBYTE-2 ;WORD
INFO .EQU -8 ;4 WORDS
NUMER .EQU INFO-4 ;POINT
DENOM .EQU NUMER-4 ;POINT
VARSIZE .EQU DENOM ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
CLR RESULT(A6) ;INIT RESULT TO 0
CLR -(SP) ;MAKE ROOM FOR FCN CALL BELOW
MOVE BYTECOUNT(A6),-(SP) ;PUSH BYTE COUNT
BLE.S GOHOME ;QUIT IF COUNT <= 0
;UNLK TAKES CARE OF SP
MOVE.L TEXTBUF(A6),A0 ;GET ADDR OF BUFFER
ADD FIRSTBYTE(A6),A0 ;ADD STARTING INDEX
MOVE.L A0,-(SP) ;PUSH TEXTADDR
MOVE.L #$00010001,D0
MOVE.L D0,NUMER(A6) ;NUMER := (1,1)
MOVE.L D0,DENOM(A6) ;DENOM := (1,1)
PEA NUMER(A6) ;PUSH VAR NUMER
PEA DENOM(A6) ;PUSH VAR DENOM
PEA INFO(A6) ;PUSH VAR INFO
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
BEQ.S STD ;YES, USE STDTXMEAS
MOVE.L D0,A0 ;NO, GET GRAFPROCS
MOVE.L TXMEASPROC(A0),A0 ;GET TXMEAS CAPTURE PROC
JSR (A0) ;CALL IT
BRA.S NOTSTD ;AND CONTINUE
STD JSR STDTXMEAS
NOTSTD MOVE (SP)+,D1 ;POP UNSCALED WIDTH
MOVE NUMER+H(A6),D0 ;get numer
MOVE DENOM+H(A6),D2 ;get denom
CMP D2,D0 ;is numer same as denom ?
BEQ.S DONE ;yes, skip muldiv
MULU D0,D1 ;MUL BY NUMER
MOVE D2,D0 ;COPY DENOM
LSR #1,D0 ;CALC DENOM DIV 2
ADD D0,D1 ;ADD DENOM DIV 2
DIVU D2,D1 ;DIV BY DENOM
DONE MOVE D1,RESULT(A6) ;RETURN SCALED WIDTH
GOHOME UNLINK PARAMSIZE,'TEXTWIDT'
.FUNC StdTxMeas,5
;------------------------------------------
;
; FUNCTION StdTxMeas(count: INTEGER; textAddr: Ptr;
; VAR numer,denom: Point;
; VAR info: FontInfo): INTEGER;
;
; Measure some text, returning unscaled values plus updated scale factor.
; Fills info record with unscaled ascent, descent, widMax, and leading,
; and returns unscaled integer width as the function value.
;
; Also leaves unscaled fixed point width in QD global 'fixTxWid'
; and stashes FMOutPtr in QD global 'fontPtr' for DrawText.
;
PARAMSIZE .EQU 18
RESULT .EQU PARAMSIZE+8 ;FCN RESULT IS A WORD
COUNT .EQU RESULT-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG
NUMER .EQU TEXTADDR-4 ;LONG, VAR ADDR
DENOM .EQU NUMER-4 ;LONG, VAR ADDR
INFO .EQU DENOM-4 ;LONG, ADDR OF FONTINFO
INREC .EQU -16 ;FMInput record
VARSIZE .EQU INREC
LINK A6,#VARSIZE ;ALLOCATE LOCALS
MOVE.L A4,-(SP) ;SAVE REG
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A0 ;GET CURRENT GRAFPORT
LEA INREC(A6),A1 ;POINT TO FMINPUT RECORD
MOVE TXFONT(A0),(A1)+ ;GET TXFONT FROM THEPORT
MOVE TXSIZE(A0),(A1)+ ;GET TXSIZE FROM THEPORT
MOVE.B TXFACE(A0),(A1)+ ;GET TXFACE FROM THEPORT
ST (A1)+ ;ALWAYS SET NEEDBITS TRUE
MOVE DEVICE(A0),(A1)+ ;GET DEVICE FROM THEPORT
MOVE.L NUMER(A6),A0 ;POINT TO NUMER
MOVE.L (A0),(A1)+ ;INSTALL INPUT NUMER
MOVE.L DENOM(A6),A0 ;POINT TO DENOM
MOVE.L (A0),(A1)+ ;INSTALL INPUT DENOM
CLR.L -(SP) ;ROOM FOR FCN RESULT
PEA INREC(A6) ;PUSH INPUT RECORD
_SwapFont ;CALL FMSWAPFONT
MOVE.L (SP)+,A1 ;POP FMOUTPUT POINTER
MOVE.L A1,FONTPTR(A4) ;STASH FMOUTPTR FOR LATER
MOVE.L INFO(A6),A0 ;POINT TO VAR INFO RECORD
CLR.L (A0) ;INIT TO (0,0,0,0)
CLR.L 4(A0) ;ALL 4 WORDS
MOVE.B 13(A1),1(A0) ;FILL IN UNSIGNED ASCENT
MOVE.B 14(A1),3(A0) ;FILL IN UNSIGNED DESCENT
MOVE.B 15(A1),5(A0) ;FILL IN UNSIGNED WIDMAX
MOVE.B 16(A1),D0 ;GET SIGNED LEADING
EXT.W D0 ;SIGN EXTEND TO WORD
MOVE.W D0,6(A0) ;FILL IN LEADING
;
; UPDATE NUMER AND DENOM
;
MOVE.L NUMER(A6),A0 ;GET VAR ADDR
MOVE.L 18(A1),(A0) ;UPDATE NUMER
MOVE.L DENOM(A6),A0 ;GET VAR ADDR
MOVE.L 22(A1),(A0) ;UPDATE DENOM
MOVE.L TEXTADDR(A6),A0 ;POINT TO CHARACTERS
MOVE.L WidthPtr,A1 ;POINT TO WIDTH TABLE
CLR.L D1 ;INIT WIDTH TO 0.0
MOVE COUNT(A6),D2 ;GET CHARACTER COUNT
BRA.S MORE ;GO TO LOOP START
NEXTCH CLR D0 ;GET READY FOR BYTE
MOVE.B (A0)+,D0 ;GET A CHARACTER
LSL #2,D0 ;QUAD FOR TABLE OFFSET
ADD.L 0(A1,D0),D1 ;ADD FIXED POINT WIDTH
MORE DBRA D2,NEXTCH ;LOOP FOR ALL CHARS
MOVE.L D1,fixTxWid(A4) ;STASH FIXED POINT WIDTH
SWAP D1 ;GET HI WORD = INTEGER PORTION
MOVE D1,RESULT(A6) ;UPDATE FUNCTION RESULT
MOVE.L (SP)+,A4 ;RESTORE REG
UNLINK PARAMSIZE,'STDTXMEA'
.PROC MeasureText
;--------------------------------------------------------------------
;
; PROCEDURE MeasureText(count: INTEGER; textAddr,charLocs: Ptr);
;
; Measure some text, returning (scaled) screen widths in charlocs.
;
; Charlocs points to an array of count+1 integers.
;
PARAMSIZE .EQU 10
COUNT .EQU PARAMSIZE+8-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG, Ptr to ASCII
CHARLOCS .EQU TEXTADDR-4 ;LONG, Ptr to output array
INREC .EQU -16 ;FMInput record
VARSIZE .EQU INREC
LINK A6,#VARSIZE ;ALLOCATE LOCALS
MOVEM.L D3-D4/A2,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
;
; Call swapfont to set up width table and return numer,denom:
;
LEA INREC(A6),A1 ;POINT TO FMINPUT RECORD
MOVE TXFONT(A0),(A1)+ ;GET TXFONT FROM THEPORT
MOVE TXSIZE(A0),(A1)+ ;GET TXSIZE FROM THEPORT
MOVE.B TXFACE(A0),(A1)+ ;GET TXFACE FROM THEPORT
ST (A1)+ ;ALWAYS SET NEEDBITS TRUE
MOVE DEVICE(A0),(A1)+ ;GET DEVICE FROM THEPORT
MOVE.L #$00010001,(A1)+ ;INSTALL INPUT NUMER = 1,1
MOVE.L #$00010001,(A1)+ ;INSTALL INPUT DENOM = 1,1
CLR.L -(SP) ;ROOM FOR FCN RESULT
PEA INREC(A6) ;PUSH INPUT RECORD
_SwapFont ;CALL FMSWAPFONT
MOVE.L (SP)+,A0 ;POP FMOUTPUT POINTER
MOVE.W 18+H(A0),D3 ;GET NUMER.H
MOVE.W 22+H(A0),D4 ;GET DENOM.H
;
; Step thru characters, adding up unscaled widths and storing in charLocs:
;
MOVE.L TEXTADDR(A6),A0 ;POINT TO CHARACTERS
MOVE.L WidthPtr,A1 ;POINT TO WIDTH TABLE
MOVE.L CHARLOCS(A6),A2 ;POINT TO CHARLOCS
CLR.L D1 ;INIT WIDTH TO 0.0
MOVE COUNT(A6),D2 ;GET CHARACTER COUNT
NEXTCH SWAP D1 ;GET HI WORD OF WIDTH
MOVE.W D1,(A2)+ ;STORE IN CHARLOCS
SWAP D1 ;RETURN WIDTH TO FIXED POINT
CLR D0 ;GET READY FOR BYTE
MOVE.B (A0)+,D0 ;GET A CHARACTER
LSL #2,D0 ;QUAD FOR TABLE OFFSET
ADD.L 0(A1,D0),D1 ;ADD FIXED POINT WIDTH
MORE DBRA D2,NEXTCH ;LOOP FOR COUNT+1 CHARLOCS
;
; if font is horizontally stretched, scale all widths accordingly
;
CMP D3,D4 ;IS NUMER.H = DENOM.H ?
BEQ.S NOSCALE ;YES, SKIP SCALING
MOVE D4,D1 ;COPY DENOM
LSR #1,D1 ;CALC DENOM DIV 2
MOVE.L CHARLOCS(A6),A2 ;NO, POINT TO CHARLOCS
MOVE COUNT(A6),D2 ;GET CHARACTER COUNT
NEXTCH2 MOVE (A2),D0 ;GET CHARLOC
MULU D3,D0 ;MUL BY NUMER
ADD D1,D0 ;ADD DENOM DIV 2
DIVU D4,D0 ;DIV BY DENOM
MOVE D0,(A2)+ ;UPDATE CHARLOC
DBRA D2,NEXTCH2 ;LOOP FOR COUNT+1 CHARLOCS
NOSCALE
MOVEM.L(SP)+,D3-D4/A2 ;RESTORE REGS
UNLINK PARAMSIZE,'MEASURET'
;--------------------------------------------------------------------
;
; FUNCTION FMSwapFont(inRec: FMInput): FMOutPtr;
;
; FMSwapFont is the only contact between QuickDraw and the Font Manager.
; It swaps in the requested font and returns a pointer to an output record
; telling how to use the font. FMSwapFont is called from StdTxMeas
; in response to DrawChar, DrawString, DrawText, CharWidth, StringWidth,
; TextWidth, and GetFontInfo.
;
; IF fontHandle returns as Nil (can't find the font), then:
; 1. The output record will be undefined except for errNum and fontHandle.
; 2. DrawString will neither draw the text nor bump the pen.
; 3. StringWidth will return 0.
; 4. GetFontInfo will return 0,0,0,0.
;
;
; FMInput = PACKED RECORD
; family: INTEGER; { i.e. Century }
; size: INTEGER; { i.e. 12 point }
; face: Style; { i.e. [bold,underlined] }
; needBits: BOOLEAN; { do we need the bitmaps ? }
; device: INTEGER; { i.e. 0 for screen }
; numer: Point; { current drawing scale }
; denom: Point; { current drawing scale }
; END;
;
;
; FMOutPtr = ^FMOutPut;
; FMOutput = PACKED RECORD
; errNum: INTEGER; { not used }
; fontHandle: Handle; { handle to font }
; bold: Byte; { how much to smear horiz }
; italic: Byte; { how much to shear }
; ulOffset: Byte; { pixels below baseline }
; ulShadow: Byte; { how big is the halo }
; ulThick: Byte; { how thick is the underline }
; shadow: Byte; { 0,1,2,or 3 only }
; extra: SignedByte; { extra white dots each char }
; ascent: Byte; { ascent measure for font }
; descent: Byte; { descent measure for font }
; widMax: Byte; { width of widest char }
; leading: SignedByte; { leading between lines }
; unused: Byte;
; numer: Point; { use this modified scale to }
; denom: Point; { draw or measure text with }
; END;
;
;
;
;--------------------------------------------------------------------------
.PROC GetFontInfo,1
.REF StdTxMeas
;------------------------------------------
;
; PROCEDURE GetFontInfo(VAR info: FontInfo);
;
; Calls StdTxMeas thru capture proc, then adjusts and scales the result.
;
; 13 MAY 85, changed so that all 4 values round UP in the case of scaling.
;
PARAMSIZE .EQU 4
INFO .EQU PARAMSIZE+8-4 ;LONG, ADDR OF INFO
NUMER .EQU -4 ;POINT
DENOM .EQU NUMER-4 ;POINT
VARSIZE .EQU DENOM ;TOTAL LOCALS
LINK A6,#VARSIZE ;ALLOCATE LOCALS
MOVE.L #$00010001,NUMER(A6) ;NUMER := (1,1)
MOVE.L #$00010001,DENOM(A6) ;DENOM := (1,1)
CLR.L -(SP) ;ROOM FOR FCN, COUNT = 0
CLR.L -(SP) ;TEXTADDR := NIL
PEA NUMER(A6) ;PUSH VAR NUMER
PEA DENOM(A6) ;PUSH VAR DENOM
MOVE.L INFO(A6),-(SP) ;PUSH VAR INFO
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
LEA STDTXMEAS,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L TXMEASPROC(A0),A0 ;NO, GET TXMEAS CAPTURE PROC
USESTD JSR (A0) ;CALL IT
TST (SP)+ ;DISCARD WIDTH FCN RSLT
;
; ADJUST WIDMAX FOR EXTRA
;
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L FONTPTR(A0),A0 ;GET FMOUTPUT RECORD
MOVE.L INFO(A6),A1 ;POINT TO RESULT INFO
MOVE.B 12(A0),D0 ;GET SIGNED EXTRA
EXT.W D0 ;EXTEND TO WORD
ADD D0,4(A1) ;ADD TO WIDMAX
;
; ADJUST ASCENT & DESCENT FOR SHADOW
;
CLR D0 ;GET READY FOR BYTE
MOVE.B 11(A0),D0 ;GET SHADOW COUNT
BEQ.S NOTSHAD ;SKIP IF ZERO
ADD #1,0(A1) ;ADJUST ASCENT
ADD D0,2(A1) ;ADJUST DESCENT
NOTSHAD
;
; SCALE RESULT IF NUMER <> DENOM
;
MOVE.L NUMER(A6),D0
CMP.L DENOM(A6),D0 ;IS NUMER SAME AS DENOM ?
BEQ.S NOSCALE ;YES, SKIP SCALING
BSR.S SCALE ;SCALE ASCENT
BSR.S SCALE ;SCALE DESCENT
MOVE (A1),D0 ;GET MAXWID
MULU NUMER+H(A6),D0 ;SCALE MAXWID
MOVE DENOM+H(A6),D1 ;get denom
SUB #1,D1 ;calc denom-1
EXT.L D1 ;extend to long
ADD.L D1,D0 ;add denom-1 to round up
DIVU DENOM+H(A6),D0 ;divide by denom
MOVE D0,(A1)+ ;UPDATE MAXWID
BSR.S SCALE ;SCALE LEADING
NOSCALE UNLINK PARAMSIZE,'GETFONTI'
SCALE MOVE (A1),D0 ;GET IT
MULU NUMER+V(A6),D0 ;SCALE IT
MOVE DENOM+V(A6),D1 ;get denom
SUB #1,D1 ;calc denom-1
EXT.L D1 ;extend to long
ADD.L D1,D0 ;add denom-1 to round up
DIVU DENOM+V(A6),D0 ;divide by denom
MOVE D0,(A1)+ ;UPDATE IT
RTS
.END

837
Util.a Executable file
View File

@ -0,0 +1,837 @@
.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