Index


RISC World

Desktop Hacker

Foundation RISCWorld

3. Finding cheats.

Every line of output in the disassembler represents one word of memory, which can be a workspace value, program data, or an instruction of the actual game code. Each word is referred to by its address, which is shown in blue on the disassembler between the interpretations of the word as data and as code.

Normally, to find cheats you search through the workspace values to find the addresses which hold the values for number of lives, time, or whatever else you wish to find. By altering the contents of these addresses you can gain more lives or time, or anything.

Then, if you understand ARM code you can search through the game code to find the code that affects a value in the workspace, and find an alteration to make to the code to achieve effects like infinite lives, or better firepower.

It is also possible to search through the program data, for example to try to find passwords.

3.1. Searching for values.

This is the easiest way of finding the address that holds a countable quantity, typically lives. Take note of the number of lives (or whatever) you have and interrupt the game, then open the Search window either from the disassembler window or by pressing F4.

Choose 'Word' search and enter the number you noted in the writable field.

If you want to enter the number in hexadecimal (as shown in the disassembler window) rather than as a normal (decimal) number, select the 'Hex' option at the bottom. Choose a list to send the search results to (between one and ninety-nine; '1' will do for the first search) and click on 'Search'. When the search operation is finished, the Lists window will open automatically to show the results.

All the addresses listed on the left contain the word value you searched for. You can quickly move the disassembler to an address in the list by clicking Select on the address, and use the List arrows on the assembler button bar to move between the addresses in the list.

If there is only one address in the list, it is likely to be the correct address for the variable you were looking for. If there is more than one, try to narrow down the list (see the next section) to one address.

Most modern games use words to store all their workspace values, but some - and in particular 8-bit games run under emulators - store byte values instead. Each word is comprised of four bytes, but bytes can only hold values up to 255. To search for byte values, use the 'Byte' option rather than 'Word' before clicking on 'Search'.

Note that it is not usually a good idea to search for values like '0', '1' or (in hex) 'FFFFFFFF'. These values tend to occur a lot in a game's memory, so a search for them will take some time and may generate a very long and unwieldy list.

3.2. Narrowing a search.

Having a list of a dozen possible addresses that could be the lives counter is not terribly useful: the list needs to be narrowed down to one or two addresses. This is done by going back to the game, changing the quantity you're searching for (for example by losing a life) and then interrupting to check which of the addresses that contained the old number of lives have changed to hold the new number of lives.

Desktop Hacker can do this automatically from the Search window. Open it and select the 'Only addresses in' option, then choose the list you sent the old results to in the field to the right. Fill in the new details you wish to search for at the top (for example, a word value of '2' if you had three lives last time and have since lost one).

You can send the new list of addresses that were in the old list and satisfy the new search conditions to a new list, or to the same list, in which case the old contents of the list are overwritten. And you can keep doing searches to narrow down the list as many times as you like. When you get stuck with one or two addresses, you can try changing their contents to see if you've got it right (see altering words [4.1]).

If you end up with an empty list, then either you've made a mistake somewhere, or there is no single word that is used to hold the variable you're looking for. If the quantity is not shown as a number on-screen - for example if 'three lives' is displayed as three icons in the corner of the screen - you could try searching for a number which is one less or one more than the actual number you are looking for. If this doesn't work either you will have to resort to using the memory compare [3.4] feature, or look for some other cheat.

Unlike when doing an original search, searching for values like zero is sensible when doing a narrowing search, because a larger list than the original cannot be generated.

It is possible to narrow a search by which addresses do not contain a certain value, as well as by those that do. So after a search for '3' you could narrow by looking for addresses that have changed and no longer hold that value. Select the 'Invert' option to search for values that do not match the given value. Selecting 'Invert' for original rather than narrowing searches is not sensible as the resulting list would be huge.

3.3. Searching for text.

This type of search allows you to find any textual information stored in the game's data, including passwords and on-screen messages.

Open the Search window, choose the 'Text' option and fill in the string to look for in the field next to the Text option. For example, if you are looking for passwords, try looking for the password for the first level; you may be able to see the passwords for subsequent levels further down in the disassembler.

Normally, text searches are case-insensitive; that is, capital and small letters are treated as the same letter. If this is not what you want, select the 'Case' option.

Finding things like passwords is often unsuccessful with commercial games as they encode the password data to stop it being easily seen. The 'Coded' option (see advanced searching [3.7]) can get around the simplest type of encoding, but there are still many games whose passwords you won't be able to get.

3.4. Compares.

Searching for distinct values is useful for finding numerical quantities like lives and score, but not so useful when the exact value of a variable is not known - for example, where energy is shown as a bar of decreasing length, or where has a certain amount of time to run before it disappears.

To allow you to find addresses that hold things you don't know the value of, the Compare feature checks the differences between two game positions, and can send addresses to a list when their contents have increased or decreased, since it is generally possible to see at least whether a quantity has increased or decreased.

To use the Compare feature, you must interrupt the game at the first position, save the game's memory (from the disassembler menu, go over 'Save' then 'Application', not 'Position') to disc, then continue the game until you get to the position with the quantity you are looking for altered, and interrupt again.

Choose 'Compare...' from the disassembler menu and drag the file you saved from the last time to the arrow on the Compare window. Set the options according to whether the quantity being searched for has increased, decreased, or just changed at all and click on 'Compare' to find the changed addresses.

The resulting list is likely to be quite large and will need further narrowing before yielding the address you are after. This can be done using further narrowing searches, more compares followed by list processing [3.5], or looking at the addresses in the list one by one to see if they might be the value you are looking for. (For example, large blocks of changed addresses together are unlikely to contain the single value you are looking for, and values that look like graphics data or that disassemble to valid code are also unlikely to be right.).

3.5. List processing .

List processing is useful for combining the results of several compare operations. The most useful options are 'And' and 'And Not'.

These options, as well as the 'Or' option, work on the list you have currently selected and one other list, which should be specified in the 'Process list' field. The two lists are processed together and the results are sent to the list currently selected.

The 'And' option sends addresses to the selected list when the address is in both the selected list and the process list. This is useful when you have two separate compare operations which need to be cross- referenced.

The 'And not' option is generally the most useful as the first step in narrowing down a long compare list, as long as it is possible to get two game states in which the quantity you are searching for is set to the same thing. The result of an 'And not' operation is a list containing all addresses that are in the selected list but are not in the process list.

So you can lose a bit of energy and do a compare to find addresses that have decreased, then restore your energy to what it was before and do another compare with the original saved position, this time for all addresses that have changed at all, sending the results to another list.

Process the first list with the second list using 'And not', and you'll be left with a list of addresses that decreased when you lost energy, but returned to what they were before when your energy was restored. This technique quickly yields a short list, but for it to work you must be able to make sure that the quantity is back to what it was.

Other list-processing functions are 'Or', which makes a list containing all the addresses that were in either the selected or the process lists, and 'Copy' which copies the process list directly to the selected list.

It is also possible to directly add or remove an address or block of addresses to a list. To add an address, enter it in the 'Add address' field and press the button; to remove an address, click on it in the list window with Adjust. Click on 'Clear' to remove all the addresses.

To add or remove a block of addresses from the list, enter the (inclusive) lowest and highest addresses in the fields at the bottom of the Lists window and click on 'Select' or 'Deselect'. This is mostly useful for creating ranges of addresses to search between in a narrowing search, and removing large blocks of irrelevant addresses for a list.

Click Menu on the Lists window to save the list or print it out.

3.6. Searching for references.

Once you have found an address, it is often useful to be able to find code in the game that refers to it, so you can change the behaviour of the game, going from a lives counter to infinite lives, or a counter that stores the delay until you are next allowed to take a shot into a rapid- fire cheat.

To use the results of a references search effectively, you must know a little ARM code.

Open the Search window and choose the 'References' option, filling in the address you want to find references to in the field next to the option.

Click on Search and you'll end of with a list of addresses that either contain a pointer to the address you're searching for, or an instruction that accesses that address. In the case of a pointer, you will probably have to do another search for references to the address containing the pointer, to find the code that accesses the pointer and hence the original address.

An instruction may refer to an address either by pointing to it with an Adr instruction (or a two-instruction AdrL directive), or indexed by a register.

Hence Desktop Hacker can spot references to an address buried in a workspace block indexed by R12 or any other register. Of course Desktop Hacker still cannot spot all possible accesses to an address.

For infinite something-or-the-other, look for a Ldr instruction with a Sub instruction shortly after it, and a Str instruction shortly after that.

Remove the Str instruction and you won't lose lives, or whatever. Anything else... you're on your own with the ARM code.

3.7. Advanced searching.

SWI search : Enter a SWI name or number in the SWI search field and select the 'SWI' option. This search will match all SWI instructions that call that SWI, regardless of condition code or whether the X version of the SWI is used.

Mnemonic search : The mnemonic search matches a string you enter with any part of any instruction in the game. Since this search has to disassemble every instruction and do a sub-string search on them, it's quite slow. The string you search for is case- and spacing-insensitive, so searching for 'BCSR' would give an address contain the instruction 'SubCs R1,R1,#1'.

When this option on the Search window is set, the following characters are used as simple wildcards with the following meanings:

  • $ = Any Byte
  • # = Any number
  • % = Any letter (A-Z, a-z)
  • & = new line character (ASCII 10 or 13)

All the wildcards also match themselves, so 'a%c' matches all of 'abc', 'aGc' and 'a%c'.

Coded text search

Select the 'Coded' option to find text encoded in the simple way favoured by PD games authors who don't know any better, namely encoding each byte by an exclusive-or with a constant. Encoded strings found this way will not be visible in the disassembler, because they are still encoded. It is left as an exercise for the reader to take each byte and exclusive or it to find the real text.

Foundation RISCWorld

 Index