home *** CD-ROM | disk | FTP | other *** search
-
- incpath include:
- maclib sm.mac
- macfile macro.i
- macfile snoopy.i
- macfile macros/main
- macfile extern/parse
- macfile extern/misc
- macfile macros/startup
- macfile extern/patch
-
- DETACHSTARTUPARGS <argTemplate>,<argFirst>,maincode,4096
-
- maincode bsr Setup
- tst d0
- bne .FAIL
-
- ;-------------- if the user only wants to quit, don't show anything
- tst.l (argQuit)
- bne .QUITONLY
-
- ;-------------- give out initial welcome to the user
- move.l (currentInstance),(outputArgs)
- SHOWMSG hello
-
- ;-------------- main loop ! Wait for signals to arrive, and process them
- .MainLoop move.l (waitsignals),d0
- CALL Wait,<(execBase).w>
- move.l d0,(signals)
-
- ;-------------- CTRL+C terminates the program
- BRBS #SIGBREAKB_CTRL_C,d0,.DONE
-
- ;-------------- if we got a message, then answer it
- move.l d0,d1
- and.l (answersignal),d1
- tst.l d1
- beq.b .NoMessage
- bsr HandleReply
- bra.b .MainLoop
- .NoMessage
- ;-------------- CTRL+D disables output
- BRBC.B #SIGBREAKB_CTRL_D,d0,.DisableOutput
- tst.b (outputactive)
- beq.b .MainLoop
- move.b #FALSE,(outputactive)
- SHOWMSG disableout
- bra .MainLoop
- .DisableOutput
- ;-------------- CTRL+E disables output
- BRBC.B #SIGBREAKB_CTRL_E,d0,.EnableOutput
- tst.b (outputactive)
- bne.b .MainLoop
- move.b #TRUE,(outputactive)
- SHOWMSG enableout
- bra .MainLoop
- .EnableOutput
- ;-------------- CTRL+F toggles the task info feature
- BRBC.B #SIGBREAKB_CTRL_F,d0,.ToggleTI
- tst.l (argTaskInfo)
- bne.b .TI_Disabled
- move.l #TRUE,(argTaskInfo)
- SHOWMSG TIenabled
- bra .MainLoop
- .TI_Disabled SHOWMSG TIdisabled
- clr.l (argTaskInfo)
- .ToggleTI
- bra .MainLoop
-
- ;-------------- sorry, calls still active
- .CALLSACTIVE lea (activeCallsErr,pc),a0
- move.l (ActiveCalls),(outputArgs)
- jsr ShowErrorMessage
- bra .MainLoop
-
- .DONE tst.l (ActiveCalls)
- bne.b .CALLSACTIVE
- bsr RemoveFunctions ; remove all functions
- tst.w d0
- beq .MainLoop
- .QUITONLY bsr Cleanup
- moveq #RETURN_OK,d0
- rts
-
- .FAIL bsr RemoveFunctions ; MUST succeed, otherwise we're really in trouble
- bsr Cleanup
- moveq #RETURN_ERROR,d0
- rts
-
- ***********************************************************************************
- ;--------------
- ENTRY Setup,d1-d7/a0-a6
- clr.l (ActiveCalls)
-
- ;-------------- empty all lists used
- prepare hides
- prepare shows
- prepare bases
- prepare watches
- prepare deviceBases
- prepare aliases
- prepare defines
- prepare resources
- move.b #TRUE,(outputactive)
-
- ;-------------- open librarys needed
- openlib int
- openlib icon
- bsr ReadWBArgs
-
- ;-------------- perhaps we only need to remove any running Snoopys ?!
- tst.l (argQuit)
- beq.b .DONTQUIT
- bsr QuitSnoopyInstances
- moveq #TRUE,d0
- bra Setup_done
- .DONTQUIT
- ;-------------- build taskname to be removeable
- bsr BuildSnoopysTaskname
-
- ;-------------- try to open script file
- move.l (argScript),d0
- bne.b .CallParser
- move.l #defaultScript,d0
- .CallParser movea.l d0,a0
- jsr ParseScriptFile
- tst d0
- bne .NODOSBASE ; this looks strange but it works just fine
-
- ;-------------- defines and aliases are not needed any longer, so they can be
- ;-------------- freed immediately
- remlist defines,sdef_SIZEOF
- remlist aliases,salias_SIZEOF
-
- ;-------------- try to find SegTracker(tm)
- clr.l (SegTracker)
- lea (SegTrackerName,pc),a1
- CALL FindSemaphore,<(execBase).w>
- tst.l d0
- beq.b .NOSEMAPHORE
- movea.l d0,a0
- move.b #TRUE,(SegTrackerOn)
- move.l (segs_Find,a0),(SegTracker)
- .NOSEMAPHORE
- ;-------------- create msgport
- CALL CreateMsgPort,<(execBase).w>
- move.l d0,(myport)
- beq .NOMSGPORT
- move.l (ThisTask,a6),(thistask)
- movea.l d0,a1
- move.l #currentPortName,(LN_NAME,a1)
- moveq #0,d0
- move.b (MP_SIGBIT,a1),d0
- moveq #1,d1
- lsl.l d0,d1
- move.l d1,(answersignal)
- or.l #MASK_SIGNALS,d1
- move.l d1,(waitsignals)
- CALL AddPort
-
- ;-------------- open CON: window
- move.l #windowName,d1
- tst.b (outputMemory)
- beq.b .NOOUTPUTKEYWRD
- move.l #outputMemory,d1
- .NOOUTPUTKEYWRD tst.l (argOutput)
- beq.b .DefaultWindow
- move.l (argOutput),d1
- .DefaultWindow move.l #MODE_READWRITE,d2
- CALL Open,<(dosBase)>
- move.l d0,(window)
- beq.b .NOWINDOW
- jsr SetCmdlineSHOWs
-
- ;-------------- patch functions
- bsr PatchFunctions
- tst.w d0
- beq.b .NODOSBASE
-
- ;-------------- set my priority (if applicable)
- move.l (priority),d0
- tst.l (argPri)
- beq.b .NOPRICMD
- movea.l (argPri),a0
- move.l (a0),d0
- .NOPRICMD movea.l (execBase).w,a6
- movea.l (ThisTask,a6),a1
- CALL SetTaskPri
-
- moveq #RETURN_OK,d0
- bra.b Setup_done
-
- .NOWINDOW lea (nowindowErr,pc),a0
- bra.b .FAIL
- .NOMSGPORT lea (nomsgportErr,pc),a0
- .FAIL jsr ShowErrorMessage
- .NODOSBASE moveq #RETURN_ERROR,d0
- DONE Setup
-
- ***********************************************************************************
- ;--------------
- ENTRY Cleanup,d0-d7/a0-a6
-
- bsr RemoveDeviceBases
- bsr RemoveLibraryBases
-
- ;-------------- close window
- move.l (window),d1
- beq.b .NoWindow
- CALL Close,<(dosBase)>
- .NoWindow
- ;-------------- remove msgport
- move.l (myport),d0
- beq.b .NoMsgPort
- movea.l d0,a1
- CALL RemPort,<(execBase).w>
- bsr RemoveAllMessages
- movea.l (myport),a0
- CALL DeleteMsgPort
- .NoMsgPort
- ;-------------- close CLI arguments
- move.l (argRdargs),d1
- beq.b .NoRdArgs
- CALL FreeArgs,<(dosBase)>
- .NoRdArgs
- ;-------------- close librarys
- closelb int
- closelb icon
-
- ;-------------- remove structures
- remlist defines,sdef_SIZEOF
- remlist aliases,salias_SIZEOF
- remlist bases,sbase_SIZEOF
- remlist resources,sbase_SIZEOF
- remlist hides,stask_SIZEOF
- remlist shows,stask_SIZEOF
- remlist watches,spatch_SIZEOF
- remlist deviceBases,sdevbase_SIZEOF
- DONE Cleanup
-
- ***********************************************************************************
- ;-------------- remove all remaining messages from the port (so that we can be sure
- ;-------------- we have not lost any memory
- ;--------------
- ENTRY RemoveAllMessages,d0-d7/a0-a6
-
- ;-------------- free message memory
- movea.l (execBase).w,a6
- .LOOP movea.l (myport),a0
- CALL GetMsg
- tst.l d0
- beq.b .DONE
- movea.l d0,a1
- move.l #smsg_SIZEOF,d0
- CALL FreeMem
- bra.b .LOOP
- .DONE DONE RemoveAllMessages
-
- ***********************************************************************************
- ;-------------- remove all library bases
-
- ENTRY RemoveLibraryBases,d0-d7/a0-a6
- lea (bases),a5
- movea.l (LH_HEAD,a5),a5
- movea.l (execBase).w,a6
- .BASELOOP tst.l (LN_SUCC,a5) ; a5 = current node
- beq.b .BASEDONE
- move.l (sbase_Library,a5),d0
- beq.b .NEXTBASE
- clr.l (sbase_Library,a5)
- movea.l d0,a1
- CALL CloseLibrary
- .NEXTBASE movea.l (LN_SUCC,a5),a5
- bra.b .BASELOOP
- .BASEDONE DONE RemoveLibraryBases
-
- ***********************************************************************************
- ;-------------- remove all device bases
-
- ENTRY RemoveDeviceBases,d0-d7/a0-a6
- lea (deviceBases),a5
- movea.l (LH_HEAD,a5),a5
- .BASELOOP2 tst.l (LN_SUCC,a5) ; a5 = current node
- beq.b .BASEDONE2
-
- ;-------------- remove message port
- ;move.l (sdevbase_MsgPort,a5),d0
- ;beq.b .NOMSGPORT
- ;movea.l d0,a0
- ;CALL DeleteMsgPort,<(execBase).w>
- .NOMSGPORT
- ;-------------- remove device bases
- move.l (sdevbase_Device,a5),d0
- beq.b .NEXTBASE2
- clr.l (sdevbase_Device,a5)
- movea.l d0,a1
- CALL Forbid,<(execBase).w>
- subq.w #1,(LIB_OPENCNT,a1)
- move.b (LIB_FLAGS,a1),d0
- bset #LIBB_CHANGED,d0
- move.b d0,(LIB_FLAGS,a1)
- CALL SumLibrary
- CALL Permit
-
- ;-------------- free all patches for this device)
- .NEXTBASE2 lea (sdevbase_Patches,a5),a0
- move.l #spatch_SIZEOF,d0
- jsr RemoveList
- movea.l (LN_SUCC,a5),a5
- bra.b .BASELOOP2
- .BASEDONE2 DONE RemoveDeviceBases
-
- ***********************************************************************************
- ;-------------- build a unique taskname for the current copy of Snoopy [this is
- ;-------------- required even if option QUIT was given]
- ;--------------
- ENTRY BuildSnoopysTaskname,d0-d7/a0-a6
- moveq #0,d7 ; used to count the number of Snoopys installed
-
- ;-------------- examine waiting tasks
- CALL Forbid,<(execBase).w> ; stop multitasking
- lea (TaskWait,a6),a4
- movea.l (LH_HEAD,a4),a4
- .LOOP1 tst.l (LN_SUCC,a4)
- beq.b .DONE1
- bsr.b .FINDSNOOPY
- movea.l (LN_SUCC,a4),a4
- bra.b .LOOP1
-
- ;-------------- examine ready tasks
- .DONE1 lea (TaskReady,a6),a4
- movea.l (LH_HEAD,a4),a4
- .LOOP2 tst.l (LN_SUCC,a4)
- beq.b .DONE2
- bsr.b .FINDSNOOPY
- movea.l (LN_SUCC,a4),a4
- bra.b .LOOP2
- .DONE2 CALL Permit,<(execBase).w> ; reallow multitasking
- addq.w #1,d7 ; "addq.l" would be too pretentious, really.... ;-)
- move.l d7,(currentInstance)
-
- ;-------------- build new taskname and portname
- lea (outputArgs),a1
- move.l d7,(a1)
- lea (taskNameFormat,pc),a0
- lea (currentTaskName),a2
- jsr SPrintf
- lea (taskPortFormat,pc),a0
- lea (currentPortName),a2
- jsr SPrintf
-
- ;-------------- install taskname
- movea.l (ThisTask,a6),a0
- move.l #currentTaskName,(LN_NAME,a0)
- bra.b BuildSnoopysTaskname_done
-
- ;-------------- trys to find out the name for a task
- .FINDSNOOPY move.l (LN_NAME,a4),d0
- beq.b .SKIP
- movea.l d0,a0
- lea (taskNameFormat,pc),a1
- moveq #taskNameFormat_SIZEOF-1,d0
- .STRCMP move.b (a0)+,d1
- cmp.b (a1)+,d1
- bne.b .SKIP
- dbra d0,.STRCMP
- moveq #STVFORMAT_DEC,d0
- jsr StringToValue
- cmp.w d7,d0
- bls.b .SKIP
- move.w d0,d7
- .SKIP rts
-
- DONE BuildSnoopysTaskname
-
- ***********************************************************************************
- ;-------------- yeah, we got ourselfs a message; now show it and go home
- ;--------------
- ENTRY HandleReply,d0-d7/a0-a6
-
- .LOOP movea.l (myport),a0
- CALL GetMsg,<(execBase).w>
- move.l d0,(message)
- tst.l d0
- beq HandleReply_done
- movea.l d0,a5 ; a5=message
-
- ;-------------- output handling is different if its a device message
- move.w (smsg_Type,a5),d0
- BRBS #MSGTYPEB_DEBUG,d0,.HANDLEDEBUG
- BRBS #MSGTYPEB_DEVICE,d0,.HANDLEDEVICE
-
- ;-------------- now we have the message and its data, so lets go for it !
- tst.b (outputactive)
- beq .SkipOutput
-
- ;-------------- if the task is hidden, skip output
- movea.l (smsg_Task,a5),a0
- bsr IsTaskHidden
- tst d0
- bne.b .SkipOutput
-
- ;-------------- handle
- movea.l (smsg_Info,a5),a0
- move.l (spatch_Flags,a0),d0
- BRBC.B #SINFOB_SKIPSIMILAR,d0,.SKIPSIMILAR
- move.l a0,d0
- cmp.l (lastMessage),d0
- beq.b .SkipOutput
- move.l d0,(lastMessage)
- .SKIPSIMILAR
- ;-------------- show extended task info if applicable
- tst.l (argTaskInfo)
- beq.b .NoTaskInfo
- movea.l (smsg_Task,a5),a0
- bsr ShowTaskInfo
- .NoTaskInfo
- ;-------------- if SEGTRACKER is there, show segment of pc
- tst.l (SegTracker)
- beq.b .NoSegTracker
- movea.l (smsg_RegsBeforeCall+sregs_I7,a5),a0 ; a0=address to show
- movea.l (smsg_Info,a5),a1 ; a1=PatchInfo
- move.l (spatch_Flags,a1),d0
- BRBS.B #SINFOB_NOSEGTRACKER,d0,.NoSegTracker
- bsr ShowSegTracker
- .NoSegTracker
- ;-------------- prepare output data
- .SHOWMESSAGE movea.l (smsg_Info,a5),a4 ; a4=PatchInfo
- lea (spatch_Arguments,a4),a1 ; a1 = current position in argument template
- moveq #TRUE,d0
- bsr SetupOutputData
-
- ;-------------- send message
- lea.l (spatch_Template,a4),a0
- jsr ShowMessage
- move.l (window),d1
- CALL Flush,<(dosBase)>
- bsr.b .NEWLINE
-
- ;-------------- free message memory
- .SkipOutput movea.l (message),a1
- move.l #smsg_SIZEOF,d0
- CALL FreeMem,<(execBase).w>
- bra .LOOP
-
- .NEWLINE move.l (window),d1
- move.l #newlineMsg,d2
- moveq #1,d3
- CALL Write,<(dosBase)>
- move.l (window),d1
- CALL Flush
- rts
-
- ;---------------------------------------------------------------------------
- ;-------------- this is were we deal with USER-DEBUG messages
- ;--------------
-
- ;-------------- skip if output deactivated
- .HANDLEDEBUG tst.b (outputactive)
- beq .LISTDONE
-
- ;-------------- if the task is hidden, skip output
- movea.l (message),a5
- movea.l (sumsg_Task,a5),a0
- bsr IsTaskHidden
- tst d0
- bne .LISTDONE
-
- ;-------------- show extended task info if applicable
- tst.l (argTaskInfo)
- beq.b .NoDebugTaskInfo
- movea.l (sumsg_Task,a5),a0
- bsr ShowTaskInfo
- .NoDebugTaskInfo
- ;-------------- if SEGTRACKER is there, show segment of pc
- tst.l (SegTracker)
- beq.b .NoDebugSegTracker
- movea.l (sumsg_RegsBeforeCall+sregs_I7,a5),a0 ; a0=address to show
- ;-------------- SKIPSEGTRACKER not supported for Debug calls
- bsr ShowSegTracker
- .NoDebugSegTracker
- move.l (sumsg_Template,a5),d0
- beq .DebugUseDefaultTemplate
- movea.l d0,a4
- lea (4,a4),a1 ; a1 = current position in argument template
- bsr SetupOutputData
- moveq #FALSE,d0
- bsr SetupOutputData
-
- ;-------------- send message
- movea.l (sumsg_Template,a5),a0
- movea.l (a0),a0
- jsr ShowMessage
- move.l (window),d1
- CALL Flush,<(dosBase)>
- bsr .NEWLINE
- bra .LISTDONE
-
- ;-------------- no explicit user template, use default
- .DebugUseDefaultTemplate
- lea (outputArgs),a0
- lea (sumsg_RegsBeforeCall,a5),a1
- SAVEDEBUGREGISTERS
- lea (sumsg_RegsAfterCall,a5),a1
- SAVEDEBUGREGISTERS
- lea (DebugDefTempMsg,pc),a0
- jsr ShowMessage
- move.l (window),d1
- CALL Flush,<(dosBase)>
- bra .LISTDONE
-
- ;---------------------------------------------------------------------------
- ;-------------- the rest of this function deals with the device messages
- ;--------------
-
- ;-------------- skip if output deactivated
- .HANDLEDEVICE tst.b (outputactive)
- beq .LISTDONE
-
- ;-------------- if the task is hidden, skip output
- movea.l (message),a4
- movea.l (sdmsg_Task,a4),a0
- bsr IsTaskHidden
- tst d0
- bne .LISTDONE
-
- ;-------------- lets see if we understand this message
- movea.l (sdmsg_DeviceBase,a4),a5
- lea (sdevbase_Patches,a5),a5
- movea.l (LH_HEAD,a5),a5 ; a5=current patch
- move.w (sdmsg_SIZEOF+IO_COMMAND,a4),d0 ; d0=current command
- .LISTLOOP tst.l (LN_SUCC,a5)
- beq.b .LISTDONE
-
- ;-------------- offset=-1 -> show always
- cmpi.w #-1,(spatch_Offset,a5)
- beq.b .SHOWALWAYS
- cmp.w (spatch_Offset,a5),d0
- bne.b .SKIPLIST
-
- ;-------------- show only if the appropriate bits are set
- .SHOWALWAYS move.l (spatch_Flags,a5),d0
- move.w (smsg_Type,a4),d1
- BRBS.B #MSGTYPEB_BEGINIO,d1,.ITSBEGINIO
- BRBC.B #SINFOB_ABORTIO,d0,.SKIPLIST
- bra.b .ITSOK
- .ITSBEGINIO BRBC.B #SINFOB_BEGINIO,d0,.SKIPLIST
- .ITSOK
- ;-------------- show extended task info if applicable
- tst.l (argTaskInfo)
- beq.b .NoDTaskInfo
- movea.l (sdmsg_Task,a4),a0
- bsr ShowTaskInfo
- ;-------------- if SEGTRACKER is there, show segment of pc
- .NoDTaskInfo tst.l (SegTracker)
- beq.b .NoDSegTracker
- movea.l (sdmsg_PC,a4),a0 ; a0=address to show
- move.l (spatch_Flags,a5),d0
- BRBS.B #SINFOB_NOSEGTRACKER,d0,.NoDSegTracker
- bsr ShowSegTracker
- .NoDSegTracker movea.l a5,a0
- bsr.b ShowDeviceMessage
- bsr .NEWLINE
- bra.b .LISTDONE
- .SKIPLIST movea.l (LN_SUCC,a5),a5
- bra.b .LISTLOOP
-
- ;-------------- free message memory and return to main loop
- .LISTDONE movea.l (message),a1
- moveq #0,d0
- move.w (MN_LENGTH,a1),d0
- CALL FreeMem,<(execBase).w>
- bra .LOOP
-
- DONE HandleReply
-
- ***********************************************************************************
- ;--------------
- ;-------------- => a0: (struct SnoopyPatch *)
- ;--------------
- ENTRY ShowDeviceMessage,d0-d7/a0-a6
-
- ;-------------- prepare output data
- movea.l (message),a5
- movea.l a0,a4 ; a4 = patch
- bsr SetupDeviceOutputData
-
- ;-------------- send message
- lea.l (spatch_Template,a4),a0
- jsr ShowMessage
- move.l (window),d1
- CALL Flush,<(dosBase)>
- DONE ShowDeviceMessage
-
- ***********************************************************************************
- ;--------------
- ;-------------- -> a4: Patch Info
- ;-------------- a5: Register Data
-
- ENTRY SetupDeviceOutputData,d0-d7/a0-a6
- lea (outputArgs),a0 ; a0 = current output offset
- lea (spatch_Arguments,a4),a1 ; a1 = current position in argument template
- movea.l (message),a3
- lea (sdmsg_SIZEOF,a3),a2
-
- ;-------------- done ? then lets go !
- .LOOP move.w (sarg_Opcode,a1),d0
- cmpi.w #REG_DONE,d0
- beq.b SetupDeviceOutputData_done
-
- ;-------------- if REGB_INDIRECT is given, I display internal data!!!!!!!!!
- BRBS #REGB_INDIRECT,d0,.SHOWINTERNAL
- BRBS.B #REGB_BYTE,d0,.SETBYTE
- BRBS.B #REGB_WORD,d0,.SETWORD
- .SETLONG move.l (sarg_Offset,a1),d0
- move.l (a2,d0.l),(a0)+
- bra.b .NEXT
- .SETWORD move.l (sarg_Offset,a1),d0
- move.w (a2,d0.l),(a0)+
- bra.b .NEXT
- .SETBYTE move.l (sarg_Offset,a1),d0
- move.b (a2,d0.l),d0
- ext.w d0
- move.w d0,(a0)+
- .NEXT lea (sarg_SIZEOF,a1),a1
- bra.b .LOOP
-
- ;--------------
- .SHOWINTERNAL andi.w #%111,d0 ; get bit number
- tst.b d0
- beq.b .SHOWCALLTYPE
-
- ;-------------- NOT SUPPORTED!
- bra.b .NEXT
-
- .SHOWCALLTYPE move.l #abortIOMsg,d0
- move.w (smsg_Type,a3),d1
- BRBC.B #MSGTYPEB_BEGINIO,d1,.ISABORTIO
- move.l #beginIOMsg,d0
- .ISABORTIO move.l d0,(a0)+
- bra.b .NEXT
-
- DONE SetupDeviceOutputData
-
- ***********************************************************************************
- ;-------------- checks if the current task is hidden, returns TRUE if so
- ENTRY IsTaskHidden,d1-d7/a0-a6
-
- ;-------------- a3 = task pointer
- movea.l a0,a3
-
- ;-------------- find taskname to a4
- movea.l a0,a1
- cmpi.b #NT_PROCESS,(LN_TYPE,a0)
- bne.b .DEFAULT
- tst.l (pr_TaskNum,a0)
- beq.b .DEFAULT
- move.l (pr_CLI,a0),d0
- lsl.l #2,d0
- movea.l d0,a0
- move.l (cli_CommandName,a0),d0
- lsl.l #2,d0
- addq.l #1,d0
- movea.l d0,a4
- bra.b .DONE
- .DEFAULT movea.l (LN_NAME,a0),a4
- .DONE
- ;-------------- handle SHOWs
- tst.b (showsactive)
- beq.b .NoSHOWs
- lea (shows),a5
- bsr.b CheckIfIsInList
- not.l d0
- bra.b IsTaskHidden_done
- .NoSHOWs
- ;-------------- handle HIDEs
- lea (hides),a5
- bsr.b CheckIfIsInList
- DONE IsTaskHidden
-
- ***********************************************************************************
- ;-------------- checks if an entry can be found in a list
- ;--------------
- ;-------------- -> a5: struct List *HEAD
- ;-------------- a4: STRPTR name
- ;-------------- a3: APTR task
- ;-------------- <- d0: TRUE=Member of this list, FALSE otherwise
- ;--------------
- ENTRY CheckIfIsInList,d1-d7/a0-a6
- cmpa.l #0,a4
- beq.b .NotInList
- movea.l (LH_HEAD,a5),a5
- .LOOP tst.l (LN_SUCC,a5) ; a5 = current node
- beq.b .NotInList
- movea.l a4,a0
- move.l (stask_Pointer,a5),d0
- beq.b .CHECKNAME
- cmpa.l d0,a3
- beq.b .InList
- .CHECKNAME lea (stask_Name,a5),a1
-
- ;-------------- NEW: exact matching enabled
- tst.l (argMatch)
- bne.b .STRCMP
-
- .STRICMP move.b (a1)+,d0
- beq.b .InList
- move.b (a0)+,d1
- UCASE d0
- UCASE d1
- cmp.b d1,d0
- beq.b .STRICMP
- movea.l (LN_SUCC,a5),a5
- bra.b .LOOP
- .NotInList moveq #0,d0
- bra.b CheckIfIsInList_done
-
- ;-------------- NEW: enable exact matching
- .STRCMP move.b (a1)+,d0
- beq.b .SEEMSTOMATCH
- move.b (a0)+,d1
- cmp.b d1,d0
- beq.b .STRCMP
- movea.l (LN_SUCC,a5),a5
- bra.b .LOOP
- .SEEMSTOMATCH tst.b (a0)+
- bne.b .LOOP
- .InList moveq #-1,d0
- DONE CheckIfIsInList
-
- ***********************************************************************************
- ;-------------- show an information line about the task that called this function
- ;--------------
- ENTRY ShowTaskInfo,d1-d7/a0-a6
- lea (taskinfoMsg),a1
- move.l a0,(outputArgs)
- cmpi.b #NT_PROCESS,(LN_TYPE,a0)
- bne.b .DEFAULT
- tst.l (pr_TaskNum,a0)
- beq.b .DEFAULT
- move.l (pr_CLI,a0),d0
- lsl.l #2,d0
- movea.l d0,a0
- move.l (cli_CommandName,a0),(outputArgs+4)
- lea (taskbcplMsg),a1
- bra.b .DONE
- .DEFAULT move.l (LN_NAME,a0),(outputArgs+4)
- .DONE move.l a1,a0
-
- ;-------------- new: if SegTracker is enabled also, combine both outputs
- tst.l (SegTracker)
- beq.b .SHOWMESSAGE
- move.l (outputArgs),(st_SegTaskAddr)
- move.l (outputArgs+4),(st_SegFilename)
- bra.b ShowTaskInfo_done
-
- .SHOWMESSAGE jsr ShowMessage
- move.l (window),d1
- CALL Flush,<(dosBase)>
- DONE ShowTaskInfo
-
- ***********************************************************************************
- ;--------------
- ;-------------- => a0: APTR address to show
- ENTRY ShowSegTracker,d0-d7/a0-a6
- move.l a0,d7 ; address to show
-
- ;-------------- the manual says we have to do this, so we do it
- ;-------------- (although we really couldn't care less, I tell you)
- CALL Forbid,<(execBase).w>
-
- ;-------------- call SegTracker to find Hunk & Offset
- movea.l d7,a0
- lea (st_SegHunk),a1
- lea (st_SegOffset),a2
- movea.l (SegTracker),a6
- jsr a6
- tst.l d0
- beq .NOTFOUND
-
- ;-------------- name found, copy it to our internal buffer
- movea.l d0,a0
- lea (errorMsgBuffer),a1
- move.l a1,(st_SegName)
- moveq #128-1,d0
- .STRCPY move.b (a0)+,(a1)+
- beq.b .STRCPYEND
- dbra d0,.STRCPY
- .STRCPYEND move.l d7,(st_SegAddress)
-
- ;-------------- lets see if we can find the address
- movea.l d7,a0
- lea (st_SegList),a1
- movea.l a1,a2
- movea.l (SegTracker),a6
- jsr a6
-
- move.l (st_SegList),d0
- move.l (st_SegHunk),d1
- cmp.l d0,d1
- bne.b .USESEGLIST
- move.l (st_SegOffset),d1
- cmp.l d0,d1
- bne.b .USESEGLIST
- clr.l (st_SegList)
- .USESEGLIST
- ;-------------- display the message
- move.l (window),d1
- move.l #SegTrackerMsg,d2
- tst.l (argTaskInfo)
- beq.b .NOTASKINFO
- move.l #SegTrackerMsgTI,d2
- .NOTASKINFO move.l #st_SegAddress,d3
- CALL VFPrintf,<(dosBase)>
- move.l (window),d1
- CALL Flush
- bra.b .DONE
-
- ;-------------- show warning
- .NOTFOUND tst.l (flagSkipSegNotFound)
- bne.b .DONE
- lea (SegTrackerFail,pc),a0
- jsr ShowMessage
- move.l (window),d1
- CALL Flush,<(dosBase)>
- .DONE CALL Permit,<(execBase).w>
- DONE ShowSegTracker
-
- ***********************************************************************************
- ;-------------- setup outputArgs to contain the registers as specified by
- ;-------------- the register template
- ;--------------
- ;-------------- -> a4: Patch Info
- ;-------------- a5: Register Data
- ;-------------- d0: BOOL type
- ENTRY SetupOutputData,d0-d7/a0-a6
- lea (outputArgs),a0 ; a0 = current output offset
- move.w d0,d7
-
- ;-------------- done ? then lets go !
- .LOOP move.w (sarg_Opcode,a1),d0
- cmpi.w #REG_DONE,d0
- beq SetupOutputData_done
-
- ;-------------- set correct register data to a2
- tst.w d7
- beq.b .DebugRegList
- lea (smsg_RegsBeforeCall,a5),a2 ; a2 = regs before call ( default )
- BRBC.B #REGB_RESULT,d0,.BeforeCall
- lea (smsg_RegsAfterCall,a5),a2 ; a2 = regs before call ( default )
- bclr #REGB_RESULT,d0
- .BeforeCall bra.b .DebugRegListDone
- .DebugRegList lea (sumsg_RegsBeforeCall,a5),a2 ; a2 = regs before call ( default )
- BRBC.B #REGB_RESULT,d0,.DebugRegListDone
- lea (sumsg_RegsAfterCall,a5),a2 ; a2 = regs before call ( default )
- bclr #REGB_RESULT,d0
- .DebugRegListDone
-
-
- ;-------------- use boolean tables if applicable
- BRBS.B #REGB_BOOLEAN,d0,.UseBOOLEAN
-
- ;-------------- set correct jump table to a3
- bclr #REGB_WORD,d0
- lea (.JumpWORD,pc),a3
- BRBC.B #REGB_LONG,d0,.NotLONG
- lea (.JumpLONG,pc),a3
- bclr #REGB_LONG,d0
- .NotLONG BRBC.B #REGB_BYTE,d0,.NotBYTE
- lea (.JumpBYTE,pc),a3
- bclr #REGB_BYTE,d0
- .NotBYTE
- ;-------------- find correct table offset
- .ShowOutput BRBS.B #REGB_DATA,d0,.ISDATA
- BRBC.B #REGB_ADDR,d0,.ISADDR
- lea (8*4,a3),a3
- bra.b .ISDATA
- .ISADDR BRBC.B #REGB_INDIRECT,d0,.ISDATA
- lea (2*8*4,a3),a3
- .ISDATA
- ;-------------- now get the register data and save it
- andi.w #%111,d0
- lsl.w #2,d0
- movea.l (a3,d0.w),a3
- jsr a3
- tst.w d7
- bne.b .ITSAPATCH
- .ITSADEBUGMSG lea (2,a1),a1
- bra .LOOP
-
- .ITSAPATCH lea (sarg_SIZEOF,a1),a1
- bra .LOOP
-
- ;-------------- this isn't really 'clean code', but well it works
- .UseBOOLEAN bclr #REGB_WORD,d0
- lea (.JumpWORDBOOL,pc),a3
- BRBC.B #REGB_LONG,d0,.NotLONGBOOL
- lea (.JumpLONGBOOL,pc),a3
- bclr #REGB_LONG,d0
- .NotLONGBOOL BRBC.B #REGB_BYTE,d0,.NotBYTEBOOL
- lea (.JumpBYTEBOOL,pc),a3
- bclr #REGB_BYTE,d0
- .NotBYTEBOOL bclr #REGB_BOOLEAN,d0
- bra.b .ShowOutput
-
- REGLIST LONG,L
- REGLIST WORD,W
- REGLIST BYTE,B
- REGLIST LONGBOOL,LB
- REGLIST WORDBOOL,WB
- REGLIST BYTEBOOL,BB
-
- SAVEREG A0
- SAVEREG A1
- SAVEREG A2
- SAVEREG A3
- SAVEREG A4
- SAVEREG A5
- SAVEREG D0
- SAVEREG D1
- SAVEREG D2
- SAVEREG D3
- SAVEREG D4
- SAVEREG D5
- SAVEREG D6
- SAVEREG D7
- SAVEREG I0
- SAVEREG I1
- SAVEREG I2
- SAVEREG I3
- SAVEREG I4
- SAVEREG I5
- SAVEREG I6
- SAVEREG I7
-
- .LONGBOOLEAN move.l #SuccessMsg,d1
- tst.l d0
- bne.b .LONGISTRUE
- move.l #FailureMsg,d1
- .LONGISTRUE move.l d1,(a0)+
- rts
-
- .WORDBOOLEAN move.l #SuccessMsg,d1
- tst.w d0
- bne.b .WORDISTRUE
- move.l #FailureMsg,d1
- .WORDISTRUE move.l d1,(a0)+
- rts
-
- DONE SetupOutputData
-
- ***********************************************************************************
- ;-------------- patch all functions in the watch list
- ;--------------
- ENTRY PatchFunctions,d1-d7/a0-a6
-
- ;-------------- 1.PASS: patch all library functions
- lea (watches),a5
- movea.l (LH_HEAD,a5),a5
- movea.l (execBase).w,a6
- .LOOPPASS1 tst.l (LN_SUCC,a5) ; a5 = current node
- beq.b .DONEPASS1
- movea.l a5,a0
- bsr.b InstallPatch
- tst d0
- beq.b .LIBFAILED
- movea.l (LN_SUCC,a5),a5
- bra.b .LOOPPASS1
-
- ;-------------- 2.PASS: patch all device functions
- .DONEPASS1 lea (deviceBases),a5
- movea.l (LH_HEAD,a5),a5
- movea.l (execBase).w,a6
- .LOOPPASS2 tst.l (LN_SUCC,a5) ; a5 = current node
- beq.b .DONEPASS2
-
- ;-------------- patch BeginIO()
- movea.l a5,a0
- lea (BeginIO_Patch),a1
- lea (BeginIO_Jump),a2
- move.l (BeginIO_SIZEOF),d0
- move.w #DEV_BEGINIO,d1
- bsr InstallDevicesPatch
- tst d0
- beq.b .DEVFAILED
-
- ;-------------- patch AbortIO()
- movea.l a5,a0
- lea (AbortIO_Patch),a1
- lea (AbortIO_Jump),a2
- move.l (AbortIO_SIZEOF),d0
- move.w #DEV_ABORTIO,d1
- bsr InstallDevicesPatch
- tst d0
- beq.b .DEVFAILED
-
- movea.l (LN_SUCC,a5),a5
- bra.b .LOOPPASS2
- .DONEPASS2 moveq #TRUE,d0
- bra.b PatchFunctions_done
-
- .DEVFAILED clr.l (sdevbase_IOSize,a5)
- moveq #FALSE,d0
- bra.b PatchFunctions_done
-
- .LIBFAILED clr.l (spatch_Library,a5) ; to indicate failed patch
- moveq #FALSE,d0
- DONE PatchFunctions
-
- ***********************************************************************************
- ;-------------- Patch a system function
- ;--------------
- ;-------------- => a0: APTR Patchinfo
- ;-------------- <= d0: LONG success
- ;--------------
- ENTRY InstallPatch,d1-d7/a0-a6
- movea.l a0,a5
- move.l a0,(PatchInfoStruct)
-
- ;-------------- allocate patch duplicate
- move.l (Patch_SIZEOF),d0
- move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
- CALL AllocMem,<(execBase).w>
- tst.l d0
- beq.b .FAIL
- movea.l d0,a4
-
- ;-------------- setup original vector
- movea.l (spatch_Library,a5),a1
- move.w (spatch_Offset,a5),d1
- addq.w #2,d1
- move.l (a1,d1.w),(OriginalVector0+2)
- move.l (a1,d1.w),(OriginalVector1+2)
- move.l (a1,d1.w),(Patch_START+sphead_OriginalFunction)
-
- ;-------------- this is VERY important because otherwise Snoopy couldn't
- ;-------------- handle multiple instances so well
- move.l (ThisTask,a6),(Patch_START+sphead_Owner)
-
- ;-------------- copy patch memory
- movea.l a4,a0
- lea (Patch_START),a1
- move.l (Patch_SIZEOF),d0
- subq.w #1,d0
- .LOOP move.b (a1)+,(a0)+
- dbra d0,.LOOP
-
- ;-------------- install new function
- movea.l (spatch_Library,a5),a1
- move.w (spatch_Offset,a5),d0
- ext.l d0
- movea.l d0,a0
- move.l a4,d0
- addi.l #sphead_SIZEOF,d0
- CALL SetFunction
-
- .SUCCESS moveq #TRUE,d0
- bra.b InstallPatch_done
-
- .FAIL moveq #FALSE,d0
- DONE InstallPatch
-
- ***********************************************************************************
- ;-------------- Patch a system function
- ;--------------
- ;-------------- => a0: APTR Patchinfo
- ;-------------- <= d0: LONG success
- ;--------------
- STRUCTURE idpStack,0
- APTR idps_DeviceBase
- APTR idps_BeginOfPatch
- APTR idps_JumpAddress
- APTR idps_SizeOfPatch
- WORD idps_Offset
- LABEL idps_SIZEOF
-
- ENTRY InstallDevicesPatch,d1-d7/a0-a6,idps_SIZEOF,a5
- move.l a0,(idps_DeviceBase,a5)
- move.l a1,(idps_BeginOfPatch,a5)
- move.l a2,(idps_JumpAddress,a5)
- move.l d0,(idps_SizeOfPatch,a5)
- move.w d1,(idps_Offset,a5)
-
- ;-------------- allocate patch duplicate
- move.l (idps_SizeOfPatch,a5),d0
- move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
- CALL AllocMem,<(execBase).w>
- tst.l d0
- beq.b .FAIL
- movea.l d0,a4 ; a4 = patch memory
-
- ;-------------- setup original vector
- movea.l (idps_DeviceBase,a5),a3 ; a3 = (SnoopyDeviceBase *)
- movea.l (sdevbase_Device,a3),a1 ; a1 = (struct Device *)
- move.w (idps_Offset,a5),d1 ; d1 = (function offset)
- addq.w #2,d1
- movea.l (idps_JumpAddress,a5),a0
- move.l (a1,d1.w),(2,a0) ; set jump address
- movea.l (idps_BeginOfPatch,a5),a0
- move.l (a1,d1.w),(sphead_OriginalFunction,a0)
- move.l (sdevbase_IOSize,a3),(sphead_Info,a0)
- move.l a3,(sphead_DevicePtr,a0)
-
- ;-------------- copy patch memory
- movea.l a4,a0
- movea.l (idps_BeginOfPatch,a5),a1
- move.l (ThisTask,a6),(sphead_Owner,a1)
- move.l (idps_SizeOfPatch,a5),d0
- subq.w #1,d0
- .LOOP move.b (a1)+,(a0)+
- dbra d0,.LOOP
-
- ;-------------- install new function
- movea.l (sdevbase_Device,a3),a1
- move.w (idps_Offset,a5),d0
- ext.l d0
- movea.l d0,a0
- move.l a4,d0
- addi.l #sphead_ExtSIZEOF,d0
- CALL SetFunction
- .SUCCESS moveq #TRUE,d0
- bra.b InstallDevicesPatch_done
-
- .FAIL moveq #FALSE,d0
- DONE InstallDevicesPatch
-
- ***********************************************************************************
- ;-------------- remove the patch of all functions in the watch list
- ;--------------
- ENTRY RemoveFunctions,d1-d7/a0-a6
- lea (watches),a5
- movea.l (LH_HEAD,a5),a5
- movea.l (execBase).w,a6
- .LOOP1 tst.l (LN_SUCC,a5) ; a5 = current node
- beq.b .DONE1
- movea.l a5,a0
- bsr RemovePatch
- tst.w d0
- beq.b .FAILURE
- movea.l (LN_SUCC,a5),a5
- bra.b .LOOP1
- .DONE1
- lea (deviceBases),a5
- movea.l (LH_HEAD,a5),a5
- .LOOP2 tst.l (LN_SUCC,a5) ; a5 = current node
- beq.b .DONE2
- movea.l a5,a0
-
- ;-------------- unpatch BeginIO()
- movea.l a5,a0
- lea (BeginIO_Patch),a1
- lea (BeginIO_Jump),a2
- move.l (BeginIO_SIZEOF),d0
- move.w #DEV_BEGINIO,d1
- bsr RemoveDevicePatch
- tst d0
- beq.b .BEGINIOERR
-
- ;-------------- unpatch AbortIO()
- movea.l a5,a0
- lea (AbortIO_Patch),a1
- lea (AbortIO_Jump),a2
- move.l (AbortIO_SIZEOF),d0
- move.w #DEV_ABORTIO,d1
- bsr RemoveDevicePatch
- tst d0
- beq.b .ABORTIOERR
-
- movea.l (LN_SUCC,a5),a5
- bra.b .LOOP2
- .DONE2 moveq #TRUE,d0
- bra.b RemoveFunctions_done
-
- ;-------------- error in DEV_BEGINIO()
- .BEGINIOERR move.l #closeBeginIoErr,d2
- bra.b .DEVICEERROR
-
- ;-------------- error in DEV_ABORTIO()
- .ABORTIOERR move.l #closeAbortIoErr,d2
- .DEVICEERROR movea.l (sdevbase_Device,a5),a1
- movea.l (LN_NAME,a1),a1
- bra.b .SHOWERRORMSG
-
- ;-------------- show error messages
- .FAILURE lea (spatch_Template,a5),a1
- move.l #closesnoopyErr,d2
- .SHOWERRORMSG move.l a1,(outputArgs)
- move.l (window),d1
- move.l #outputArgs,d3
- CALL VFPrintf,<(dosBase)>
- move.l (window),d1
- CALL Flush
- moveq #FALSE,d0
- DONE RemoveFunctions
-
- ***********************************************************************************
- ;-------------- Remove patch of a system function
- ;--------------
- ;-------------- => a0: APTR Patchinfo
- ;--------------
- ENTRY RemovePatch,d1-d7/a0-a3/a5/a6
- movea.l a0,a5
-
- ;-------------- test if it is our patch
- tst.l (spatch_Library,a5)
- beq .SUCCESS
- movea.l (spatch_Library,a5),a1
- move.w (spatch_Offset,a5),d1
- addq.w #2,d1
- move.l (a1,d1.w),a1
- subi.l #sphead_SIZEOF,a1
- cmpi.l #PATCH_IDSTRING,(sphead_Ident,a1)
- bne.b .REMOVEFAILED
- movea.l (execBase).w,a6
- move.l (ThisTask,a6),d0
- cmp.l (sphead_Owner,a1),d0
- bne.b .REMOVEFAILED
- movea.l a1,a4 ; a4 = patched memory
- tst.l (sphead_OriginalFunction,a4)
- beq.b .SUCCESS
-
- ;-------------- restore original function
- movea.l (spatch_Library,a5),a1
- move.w (spatch_Offset,a5),d0
- ext.l d0
- movea.l d0,a0
- move.l (sphead_OriginalFunction,a4),d0
- CALL SetFunction,<(execBase).w>
- clr.l (sphead_OriginalFunction,a4)
-
- ;-------------- free patched memory
- movea.l a4,a1
- move.l (Patch_SIZEOF),d0
- CALL FreeMem
-
- .SUCCESS moveq #TRUE,d0
- bra.b RemovePatch_done
-
- ;--------------
- .REMOVEFAILED moveq #FALSE,d0
- DONE RemovePatch
-
- ***********************************************************************************
- ;-------------- Remove patch of a system device
- ;--------------
- ;-------------- => a0: SnoopyDeviceBase *
- ;--------------
- ENTRY RemoveDevicePatch,d1-d7/a0-a6,idps_SIZEOF,a5
- move.l a0,(idps_DeviceBase,a5)
- move.l a1,(idps_BeginOfPatch,a5)
- move.l a2,(idps_JumpAddress,a5)
- move.l d0,(idps_SizeOfPatch,a5)
- move.w d1,(idps_Offset,a5)
-
- ;-------------- test if it is our patch
- movea.l (idps_DeviceBase,a5),a3 ; a3 = SnoopyDeviceBase *
- movea.l (sdevbase_Device,a3),a1
- move.w (idps_Offset,a5),d1
- addq.w #2,d1
- movea.l (a1,d1.w),a1
- suba.l #sphead_ExtSIZEOF,a1
- cmpi.l #PATCH_IDSTRING,(sphead_Ident,a1)
- bne.b .REMOVEFAILED
- movea.l (execBase).w,a6
- move.l (ThisTask,a6),d0
- cmp.l (sphead_Owner,a1),d0
- bne.b .REMOVEFAILED
- move.l a1,a4 ; a4 = patched memory
- tst.l (sphead_OriginalFunction,a4)
- beq.b .SUCCESS
-
- ;-------------- restore original function
- movea.l (sdevbase_Device,a3),a1
- move.w (idps_Offset,a5),d0
- ext.l d0
- movea.l d0,a0
- move.l (sphead_OriginalFunction,a4),d0
- CALL SetFunction,<(execBase).w>
- clr.l (sphead_OriginalFunction,a4)
-
- ;-------------- free patched memory
- movea.l a4,a1
- move.l (idps_SizeOfPatch,a5),d0
- CALL FreeMem
-
- .SUCCESS moveq #TRUE,d0
- bra.b RemoveDevicePatch_done
-
- ;--------------
- .REMOVEFAILED moveq #FALSE,d0
- DONE RemoveDevicePatch
-
- ***********************************************************************************
- ;-------------- remove any running instance of Snoopy
- ;--------------
- ENTRY QuitSnoopyInstances,d0-d7/a0-a6
-
- ;-------------- d7 = Instance Number; if d7 == 0, remove ALL instances,
- ;-------------- else remove only the numbered instance
- movea.l (argQuit),a0
- move.l (a0),d7
- beq .REMOVEALL
-
- ;-------------- stop fooling around
- CALL Forbid,<(execBase).w>
-
- ;-------------- examine waiting tasks
- lea (TaskWait,a6),a4
- movea.l (LH_HEAD,a4),a4
- .LOOP1 tst.l (LN_SUCC,a4)
- beq.b .DONE1
- bsr.b .FINDSNOOPY
- bsr.b .REMTASK
- movea.l (LN_SUCC,a4),a4
- bra.b .LOOP1
-
- ;-------------- examine ready tasks
- .DONE1 lea (TaskReady,a6),a4
- movea.l (LH_HEAD,a4),a4
- .LOOP2 tst.l (LN_SUCC,a4)
- beq.b .DONE2
- bsr.b .FINDSNOOPY
- bsr.b .REMTASK
- movea.l (LN_SUCC,a4),a4
- bra.b .LOOP2
- .DONE2 CALL Permit
- bra QuitSnoopyInstances_done
-
- ;-------------- remove task if it fits
- .REMTASK tst.w d1
- beq.b .FAILREMTASK
- cmp.w d7,d1
- bne.b .FAILREMTASK
- movea.l a4,a1
- move.l #SIGBREAKF_CTRL_C,d0
- CALL Signal
- .FAILREMTASK rts
-
- ;-------------- trys to find out the name for a task
- ;--------------
- ;-------------- <= d0:BOOL success
- ;-------------- d1:LONG instance number of the task currently found
- .FINDSNOOPY movea.l (LN_NAME,a4),a0
- lea (taskNameFormat,pc),a1
- moveq #taskNameFormat_SIZEOF-1,d0
- .STRCMP move.b (a0)+,d1
- cmp.b (a1)+,d1
- bne.b .SKIP
- dbra d0,.STRCMP
- moveq #STVFORMAT_DEC,d0
- jsr StringToValue
- move.l d0,d1
- moveq #TRUE,d0
- rts
- .SKIP moveq #FALSE,d0
- rts
-
- MAX_ACTIVESNOOPYS equ MAX_INPUT
-
- ;-------------- find all active snoopy numbers and store them in InputMemory[]
- .REMOVEALL lea (inputMemory),a3
- CALL Forbid,<(execBase).w>
- lea (TaskWait,a6),a4
- bsr.b .FINDSNOOPYS
- lea (TaskReady,a6),a4
- bsr.b .FINDSNOOPYS
- CALL Permit
-
- ;-------------- now of course I could be write a quicksort algorithm, but
- ;-------------- really the following method is easier: I just try to find
- ;-------------- the maximum element, break it, then start the loop again
- move.l a3,d7
- subi.l #inputMemory+1,d7
- .ra_Loop move.l d7,d2 ; loop counter
- lea (inputMemory),a3
- moveq #0,d0 ; current maximum
- .ra_FindMax move.b (a3),d1
- cmp.b d1,d0
- bge.b .ra_NotMax
- move.b d1,d0
- move.l a3,a2
- .ra_NotMax addq.l #1,a3
- dbra d2,.ra_FindMax
- tst d0
- beq.b QuitSnoopyInstances_done
- clr.b (a2)
-
- ;-------------- clear this element
- lea (outputArgs),a1
- move.l d0,(a1)
- lea (taskNameFormat,pc),a0
- lea (currentTaskName),a2
- jsr SPrintf
- lea (currentTaskName),a1
- CALL FindTask
- tst.l d0
- beq.b .ra_Loop
- movea.l d0,a1
- move.l #SIGBREAKF_CTRL_C,d0
- CALL Signal
- bra.b .ra_Loop
-
- .FINDSNOOPYS movea.l (LH_HEAD,a4),a4
- .fs_LOOP tst.l (LN_SUCC,a4)
- beq.b .fs_DONE
- bsr .FINDSNOOPY
- tst.b d0
- beq.b .fs_SKIP
- move.b d1,(a3)+
- .fs_SKIP movea.l (LN_SUCC,a4),a4
- bra.b .fs_LOOP
- .fs_DONE rts
-
- DONE QuitSnoopyInstances
-
- ***********************************************************************************
- ;-------------- note: I use some very old code here stolen from a program I wrote
- ;-------------- some year ago together with a friend of mine (Stefan Scherer);
- ;-------------- this code isn't well documented but it works just fine so why bother....
- ENTRY ReadWBArgs,d0-d7/a0-a6
- lea (TTHStruktur),a3
- move.l (tth_WBStartup,a3),d0
- beq ReadWBArgs_done
- tst.l (argRdargs)
- bne ReadWBArgs_done
- clr.l (argRdargs)
-
- ;-------------- normal startup from workbench
- .vonWorkbench movea.l d0,a3
- move.l (sm_NumArgs,a3),d0
- movea.l (sm_ArgList,a3),a3
- cmpi.l #1,d0
- beq.b .DEFSTART
- lea (wa_SIZEOF,a3),a3
-
- .DEFSTART move.l (wa_Lock,a3),d1 ; DirLock zeigt auf
- CALL CurrentDir,<(dosBase)> ; Pfad des Programms
- move.l (wa_Name,a3),a0
- .LeseIcon CALL GetDiskObject,<(iconBase)> ; ".info"-Datei lesen
- BRF d0,ReadWBArgs_done ; Fehler, dann weiter
-
- ;-------------- Tool Types auswerten
- move.l d0,a3
- cmpi.b #WBPROJECT,(do_PAD_BYTE-1,a3)
- beq .USEPROJECT
- move.l (do_ToolTypes,a3),a3
- move.l a3,a0
- lea (TTScript,pc),a1
- push a0
- CALL FindToolType
- pop a0
- move.l d0,(argScript)
-
- .READTOOLTYPES movea.l a0,a5
- lea (TTIncdir,pc),a1
- movea.l a5,a0
- CALL FindToolType
- move.l d0,(argIncdir)
- lea (TTOutput,pc),a1
- movea.l a5,a0
- CALL FindToolType
- move.l d0,(argOutput)
- lea (TTPri,pc),a1
- movea.l a5,a0
- CALL FindToolType
- tst.l d0
- beq.b .SKIPPRI
- movea.l d0,a0
- moveq #STVFORMAT_DEC,d0
- jsr StringToValue
- move.l d0,(priority)
- .SKIPPRI lea (TTSticky,pc),a1
- lea (argSticky),a2
- bsr.b .GETBOOLEAN
- lea (TTNoSegTracker,pc),a1
- lea (argNoSegTracker),a2
- bsr.b .GETBOOLEAN
- lea (TTMatch,pc),a1
- lea (argMatch),a2
- bsr.b .GETBOOLEAN
- lea (TTTaskInfo,pc),a1
- lea (argTaskInfo),a2
- bsr.b .GETBOOLEAN
- bra.b ReadWBArgs_done
-
- .GETBOOLEAN movea.l a5,a0
- push a2
- CALL FindToolType
- pop a1
- tst.l d0
- beq.b .ISNTBOOL
- movea.l d0,a0
- jsr FindBooleanKeyword
- .ISNTBOOL rts
-
- .USEPROJECT push a3
- lea (TTHStruktur),a3
- move.l (tth_WBStartup,a3),a3
- move.l (sm_ArgList,a3),a3
- lea (wa_SIZEOF,a3),a3
- move.l (wa_Name,a3),(argScript)
- pop a3
- move.l (do_ToolTypes,a3),a3
- move.l a3,a0
- bra .READTOOLTYPES
- DONE ReadWBArgs
-
- ***********************************************************************************
-
- cstr "$VER: ",IDSTRING
-
- ;-------------- library definitions
- dosName cstr "dos.library"
- intName cstr "intuition.library"
- iconName cstr "icon.library"
-
- ;-------------- global text messages
- defaultScript cstr DEFAULTSCRIPT
- TIenabledMsg cstr 'TaskInfo enabled\n'
- TIdisabledMsg cstr 'TaskInfo disabled\n'
- taskinfoMsg cstr 'Task %08lx : "%s"\n'
- taskbcplMsg cstr 'Task %08lx : "%b"\n'
- helloMsg cstr "Welcome to ",IDSTRING,"[%ld] - written by ",AUTHORSTRING,"\n"
- disableoutMsg cstr "Output disabled - press CTRL+E to enable again. \n"
- enableoutMsg cstr "Output enabled - press CTRL+D to disable. \n"
- windowName cstr "con:0/0/640/150/",IDSTRING
-
- ;-------------- template for dos/ReadArgs()
- argTemplate dc.b "SCRIPT,"
- dc.b "TASKINFO/S,"
- dc.b "OUTPUT/K,"
- dc.b "PRI/N,"
- dc.b "SHOW/K/M,"
- dc.b "STICKY/S,"
- dc.b "MATCH/S,"
- dc.b "QUIT/K/N,"
- dc.b "INCDIR/K,"
- dc.b "NOSEGTRACKER/S"
- dc.b 0
-
- ;-------------- workbench tooltypes
- TTScript cstr "SCRIPT"
- TTPri cstr "PRI"
- TTOutput cstr "OUTPUT"
- TTSticky cstr "STICKY"
- TTNoSegTracker cstr "NOSEGTRACKER"
- TTTaskInfo cstr "TASKINFO"
- TTMatch cstr "MATCH"
- TTIncdir cstr "INCDIR"
-
- ;-------------- name of SegTracker semaphore
- SegTrackerName cstr "SegTracker"
- SegTrackerMsg cstr "$%08lx - %s : Hunk %ld, Offset $%08lx, SegList $%08lx\n"
- SegTrackerMsgTI cstr 'PC=$%lx,N="%s",H=%ld,O=$%lx,S=$%lx,A=%lx,T="%s"\n'
- SegTrackerFail cstr "(Segment not found)\n"
- SegTrackerOn dc.b FALSE
-
- ;-------------- error messages for this module
- nowindowErr cstr "ERROR, cannot open output stream"
- nomsgportErr cstr "ERROR, cannot create msgport"
- closesnoopyErr dc.b 10,'*** WARNING *** Something else has patched the vectors Snoopy looks into'
- dc.b 10,'You will have to wait for the other program to finish and try Snoopy again'
- dc.b 10,'The function I have trouble with is the one with the template'
- dc.b 10,'"%s"',10,0
- closeBeginIoErr cstr "ERROR, cannot remove DEV_BEGINIO() for %s\n",0
- closeAbortIoErr cstr "ERROR, cannot remove DEV_ABORTIO() for %s\n",0
- activeCallsErr cstr "ERROR, %ld calls still working",0
- newlineMsg cstr '\n'
-
- ;-------------- new: flexible naming schedule
- taskNameFormat dc.b "Snoopy Task."
- taskNameFormat_SIZEOF equ *-taskNameFormat
- cstr "%ld",0
- taskPortFormat cstr "Snoopy Port.%ld",0
-
- ;-------------- success/failure messages
- SuccessMsg cstr "YES"
- FailureMsg cstr "NO"
-
- ;-------------- internal messages : not documented (try to find out yourself....)
- abortIOMsg cstr "AbortIO"
- beginIOMsg cstr "BeginIO"
-
- ;-------------- user messages
- DebugDefTempMsg dc.b "**** Userfunction before call *********************************************",10
- dc.b "Dx:%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx",10
- dc.b "Ax:%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx",10
- dc.b "():%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx",10
- dc.b "**** Userfunction after call",10
- dc.b "Dx:%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx",10
- dc.b "Ax:%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx",10
- dc.b "():%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx",10,0
-
- section memory,bss
-
- ;-------------- library bases (guess what)
- defs.l dosBase,1
- defs.l intBase,1
- defs.l iconBase,1
-
- ;-------------- all internal lists
- defs.b hides,LH_SIZE
- defs.b shows,LH_SIZE
- defs.b bases,LH_SIZE
- defs.b watches,LH_SIZE
- defs.b deviceBases,LH_SIZE
- defs.b aliases,LH_SIZE
- defs.b defines,LH_SIZE
- defs.b resources,LH_SIZE
-
- ;-------------- other global data
- defs.l SegTracker,1 ; SegTracker semaphore or NULL if it doesn't exist
- defs.l myport,1 ; port where all Snoopy messages arrive
- defs.l window,1 ; pointer to current output channel
- defs.l thistask,1 ; pointer to my own task
- defs.l ActiveCalls,1 ; counts the number of active calls
-
- ;-------------- internal data (locally used only within this module)
- answersignal ds.l 1 ; the signalmask used for SendMsg()/GetMsg() answers
- waitsignals ds.l 1 ; signals to Wait() for
- message ds.l 1 ; last message recieved by GetMsg()
- signals ds.l 1 ; signals actually recieved by Wait()
- lastMessage ds.l 1 ; pointer to last message (for SKIPSIMILAR)
-
- ;-------------- stuff for ReadArgs
- argRdargs ds.l 1 ; for allocated memory (dos.library INTERNALs)
- argFirst
- defs.l argScript,1 ; name of scriptfile or NULL for defaults
- defs.l argTaskInfo,1 ; TRUE if extended task info is to be given
- defs.l argOutput,1 ; name of redirected filename or NULL for the window
- defs.l argPri,1 ; priority number or NULL
- defs.l argShow,1 ; array of tasknames to show or NULL
- defs.l argSticky,1 ; KEEP STICKY
- defs.l argMatch,1 ; use exact matching
- defs.l argQuit,1 ; remove snoopy instances
- defs.l argIncdir,1
- defs.l argNoSegTracker,1
- outputactive ds.b 1
- defs.b showsactive,1
-
- ;-------------- contains the actual task/port names made by BuildSnoopysTaskname()
- currentTaskName ds.b 40
- currentPortName ds.b 40
- currentInstance ds.l 1 ; instance counter
-
- ;-------------- segtracker output data
- st_SegAddress ds.l 1
- st_SegName ds.l 1
- st_SegHunk ds.l 1
- st_SegOffset ds.l 1
- st_SegList ds.l 1
- st_SegTaskAddr ds.l 1
- st_SegFilename ds.l 1
- errorMsgBuffer ds.b 256
-
- ***********************************************************************************
- ;--------------
-