Console compatibility with SM64 ROM hacks

This page lists the problems found over the past few years to help figure out how to get custom SM64 ROM hacks to work on real N64 hardware. Each issue that we have discovered is detailed here, and also includes ways to fix those issues.


Misaligned decompressed MIO0 blocks

In SM64, the game will load up scripts & models using level script commands for each level. Level script command 0x17 is used from copying uncompressed data from the ROM into RAM, and the commands 0x18 & 0x1A are used to read compressed MIO0 data from the ROM and then decompress the data into RAM. The MIO0 compression was necessary to make SM64 fit within an 8MB cartridge. Since ROM hackers don't really need to worry about file sizes (up to 64MB), we use ROM extenders to decompress the data into another place in the ROM file and convert all of the 0x18 level commands into 0x17 commands.

The problem with early extender tools, like VL-Tone's original SM64 ROM extender, is that the addresses where the decompressed data was stored was in a bad alignment. The N64 requires a 2-byte alignment for ROM addresses, and an 8-byte alignment for RAM addresses when copying data. This means that if the start/end ROM addresses within the 0x17/0x18/0x1A commands were odd, then copying data from ROM to RAM would fail. This creates the white screen freeze after a file is selected.

For example, here are some load commands from the first hub area in SM64 The Green Stars:

17 0C 00 12 003CF0D0 003D0DC0 // Load Segment 0x12 from ROM 0x003CF0D0 to 0x003D0DC0
17 0C 01 07 00E0BB07 00E84C1F // Load Segment 0x07 from ROM 0x00E0BB07 to 0x00E84C1F
17 0C 00 0B 00DA2785 00DA951D // Load Segment 0x0B from ROM 0x00DA2785 to 0x00DA951D
17 0C 01 0E 01C90000 01D50068 // Load Segment 0x0E from ROM 0x01C90000 to 0x01D50068
1A 0C 00 09 00D2320D 00D31321 // Load Segment 0x09 from MIO0 at ROM 0x00D2320D to 0x00D31321

The segments 0x07, 0xB, and 0x09 will fail to load on console, since the ROM address values are odd. Segments 0x12 and 0xE will load just fine, since the ROM address values are even.

How to fix it?

To fix this issue, we will have to look through the entire ROM file and adjust every 0x17/0x18/0x1A level script commands that have odd ROM address values. Thankfully, some people have made tools to do this automatically like queueRAM's sm64compress tool.

If you want to make your own tool that will implement this fix, then you can follow these steps:

1.) Look through all of the levels scripts to find 0x17/0x18/0x1A commands
2.) Test if either the ROM start address or ROM end address is odd.
3.) Adjust bytes if true.
  3a.) If both the start & end addresses are odd, then move the entire bank over by 1 byte.
  3b.) If only the end address is odd, then just increment the end address by 1.
  3c.) If only the start address is odd, then move the entire bank by 1 byte and also increment the end address by 1.
Note: Banks can be used multiple times, so you will have to remember which addresses you've already adjusted.

Improper use of Fast3D's SetCombine (0xFC) command

In the display lists that draw the level's triangles, you might see a 0xFC command near the top. This is the command that will configure the RDP's color combiner. Like it's name suggests, the color combiner will take in inputs from many different sources and combine them into a single color that affects how the polygons in a model will look. Basically, using a wrong combine value will cause the level to not look the way you want.

The problem with earlier versions of the SM64 Editor is that it only used a single 0xFC command for all of the display lists:  FC 12 7F FF FF FF F8 38 . This one command was only meant to work with solid RGBA textures in levels that have fog. For levels without fog, all of all the geometry will just flash between different solid colors. (see gif above)

How to fix it?

To fix this issue, we need to go through all the Fast3D display lists of every single level and determine if the 0xFC is fine to use or not. If the wrong 0xFC command is being used, then we need to replace it with a correct one. There are 4 0xFC commands that we need to know:

FC 12 7E 24 FF FF F9 FC = Solid RGBA texture (No fog)
FC 12 18 24 FF 33 FF FF = Alpha RGBA texture (No fog)
FC 12 7F FF FF FF F8 38 = Solid RGBA texture (With fog)
FC FF FF FF FF FC F2 38 = Alpha RGBA texture (With fog)

We don't need to worry about other texture formats, since every single version of the SM64 Editor has only ever used RGBA16 textures.

To figure out if a level has fog or not, you will have to look at any 0xB7 (F3D_SETGEOMETRYMODE) commands that you see before a 0xFC command occurs. If the parameters contain a 0x10000 flag, then fog will be enabled in the level.

Warping triangles

Some versions of the SM64 Editor, like v1.9.3S, will have warping polygons when the player is moving around the level. This issue was caused by setting the camera frustum's far value to be a negative number (0x9696 = -26,986) in the Geometry Layout Command 0xA (Set Camera Frustum).

How to fix it?

This issue can be fixed by changing the camera's far value back to being a positive number. The largest possible positive number is 0x7FFF (‭32767‬). A simple way to fix this problem is to look through all the bytes in the ROM file and find a specific pattern of bytes:

1.) Find all occurrences of: 0A 01 00 2D 00 64 96 96 80 29 AA 3C
2.) Replace occurrence with: 0A 01 00 2D 00 64 7F 7F 80 29 AA 3C 


The RCVI hack is an option in the SM64 editor, under the “ROM Settings” tab, that can potentially reduce lag in emulators. The hack simply changes two bytes at ROM offset 0xF00C2 from  02 0D  to  08 34 . However, this hack prevents the game from working properly on console. It produces the strange visual artifacts seen in the image above on boot.

How to fix it?

To fix this issue, you only need to revert the two bytes back to normal. Just change the two bytes at ROM offset 0xF00C2 to  02 0D . Once that is done, make sure to use a program like n64crc.exe to recalculate the ROM's checksum.

Trying to write to the framebuffer's area of memory (8038F800-803FFFFF)

Older versions of the SM64 Editor moved the sound allocation to address 0x803D0000. The problem with using that address is that the region from 0x8038F800 to 0x803FFFFF is constantly being overwritten with the game's framebuffer, so any data that gets stored within that region will be erased immediately. Some graphic plugins for Project64, like jabo's, have the option of writing the framebuffer to memory turned off by default, which is probably why this was not caught earlier.

How to fix it?

To fix the music allocation issue, you just need to do the following:

1.) Check if the 2 bytes at ROM offset 0xD48B6 is equal to 0x803D.
2.) If so, then change that value to 0x805C.

Later versions of the SM64 Editor will put the music memory pool in extended memory, which is safe to use. Please do not store data within 0x8038F800-0x803FFFFF if you want your hack to be compatible.

The problem with N64 emulators

As we all know, Nintendo 64 emulation has never been perfect in the 20+ years since the console's release. This is mainly due to the architecture that was created by Silicon Graphics back in the mid 1990's. The console truly was a unique piece of hardware. While most N64 emulators do a good enough job for casual players who want to only play games, there are some inaccuracies that can create problems for ROM hackers.

See Also