; ; File: ToolboxEventMgr.a ; ; Contains: Event-Oriented ROM-Based Routines for User Interface ToolBox ; ; ; Change History (most recent first): ; ; 1/28/94 chp Remove TNT-specific hack from . ; 11/10/93 fau In TryDevice, don't do anything if debugging TNT, as we don't ; support the old SCSI API yet. ; 11/19/92 RB When looking for FKEY's, look in ROM first. ; 11/3/92 SWC Changed SCSIEqu.a->SCSI.a. ; 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 ; IMPORT DisableTimeOut ; ; ; 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 SUBQ #2,SP ; make room for result MOVE.L D0,-(SP) ; push return address MOVE.L D1,-(SP) ; push MyEvent MOVEM.L D1-D2,-(SP) ; push Mask/Result,MyEvent ; Call GNECommon with stack like this: result, return(user), MyEvent, Mask/Result, MyEvent, return(us) MOVEQ #0,D0 ; clear D0 to indicate GetNextEvent BSR.S GNECommon ; do common GetNextEvent Stuff ; 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 MOVE.L (SP)+,A1 ; MyEvent pointer MOVE.W D0,4(SP) ; pass result to caller (leave ret addr) MOVE.L JGNEFilter,-(SP) ; filter proc? BNE.S @1 ; =>yes, RTS to it ...WAS BGT.S!!! <11Apr85> ADDQ #4,SP ; else strip it off the stack @1 RTS ; return to caller ; 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 ; clear DS Window if there is one BSET #7,DSWndUpdate ; is there a disk switched window to remove? BNE.S @1 ; =>no, just set up for GNE Filter Proc TST.B WWExist ; does a window world exist? BNE.S @1 ; no, one less world to worry about SUBQ #4,SP ; make space to keep current port MOVE.L SP,-(SP) ; and point to it _GetPort ; remember current port on stack MOVE.L WMgrPort,-(SP) ; get port w/wide open clip/vis _SetPort ; and set it SUBQ #4,SP ; get frontWindow for PaintBehind _FrontWindow ; SUBQ #4,SP ; get a region for PaintBehind _NewRgn ; MOVE.L (SP),A3 ; and set region to the deep squid window PEA DSAlertRect ; _RectRgn ; MOVE.L A3,-(SP) ; cover up that ugly alert _PaintBehind ; MOVE.L A3,-(SP) ; and then throw away the clobbered region _DisposRgn _SetPort ; window gone! Restore old port from stack @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! CSS <13Jan86 JTC> MOVE.B evtMessage+2(A3), D0 ; Get the raw keycode CMP.B #$3F, D0 ; Keyboard or Keypad? BHI.S TrySysEvent ; Keypad -- punt MOVE.B evtMessage+3(A3),D1 ;low byte is ascii code (or fkey code) <09Apr85> SUB.B #$30, D1 ; convert from char to num 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 TST.B ScrDmpEnb ; Check the ScrDmpEnb flag BEQ.S @CheckOtherFKEYs ; if it's false, don't do the FKEY ; end roll-in CheckInhibitFKEYInGetNextEvent patch 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 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 ; cmp.w #2,D1 ; check for 1,2,0 bgt.s DoneFKey ; tst.w D1 ; bmi.s DoneFKey ; bne.s @1 ; if Command-Shift-0 moveq #3,D1 ; make it drive #3 @1 moveq #1,D2 ;flag as from the keyboard move.l jDoEject,A0 ; jsr (A0) ; do the eject now bra.s DoneFKey ; @2 MOVE.L D0,A0 MOVE.L (A0),D0 ; dereference BEQ.S DoneFKey ; exit if purged _Hlock ; lock the FKEY code, MOVE.L A0,-(SP) ; save for unlock MOVE.L (A0),A0 ; dereference JSR (A0) MOVE.L (SP)+,A0 ; recover handle _HUnLock ; unlock it ; ; 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?? 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 BNE.S @1 ; don't poll if we've already done it once CMP.L #20*60,Ticks ; have we been running for 20 seconds? BLO.S @1 ; no, too early yet BSET.B #7,SCSIPoll ; set it so we don't do it again BSR TryDevice ; see if that device is out there @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 isn’t there, don’t call GetMouse<4> ; Window Manager exists. Set the port to the Window Manager’s 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 Manager’s 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 ; ; 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 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 AND.B #$07,D0 ; mask off ID bits MOVE.W D0,-(SP) ; push SCSI ID for the select _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 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 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 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 PYG moveq.l #$FFFFFFFF,d4 ; pick a supposed invalid first value 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 PYG moveq.l #maxTickCount,d3 ; if overflow, peg to max tick count PYG @WaitTimeOK ; 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 BEQ.S @WaitLoop ; Loop if nil cmp.l evtMouse(A2),d4 ; is it the same as the last one? PYG beq.s @WaitLoop ; if so, loop PYG move.l evtMouse(A2),d4 ; and save new value PYG SUBQ.W #2, SP ; Make space MOVE.L evtMouse(A2), -(SP) ; pt for PtInRgn PYG MOVE.L D0, -(SP) ; rgn for PtInRgn _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 PYG UNLK A6 MOVE.L (SP), A0 ; Get return address LEA retBool-4(SP), SP ; Pop the arguments JMP (A0) ; Return ENDPROC END