supermario/base/SuperMarioProj.1994-02-09/Toolbox/ToolboxEventMgr/ToolboxEventMgr.a

780 lines
28 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;
; File: ToolboxEventMgr.a
;
; Contains: Event-Oriented ROM-Based Routines for User Interface ToolBox
;
;
; Change History (most recent first):
;
; <SM10> 1/28/94 chp Remove TNT-specific hack from <SM9>.
; <SM9> 11/10/93 fau In TryDevice, don't do anything if debugging TNT, as we don't
; support the old SCSI API yet.
; <SM8> 11/19/92 RB When looking for FKEY's, look in ROM first.
; <SM7> 11/3/92 SWC Changed SCSIEqu.a->SCSI.a.
; <SM6> 10/22/92 CSS Change some branch short instructions to word branches.
; <9> 7/21/92 CSS Clean up previous comment so this file can be copied exactly
; into SuperMario.
; <8> 6/8/92 JSM Check emProcessMgrExists to see if we need to do HLE stuff
; instead of calling Gestalt, re-roll-in
; CheckInhibitFKEYInGetNextEvent and FixCheckActivate patches more
; intelligently (simply bypass the GetResource call if ScrDmpEnb
; is false for CheckInhibitFKEYInGetNextEvent, and just delete the
; code that FixCheckActivate was bypassing).
; <7> 6/2/92 JSM Check emProcessMgrExists to see if we can call HLE stuff instead
; of using Gestalt.
; <6> 2/10/92 JSM Moved this file to ToolboxEventMgr folder, keeping all the old
; revisions.
; <5> 10/17/91 JSM Cleanup header, roll-in HLEAvail and GetNextHLE patches (still
; need to not call Gestalt all the time), remove some code
; conditionalized for onMacPP.
; <4> 9/11/91 stb & bbm: roll in GetMouse patch to set the window mgr port for the
; journalling driver
; <2> 6/12/91 LN Changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a'
; <1.4> 12/4/89 MSH Ported IdleUpdate call from forked off hcmac sources.
; <1.3> 8/28/89 SES Removed references to nFiles.
; <1.2> 11/17/88 DHD Made the journaling _Control call be IMMED
; <1.1> 11/10/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <•1.6> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
; <1.5> 9/8/88 MSH Removed all traces of sleep/idle support.
; <1.4> 6/24/88 MSH Removed the go to sleep code from getnextevent for HcMac.
; <1.3> 5/16/88 BBM Added WaitNextEvent Proc. aka Phil Goldman and Ed Tecot. Cleaned
; up comments.
; <1.2> 4/18/88 CSL added support for SLEEP & IDLE in GetNextEvent for HcMac
; <1.1> 3/28/88 BBM Second try at idle now looks for events while wasting time in
; slow mode.
; <1.0> 2/11/88 BBM Adding file for the first time into EASE…
; 11/17/88 DHD Made the Journaling Control call be immediate.
;
BLANKS ON
STRING ASIS
LOAD 'StandardEqu.d'
INCLUDE 'HardwarePrivateEqu.a'
INCLUDE 'SCSI.a'
INCLUDE 'GestaltEqu.a' ; <5>
INCLUDE 'MFPrivate.a' ; <5>
;
MiscMGR PROC EXPORT
;
; Definitions for the external world
;
EXPORT GetMouse
EXPORT StillDown
EXPORT Button
EXPORT WaitMouseUp
EXPORT TickCount
EXPORT GetKeys
EXPORT GetNextEvent
EXPORT EventAvail
IMPORT EnableTimeOut ; <A300/29Oct86>
IMPORT DisableTimeOut ; <A300/29Oct86>
;
; PROCEDURE GetKeys(VAR k: keyMap) returns 128 bits (4 longs) worth of keyMap state.
;
GetKeys
MOVE.L 4(SP),A1 ; Get user's dest. address
LEA KeyMap,A0 ; point to keymap
MOVE.L (A0)+,(A1)+ ; move in first long
MOVE.L (A0)+,(A1)+ ; move in second long
MOVE.L (A0)+,(A1)+ ; move in third long
MOVE.L (A0)+,(A1)+ ; move in last long
MOVE.L 4(SP),A1 ; Get user's dest. address
MOVEQ #jcGetKeys,D1 ; GetKeys code
BSR.S GetJournal ; and journal it
MOVE.L (SP)+,(SP) ; strip parameter
RTS
;
; FUNCTION Button:BOOLEAN is a function that returns the state of the mouse button
;
Button
LEA 4(SP),A1 ; Get pointer to function result
CLR (A1) ; return false for now
TST.B MBState ; See if button down
BMI.S itsUp ; and skip if not
ADDQ.B #1,(A1) ; Turn false into truth
itsUp
MOVEQ #jcButton,D1 ; Button code
BRA.S GetJournal ; and go journal it if need be(implied return)
;
; FUNCTION TickCount:LongInt returns the current time in Ticks, fall into common
; journaling code
;
TickCount
LEA 4(SP),A1 ; point to function result
MOVE.L Ticks,(A1) ; Return the ticks count
MOVEQ #jcTickCount,D1 ; Time code
;
; GetJournal is the main routine that implements journaling for GetMouse,
; Button, Time and GetKeys. It takes a "caller code" in D1 (passed on through
; the journaling hook) and a pointer to the actual data we're polling (for
; example, its TICKS for the Time call) in A1
;
GetJournal
MOVE.W JournalFlag,D0 ; is journaling on?
BEQ.S adios ; if not, skip
BPL.S ItsRecord ;
; handle playBack
MOVEQ #JPlayCtl,D0 ; say its PlayBack
BRA.S CallJournal ; invoke the journal
; handle record
ItsRecord
MOVEQ #JRecordCtl,D0 ; say its Record and fall into callJournal
; routine to invoke the journal. D0 has control code, D1 has "which" selector
; and A0 is the address to stuff the result
CallJournal
SUB #40,SP ; make some space for parameter block
LEA IORefNum(SP),A0 ; <24Oct85>
MOVE JournalRef,(A0)+ ; IORefNum <-- refNum <24Oct85>
MOVE D0,(A0)+ ; CSCode <-- journal call <24Oct85>
MOVE.L A1,(A0)+ ; CSParam <-- result pointer <24Oct85>
MOVE.W D1,(A0)+ ; CSParam+4 <-- caller code <24Oct85>
MOVE.W D3,(A0)+ ; CSParam+6 <-- GNE vs OSAvail flag <24Oct85>
MOVE.L SP,A0 ; point up param block
_Control ,IMMED
ADD #40,SP ; pop off param block
BNE.S BadJournal ; if couldn't find it, turn off journal
RTS ; all done
BadJournal
CLR.W JournalFlag ; turn journal off if no good
ST CRSRCouple ; recouple cursor
adios RTS
;
; PROCEDURE GetMouse(VAR mousePt: Point);
;
; GetMouse is a routine that returns the current mouse position in the local
; coordinates of the current grafPort
;
GetMouse
MOVE.L 4(SP),A1 ; put user's result ptr in A1
MOVE.L Mouse,(A1) ; send back the mouse coordinates
MOVEQ #jcGetMouse,D1 ; GetMouse code
BSR.S GetJournal ; and journal it (in global space)
MOVE.L 4(SP),-(SP) ; put user's result ptr on stack
_GlobalToLocal ; map to local coordinates
MOVE.L (SP)+,(SP) ; strip parameter
RTS
;
; FUNCTION StillDown: BOOLEAN;
;
; returns true only if the button is down AND there are no button events in the queue
;
;
StillDown
LINK A6,#-20 ;get a buffer for events
CLR.W 8(A6) ;assume StillDown := false
;
SUBQ #2,SP ;make room for function result
_Button ;is the button down?
TST (SP)+ ;inspect result
BEQ.S SDDone ;if not, we're done, return false
;
SUBQ #2,SP ;make room for result
MOVE #7,-(SP) ;7 is mask for button events
PEA -20(A6) ;push pointer to event buffer
_EventAvail ;are there any?
TST (SP)+ ;well...
BNE.S SDDONE ;if there are, return false
;
ADDQ.B #$01,8(A6) ;return true(Turn false into true)
;
SDDONE UNLK A6
RTS
;
; FUNCTION WaitMouseUp:BOOLEAN is sort of like StillDown but eats the
; buttonUp event.
;
WaitMouseUp
LINK A6,#-20 ;get a buffer for events
CLR.W -(SP) ;make room for result
_StillDown ;is it still down?
MOVE (SP)+,8(A6) ;update our result
BNE.S ItStillDown ;branch if stillDown
;
; its not stillDown so eat the buttonUp event
;
SUBQ #2,SP ;make room for result
MOVE.W #4,-(SP) ;event 2 (mouseUp) only
PEA -20(A6) ;push buffer address
_GetNextEvent ;get it
ItStillDown
UNLK A6 ;deallocate stack frame
RTS ;all done so return to caller
;
; FUNCTION EventAvail(eventMask: INTEGER; VAR myEvent: eventRecord): BOOLEAN;
;
; Here is the high-level EventAvail that is called by the applications.
; Its really just a special case of GetNextEvent (see below), but it
; doesn't remove events from the queue.
;
EventAvail
MOVEQ #-1,D0 ; set D0 to indicate EventAvail
BRA.S GNECommon ;use common code
;
; FUNCTION GetNextEvent(eventMask: INTEGER; VAR myEvent: eventRecord): BOOLEAN;
;
; Here is the high-level GetNextEvent that is called by the applications.
; It calls the OS "GetOSEvent" for raw events, supplies updates by
; calling CheckUpdate, and calls the journalling and desk Ornament mechanisms
; as appropriate.
; If a filter proc is installed, it passes control to the filter proc before returning
; to the caller.
;
GetNextEvent
MOVEM.L (SP)+,D0-D2 ; pull return,MyEvent,Mask/Result <EHB 28-Jan-85>
SUBQ #2,SP ; make room for result <EHB 28-Jan-85>
MOVE.L D0,-(SP) ; push return address <EHB 28-Jan-85>
MOVE.L D1,-(SP) ; push MyEvent <EHB 28-Jan-85>
MOVEM.L D1-D2,-(SP) ; push Mask/Result,MyEvent <EHB 28-Jan-85>
; Call GNECommon with stack like this: result, return(user), MyEvent, Mask/Result, MyEvent, return(us)
MOVEQ #0,D0 ; clear D0 to indicate GetNextEvent <EHB 28-Jan-85>
BSR.S GNECommon ; do common GetNextEvent Stuff <EHB 28-Jan-85>
; set things up to call a GetNextEvent Filter Proc. This is what a call to GNEFilter looks like:
; Entry: A1 = MyEvent Pointer
; D0 = result
; (SP) = return address to caller
; 4(SP) = result to caller
; Exit: Just like return from GetNextEvent
MOVE.W (SP)+,D0 ; pull result <EHB 28-Jan-85>
MOVE.L (SP)+,A1 ; MyEvent pointer <EHB 28-Jan-85>
MOVE.W D0,4(SP) ; pass result to caller (leave ret addr) <EHB 28-Jan-85>
MOVE.L JGNEFilter,-(SP) ; filter proc? <EHB 28-Jan-85>
BNE.S @1 ; =>yes, RTS to it ...WAS BGT.S!!! <11Apr85>
ADDQ #4,SP ; else strip it off the stack <EHB 28-Jan-85>
@1
RTS ; return to caller <EHB 28-Jan-85>
; here is common GetNextEvent/EventAvail code. The DS window check is done here because the
; registers are already saved here.
GNECommon
LINK A6,#0 ;set up a stack frame
MOVEM.L D3/A3,-(SP) ;save some work registers
MOVE.L D0,D3 ;put D0 in D3 to discriminate GetNextEvent
BNE.S @1 ; don't clear DS window if EventAvail <EHB 28-Jan-85>
; clear DS Window if there is one
BSET #7,DSWndUpdate ; is there a disk switched window to remove?<EHB 28-Jan-85>
BNE.S @1 ; =>no, just set up for GNE Filter Proc <EHB 28-Jan-85>
TST.B WWExist ; does a window world exist? <EHB 28-Jan-85>
BNE.S @1 ; no, one less world to worry about <EHB 28-Jan-85>
SUBQ #4,SP ; make space to keep current port <EHB 28-Jan-85>
MOVE.L SP,-(SP) ; and point to it <EHB 28-Jan-85>
_GetPort ; remember current port on stack <EHB 28-Jan-85>
MOVE.L WMgrPort,-(SP) ; get port w/wide open clip/vis <KWK 13-May-85>
_SetPort ; and set it <KWK 13-May-85>
SUBQ #4,SP ; get frontWindow for PaintBehind <EHB 28-Jan-85>
_FrontWindow ; <EHB 28-Jan-85>
SUBQ #4,SP ; get a region for PaintBehind <EHB 28-Jan-85>
_NewRgn ; <EHB 28-Jan-85>
MOVE.L (SP),A3 ; and set region to the deep squid window <EHB 28-Jan-85>
PEA DSAlertRect ; <EHB 28-Jan-85>
_RectRgn ; <EHB 28-Jan-85>
MOVE.L A3,-(SP) ; cover up that ugly alert <EHB 28-Jan-85>
_PaintBehind ; <EHB 28-Jan-85>
MOVE.L A3,-(SP) ; and then throw away the clobbered region <EHB 28-Jan-85>
_DisposRgn
_SetPort ; window gone! Restore old port from stack <EHB 28-Jan-85>
@1
CLR.W 14(A6) ;set result to FALSE (assume no event)
MOVE.L 8(A6),A3 ;point A3 to the event record
; First, see if an activate event and return if so (Z flag reset if found one)
MOVE.W 12(A6),D0 ;get the caller's event mask
MOVE.L A3,A0 ;get event pointer in A0
BSR CheckActivate ; See if activate
BEQ.S Dormant ; if got one, indicate it and jump to sys
ADDQ.B #01,14(A6) ; turn the false into true
BRA.S PassToSystem
; See if there are any events.
Dormant
MOVE.W 12(A6),D0 ;get the caller's event mask
MOVE.L A3,A0 ;get event pointer in A0
TST D3 ;EventAvail or GetNextEvent?
BPL.S DontPeek ;branch if its not an eventAvail
_OSEventAvail ;ask OS for next event
BRA.S GoCheckHLE ;go check if we got a high level event <5>
DontPeek
_GetOSEvent ;ask the OS for an event
; Check for high level event
GoCheckHLE
tst.w EvtNum(a3) ; find something? <5>
bne.s GoCheckJournal ; if so, get out without further ado <5>
; no OS events. Should we look for high-level events?
move.w 12(a6),d0 ; get the caller's event mask <5>
btst #highLevelEvtBit,d0 ; high-level events requested? <5>
beq.s GoCheckJournal ; if not, just go on <5>
; We need to check for high level events. Determine whether Process Mgr is around yet.
move.l ExpandMem,a0 ; get ExpandMem <7>
tst.w ExpandMemRec.emProcessMgrExists(a0) ; is Process Mgr up yet? <7>
beq.s GoCheckJournal ; exit now if we're still too early <7>
; Ask the Process Mgr for a high level event.
CallGetHLEvent
clr.w -(sp) ; allocate result storage <5>
move.w 12(a6),-(sp) ; pass event mask <5>
move.l a3,-(sp) ; pass address of event record <5>
tst.w d3 ; EventAvail or GetNextEvent? <5>
seq -(sp) ; pass Boolean: GNE - true, EA - false <5>
_GetNextHighLevelEvent ; call Process Mgr <5>
addq #2,sp ; pop result <5>
; Go check the journal
GoCheckJournal
MOVE.L A3,A1 ; pass the eventPtr
MOVEQ #jcEvent,D1 ; event code
BSR GetJournal ; invoke the journal
; Check to see if we got an event and set return code so far
TST.W EvtNum(A3) ; did we get an event?
BEQ.S noneYet
ADDQ.B #1,14(A6) ; if so, return TRUE(Turn false into true)
BRA.S PassToSystem ; and then pass to system code
noneYet
MOVE.W 12(A6),D0 ;get caller's event mask
BTST #UpdatEvt,D0 ;is it enabled?
BEQ.S PassToSystem ;if not, don't bother to check
CLR.W -(SP) ;make space for function result
MOVE.L A3,-(SP) ;push the event pointer
_CheckUpdate ;any update events?
MOVE.W (SP)+,14(A6) ;return the result
; OK, we got an event so see if the system wants it. But before passing it to an
; accessory, see if it's an FKey. <13Jan86 JTC>
PassToSystem
TST D3 ;was it an EventAvail call?
BMI DoneGNE ;don't pass those to the system
TST.W 14(A6) ;did we really, truly get one?
BEQ DoneGNE ;if not, we're done
; If Command AND Shift AND not-Option AND low byte of evtMessage between 0 and 9 AND
; key up or down THEN we take the event (i.e. returning FALSE to app) and, if it's up,
; actually try the FKey stuff.
TryFKey
MOVEQ #$0B,D1 ;seek cmdKey, shiftKey, not alphaLock, and optionKey <09Apr85>
AND.B evtMeta(A3),D1 ;high byte of meta word contains modifier bits <09Apr85>
SUBQ.B #$03,D1 ;want cmdKey AND shiftKey BUT NOT optionKey <09Apr85>
BNE TrySysEvent ;if not so, no FKey action! <SM6> CSS <13Jan86 JTC>
MOVE.B evtMessage+2(A3), D0 ; Get the raw keycode <PMAB102/20Apr87>
CMP.B #$3F, D0 ; Keyboard or Keypad? <PMAB102/20Apr87>
BHI.S TrySysEvent ; Keypad -- punt <PMAB102/20Apr87>
MOVE.B evtMessage+3(A3),D1 ;low byte is ascii code (or fkey code) <09Apr85>
SUB.B #$30, D1 ; convert from char to num <C89/28Jul86>
CMPI.B #10,D1
BCC.S TrySysEvent ;10-255 falls out of FKey range <13Jan86 JTC>
MOVE.W evtNum(A3),D0 ;what kind of event? <09Apr85>
SUBQ.W #keyUpEvt,D0 ;quick compare <09Apr85>
BEQ.S DoneFKey ;return FALSE and NULLify the event <13Jan86 JTC>
ADDQ.W #keyUpEvt-keyDwnEvt,D0 ;quick compare with keyDwnEvt <09Apr85>
BNE.S TrySysEvent ;exit if neither key up nor down <13Jan86 JTC>
;
; Have FKey code in D1, so use code stolen from GNEFilter of yore, to load and execute <09Apr85>
; possible resource.
;
; begin roll-in CheckInhibitFKEYInGetNextEvent patch - honor ScrDmpEnb <SM4>
TST.B ScrDmpEnb ; Check the ScrDmpEnb flag <SM4>
BEQ.S @CheckOtherFKEYs ; if it's false, don't do the FKEY <SM4>
; end roll-in CheckInhibitFKEYInGetNextEvent patch <SM4>
SUBQ #4,SP ; load in appropriate function-key package
MOVE.L #'FKEY',-(SP)
MOVE.W D1,-(SP) ; types 0-9
MOVE.W #MapTrue,RomMapInsert ; look in ROM first <SM8> rb
_GetResource
MOVE.L (SP)+,D0
BNE.S @2 ; br if we got the resource
;
;No FKEY=n resource for these keys (Command-Shift-1 to -0) so do the eject
;disk thing for -1, -2 and -0.
;
@CheckOtherFKEYs ; <SM4>
cmp.w #2,D1 ; check for 1,2,0 <C150/09sep86>
bgt.s DoneFKey ; <C150/09sep86>
tst.w D1 ; <C150/09sep86>
bmi.s DoneFKey ; <C150/10sep86>
bne.s @1 ; if Command-Shift-0 <C150/09sep86>
moveq #3,D1 ; make it drive #3 <C150/09sep86>
@1 moveq #1,D2 ;flag as from the keyboard <C150/10sep86>
move.l jDoEject,A0 ; <C150/10sep86>
jsr (A0) ; do the eject now <C150/09sep86>
bra.s DoneFKey ; <C150/09sep86>
@2 MOVE.L D0,A0
MOVE.L (A0),D0 ; dereference
BEQ.S DoneFKey ; exit if purged
_Hlock ; lock the FKEY code, <C169/06oct86>
MOVE.L A0,-(SP) ; save for unlock
MOVE.L (A0),A0 ; dereference
JSR (A0)
MOVE.L (SP)+,A0 ; recover handle
_HUnLock ; unlock it <C169/06oct86>
;
; The system handled the event so return false. FKey ups and downs are turned
;to NULLs to hide them from Modal Dialog, e.g. <28Oct85>
;
DoneFKey
CLR.W evtNum(A3) ; continue as if an accessory <28Oct85>
BRA.S HandBySys ; had sucked it up <13Jan86JTC>
; SEvtEnb is zero if the application wants to disable systemEvent. Test it.
TrySysEvent ; <13Jan86 JTC>
TST.B SEvtEnb ; System event enabled?? <EHB 28-Jan-85>
BEQ.S DoneGNE ; if not, let the app have a crack! <13Jan86 JTC>
SUBQ #2,SP ;make room for function result
MOVE.L A3,-(SP) ;push the event record
_SystemEvent ;call the desk manager
TST (SP)+ ;did the system want it?
BEQ.S DoneGNE ;if not, leave TRUE and quit... <13Jan86 JTC>
; Common exit point if handled by FKey or SystemEvent code. Set FALSE and go... <13Jan86 JTC>
HandBySys ; <09Apr85>
CLR.W 14(A6) ;return FALSE
; all done with GetNextEvent so restore the registers and return to the caller
DoneGNE
; The following is a one-time check to see if the internal drive (SCSI ID in low
; memory) is up to speed by now. If so, then clear high bit of PRAM startup
; device timeout value (PRAM address $01, byte length) to indicate that device
; 0 is there (and the startup code will wait for it at the next boot).
BTST.B #7,SCSIPoll ; bit 7 is cleared by InitSCSIMgr <C613/12Jan87>
BNE.S @1 ; don't poll if we've already done it once <C613/12Jan87>
CMP.L #20*60,Ticks ; have we been running for 20 seconds? <A349/04Nov86>
BLO.S @1 ; no, too early yet <A300/29Oct86>
BSET.B #7,SCSIPoll ; set it so we don't do it again <C613/12Jan87>
BSR TryDevice ; see if that device is out there <C613/12Jan87>
@1
; see if there was no event, if so do a get mouse to tickle tracking
; Historical note: by this time, an FKey is made to look like "no event", in which <13Jan86 JTC>
; case the mouse update is done...
TST.W EvtNum(A3) ; did we get one?
BNE.S NeverMind ; if not, go check for possible update evt
; be sure to set the port to the WMgrPort for the journalling driver
TST.W WWExist ; see if the window mgr and QD exist <4>
bne.s NeverMind ; if window mgr isnt there, dont call GetMouse<4>
; Window Manager exists. Set the port to the Window Managers port before calling _GetMouse
sub.w #4,sp ; room for the result <4>
move.l sp,-(sp) ; push address of var param result <4>
_GetPort ; Save the current port on the stack <4>
move.l WMgrPort,-(sp) ; <4>
_SetPort ; Set the port to the Window Managers port <4>
PEA TempRect ;we don't care about it so stuff it here
_GetMouse ;read the mouse so it will be journalled
_SetPort ; restore the old port; it's on the stack. <4>
NeverMind
MOVEM.L (SP)+,D3/A3 ;restore registers
UNLK A6 ;unbuild stack frame
MOVE.L (SP)+,A0 ;get return address
ADDQ #6,SP ;strip both parameters
JMP (A0) ;return to caller
; CheckActive is used to generate active and deactive events. It is entered
; and exited with D0 containing the event mask and A0 and A3 pointing to the
; event record. If D3 is set, its an EventAvail call rather than a GetNextEvent
; call. On exit, if the z-flag is clear, it had an event.
; First see if the event is enabled.
CheckActivate ; <19feb86> BBM
BTST #ActivateEvt,D0 ;is it enabled?
BEQ.S DoneChkActive ;if not, we're done
MOVE.L CurDeActive,D1 ;get the deactived window
BGT.S GotDActive ;if non-zero and non-neg, go post it
MOVE.L CurActivate,D1 ;how about an activate one?
BLE.S DoneChkActive ;if none, we're done
MOVEQ #1,D2 ;flag the activate
; we got an activated or deactived window so make the event
GotActCommon
MOVEQ #0,D0 ;use a mask of zero
_OSEventAvail ;get a NULL event record
MOVE.W #ActivateEvt,(A0)+ ;flag it as (de)activate event
MOVE.L D1,(A0) ;the windowPtr is the message
; Roll-in FixCheckActivate patch <SM4>
;
; A bug occurs in the IIci ROM under 32-bit mode. The high bit of CurActivate and CurDeactivate
; are used as flags to indicate that the events have already been sent. (0 in either also means that
; the event was sent.) The problem is that the ROM code (written for 24-bit machines) refers to the
; windowKind field without stripping off this high bit. Under some circumstances, this would cause
; a bus error. Since the code that checks the window is only used to set the system/application bit
; in the modifiers of the activate/deactivate event, and that bit was never documented in a released
; version of Inside Mac. (and no one uses it), we can fix the bug by getting rid of the code that
; sets the system/application bit.
; put the bits into evtMeta
MOVE.W EvtMeta(A3),D0 ;get it
AND #$FFFC,D0 ;mask in low bits
OR D2,D0 ;or in flag bits
MOVE.W D0,EvtMeta(A3) ;stuff it back
; eat up the event by clearing buffer if not a peek call
TST.W D3 ;is it a peek call?
BNE.S GotDone1 ;if so, we're done
LSR #1,D0 ;activate or deactivate?
BCC.S ClearDAct ;if deactivate, go clear it
BSET #7,CurActivate ;clear activate event
GotDone1
MOVEQ #-1,D1 ;clear z flag to say we got something
RTS
DoneChkActive
MOVEQ #0,D1 ;set z flag to say we got nothing
RTS
ClearDAct
BSET #7,CurDeActive
BRA.S GotDone1
GotDActive CLR D2 ;flag the deactivate
BRA.S GotActCommon ;go use common code
;--------------------------------------------------------------------------
;
; TryDevice -- we do a one-time check of the SCSI ID for the internal hard
; disk some number of seconds after bootup. Since the internal disk is
; powered from the CPU's power supply, it is likely that the startup code
; will be ready to boot off a floppy before the disk has spun up to full
; speed. Unless we have some way to know if there is an internal drive,
; the start code won't know whether or not to wait for the device. This
; 'lightning bolt' happens once per bootup, setting a field in parameter
; RAM that the startup code looks at. If we find a SCSI device ready that
; corresponds to the internal disk SCSI ID stored in parameter RAM, then
; we set a field in parameter RAM so the startup code will wait for it
; at the next bootup. This introduces some hysteresis in the process if the
; user changes the ID of his internal drive, but it was deemed to be more
; preferable than the alternative of a Control Panel setting to enable and
; disable waiting for the internal hard disk. The default ID to check is
; 0, but can be changed in parameter RAM (which gets stored into the SCSIPoll
; variable by InitSCSIMgr).
;
TryDevice ; This subroutine new <A300/29Oct86>
CLR.L -(SP) ; 6-byte Test Unit Ready command block
CLR.L -(SP) ; (6 zeroes) and 2-byte return value
_SCSIGet ; arbitrate for the SCSI bus
TST.W (SP) ; success?
BNE.S TryDevDone ; if arbitrate failed, don't change PRAM
MOVE.B SCSIPoll,D0 ; get SCSI ID of the int. drive <C613>
AND.B #$07,D0 ; mask off ID bits <C613>
MOVE.W D0,-(SP) ; push SCSI ID for the select <C613>
_SCSISelect ; try to select (max. wait 250 ms.)
TST.W (SP) ; success?
BEQ.S SelectOK ; branch if select succeeded
_DisableDynWait ; don't wait for that id on bootup <A349/04Nov86>
BRA.S TryDevDone ; exit
SelectOK
PEA 2(SP) ; address of Test Unit Ready command
MOVE.W #6,-(SP) ; length of Test Unit Ready command
_SCSICmd ; do the command
;
; If something went wrong with the command, then we need to do
; SCSIComplete anyway, so it isn't necessary to check the
; return value. Since we don't need the space for the command
; block any more, we just reuse it for the status and message
; values (each a word) returned by SCSIComplete. Before pushing
; anything else, these EA's are 2(sp) and 4(sp), so we PEA 2(sp)
; for the first (which adds 4 bytes to the stack), and PEA 8(sp)
; for the second [PEA 4+4(sp)].
;
PEA 2(SP) ; address for status value
PEA 8(SP) ; address for message value
MOVEQ.L #60,D0 ; maximum number of ticks to wait <A349/04Nov86>
MOVE.L D0,-(SP) ; push it
_SCSIComplete ; wrap things up, ignore return code
;
; If we got this far, then there is a device 0, so enable timeout
;
_EnableDynWait ; startup code will wait for dev. 0 <A349/04Nov86>
TryDevDone
ADDQ.L #8,sp ; clean up local variables
RTS
ENDPROC
;____________________________________________________________________________________
;
; Proc WaitNextEvent
;
; by Phil Goldman and Ed Tecot
;
; This is the Classic Mac OS version of WaitNextEvent. It is completely replaced
; in MultiFinder.
;
; Modification History:
; S380 04Feb88 EMT Fix WaitNextEvent when mouseRgn is nil
; S426 16Mar88 PYG Handle overflow for timeout and control of mouse-moved diarrhea
;
WaitNextEvent PROC EXPORT
mouseMovedMsg EQU $FA000000
maxTickCount EQU $FFFFFFFF
; Stack Frame
retAddr EQU 4
mouseRgn EQU retAddr+4
timeOut EQU mouseRgn+4
theEvent EQU timeOut+4
eventMask EQU theEvent+4
retBool EQU eventMask+2
; Locals
; d3: Tick time to wakeup (i.e. return)
; d4: Last mouse position
LINK A6, #0 ; Set up stack frame
MOVEM.L D3-d4/A2, -(SP) ; Save registers <S436/22Mar88> PYG
moveq.l #$FFFFFFFF,d4 ; pick a supposed invalid first value <S436/22Mar88> PYG
; for the previous mouse position
MOVE.L Ticks, D3 ; Save Ticks on entry
ADD.L timeOut(A6), D3 ; D3 is wakeup time
bcc.s @WaitTimeOK ; if no (unsigned) overflow, branch <S426/16Mar88> PYG
moveq.l #maxTickCount,d3 ; if overflow, peg to max tick count <S426/16Mar88> PYG
@WaitTimeOK ; <S426/16Mar88> PYG
MOVE.L theEvent(A6), A2 ; We'll use this often
@WaitLoop
_SystemTask
SUBQ.W #2, SP ; Make space for return value
MOVE.W eventMask(A6), -(SP)
MOVE.L A2, -(SP) ; theEvent
_GetNextEvent
MOVE.B (SP)+, retBool(A6) ; Stuff the boolean return value
BNE.S @WaitDone ; If non-zero, we're done
; GetNextEvent correctly stuffs evtTicks, evtMouse, evtMeta, and evtMBut fields
CMP.L evtTicks(A2), D3 ; Time to wake up?
BLS.S @WaitDone ; If so, we're done
MOVE.L mouseRgn(A6), D0 ; Get the mouseRgn <S380>
BEQ.S @WaitLoop ; Loop if nil <S380>
cmp.l evtMouse(A2),d4 ; is it the same as the last one? <S436/22Mar88> PYG
beq.s @WaitLoop ; if so, loop <S426/16Mar88> PYG
move.l evtMouse(A2),d4 ; and save new value <S436/22Mar88> PYG
SUBQ.W #2, SP ; Make space
MOVE.L evtMouse(A2), -(SP) ; pt for PtInRgn <S426/16Mar88> PYG
MOVE.L D0, -(SP) ; rgn for PtInRgn <S380>
_PtInRgn
TST.B (SP)+ ; Is it in the region?
BNE.S @WaitLoop ; If it is, loop around
MOVE.W eventMask(A6), D0
BTST #app4Evt, D0 ; Accept app4?
BEQ.S @WaitDone ; No, get out
; Manufacture a mouse moved event
MOVE.W #app4Evt, evtNum(A2) ; what = app4Evt
MOVE.L #mouseMovedMsg, evtMessage(A2) ; message = MouseMoved
ST.B retBool(A6) ; return True
@WaitDone
MOVEM.L (SP)+, D3-d4/A2 ; Restore registers <S436/22Mar88> PYG
UNLK A6
MOVE.L (SP), A0 ; Get return address
LEA retBool-4(SP), SP ; Pop the arguments
JMP (A0) ; Return
ENDPROC
END