mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-01 11:29:27 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
351 lines
14 KiB
Plaintext
351 lines
14 KiB
Plaintext
;
|
|
; File: DeviceLoop.a
|
|
;
|
|
; Contains: _DeviceLoop, a trap to assist in multi-device drawing
|
|
;
|
|
; Written by: Chris Derossi
|
|
;
|
|
; Copyright: © 1990-1991 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <8> 1/13/92 PN Adding the quick draw "DeviceLoop" into ROM
|
|
; <7> 3/26/91 dba csd: take out VisRgnChanged, since I didnÕt really understand
|
|
; <6> 9/14/90 csd Used the interfaces instead of local definitions.
|
|
; <5> 8/20/90 dba call VisRgnChanged, now that it exists
|
|
; <4> 7/16/90 DC Fixed bug which I so graciously introduced into this code with
|
|
; change <3> Used d0 to hold first GDevice to check in stead of
|
|
; A4.
|
|
; <3> 7/12/90 DC changed loop priming to use TheGDevice instead of DeviceList
|
|
; whe TheGDevice is not equal to MainDevice (off-screen case)
|
|
; <2> 4/11/90 dba put in the trap number
|
|
; <1> 4/11/90 dba made it a linked patch
|
|
;
|
|
|
|
print push,off
|
|
load 'StandardEqu.d'
|
|
include 'LinkedPatchMacros.a'
|
|
print pop
|
|
|
|
;----------------------------------------------------------------------------------------------
|
|
; PROCEDURE DeviceLoop(drawingRgn : RgnHandle; drawingProc : ProcPtr;
|
|
; userData : LongInt; flags : DeviceLoopFlags);
|
|
;----------------------------------------------------------------------------------------------
|
|
; When DeviceLoop gets called, it searches all the active screen devices for the
|
|
; ones that intersect the drawingRgn. The drawingRgn is in local coordinates, and
|
|
; will usually be a portÕs visRgn (after a BeginUpdate call). For each device which
|
|
; intersects drawingRgn, the drawingProc routine is called. When the drawingProc is called,
|
|
; the current portÕs visRgn will be the intersection of the original visRgn and the
|
|
; intersecting portions of the device.
|
|
; The drawingProc should be declared as follows:
|
|
;
|
|
; PROCEDURE DrawingProc(depth : Integer; deviceFlags : Integer; targetDevice : GDHandle;
|
|
; userData : LongInt);
|
|
;
|
|
; where depth will be the pixelSize of the device, and flags are the gdFlags from
|
|
; the GDevice. The userData passed to DeviceLoop is also passed to the drawingProc.
|
|
;
|
|
; When called from a machine without Color QuickDraw, the targetDevice parameter passed to the
|
|
; drawing proc is set to NIL.
|
|
;
|
|
; The following flags may be passed to DeviceLoop:
|
|
;
|
|
; singleDevices If this flag is set, then similar devices are not grouped together when the
|
|
; drawingProc is called. If this flag is not set, DeviceLoop will only call
|
|
; the drawingProc once for each set of similar devices, but only the first
|
|
; one found is passed as targetDevice. It is assumed to be representative of
|
|
; all the similar devices.
|
|
; dontMatchSeeds If this flag is set, then color table seeds are not considered significant
|
|
; when comparing devices for similarity. Device similarity is based on color
|
|
; table depth and important gdevice flags (at this time, only the
|
|
; monochrome/color flag is considered important). This flag is ignored if
|
|
; the singleDevices flag is set.
|
|
; allDevices When this flag is set, the drawingRgn is ignored and DeviceLoop will call
|
|
; the drawingProc for all active screen gdevices. Whether or not similar
|
|
; devices are grouped together for a single call to the drawingProc depends
|
|
; on the setting of the singleDevices flag. The current portÕs visRgn is not
|
|
; affected when this flag is set.
|
|
;----------------------------------------------------------------------------------------------
|
|
; Register Use:
|
|
; D3 current deviceÕs ordinal number for indexing into finished bitmap
|
|
; D4 RgnHandle for working region
|
|
; D5 bitmap of devices weÕve done
|
|
; D6 depth of current device (high word) & flags of current device (low word)
|
|
; D7 ctSeed of current device
|
|
; A2 current port
|
|
; A3 pointer to current device
|
|
; A4 handle to current device
|
|
;----------------------------------------------------------------------------------------------
|
|
|
|
|
|
DeviceLoop patchproc _DeviceLoop,(Plus,SE,II,Portable,IIci)
|
|
|
|
activeScreenMask EQU $A000
|
|
importantFlagsMask EQU $A001
|
|
fakeDeviceFlags EQU $A801
|
|
|
|
DeviceLoopFrame RECORD {A6Link},DECR
|
|
StartParams EQU *
|
|
drawingRgn DS.L 1
|
|
drawingProc DS.L 1
|
|
userData DS.L 1
|
|
flags DS.L 1
|
|
ParamSize EQU StartParams-*
|
|
Return DS.L 1
|
|
A6Link DS.L 1
|
|
savedVis DS.L 1
|
|
localRect DS.W 4
|
|
callerRegs DS.L 8
|
|
visAndDrawRgn DS.L 1
|
|
LocalSize EQU *
|
|
ENDR
|
|
|
|
with DeviceLoopFrame
|
|
|
|
link A6, #LocalSize
|
|
movem.l D3-D7/A2-A4, callerRegs(A6) ; save the callers registers
|
|
|
|
btst #6, ROM85 ; Color QuickDraw available?
|
|
bnz @classicQD ; if not, handle old case
|
|
|
|
move.l TheGDevice, D0 ; Get the handle to the current GDevice
|
|
move.l MainDevice, D1 ; Get the handle to the main device
|
|
cmp.l D0, D1 ; if the two are not equalÉ
|
|
bne.s @checkForOne ; we use TheGDevice to prime our device loop
|
|
move.l DeviceList, D0 ; otherwise, we use DeviceList
|
|
|
|
@checkForOne
|
|
movea.l D0, A0 ; D0 here contains the first GDevice of the list we will use.
|
|
move.l (A0), A0
|
|
tst.l gdNextGD(A0) ; is there a second device?
|
|
beq @oneDevice ; if not, quick exit
|
|
|
|
move.l D0, A4 ; put the beginning of the device list we are using in A4
|
|
move.l (A5), A2 ; point to QD globals
|
|
move.l thePort(A2), A2 ; point to current port
|
|
move.l flags(A6), D0 ; what are the current options?
|
|
btst #allDevicesBit, D0 ; are we ignoring drawingRgn?
|
|
bnz.s @regionsReady ; if so, thereÕs no region work
|
|
|
|
move.l visRgn(A2), savedVis(A6) ; save the untouched visRgn
|
|
subq #4, SP ; room for region handle
|
|
_NewRgn
|
|
move.l (SP)+, visRgn(A2) ; new working visRgn
|
|
subq #4, SP ; room for region handle
|
|
_NewRgn
|
|
move.l (SP)+, D4 ; new device rect region
|
|
move.l savedVis(A6), -(SP) ; current real visRgn
|
|
move.l drawingRgn(A6), -(SP) ; callerÕs drawing region
|
|
subq #4, SP ; room for region handle
|
|
_NewRgn
|
|
move.l (SP), visAndDrawRgn(A6) ; for intersection of vis and drawing regions
|
|
_SectRgn ; calculate clipped drawing region
|
|
@regionsReady
|
|
|
|
moveq #0, D5 ; clear finished bitmap
|
|
moveq #0, D3 ; weÕre starting with device 0
|
|
@deviceIntersect
|
|
move.l A4, D0 ; is the GDHandle NIL?
|
|
beq @noMore ; if so, no more devices
|
|
move.l (A4), A3 ; point at the GDevice record
|
|
bsr TestAndIntersect ; is device good for drawing?
|
|
bz.s @nextDevice ; if not, keep searching
|
|
|
|
move.l flags(A6), D0 ; get the callerÕs options
|
|
btst #allDevicesBit, D0 ; are we ignoring regions?
|
|
bnz.s @visRgnSetup ; if so, donÕt change the visRgn
|
|
|
|
move.l D4, -(SP) ; rectangle region handle
|
|
pea localRect(A6) ; this device (local coords)
|
|
_RectRgn ; region = device rect (local)
|
|
move.l D4, -(SP) ; device rect region (local)
|
|
move.l visAndDrawRgn(A6), -(SP) ; ANDed with clipped drawing region
|
|
move.l visRgn(A2), -(SP) ; turns into portÕs visRgn
|
|
_SectRgn
|
|
move.l (A4), A3 ; fix GDevicePtr
|
|
@visRgnSetup
|
|
|
|
move.l gdPMap(A3), A0 ; deviceÕs PixMapHandle
|
|
move.l (A0), A0 ; deviceÕs PixMapPtr
|
|
move.w pmPixelSize(A0), D6 ; deviceÕs depth
|
|
swap D6 ; put depth high
|
|
move.w gdFlags(A3), D6 ; get device flags in low word
|
|
move.l pmTable(A0), A0 ; deviceÕs color table handle
|
|
move.l (A0), A0
|
|
move.l ctSeed(A0), D7 ; stash deviceÕs ctab seed
|
|
move.l flags(A6), D0 ; get callerÕs flags
|
|
btst #singleDevicesBit, D0 ; should we group devices?
|
|
bnz.s @groupingDone ; if not, donÕt call AddSimilar
|
|
bsr AddSimilarDevices ; find all the like devices
|
|
@groupingDone
|
|
movem.l D3-D7/A2-A4/A6, -(SP) ; save OUR registers
|
|
swap D6
|
|
move.l D6, -(SP) ; pass depth and flags
|
|
move.l A4, -(SP) ; and the GDHandle
|
|
move.l userData(A6), -(SP) ; and finally the userÕs long
|
|
move.l drawingProc(A6), A0 ; pointer to drawing procedure
|
|
movem.l callerRegs(A6), D3-D7/A2-A4 ; restore callerÕs registers
|
|
move.l A6Link(A6), A6 ; and restore callerÕs A6
|
|
jsr (A0) ; call the drawing procedure
|
|
movem.l (SP)+, D3-D7/A2-A4/A6 ; get OUR register set back
|
|
move.l (A4), A3 ; fix GDevicePtr
|
|
@nextDevice
|
|
move.l gdNextGD(A3), A4 ; get next device in chain
|
|
addq #1, D3 ; increment device number
|
|
bra.s @deviceIntersect ; try this one
|
|
|
|
@classicQD
|
|
move.l A6, -(SP) ; save our stack frame ptr
|
|
move.w #1, -(SP) ; pass depth (always 1)
|
|
move.w #fakeDeviceFlags, -(SP) ; and gdflags (something reasonable)
|
|
clr.l -(SP) ; NIL for GDHandle
|
|
bra.s @simpleDeviceCommon
|
|
|
|
@oneDevice
|
|
move.l A6, -(SP) ; save our stack frame ptr
|
|
move.l gdPMap(A0), A1 ; PixMapHandle
|
|
move.l (A1), A1 ; PixMapPtr
|
|
move.w pmPixelSize(A1), -(SP) ; pass depth
|
|
move.w gdFlags(A0), -(SP) ; and gdflags
|
|
move.l D0, -(SP) ; and the GDHandle
|
|
|
|
@simpleDeviceCommon
|
|
move.l userData(A6), -(SP) ; and the userÕs long
|
|
move.l drawingProc(A6), A0 ; the procedureÕs address
|
|
move.l A6Link(A6), A6 ; and restore callerÕs A6
|
|
jsr (A0) ; call the drawing code
|
|
move.l (SP)+, A6 ; restore access to our stack frame
|
|
bra.s @exit
|
|
|
|
@noMore
|
|
move.l flags(A6), D0 ; what are the current options?
|
|
btst #allDevicesBit, D0 ; are we ignoring drawingRgn?
|
|
bnz.s @exit ; if so, no regions to clean up
|
|
|
|
move.l visRgn(A2), -(SP) ; temp working visRgn
|
|
_DisposRgn
|
|
move.l visAndDrawRgn(A6), -(SP) ; temp clipped drawingRgn
|
|
_DisposRgn
|
|
move.l D4, -(SP) ; temp device rect rgn
|
|
_DisposRgn
|
|
move.l savedVis(A6), visRgn(A2) ; put original visRgn back
|
|
@exit
|
|
movem.l callerRegs(A6), D3-D7/A2-A4 ; restore regs
|
|
unlk A6
|
|
move.l (SP)+, A0 ; clean stack and return
|
|
lea ParamSize(SP), SP
|
|
jmp (A0)
|
|
|
|
|
|
AddSimilarDevices
|
|
; Starting with gdNextGD(A3), find all the devices that:
|
|
; have the same depth as D6 (high word)
|
|
; have the same important flags as D6 (low word)
|
|
; optionally have the same ctSeed as D7
|
|
; havenÕt yet been drawn to
|
|
; are active screens (automatic because the flag bit for active is in importantFlagsMask)
|
|
; intersect drawingRgn(A6)
|
|
;
|
|
; When such a device is found, do:
|
|
; visRgn(A2) := visRgn(A2) | (gdRect & clipped drawingRgn)
|
|
; mark doneDevices bitmap (D5.L) so we donÕt do this one again
|
|
|
|
movem.l A3-A4/D3/D6, -(SP) ; save original state
|
|
andi.w #importantFlagsMask, D6 ; keep only pertinent flags
|
|
move.l gdNextGD(A3), A4 ; start with next device
|
|
addq #1, D3 ; which is next in number, too
|
|
@addLoop
|
|
move.l A4, D0 ; is there a GDHandle?
|
|
bz.s @noMore ; if NIL, then weÕre done
|
|
|
|
move.l (A4), A3 ; handle->ptr
|
|
bsr.s TestAndIntersect ; see if device is okay by itself
|
|
bz.s @nextDevice ; if not, try next one
|
|
|
|
move.w gdFlags(A3), D0 ; get device attributes
|
|
andi.w #importantFlagsMask, D0 ; strip unimportant ones
|
|
cmp.w D0, D6 ; is this device similar to test device?
|
|
bne.s @nextDevice ; if not, donÕt use it
|
|
|
|
move.l gdPMap(A3), A0 ; get deviceÕs PixMapHandle
|
|
move.l (A0), A0 ; get deviceÕs PixMapPtr
|
|
move.l D6, D0 ; get depth and flags
|
|
swap D0 ; get depth into low word
|
|
cmp.w pmPixelSize(A0), D0 ; save depth as test device?
|
|
bne.s @nextDevice ; if not, donÕt use it
|
|
|
|
move.l flags(A6), D0 ; get the option flags
|
|
btst #dontMatchSeedsBit, D0 ; should we check ctSeeds?
|
|
bnz.s @seedsChecked ; if not, skip this next check
|
|
move.l pmTable(A0), A0 ; handle to color table
|
|
move.l (A0), A0
|
|
cmp.l ctSeed(A0), D7 ; are the seeds the same?
|
|
bne.s @nextDevice ; if not, donÕt use this one
|
|
@seedsChecked
|
|
|
|
move.l flags(A6), D0 ; what are the current options?
|
|
btst #allDevicesBit, D0 ; are we ignoring drawingRgn?
|
|
bnz.s @visRgnSetup ; if so, no regions to setup
|
|
|
|
move.l D4, -(SP) ; rectangle region handle
|
|
pea localRect(A6) ; this device (local coords)
|
|
_RectRgn ; region = device rect (local)
|
|
move.l D4, -(SP) ; device rect region (local)
|
|
move.l visAndDrawRgn(A6), -(SP) ; ANDed with clipped drawing region
|
|
move.l D4, -(SP) ; turns into intersected rect region
|
|
_SectRgn
|
|
move.l D4, -(SP) ; intersected device rect region
|
|
move.l visRgn(A2), -(SP) ; and previously setup visRgn
|
|
move.l (SP), -(SP) ; get ORed together
|
|
_XorRgn ; XOr is a fast way to Union when guaranteed no overlap
|
|
move.l (A4), A3 ; fix GDevicePtr
|
|
|
|
@visRgnSetup
|
|
bset.l D3, D5 ; mark this device done
|
|
@nextDevice
|
|
move.l gdNextGD(A3), A4 ; get next device in chain
|
|
addq #1, D3 ; increment device number
|
|
bra.s @addLoop ; try this one
|
|
@noMore
|
|
movem.l (SP)+, A3-A4/D3/D6 ; restore callerÕs state
|
|
rts
|
|
|
|
|
|
TestAndIntersect
|
|
; Inputs:
|
|
; A3 device to test (dereferenced GDHandle)
|
|
; D3 this deviceÕs ordinal number
|
|
; Outputs:
|
|
; CCs zero if not okay, non-zero if okay
|
|
; localRect(A6) is set to devices rectangle in local coordinates
|
|
|
|
btst.l D3, D5 ; this device already done?
|
|
bnz.s @fail ; if so, itÕs not okay
|
|
move.w gdFlags(A3), D0 ; get this deviceÕs flags
|
|
andi.w #activeScreenMask, D0 ; extract screen & active bits
|
|
cmpi.w #activeScreenMask, D0 ; are both bits set?
|
|
bne.s @fail ; if not, donÕt use device
|
|
move.l gdRect(A3), localRect(A6) ; copy topLeft of device rect
|
|
move.l gdRect+4(A3), localRect+4(A6) ; and bottomRight
|
|
pea localRect(A6) ; push address of copied device rect
|
|
_GlobalToLocal ; and convert it to local coords.
|
|
pea localRect+bottom(A6) ; push address of copied device rect bottomRight
|
|
_GlobalToLocal ; and convert it to local coords.
|
|
|
|
move.l flags(A6), D0 ; get the options
|
|
btst #allDevicesBit, D0 ; should we accept all screens?
|
|
bnz.s @exit ; if set, exit with CCs non-zero
|
|
|
|
subq #2, SP ; room for boolean result
|
|
pea localRect(A6) ; local version of GDRect
|
|
move.l drawingRgn(A6), -(SP) ; region to test
|
|
_RectInRgn ; does device intersect region?
|
|
tst.b (SP)+ ; see if it does
|
|
bra.s @exit
|
|
@fail
|
|
moveq #0, D0
|
|
@exit
|
|
rts
|
|
|
|
END
|