5.1. Writing code for Desktop Hacker

The old external code system used by The Hacker is no longer supported. Instead, you should code a normal Wimp task, and use Desktop Hacker's SWIs and messages to communicate. This has the advantage that you don't need to program in ARM code - you can use C, BASIC, or any other language. Create yourself an application with a Desktop Hacker axe somewhere in the icon; ideally, the application name should begin '!dH', but this may not always be appropriate.

There are two parts to Desktop Hacker: the actual DesktopHacker module task, which provides all the hacking facilities that the user uses; and the SWIVe code (so named because it works by claiming the SWI hardware vector), which, when the hot-keys are pressed, stops the game and starts a Wimp task. SWIVe sends Wimp messages to Desktop Hacker (and external tasks; it is a broadcast message) when the game is stopped, restarted, or quit.

Desktop Hacker sends a message to SWIVe telling it to continue when the Continue button is clicked, or when Select is clicked on the icon bar icon, or whatever. Desktop Hacker may also send a Wimp Message_Quit (message 0) telling SWIVe to shut the game down entirely. Other external tasks (including the Task Manager) may send messages to SWIVe. SWIVe will appear in the Task Display either as 'Desktop Hacker Game' if the program interrupted did not call Wimp_Initialise, or the real name of the stopped task if it did.

Apart from the memory of the SWIVe task, there are a few other details Desktop Hacker holds. The only directly readable one is the environment variable dHacker$Obey$Dir, which holds what Obey$Dir held when the hot-keys were pressed.

WIMP messages

Message_HackerTask
Message &82740

Purpose

This message is broadcast by SWIVe to inform Desktop Hacker and any external tasks of a hacking session starting/ending. No parameters are passed using the message; external tasks should call the SWI DesktopHacker_ReadState to find out the current state.

SWIVe sends this message when:

  1. The hotkeys have been pressed (or dHacker has been activated by a hackpoint) and the task is initialising.
  2. SWIVe has been told to continue by Desktop Hacker, or an external task, and the task is ending.
  3. SWIVe has been told to quit by Desktop Hacker, an external task, or the Task Manager, and the task is ending.
  4. SWIVe has been told to load a game file; this has been done successfully, and a completely new game position is established.

Message_HackerContinue
Message &82741

Purpose
This message is sent by Desktop Hacker, or any other task, to tell the SWIVe code to restart the stopped program. No parameters are passed.

Message_HackerGameFile
Message &82742

Purpose
This message is sent by Desktop Hacker, or any other task, to tell the SWIVe code to load in the game file whose path is specified.
Format
+12 = 0 (this is never a reply)
+16 = &82742 (Message_HackerGameFile)
+20 = unused
+24 = unused
+28 = unused
+32 = unused
+36 = unused
+40 = unused
+44 = null-terminated filename of game file to load

Message_HackerAltered
Message &82743

Purpose

This message is broadcast by Desktop Hacker whenever the memory of the stopped task has been altered, either by the user, or by certain DesktopHacker_MemoryAccess calls. External tasks that display details in a window that depend on the contents of the stopped game's application memory should rescan and redraw where necessary when this message is received. No parameters are passed.

Note that this message is not broadcast when a game file is loaded which changes the application memory contents completely; instead the SWIVe code broadcasts Message_HackerTask.

SWIs

DesktopHacker_ReadState
SWI &82740

Purpose
This SWI allows external tasks to read information about Desktop Hacker which may be needed to perform their function.
On entry
-
On exit
R0 = 0 if Desktop Hacker is idling or running a single-tasking task
R0 = 1 if Desktop Hacker is running a task that's called Wimp_Init
R0 = 2 if Desktop Hacker has interrupted a task
R1 = task handle of hacked task if R0=1 or 2, else preserved
Use

If your task requires the application memory of a hacked game, you should only allow use of the task when R0=2.

Note that the task specified in R1 does not have the same in it when stopped as when it is running. See the format of saved game files for details of what is in the application area when stopped.

If you just want to access the main application area, though, and not the full info bundles, you should use the SWI DesktopHacker_MemoryAccess.

If you do access Desktop Hacker or its game's WimpSlot directly using Wimp_TransferBlock, be aware that there is a bug in RISC OS 3.7's implementation of the SWI affecting use of the call twice or more in a row between code synchronisations. To combat this, you should call OS_SynchroniseCodeAreas once after each call to Wimp_TransferBlock. Failure to do so on a machine equipped with RISC OS 3.7 but not equipped with the patches produced by Acorn or DoggySoft will result in things going wrong in inexplicable ways - you have been warned.

DesktopHacker_MemoryAccess
SWI &82741

Purpose

This SWI loads and stores data to and from the game's WimpSlot. You should always use this SWI to access the game's application memory, rather than using Wimp_TransferBlock, as (a) this SWI automatically re-maps the word at &8000, and (b) it uses a cache in RMA to make access much quicker (Wimp_TransferBlock is very, very slow). At present, the cache is 8K long. If you do alter the game using Wimp_TransferBlock, you must call DesktopHacker_MemoryAccess 4 to invalidate the cache, or other users of the cache may not like it.

Note, if you're searching through memory, you will find it is much quicker to search forwards rather than backwards, due to the rather simplistic cache algorithm. Only read-cacheing is performed, not write-buffering.

No DesktopHacker_MemoryAccess operation may be used when the game is not being hacked (R0 on exit from DesktopHacker_ReadState is not 2).

On entry
R0 = reason code
other registers dependent on reason code
On exit
dependent on reason code

DesktopHacker_MemoryAccess 0

Purpose
Load one word
On entry
R0 = 0 (reason code)
R1 = address
On exit
R0=value
R1 preserved

DesktopHacker_MemoryAccess 1

Purpose
Store one word
On entry
R0 = 1 (reason code)
R1 = address
R2 = value
On exit
R0 corrupted
R1, R2 preserved

DesktopHacker_MemoryAccess 2

Purpose
Load block
On entry
R0 = 2 (reason code)
R1 = start address (game)
R2 = length
R3 = buffer (in your memory)
On exit
R0-R3 preserved

DesktopHacker_MemoryAccess 3

Purpose
Store block
On entry
R0 = 3 (reason code)
R1 = start address (game)
R2 = length
R3 = buffer (in your memory)
R4 = your task handle, or -1 if in unpaged memory such as RMA
On exit
R0-R4 preserved
Use
Note that the buffer must be paged in when the SWI is used, despite the fact that you pass the task handle. The task handle is needed by Wimp_TransferBlock for efficient transfer.

DesktopHacker_MemoryAccess 4

Purpose
Invalidate cache
On entry
R0 = 4 (reason code)
On exit
R0 preserved
Use
Under Desktop Hacker 1.05 or later, invalidating the cache also ensures that its contents are zeroed. This is to make sure that programs like dHMusic don't find portions of the game's memory in the RMA and generate false alarms.

DesktopHacker_MemoryAccess 5

Purpose
Find length of game
On entry
R0 = 5 (reason code)
On exit
R0 = length of game's real WimpSlot in bytes
Errors
MemoryAccess cannot be used as no game is hacking (&82760)
Bad DesktopHacker_MemoryAccess address (&8275F)
Unknown DesktopHacker_MemoryAccess reason code (&82750)
Plus any errors returned by Wimp_TransferBlock

DesktopHacker_ReadList
SWI &82742

On entry
R0 = list number
On exit
R0 = Desktop Hacker's task handle
R1 = pointer to list block
R2 = length of list block
Use

On exit R1 points to a list (see format of list files), the only difference being that the first four bytes are an offset to the first byte after the end of the list, rather than the header "List".

Note that the pointer is in Desktop Hacker's application space. If you want to read the contents of the list you will need to use Wimp_TransferBlock with the R0 and R1 supplied by this SWI, and the length of block to transfer as R2.

There is no SWI provided to alter lists - doing so would be very slow as very many calls to Wimp_TransferBlock would be needed, along, perhaps, with resizing of the WimpSlot which is not possible as Desktop Hacker is not paged in. If you do want to send a list to Desktop Hacker, simply use the data transfer protocol - make up a Wimp message block as if a list file was dragged to Desktop Hacker (use the icon bar (-2) as the destination window handle; the destination icon handle is unimportant), using Message_DataSave. Data transfer will be conducted as normal, and the window containing the list will be opened. Note that Desktop Hacker does not support RAMTransfer.

Errors
Invalid list number (&8275E)
Any errors returned by Wimp_TransferBlock

DesktopHacker_BreakPoint
SWI &82743

On entry
-
On exit
Registers preserved
Use

This SWI sets a flag which tells Desktop Hacker to interrupt as soon as possible. Usually, this will be immediately, but it may be called later if IRQs or FIQs are disabled, or the processor is in IRQ or FIQ mode. Of course it will also only interrupt if you are the current hacking task.

In order to get all the registers for the Game Info window, not just R0-R8, this SWI is trapped in the SWIVe code; the actual SWI command code does nothing. You will not receive an error if the situation isn't suitable for a breakpoint. Instead, just the SWI command code is called, and so nothing will happen.

This SWI is only implemented on Desktop Hacker 1.06 and above.

* commands

*DesktopHacker command

Purpose
Start a new task or game file to be hacked
Use

This command is used by Desktop Hacker when a game is dragged to it. It cannot be used from the command line. However, there is no reason why external tasks should not use it, if they need to. It should only be used by being passed to Wimp_StartTask, and to be sure of compatibility with special fields, you should surround the parameter of a Run command (if that's what you're using) with quotes. For example, for BASIC:

SYS "Wimp_StartTask","DesktopHacker Run ""CFS#adfs::HD.$.File"""

*Desktop_Hacker

Purpose
This is just the command used to start the Desktop Hacker Wimp task, as is needed by module tasks. Don't use it.

*SetHackPoint *ClearHackPoint *ListHackPoints

See breakpoints.


--) /!\ Format of saved game files
/\ /!\ Technical stuff


ajc@doggysoft.co.uk
23rd April 1998