; ; File: StartAlert.a ; ; Contains: This file contains the system alert manager, assembled as part of ; the ROM-based boot code. The system alert manager is called as the ; result of either a system error (when no debugger is installed) or ; through the SysAlert trap interface (used by Disk-switch). It assumes ; that the system is broken and tries to use as little of it as possible ; to get a message up on the screen. The message includes text, icons ; and some buttons, which execute user definable code when pushed. ; ; If the system alert manager was entered as the result of an NMI (system ; error 13), MicroBug is called. This the minimal set of get/set/go cmds ; for examining/altering the state of the machine. It uses the system alert ; rectangle as a display window. ; ; Written by: Andy Hertzfeld 20-Mar-83 ; modified by Ken Krugler 4-May-85 ; ; Copyright: © 1983-1991 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; <4> 9/27/91 JSM DonÕt use hasCQD conditional, all future ROMs will have color ; QuickDraw. ; <3> 9/16/91 JSM Cleanup header. ; <2> 6/12/91 LN Changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a' ; <1.5> 8/22/89 SES Removed references to nFiles. ; <1.4> 7/7/89 SWC NEEDED FOR AURORA: Zeroed DSErrCode when entering MicroBug since ; at that point, a fatal error hasn't occurred. ; <1.3> 5/4/89 SWC Code cleanup and conditionals reduction for universal ROM. ; <1.2> 1/16/89 GGD Added a scratch register parameter to the BigJMP macro calls ; since it will be needed when they change to use PC relative ; addressing. ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <¥1.1> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles ; <1.0> 2/10/88 BBM Adding file for the first time into EASEÉ ; 11/16/87 MSH Changed alert box sizing and placement to be like Mac 2. ; 10/29/87 rwh Port to Modern Victorian (onMvMac) ; 9/3/87 RDC Change check for NMI exception to D0=13 on all systems ; 9/1/87 MSH Added support for HcMac (Laguna) ; 2/15/87 RDC Fixed bug in DSErrHandler for fetch of error code on NuMac ; 1/28/87 WRL Dispose of the color icon after plotting it. ; 1/24/87 WRL When displaying a dialog box, SysErr now looks for a 'cicn' ; resource of the same ID as the icon it is about to display. This ; allows color icons to appear in system dialog boxes. ; 1/19/87 GWN Changed branch to test mgr to a branch to CritErr. ; 1/2/87 GWN Centered MicroBug port. ; 12/31/86 GWN Modified DrawSysErr so the box is centered on the screen ; depending upon the size of the screen. The objects drawn in the ; box are also centered. ; 12/30/86 GWN Fixed "MacsBug Installed" message. Temp hack for TFB video card. ; 12/19/86 bbm Fixed offset in hittest for buttons (global to localed the ; mouse) ; 11/20/86 DAH Jump to TestManager if no DSAlertTab. ; 10/31/86 DAH Once again change the sad mac code display so the major code is ; in d7 and the minor code is in d6 to match test fail codes. ; 10/29/86 DAH swap the error display in sad mac ; 10/9/86 bbm Modified to mpw aincludes. ; 9/18/86 WRL Made this a separate PROC. ; 6/26/86 WRL Moved SystemBeep function to :OS:Beep.a ; 6/3/86 CSL Added changes for Aladddin (onMacPP). ; 5/29/86 WRL DAH Support for new CritErr. ; 4/14/86 RDC Added changes for 68020 Reno project (NuMac) - Changed variable ; for NMI debounce ; 11/3/85 JTC Heighten erase rect in MicroBug command line. ; 10/23/85 EHB Set CurMap to SysMap in case font swap needed. ; 10/16/85 EHB Made DSError set clipping to the box (restore after) ; 10/16/85 EHB Commented out systemAlert which isn't used ; 10/16/85 EHB Made FakeRgn same size as QuickDraw's wide open clip. ; 10/16/85 EHB Made MicroBug set clipping to the box (restore after) ; 8/23/85 RDC Changed code for syserror msg display for MidMac ; 8/5/85 RDC Added code to adjust system error msg display for MidMac ; 7/23/85 RDC Added changes for MidMac - changed test for MicroBug jump - ; reset NMI indicator bit when keyboard char received ; 5/21/85 KWK Fixed non-save of D1/D2 in PrintNHex routines. ; 5/13/85 KWK G
works again, so does regular syserror stuff, also ; uses equate for setting up the DS alert rect. ; 5/12/85 KWK Re-added CritErr call if no DS table ; 5/10/85 KWK Errors in drawing/DSAT punt to MicroBug, fixed restore of error ; code after drawing box. ; 5/7/85 KWK Multiple MicroBug cleanup/enhancements ; 5/4/85 KWK Added MicroDB, new DeepShit entry code ; 4/29/85 SC D4 new parameter for boot beep ; 4/29/85 SC Made SystemBeep not beep if sound is active ; 8/16/83 SC Added parameter to SystemBeep ; 8/6/83 SC Added SystemBeep ; 6/23/83 AJH made it init VBL manager before tracking button ; 6/21/83 AJH made it recouple cursor ; 6/14/83 AJH made it stash deep shit ID in low mem ; 6/2/83 AJH made it check for no dsAlerts as the 1st thing ; 5/14/83 AJH made it init and show cursor if we have any buttons ; 4/13/83 AJH Made it increment buttonID if restProc installed ; 4/5/83 AJH Added procID field to alert definition structure ; BLANKS ON STRING ASIS PRINT OFF ; LOAD 'StandardEqu.d' INCLUDE 'HardwarePrivateEqu.a' PRINT ON ; PROC EXPORT AllocFakeRgns ; EXPORT DSErrorHandler ; IMPORT TMRestart ; TestManager entry point IMPORT CritErr ; Critical Error handler, in case we fail. ; --------------------------------------------------------------------------- ; Routine AllocFakeRgns 4a50 ; Arguments ; Function Sets up a dummy vis and clip region for the system alert port ; --------------------------------------------------------------------------- AllocFakeRgns LEA VisRgn(A6),A1 ; get pointer to visRgn handle LEA PortRec(A6),A0 ; point to fake master pointer MOVE.L A0,(A1)+ ; set up visRgn's master pointer on the stack ADDQ #4,A0 MOVE.L A0,(A1)+ ; ditto with the clipRgn's LEA GetParam,A1 ; point the "master pointers" to a region MOVE.L A1,(A0) ; at GetParam to prevent a ROM write MOVE.L A1,-(A0) ; <1.3> OpenClip ; clip wide open (used on exit from syserr) LEA FakeRgn+10,A0 ; copy the region data to RAM <1.3> LEA GetParam+10,A1 ; <1.3> MOVE.L -(A0),-(A1) ; <1.3> MOVE.L -(A0),-(A1) ; <1.3> MOVE.W -(A0),-(A1) ; <1.3> RTS FakeRgn DC.W 10 DC.W $8001,$8001,$7FFF,$7FFF ; <16-Oct-85> ;--------------------------------------------------------------------------- ; ClipBox 4a80 sets the clipRegion (stored in GetParam) to the DS Alert rect. ; Trashes A0 and A1. ;--------------------------------------------------------------------------- ClipBox LEA DSAlertRect+8,A0 ; point to our rect <16-Oct-85><1.3> LEA GetParam+2+8,A1 ; point to vis/clip region <16-Oct-85><1.3> MOVE.L -(A0),-(A1) ; DSAlertRect -> GetParam+2 <1.3> MOVE.L -(A0),-(A1) ; <1.3> MOVE.L A1,-(SP) ; offset the clip's rect <16-Oct-85> BCLR #7,(A1) ; clear flag bit <16-Oct-85> MOVE.L (A5),A0 ; get the port <16-Oct-85> MOVE.L (A0),A0 ; <16-Oct-85> MOVE.L PortBounds(A0),-(SP) ; push dh,dv <16-Oct-85> _OffsetRect ; <16-Oct-85> RTS ; <16-Oct-85> ;--------------------------------------------------------------------------- ; Routine DSErrorHandler 4a9e ; Arguments DSErrCode (input) System error value ; Function Creates temporary QD world on stack & uses the current Deep shit ; alert table (DSAT) to decide what to draw/do based on the system ; error value. Allows 2 strings, 1 icon and N button to be drawn ; for any error value. The restart proc creates a default 'resume' ; button in addition to the main (typically 'restart') button. In ; addition, a procedure (called before drawing buttons) can be ; associated with an alert. ; Uses A0-A6/D0-D7 ; NOTE: Interrupts off on entry, assumes reasonable SP, D7.L must ; always be DSAlertTab ptr after setup ; Called by SystemError & SystemAlert ;--------------------------------------------------------------------------- DSErrorHandler MOVE.W #$2500,SR ; turn off interrupts 'cept power off MOVEQ #0,D6 ; clear upper word stuff <1.3> MOVE.W DSErrCode,D6 ; get saved error code MOVE.L DSAlertTab,D7 ; get alert table pointer BNE.S @GoAlert ; installed, go nuts ; no deepshit alert table, keymap/resource map probably not set up either, so just bailout MOVEQ #15,D7 ; test 15 => system alert error <1.3> BigJmp CritErr,A0 ; Go directly to CritErr <1.2> ; setup the world for QuickDraw @GoAlert MOVE.W #$2000,SR ; turn on interrupts MOVE.W CurMap,-(SP) ; save and set for System map, <24Oct85> MOVE.W SysMap,CurMap ; to ensure FONT 0 is available <24Oct85> LEA -4(SP),A5 ; start A5 here SUB.W #GrafSize+140,SP ; allocate global, port space MOVE.L SP,A6 ; remember start of port PEA -4(A5) ; point to QD global space MOVE.B QDExist,D3 ; preserve state of QDExist flag (don't let us affect it) _InitGraf ; initialize QuickDraw MOVE.B D3,QDExist ; allocate a grafPort using the space above the screen and initialize it BSR.S AllocFakeRgns ; init dummy vis and clip MOVE.L A6,-(SP) ; push address of grafPort _InitPort ; initialize the port ; decide whether to draw box or not, also whether to fall into MicroBug MOVE.W D6,D0 ; get error code <1.3> BMI.S @SkipDBox ; neg => don't redraw alert box CMP.W #13,D0 ; programmer's switch hit with no MacsBug? BEQ MicroBug ; -> yes, use the ROM-based version BSR DrawBox ; draw and clear the alert box ; move the port to the center of the screen @SkipDBox TST.B DSAlertRect ; is this a system alert? (vs system error?) BPL.S @IsSysAlert ; branch if so. MOVE.L DSCtrAdj,-(SP) ; Adjust TL of screen _MovePortTo ; and move the port. @IsSysAlert BSR.S ClipBox ; set the clip to the alert rect MOVE.W D6,D0 ; get error code <1.3> BSR FindObject ; look it up, set A0 to pt to it BNE.S @GotAlert ; found it, now draw everything associated with it ; tricky stuff...didn't find the specific alert id, so default to the first one. Note, this ; is required for the normal user alerts to work, as the 'Sorry, as system error has occured..' ; has an id of -1, thus will never be found, but it is the first alert in the table, thus it ; gets called for any system error (1..13), and its proc gets the exact error number from the ; DSErrCode location and draws the 'ID = ' string. MOVE.L D7,A0 ; get start of table ADDQ.W #6,A0 ; bump past #of entries, entry id, entry length <1.3> ; we found the alert definition record so draw any appropriate fields @GotAlert MOVE.L A0,A3 ; keep record pointer in A3 BSR DrawText ; draw the message BSR DrawText ; draw it ; Draw the icon, if any. It gets the icon structure (the bits ; and where to plot them) from the logical ID passed in D0... MOVE.W (A3)+,D0 ; get the icon ID BEQ.S @NoIcon ; skip if there isn't one BSR.S FindObject ; get the icon data structure BEQ.S @NoIcon ; if none, skip CMPI.W #30,DSErrCode ; Is the error fatal? BLO.S @FatalError ; If so, don't bug the resource manager. MOVE.L A0,A2 ; Save the pointer to the rectangle in A2 SUBQ.W #4,SP ; make room for color icon handle <1.3> MOVE.W -4(A2),-(SP) ; Push icon ID _GetCIcon ; Get the color icon of the same ID if present TST.L (SP) ; Did we get a color icon (leave the handle on the stack)? BEQ.S @NoColor ; Branch if not MOVE.L A2,-(SP) ; Push a pointer to the rectangle to plot it in MOVE.L 4(SP),-(SP) ; Push a handle to the color icon. _PlotCIcon ; Plot the color icon _DisposCIcon ; Dispose of it BRA.S @NoIcon ; Skip the black and white icon @NoColor ADDQ.W #4,SP ; Restore stack. MOVE.L A2,A0 ; Restore A0 so that we can plot the b/w version @FatalError PEA 8(A0) ; push a pointer to the icon bits MOVE.L A0,-(SP) ; push a pointer to the rectangle PEA 4(SP) ; push handle to the icon bits _PlotIcon ; plot the icon ADDQ.W #4,SP ; pop off the icon pointer ; call the alert's procedure, if any... @NoIcon MOVE.W (A3)+,D0 ; get the proc ID BEQ.S @NoProc ; if none, skip BSR.S FindObject ;look up the proc BEQ.S @NoProc ;if not found, skip JSR (A0) ;invoke it ; draw any buttons... @NoProc MOVE.W (A3)+,D0 ;get the buttonList BEQ.S @NoSemantics ;if none, we're done ; if there's a restart proc installed, increment buttonID number TST.L RestProc ;is a restart procedure installed? BEQ.S @NoRestart ADDQ.W #1,D0 ;yes, increment the buttonID number @NoRestart BSR DoButtons ;draw the button list and hit test it BEQ.S @NoSemantics ;if none, we're done <1.3> ; we got a semantic routine associated with a button so invoke it MOVE.L A0,-(SP) ; set up routine BRA OpenClip ; set clip to full size and jump to A0 routine <1.3> ; there is no button list, or the button that was pushed denies responsibility, ; so just return to caller normally. @NoSemantics RTS2SysErr BSR OpenClip ; set clip back to full size ADD.W #GrafSize+140,SP ; cut back the stack MOVE.W (SP)+,CurMap ; restore CurMap from stuffed SysMap <24Oct85> MOVEQ #0,D0 ; return no error RTS ; exit back to SystemError code ;--------------------------------------------------------------------------- ; FindObject 4b88 takes the logical alert ID in D0 and scans through the ; association until it finds an entry with the matching ID. It returns ; a pointer to the object body in A0, which is NIL if it couldn't ; find anything. The z-Flag will be set if we couldn't find it. ;--------------------------------------------------------------------------- FindObject MOVE.L D7,A0 ;point to DS data structure MOVE.W (A0)+,D1 ;get the number of entries BRA.S @GoFindIt @NextObject CMP.W (A0)+,D0 ;is this the one we're looking for? BEQ.S @FoundObj ;-> didn't find the object we want ADDA.W (A0)+,A0 ;bump to the next object @GoFindIt DBRA D1,@NextObject ;-> keep looping if not SUBA.L A0,A0 ;couldn't find it so return NIL MOVEQ #0,D0 ; and exit with BEQ RTS @FoundObj ADDQ.W #2,A0 ;skip length word to point to the data MOVEQ #-1,D0 ; and exit with BNE RTS ;--------------------------------------------------------------------------- ; DrawText 4ba4 draws the deep shit text structure as specified by the ID in D0 ;--------------------------------------------------------------------------- DrawText MOVE.W (A3)+,D0 ;get the text ID BEQ.S @NoText ;if zero, nothing to do BSR.S FindObject ;find the text structure BEQ.S @NoText ;if not found, we're done MOVE.L (A0)+,D3 ;get the start point MOVEA.L A0,A2 ;remember start of the first line ; scan for a null ($00) indicating the end of the text or the line separation character @ScanForEOL MOVE.B (A2)+,D0 ;get the next byte <1.3> BEQ.S @DrawTxLine ;if null, go draw the last line CMP.B #'/',D0 ;is it the line separator? BNE.S @ScanForEOL ;if not, continue scanning ; we got a null or a line separator so draw the text line @DrawTxLine MOVE.B D0,-(SP) ;preserve the delimiting character MOVE.L A2,D0 ;calculate how many text characters <1.3> SUB.L A0,D0 ; are on this line <1.3> SUBQ.W #1,D0 ; (don't include the delimiter in the length) MOVE.L A0,-(SP) ;pointer to the text to draw <1.3> CLR.W -(SP) ;start at the beginning of the text MOVE.W D0,-(SP) ;how many characters to draw MOVE.L D3,-(SP) ;move to the starting text position _MoveTo _DrawText ; and draw a line of text ADDI.L #$000E0000,D3 ;move the position to the start of the next line MOVEA.L A2,A0 ;point A0 at the beginning of the next line MOVE.B (SP)+,D0 ;was the delimiter a null? BNE.S @ScanForEOL ;-> no, go do the next line @NoText RTS ;--------------------------------------------------------------------------- ; DrawBox 4bdc draws a dialog-box-like-box or a deepshit-like-box ;--------------------------------------------------------------------------- DrawBox MOVE.L DSDrawProc,D0 ; is a custom dialog draw procedure specified? BLE.S @StdProc ; -> nope MOVE.L D0,-(SP) ; push its address BSET #7,DSDrawProc ; make it a one-shot RTS ; go to it @StdProc MOVE D6,D0 BSR.S FindObject BEQ.S @old CMPI #12,-2(A0) BLT.S @old MOVE 10(A0),D0 BSR.S FindObject BEQ.S @old MOVE.L (A0)+,DSAlertRect MOVE.L (A0),DSAlertRect+4 PEA.L DSAlertRect BSR NewAlertFunc ADDQ #4,SP @old LEA DSAlertRect,A0 ; pt A0 at rect TST.B (A0) ; is this a system alert? (vs system error?) BPL.S DrawSysAlert ; yes, draw normal, do _MovePortTo ; we know it's a system error, so go stuff the rect w/what we need ; 4c1c DrawSysErr MOVEM.L A1/D1,-(SP) ; save registers. MOVE.L (A5),A1 ; LEA ScreenBits+Bounds+bottom(A1),A1 ; <1.3> MOVEQ #100,D0 ; DSRect.top <- bounds.bottom/5.34 <1.3> MULU (A1)+,D0 ; <1.3> DIVU #534,D0 ; MOVE.W D0,top(A0) ; MOVEQ #-(DSRectTL>>16),D1 ; DSCtrAdj <- DSRect.top - (Mac DSRect.top) <1.3> ADD.W D0,D1 ; <1.3> MOVE.W D1,DSCtrAdj ; <1.3> ADD.W #DSRectHei,D0 ; DSRect.bottom <- DSRect.top + DSRectHei MOVE.W D0,bottom(A0) ; MOVE.W (A1),D0 ; DSRect.left <- bounds.right/2 - DSRectLen/2 LSR.W #1,D0 ; SUB.W #DSRectLen/2,D0 ; MOVE.W D0,left(A0) ; MOVEQ #-(DSRectTL**$FFFF),D1 ; DSCtrAdj <- DSRect.left - (Mac DSRect.left) <1.3> ADD.W D0,D1 ; <1.3> MOVE.W D1,DSCtrAdj+2 ; <1.3> ADD.W #DSRectLen,D0 ; DSRect.right <- bounds.right/2 + DSRectLen/2 MOVE.W D0,right(A0) ; BSR.S DrawBox2 ; draw it BSET #7,DSAlertRect ; reset flag for system error MOVEM.L (SP)+,A1/D1 ; restore registers. RTS ; and return ; 4c6a DrawSysAlert BSR.S DrawBox2 ; draw it MOVE.L DSAlertRect,-(SP) ; push TL of rect _MovePortTo ; move there RTS ; and return ; use rect at (A0) ; 4c74 DrawBox2 MOVE.L A0, -(SP) ; rect for EraseRect MOVE.L A0, -(SP) ; rect for FrameRect MOVE.L A0, -(SP) ; rect for InsetRect MOVE.L A0, -(SP) ; rect for FrameRect MOVE.L A0, -(SP) ; rect for InsetRect <19Mar85> _EraseRect _FrameRect MOVE.L #$00020002, -(SP) _PenSize MOVE.L #$00030003, -(SP) _InsetRect _FrameRect ; draw the border MOVE.L #$FFFDFFFD,-(SP) ; <19Mar85> _InsetRect ; put the rect back to normal <19Mar85> _PenNormal ; put the pen back to normal NoButtons RTS NewAlertFunc Link A6, #-$8 MoveM.L A1-A3, -(A7) MoveA.L $8(A6), A3 Lea.L -$8(A6), A2 MoveA.L (A5), A0 Lea.L -$74(A0), A0 Move.L (A0)+, (A2) Move.L (A0), $4(A2) SubQ #$2, A7 Move (MBarHeight), (A7) Move (A7)+, D0 Add D0, (A2) Move.L A3, -(A7) Move $6(A2), D0 Add $2(A2), D0 AsR #$1, D0 Move D0, -(A7) Move $6(A3), D0 Add $2(A3), D0 AsR #$1, D0 Sub D0, (A7) Move (A2), D0 Add $4(A2), D0 AsR #$1, D0 Move D0, -(A7) Move (A3), D0 Add $4(A3), D0 AsR #$1, D0 Sub D0, (A7) _OffsetRect Move (A3), D0 Sub (A2), D0 Ext.L D0 Neg.L D0 DivS #$3, D0 Move.L A3, -(A7) Clr -(A7) Move D0, -(A7) _OffsetRect MoveM.L (A7)+, A1-A3 Unlk A6 Rts ;--------------------------------------------------------------------------- ; DoButtons draws some buttons as specified by the buttonList data structure ; defined by the ID in D0, and then hit-tests the mouse position against ; them. It returns a dispatch address in A0, which is NIL if the deep ; shit manager should just return ;--------------------------------------------------------------------------- DoButtons BSR FindObject ;find the buttonList data structure BEQ.S NoButtons ;if none, we're done MOVE.L A0,A2 ;remember the button base MOVE.W (A0)+,D3 ;get the number of buttons MOVE.L A0,A3 ;point A3 at the first button ; loop through the button list, drawing each button @DrawBtnLp MOVE.L 2(A3),-(SP) ;push topLeft ADD.L #$000E0004,(SP) ;offset it for pen position _MoveTo ;position the pen MOVE.W (A3)+,D0 ;get the string ID BSR FindObject ;find the string SUBQ.W #1,A0 ;point to low byte of length MOVE.L A0,-(SP) ;push the string pointer _DrawString ;draw the string MOVE.L A3,-(SP) ;push the rectangle pointer MOVE.L #$00100010,-(SP) ;push the roundness factor _FrameRoundRect ;frame it ADD.W #8+2,A3 ;bump to next button SUBQ.W #1,D3 ;any more buttons to do? BNE.S @DrawBtnLp ;-> yes ; set the cursor to the arrow and show it MOVE.L (A5),A0 ;get global base PEA Arrow(A0) ;push ptr to arrow image _SetCursor ;make that the cursor _ShowCursor ;make sure the cursor is visible MOVE #$2000,SR ;make sure interrupts are on ST CrsrCouple ;force the cursor to be coupled CLR.B VBLQueue ;make sure VBL manager is cool ; OK, now the buttons are drawn so poll for a mouse button down @Wait4Click TST.B MBState ;is the mouse button down? BNE.S @Wait4Click ;-> nope, wait until it is ; the mouse button went down, so loop through the button data structure to ; determine which button, if any, it went down in MOVE.L A2,A3 ;get start of button list MOVE.W (A3)+,D3 ;get the number of buttons ADDQ #2,A3 ;skip past the string ID @FindBtnHit BSR.S myPtInRect ;test if we're in the button BNE.S @TrackBtn ;if so, go track the button ; we're not in this button, so go test the next button. If we tested them ; all, go try again ADD.W #8+2+2,A3 ;bump to the next button SUBQ.W #1,D3 ;decrement button count BNE.S @FindBtnHit ;if more to test, loop BRA.S @Wait4Click ;go poll the mouse button ; at this point, we know the mouse has gone down in the rectangle pointed to ; by A3. Track the mouse until the button goes up @TrackLoop BSR.S myPtInRect ;are we in the rectangle? CMP.B D0,D3 ;did it change? BEQ.S @NoChange ;skip if it didn't ; we've moved in if we were out or out if we were in so toggle our state @TrackBtn MOVE.B D0,D3 ;flag the button on/off <1.3> BSR.S InvertBut ; and hilite or unhilite it ; now see if the mouse button went up; continue tracking until it does @NoChange TST.B MBState ;is the mouse button still down? BEQ.S @TrackLoop ;-> nope, keep looping until it's not ; the mouse went up -- if it wasn't in a button, continue polling the mouse ; button. If it was, return the address of the appropriate semantic routine TST.B D3 ;were we in the button? BEQ.S @Wait4Click ;if not, go try again MOVE.W 8(A3),D0 ;get ID of proc object BRA FindObject ; and look it up <1.3> ; myPtInRect is a little code saving utility that tests if the current ; mouse position is in the rectangle pointed to by A3 myPtInRect SUBQ #2,SP ;make room for the function result MOVE.L Mouse,-(SP) ;push the current mouse point PEA (SP) ;push address of mouse point _GlobalToLocal ;convert it to coordinates of alert MOVE.L A3,-(SP) ;push the rectangle ptr _PtInRect ;test if the point is in the button MOVE.B (SP)+,D0 ;get the result in D0 RTS ; InvertBut is a utility to invert the button whose rectangle is pointed to by A3 InvertBut MOVE.L A3,-(SP) ;push the rectangle pointer MOVE.L #$00100010,-(SP) ;push the rounding factor _InverRoundRect ;invert it RTS ; --------------------------------------------------------------------------- ; Routine MicroBug ; Arguments ; Function Minimal debugger in Rom. Allows display/set of memory/registers, ; also Go [address]. Invoked by one of two ways: ; ; 1) System alert/error & no alert definition found for error number ; 2) NMI & no debugger installed. ; ; Registers D7 Previous command ; D6-D3 DM drawing ; D0-D2 Scratch ; A7 Stack ; A6 Input buffer current position ptr ; A5 Globals ptr ; A4 Input buffer start ptr ; A0-A3 Scratch ; --------------------------------------------------------------------------- MicroBug CLR.W DSErrCode ; zero the deep shit code (no actual error) <1.4> LEA DSAlertRect,A0 ; pt A0 at rect BSR DrawSysErr ; erase/draw the deepshit error box MOVE.L DSCtrAdj,-(SP) ; adjust TL of DS rect for screen size ADD.L #DSrectTL+$00060006,(SP); so that text is inside of the rect _MovePortTo ; and move the port BSR ClipBox ; set the clipping to DSAlertRect SUB.W #evtBlkSize,SP ; room for event record <1.3> CLR.W D7 ; clear previous cmd value CLR.L MBdotAddr ; clear dot address CLR.L MBlocAddr ; clear location CmdReset MOVE.L #$001101B0,-(SP) ; BR = 120, 440 so we use 15, 440 (minus some) ; upped descender to 17 to catch ',' ';' etc. <03Nov85 JTC> CLR.L -(SP) ; set TL = 0 BSR MBDoErase ; erase it LEA MBbuffer+MBbufSize,A6 ; point to end of buffer MOVEQ #0,D6 ; init counter @0 MOVE.W #' ',-(A6) ; clear it ADDQ.W #2,D6 ; bump counter CMP.W #MBbufSize,D6 ; all done? BNE.S @0 ; nope MOVE.L A6,A4 ; set start/end ptr MOVE.L #$000F000A,-(SP) ; push h,v = 10,15 _MoveTo ; move there MOVEQ #'>',D0 ; get prompt char MOVE.W D0,-(SP) ; push on stack _DrawChar ; and draw it ; Command loop. Get events, stuff key-down chars into buffer and display them, ; wait for return. On return, process buffer. CmdLoop MOVE.L SP,A0 ; Point to event record on stack MOVEQ #1< _GetOSEvent ; any keyDown events in the queue? BNE.S CmdLoop ; -> no, wait for one ; we got a keydown event, process it BCLR #7,NMIFlag ; clear NMI indicator bit MOVEQ #$7F,D0 ; get the ASCII character value <1.3> AND.B evtMessage+3(SP),D0 ; and force it to be less than 128 <1.3> CMP.B #'a',D0 ; is it lower case? BLT.S @0 BCLR #5,D0 ; yes, force it to be upper case ; now D0.B is the character code value @0 CMP.B #13,D0 ; carriage return? BEQ.S GotCommand ; -> yes, go process the buffer CMP.B #8,D0 ; backspace? BNE.S RegChar ; -> no, all ok CMP.L A6,A4 ; anything in buffer? BEQ.S CmdLoop ; no, bail out ADDQ.W #1,D6 ; increment remaining buffer space count SUBQ.W #1,A6 ; remove one char from buffer SUBQ.W #4,SP ; room for pt MOVE.L SP,-(SP) ; @pt _GetPen ; get current pen pos, leave on stack MOVE.L (SP),-(SP) ; make copy (building rect on stack) SUBQ.W #2,SP ; room for result MOVE.B (A6),D0 ; get last char MOVE.W D0,-(SP) _CharWidth ; and measure it MOVE.W (SP)+,D3 ; get width SUB.W D3,2(SP) ; adjust left point of rect on stack CLR.W (SP) ; top pt = 0 MOVE.L SP,-(SP) ; push @rect CLR.W -(SP) ; delta h = 0 MOVE.W #2,-(SP) ; delta v = 2 _OffsetRect ; offset it BSR MBDoErase ; erase it MOVE.B #$20,(A6) MOVE.W D3,-(SP) ; char width NEG.W (SP) ; negative movement CLR.W -(SP) ; delta V = 0 _Move ; and reset the pen BRA.S CmdLoop ; return RegChar TST.W D6 ; any space left? BEQ.S CmdLoop ; no, don't add any more chars SUBQ.W #1,D6 ; dec buffer free space count MOVE.B D0,(A6)+ ; buffer it up MOVE.W D0,-(SP) ; push on stack _DrawChar ; draw it BRA.S CmdLoop ; and loop GotCommand CMP.L A4,A6 ; any chars? BNE.S @0 ; yes, do reg processing MOVE.W D7,(A6)+ ; stuff previous command @0 MOVE.W (A4)+,D7 ; get command word LEA MBcmds,A0 ; point at command table @1 MOVE.W (A0)+,D0 ; get routine name BMI.S @3 ; last command, nothing matched MOVE.W (A0)+,D2 ; get routine offset CMP.B #'@',D0 ; register display routine (wildcard digit?) BNE.S @2 ; nope MOVE.B D7,D0 ; stuff input number CMP.B #'0',D0 ; zero reg? BMI.S @1 ; no, try next command CMP.B #'7',D0 ; last reg BGT.S @1 ; no, try next command @2 CMP.W D0,D7 ; does input command match table BNE.S @1 ; try next command LEA MBcmds,A0 ; pt to start of this code JSR 0(A0,D2.W) ; execute the routine @3 BRA CmdReset ; and start cmd loop again MBcmds DC.W 'G ', GCmd-MBcmds ; since command line cleared, 'G' only matches to G & null DC.W 'DM', DMCmd-MBcmds DC.W 'SM', SMCmd-MBcmds DC.W 'TD', TDCmd-MBcmds DC.W 'D@', DCmd-MBcmds DC.W 'A@', ACmd-MBcmds DC.W 'PC', PCCmd-MBcmds DC.W 'SR', SRCmd-MBcmds DC.W -1 ; Go command. Try for address, if not there just return, else rts to it GCmd BSR ReadToken ; try for address BEQ.S GotResume MOVE.L D0,-(SP) ; stuff address BSR OpenClip ; restore clipping RTS ; and go to it GotResume ADD.W #20,SP ; get rid of event record, RTS CLR.B DSWndUpdate ; flag GNE to remove the alert . . . BRA RTS2SysErr ; return to SysError handler ; Erase the rect on the stack ; Uses D0-D2/A0-A2 MBDoErase MOVE.L (SP)+,A2 ; preserve return address MOVE.L SP,-(SP) ; push @rect _EraseRect ; erase lower pane ADDQ.W #8,SP ; flush rect JMP (A2) ; and return ; Display memory command. Get Address, do full window for the guy DMCmd MOVE.L #$007001B0,-(SP) ; push BR CLR.L -(SP) ; TL = 0 BSR.S MBDoErase ; erase the rect BSR ReadXToken ; get address @0 BCLR #0,D0 ; force even address MOVE.L D0,A3 ; set display address MOVE.L D0,MBdotAddr ; save as dot addr MOVEQ #6-1,D6 ; 6 lines MOVEQ #15,D5 ; starting V coord @1 ADD.W #15,D5 ; bump V coord MOVE.W #10,-(SP) ; push h MOVE.W D5,-(SP) ; push v _MoveTo ; move there MOVE.L A3,D0 ; get address BSR.S Print6Hx ; print out MOVEQ #7,D4 ; 8 words MOVEQ #35,D3 ; starting h coord @2 ADD.W #45,D3 ; bump h coord MOVE.W D3,-(SP) ; push h MOVE.W D5,-(SP) ; push v _MoveTo ; move there MOVE.W (A3)+,D0 ; get next word BSR.S Print4Hx ; print word DBRA D4,@2 ; word column loop DBRA D6,@1 ; line loop MOVE.L A3,MBlocAddr ; set up new address RTS ; and return Print6Hx SWAP D0 BSR.S Print4Hx SWAP D0 Print4Hx MOVE.W D0,-(SP) ROXR.W #8,D0 BSR.S Print2Hx MOVE.W (SP)+,D0 Print2Hx MOVE.W D0,-(SP) ROR.W #4,D0 BSR.S PUTHEX MOVE.W (SP)+,D0 PUTHEX ANDI.B #$0F,D0 ORI.B #'0',D0 CMPI.B #'9',D0 BLE.S @0 ADDQ.W #7,D0 @0 MOVE.L D0,-(SP) ; save D0 MOVE.W D0,-(SP) ; push on stack _DrawChar ; draw it MOVE.L (SP)+,D0 ; restore D0 RTS ; and return ; Set Memory command. Get an address, and then keep stuffing values until we're done ; Uses D0-D6/A0-A1/A3 SMCmd BSR ReadXToken MOVE.L D0,A1 LEA MBdotAddr,A0 ; point at storage MOVE.L D0,(A0)+ ; set dot and loc addresses MOVE.L D0,(A0)+ MOVE.W #'DM',D7 ; jam repeat cmd to DM @1 BSR ReadToken BEQ.S DMCmd ; using locAddr, draw lower pane MOVE.L A1,A2 ; get fixed point for shifting bytes in @2 MOVE.B D0,-1(A2,D1) ; stuff byte at last position indicated by size (D1.W) ASR.L #8,D0 ; get next byte ADDQ.L #1,A1 ; bump destination ptr SUBQ.L #1,D1 ; dec offset ptr BNE.S @2 ; not done w/this value, keep looping BRA.S @1 ; any more tokens? ; TD command. Display memory where all the regs are saved. TDCmd MOVE.L #SEVars,MBlocAddr ; set saved address to be location of regs BRA.S DMCmd ; using locAddr, draw lower pane ; Dx command. Set/display data register DCmd LEA SED0,A3 ; pt at reg 0 BRA.S SetR ACmd LEA SEA0,A3 BRA.S SetR PCCmd LEA SEPC,A3 BRA.S SetR0 SRCmd LEA SESR,A3 BSR.S ReadToken BEQ.S SetR2 ; print value MOVE.W D0,(A3) ; stuff input RTS ; and return SetR BSR.S GetHex ; convert ascii in D0.B to hex value LSL.L #2,D0 ; turn into long offset ADD.L D0,A3 ; add offset SetR0 BSR.S ReadToken BEQ.S SetR1 ; print value MOVE.L D0,(A3) ; stuff value RTS ; and return SetR2 MOVEQ #-1,D6 ; normal branch to SetR1 has D6=0 SetR1 MOVE.L #$007001B0,-(SP) ; push BR CLR.L -(SP) ; TL = 0 BSR.S MBDoErase ; erase the rect MOVE.L #$00300010,-(SP) ; push 10,30 as drawing pt _MoveTo ; go there MOVE.W (A3)+,D0 ; get current value TST.W D6 ; special SR case? BNE.S @0 ; yes, only print word BSR.S Print4Hx ; print high word MOVE.W (A3)+,D0 ; get low word @0 BRA.S Print4Hx ; print low word <1.3> GetHex AND.L #$FF,D0 ; mask off anything but low byte CMP.B #$39,D0 ; Hex digit BLE.S @0 ; assume so SUBQ.B #7,D0 ; assume 0..9 @0 AND.B #$F,D0 ; mask off low nybble RTS ; and return ; ReadXToken will return either ReadToken value or (if nothing in input buffer) ; the saved long value ; ReadToken will return in D0.L the next value in the command line. CC=NE if ; something was there. ; Uses D0-D6/A0 ReadXToken BSR.S ReadToken ; try for something BNE.S @0 ; we got something back, return it MOVE.L MBlocAddr,D0 ; return saved address @0 RTS ; and return ReadToken MOVEQ #0,D4 ; clear accumulator MOVEQ #0,D6 ; max # digits ReadMore MOVEQ #0,D5 ; count # digits CLR.W MBSign ; set sign to positive MOVEQ #0,D3 ; assume no indirection MOVEQ #0,D0 MOVEQ #0,D1 ; sub-number built here blanks CMP.L A6,A4 ; any more chars? BGE ReadExit ; if not escape leadSP MOVE.B (A4)+,D0 ; get next char CMPI.B #' ',D0 ; skip blanks BLE.S blanks ; See if leading sign or indirection CMP.B #'@',D0 ; leading @ indirection BNE.S @0 ADDQ #1,D3 ; bump indirection counter BRA.S leadSP @0 CMP.B #'+',D0 ; leading plus BEQ.S leadSP CMP.B #'-',D0 ; leading minus BNE.S getBase NOT.B MBSign ; record sign change BRA.S leadSP getBase CMP.B #'$',D0 ; leading $? BNE getLabel ; no, try for label MOVEQ #0,D0 ; clear char value MOVE.B (A4)+,D0 ; next character getNumber BSR GetHex ; convert hex ascii digit in D0.B to number ADDQ #1,D5 ; increment # digits LSL.L #4,D1 ; multiply by 16 ADD.L D0,D1 ; add in this digit ; Are we done? CMP.L A6,A4 ; any more chars? BGE.S ReadExit ; if not escape MOVE.B (A4)+,D0 ; get next char CMP.B #'0',D0 ; < ASCII zero BGE.S GetNumber ; go get more ReadExit TST D3 ; any indirection? BEQ.S @1 MOVEQ #8,D5 ; jam eight digits @0 BCLR #0,D1 ; make sure it's even MOVE.L D1,A0 ; indirect it MOVE.L (A0),D1 SUBQ #1,D3 BNE.S @0 @1 TST.B MBSign ; negative? BEQ.S @2 ; no, keep going NEG.L D1 @2 ADD.L D1,D4 ; add into result ; Clean up the bytes counter ADDQ.W #1,D5 ; round up LSR.W #1,D5 ; convert # chars to number of bytes CMP.W #4,D5 ; more than a long? BLE.S @3 ; no MOVEQ #4,D5 ; jam to a long @3 CMP.W D6,D5 ; bump max # digits if D5 > BLE.S @4 MOVE.W D5,D6 ; max # digits @4 CMPI.B #'+',D0 ; if plus or minus add a new one BEQ.S @5 CMPI.B #'-',D0 BNE.S @6 @5 MOVE.B D0,-(A4) ; push back on sign BRA ReadMore ; and keep looping @6 MOVE.L D4,D0 ; return the number MOVE.L D6,D1 ; return max digits RTS ; and return ; See if the text matches a label getLabel CMP.B #'.',D0 ; dot? BNE.S notDot MOVE.L MBdotAddr,D1 ; get saved long MOVEQ #1,D2 ; amount to skip goLabel MOVEQ #8,D5 ; all eight bytes cleanExit MOVE.B (A4)+,D0 SUBQ #1,D2 BNE cleanExit BRA ReadExit notDot MOVE D0,D2 ; build a word LSL #8,D2 MOVE.B (A4),D2 ; get second byte CMP #'PC',D2 ; PC? BNE.S notPC MOVE.L SEPC,D1 ; return the PC go2Label MOVEQ #2,D2 ; amount to skip BRA goLabel notPC CMP.B #'R',D0 ; reg references start with R BNE.S getNumber ; try for hex number CMP.B #'A',D2 ; aregs BNE.S notAs LEA SEA0,A0 ; point to address regs loc doReg MOVEQ #0,D2 ; calculate the index MOVE.B 1(A4),D2 SUB #'0',D2 BMI.S getNumber ; RAx, x < '0' CMP #7,D2 BGT.S getNumber ; RAx, x > '7' LSL #2,D2 MOVE.L 0(A0,D2),D1 MOVEQ #3,D2 ; amount to skip BRA goLabel notAs CMP.B #'D',D2 ; Dregs BNE.S getNumber ; Rx, x <> A, x <> D LEA SED0,A0 ; point to data regs loc BRA doReg ENDP ; END ;