Project

General

Profile

Actions

Emulator Issues #12565

closed

(WiiVC Majora's Mask) [NARE01] Dolphin does not emulate unaligned uncached stores the same as real Wii hardware.

Added by Rylie over 3 years ago. Updated over 3 years ago.

Status:
Fixed
Priority:
Normal
Assignee:
% Done:

0%

Operating system:
N/A
Issue type:
Bug
Milestone:
Regression:
No
Relates to usability:
No
Relates to performance:
No
Easy:
No
Relates to maintainability:
No
Regression start:
Fixed in:
5.0-14829

Description

Game Name?

The Legend of Zelda: Majora's Mask

Game ID? (right click the game in the game list, Properties, Info tab)

NARE01 (000100014e415245)

MD5 Hash? (right click the game in the game list, Properties, Verify tab, Verify Integrity button)

ac4cdf326371cf619744241ed693feb3

What's the problem? Describe what went wrong.

This is a highly technical problem that pretty much only affects speedrunners, requires hefty explanation and game knowledge, and isn't documented in the Broadway CPU manual.

To begin, let me say that The Legend of Zelda: Majora's Mask is an extremely broken videogame. In particular, it has a glitch known as SRM (Stale Reference Manipulation) that allows the player to overwrite nearly anything within the region of memory known as the "actor heap" [[https://www.zeldaspeedruns.com/mm/srm/srm-primer]]. A recently found application of SRM called "LightNode SRM" enables us to write an arbitrary (32-bit) word to an arbitrary address. This is the holy grail of glitches for any videogame, and is typically referred to as "Arbitrary RAM Write".

LightNode SRM is actually pretty weak on a real N64, because, as a MIPS machine, it doesn't support misaligned loads and stores. But the PowerPC architecture does support misaligned loads and stores, and this ability carries through to the Wii Virtual Console version of Majora's Mask (likely the GCN and Wii U VC versions as well, but those are untested since the speedrunning community does not have practice tools for those versions). The catch is that the Broadway CPU manual says very little about how misaligned loads and stores are actually implemented, merely that they incur a performance penalty.

Through testing using our practice tool, called "kz", on real Wiis, our community has discovered some idiosyncrasies about how misaligned stores work (at least within the environment of the WiiVC version of Majora's Mask). The behavior of misaligned stores on real hardware is dependent on the memory domain to which the word is being stored to. In particular, we have 4 memory domains that work on NARE (that we've discovered so far).

  1. 80xxxxxx: Emulated N64 Cached RDRAM / Wii Cached MEM1 1T-SRAM
  2. A0xxxxxx: Emulated N64 Uncached RDRAM
  3. C0xxxxxx: Wii Uncached MEM1 1T-SRAM
  4. E0xxxxxx: Not entirely sure. Possibly N64 TLB as used in Paper Mario, which released on WiiVC before Majora's Mask did.

When the misaligned store is to the 80/A0 memory domain, it works basically as expected, and Dolphin works the same as hardware. Namely, exactly 4 consecutive Bytes will be written at the specified address.

When the misaligned store is to the C0/E0 memory domain, things get interesting. Instead of writing only 4 Bytes (1 word), we see either 8 Bytes (2 words) or 16 Bytes (4 words) depending on the address being written to. If the address is such that at least one Byte will be written on either side of a doubleword boundary (so xxxxxxx0 or xxxxxxx8) then a full 4 words is written (we call this a QuadWord Write or QWW). If the crossing point is only a singleword boundary (so xxxxxxx4 or xxxxxxxC), then only 2 words are written (we call this a DoubleWord Write or DWW). Dolphin, however, treats this case the same as the previous. Only a single (misaligned) word is written, not two or four.

As you can probably imagine, this behavior that real hardware has is extremely desireable. If being able to write a singleword to an arbitrary address was powerful, being able to write a quadword is even moreso. In particular, the latest Any% route for WiiVC hard-requires the QWW behavior, which means it does not work on Dolphin.

Using the Any% route as a concrete example:
We are writing the word E02D0043 to the address C01C5557. The memory in the destination region looks like this in Dolphin after the write:

C01C5550: ????????
C01C5554: ??????E0
------------------ doubleword boundary
C01C5558: 2D0043??
C01C555C: ????????

On real Wii hardware, however, we get the following:

C01C5550: 2D0043E0
C01C5554: 2D0043E0
------------------ doubleword boundary
C01C5558: 2D0043E0
C01C555C: 2D0043E0

My conjecture about what is happening is this:
The Broadway CPU implements unaligned stores via a multistep process. First, it bitshifts the word to be written. Next, it writes that shifted word to both word-aligned addresses involved. In the case of crossing a doubleword boundary, it does the same with writing a bitshifted doubleword to both doubleword-aligned addresses involved. Note that this is a complete guess with no evidence, merely a gut feeling based on previous studies of assembly language and electronics. As to why this only affects certain memory domains, I haven't the foggiest. The memory domain-specific aspects might actually be due to the N64 emulator packaged in the WiiVC release, but I honestly believe the misaligned store duplication behavior itself is CPU hardware-level.

What steps will reproduce the problem?

Follow the steps in the video linked at the bottom (it's far too much to explain in a text format since it requires knowledge of game-specific glitches and mechanics).

Alternatively, simply load my savestate (not attached, but can be provided), target-walk into the tunnel, drop the invisible pot, and play Song of Time.

Is the issue present in the latest development version? For future reference, please also write down the version number of the latest development version.

Yes, 5.0-14519

Is the issue present in the latest stable version?

Yes, 5.0

If the issue isn't present in the latest stable version, which is the first broken version? (You can find the first broken version by bisecting. Windows users can use the tool https://forums.dolphin-emu.org/Thread-green-notice-development-thread-unofficial-dolphin-bisection-tool-for-finding-broken-builds and anyone who is building Dolphin on their own can use git bisect.)

[First broken version number here (if applicable)]

If your issue is a graphical issue, please attach screenshots and record a three frame fifolog of the issue if possible. Screenshots showing what it is supposed to look like from either console or older builds of Dolphin will help too. For more information on how to use the fifoplayer, please check here: https://wiki.dolphin-emu.org/index.php?title=FifoPlayer

[Attach any fifologs if possible, write a description of fifologs and screenshots here to assist people unfamiliar with the game.]

What are your PC specifications? (CPU, GPU, Operating System, more)

Intel 4570R CPU, Intel Iris Pro 5200 Integrated GPU, 16GB 1600 MHz DDR3 RAM, Windows 10 Pro 21H1

Is there anything else that can help developers narrow down the issue? (e.g. logs, screenshots,
configuration files, savefiles, savestates)

I do have savestates but they exceed the maximum file upload size, even when 7z-compressed. If you would like them, just let me know where you'd like me to upload them.

I also made this video demonstrating the behavior, teaching how to reproduce it, and explaining exactly what is going on in the game: [[https://youtu.be/g8IOuVOL-oU]]


Files

WiiAddressResolution.PNG (70.3 KB) WiiAddressResolution.PNG Rylie, 07/06/2021 03:52 PM
gc-unaligned.zip (456 KB) gc-unaligned.zip Standalone hwtest gamecube phire, 07/24/2021 12:42 AM
gc-unaligned-passed.png (1.68 KB) gc-unaligned-passed.png Results of running on a real gamecube phire, 07/24/2021 12:43 AM
DolphinCreditsWarp.PNG (353 KB) DolphinCreditsWarp.PNG Rylie, 07/27/2021 03:37 PM
Actions

Also available in: Atom PDF