Memory Inspector Overview
Here is a short overview of the Memory Inspector and its features. This tool can be found on "RetroAachievements" tab on any emulator integrated with RA.
Memory Inspector Dialoglink
1. Reset tolink
Click on one of these buttons to start a new test. For most things 8-bit test would be appropriate.
2. Filter Valueslink
Usually filter for either
== (equals to) last known value or
!= (different than) last known value. If you know the exact value you expect something to be, you can use
Given Value, or if you're convinced that a value should have increased, you could try
> (greater than) or
< (less than).
With every press of this button, you are filtering out values that do not match in memory between the last test and now.
4. Results windowlink
After filtering you'll see in the results window exactly what happened, how many values you've got and how many are left. Some points to note:
- Search results show live value changes, so you can more easily identify usable addresses.
- Search results are highlighted depending on their criteria. For addresses that don't fit the search filter, they will be highlighted in red. This can be disabled on the
Highlightscheckbox, if preferred.
- You can also manually exclude any selected addresses from the search. Use Ctrl or Shift to multi-select.
- Results History: You can move backwards (
<<) or forwards (
>>) through your previous filtered searches. Keep in mind if you start a new search (such as
New 8-bit Test), your history will be cleared.
Any properly formed value in this area will be watched in the watch windows and bound to the code notes on the right. The addresses must be
0x (that's zero, then letter x), followed by hexadecimal digits.
6. Watch windowlink
Any watched variable and the variables around it will be shown in this window. You can see more info below, in the Reading data in the Memory Viewer section.
7. Code Noteslink
Once you've found a memory address you want to make a note of, ensure the value is entered into the 'Watching' dropdown box. Next you can write a short description in the textbox next to it, and click
Save Note. This will send the memory address and your description to the database, so it can be shared with all developers who work on this game.
Click the dropdown arrow to view what memory addresses have been found so far, and you will be shown the description in the box next to it, to tell you what this memory address is for.
Try and keep your descriptions simple and clear, so they can be easily understood. To rename a note, select it in the drop-down menu, update the description, and click
Save Note. A dialog will prompt you to overwrite the existing note - check that it is a good change, and click OK.
If you wish to remove a note, select it in the dropdown menu, and click
8. Memory Bookmarkslink
When you click on the
Open Memory Bookmarker button you'll see this dialog:
With this, you can view multiple designated addresses at once instead of having to shuffle around in the Inspector.
The bookmarks can be renamed by double-clicking their description. If you double-click on the address, you can move straight to that point in the Mem Inspector.
Bookmarked addresses will show in the Memory Inspector as green. From here you can also Freeze any bookmarks.
This is helpful for things like health or consumables. Frozen values can be manipulated directly from the inspector. Keep in mind, freezing occurs 1 frame after gameplay. This means even when frozen, the value will change for atleast one frame before returning to the frozen value. These will always be displayed as yellow.
Reading data in the Memory Viewerlink
The first, and most important thing to know, is that the data shown in the memory viewer is in hexadecimal. Data is actually stored in binary (everything is either a 1 or 0), but the smallest working unit available to the CPU is a byte (8-bits). 8-bits can represent any value from 0 to 255, but rather than showing three characters per byte in the Memory Viewer, the data is shown in hexadecimal, which only takes two characters per byte. This has been the standard way to view raw computer data for a very long time.
- One hexadecimal digit represents a value from 0-15:
0 1 2 3 4 5 6 7 8 9 a b c d e f.
- To indicate a value is written in hexadecimal, the prefix
10 = 10,
0x10 = 16
- Two hexadecimal digits represent a value from 0-255.
- The first digit is multiplied by 16 and added to the second digit:
0x39 = 3x16 + 9 = 57,
0xa0 = 10x16 + 0 = 160.
- The first digit is multiplied by 16 and added to the second digit:
- Four hexadecimal digits represent a value from 0-65535.
- Each additional digit is multiplied by the next power of 16.
0x63a7 = 6x16³ + 3x16² + 10x16 + 7 = 25511
- Eight hexadecimal digits represent a value from 0-4294967295
0x3b9d00f3 = 3x16^7 + 11x16^6 + ... + 15x16 + 3 = 1000145139
0x00000100 = 1x16² = 256
By default, the Memory Viewer shows data in 8-bit mode. This displays each byte of memory as a separate two-character hexadecimal value. Sixteen bytes are shown per line. The address of a byte can be determined by adding the column index (displayed above the memory) to the row index (displayed to the left of the memory). Using the image above, the cursor is at
0x00200 + 7).
Before we talk about 16-bit mode and 32-bit mode, you need to understand a little about little-endianness. Values larger than 255 have to be stored in multiple bytes. However, for efficiency reasons, multi-byte values are stored in reverse order. For example, the value
0x39ce (14798) will be stored in memory with
0xce in the first byte and
0x39 in the second byte. You can see this in the image above at 0x0002c0.
When you switch the viewer to 16-bit mode, it automatically groups every two bytes and displays them as 16-bit hexadecimal values. The
0x39 bytes at 0x0002c0 get displayed as
0x39ce. The next two bytes are displayed as
0x2529 at address 0x0002c2.
NOTE: While 16-bit values are usually aligned to even addresses, that's not always the case, there's actually a non-displayed 16-bit value at 0x0002c1. Since the byte value at 0x0002c1 is
0x39 and the byte value at 0x0002c2 is
29, the 16-bit value at 0x0002c1 is
Similarly, in 32-bit mode, the four bytes from 0x0002c0 to 0x0002c3 are displayed as a single 32-bit
0x252939ce value at address 0x0002c0, but there are also 32-bit values at 0x0002c1, 0x0002c2, and 0x0002c3.
Sizes smaller than 8-bitlink
In addition to the 8-bit, 16-bit and 32-bit sizes described above, there are additional sizes that can be used when writing achievements.
Given that a byte is two hexadecimal characters that represents 8 binary bits:
0x7a = 0111 1010
Each hexadecimal character is four bits, the first four bits (repesented by the hex character
7) is the
Upper4 bits. A condition where "Upper4 = 7" would be true for this byte. The last four bits (represented by the hex character
a is the
Lower4 bits. A condition where "Lower4 = 10" would be true for this byte.
To take things one step farther, you can write conditions for each individual bit of a byte. When in 8-bit mode, the Viewer automatically shows the bits that go into the currently selected byte just above the viewer. Each bit is labelled. The left-most bit is
Bit7, and the right-most bit is