Jump to content

RAM to ROM tracing


Vexiant
 Share

Recommended Posts

Since I'm not capable of creating a topic in the "Tutorials" forum, I'll drop this here.

 

I'm sure you've heard of searching for identical hex data to locate where a RAM address is in ROM. Well, I'm here to give you an even more informative rundown!

The above method is viable most of the time, but you can of course potentially encounter an identical instance. Base 16 (hexadecimal) is just a form of a less legible binary pattern to preform an action in comparison to MIPS after all (say that because identical events can sometimes be common between games). Moreover, the Nintendo 64 OS doesn't impose any default locations when it comes to where a code or data segment is located and this includes the main heap (arbitrarily allocated data), how many "threads" there are (one stack per thread. e.g. Ocarina of Time has four iirc) or anything in relation to memory management. With that said, some games also utilize the main CPU's (VR4300) memory management unit's (MMU) translation lookaside buffer (TLB). Some games will make use of this depending on their addressing mode or kernel user mode (all of Rare's games) and it can be a total pain when it comes to reverse engineering games or trying to type up assembly codes for 'em.
With the above said, I shall supply you with a tutorial that can be used on most Nintendo 64 games to trace RAM to ROM as long as it's within a code segment!


Locating RAM to ROM (and vise versa):

I will also go into detail about how to locate the start and end of the code segment in ROM! Note: Not all Nintendo 64 games use the same "code" file (again, as noted above). Nonetheless, "standard" functions are always in lower memory. By "standard functions," I mean functions that are within the code/text segment's within RAM. As stated in the "Memory Segment" category, things in higher memory are almost always arbitrarily located as well as mapped there through the TLB which makes it incredibly difficult to trace back to ROM.

Locating the start and end of a code segment

>To locate the start of the code/text segment's in RAM, you can do this one of two ways:

1.) If you're using Nemu64, you can utilize the "Show Rom Info" option I spoke of above to obtain the RAM entry point, breakpoint the address (which is a pointer) of the entry point and it will take you to where the standard (libultra) functions start!

2.) Moreover, you can open the ROM of your choice in a hex editor and navigate only 0x8 bytes in and copy the word found there. (A word is 32-bits long XX XX XX XX)

>To locate the end of the code/text segment's in RAM: First, as also explained below, open a hex editor of your choice and navigate to 0x1000 and scroll down until the machine code ends, and take note of the address that it ends on as that is the end offset of the standard functions. Then: (End offset in ROM + RAM entry point) - 0x1000

>To trace a target RAM address from a MIPS JAL instruction in this segment:

Discovered RAM Address = (JAL instruction & 0xffffff) << 2
(Discovered RAM Address - RAM entry point) + 0x1000
"&" is a bitwise AND
"<<" is also a bitwise operator for left shift
(A quick search with your favorite search engine would suffice in relation to more information!)


Method to locating alternative code segments
>In order to locate a game's compiled main.c file, open up a hex editor and search for the ASCII text "RSP Gfx" as all ROMS have that string to specify what Microcode Library the game uses. If the game has a file table, then the ROM search will put you between the start and end address of a file table entry. That string is always found in the main code segment!
>If you've located the code segment, record the start address of it from the file table. Then, you must determine the RAM start address. See the tutorial on this page for methods.
>To get the RAM end address, simply subtract the start address from the ROM's file table from the end address from the ROM's file table. Then, add the difference to the RAM start address.
>If you have the ROM start address, RAM start address, and RAM end address, and have discovered code/text in RAM within the segment:
(Discovered RAM Address - code segment RAM start address) + code segment ROM start address


>To locate ROM to RAM, just swap RAM for ROM in the equation above: (Discovered ROM Address - code segment ROM start address) + code segment RAM start address

Note: I've only noticed yaz0 games having file tables, and the ones outside of that that also had them are: Super Smash Bros and Star Fox 64.


You can locate virtual addresses locations in ROM, but hence "virtual," you'd have to locate where they're loaded from. It's a whole complex process in itself though. The above method will suffice for now!


I hope to see some conversions and mods soon! :3 As noted, you can do this for other games too. The PointBlank (.blank) community I'm apart of and have been apart of for six years now will have a Nintendo 64 hacking wiki soon. There you will find VERY useful tutorials and general guides for hacking. It will be released at the start of February. It will include data archives for various games as well, so you guys will more than likely enjoy that! Cheers, and happy hacking!

Link to comment
Share on other sites

  • 3 weeks later...
  • 3 weeks later...

There should be a lot of zero's, and it very well may not be so with Quest 64. I know it's not with SM64. Sorry for the discrepancy as it's normally the case with most games. I'm currently extremely busy, so I'll just share this pastebin with you taken from the WIP .blank n64 hacking wiki: http://pastebin.com/TbEQw9Vr

Hopefully it's of some avail.

Link to comment
Share on other sites

  • 4 months later...

I keep getting the following error whenever I try to run any command (including just pressing enter to get a ram map) after loading up the emulator and rom. 

 

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: End16 must end in 0 or 2
   at Spectrum.Zpr.End16(Int32 addr)
   at Spectrum.Zpr.ReadRamInt16(Int32 addr)
   at Spectrum.OvlActor.SetInstanceSize()
   at Spectrum.OvlActor.GetActorFiles()
   at Spectrum.Program.GetRamMap(Boolean fetchAll)
   at Spectrum.Program.PrintAddresses()
   at Spectrum.Program.ProcessCommand(String readLine)
   at Spectrum.Program.Main(String[] args)
 
 I assume I'm doing something wrong?? 
Link to comment
Share on other sites

 Share

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.