Skip to content

Preserve AI FIFO addresses and RDRAM memory mapping in rollback states - #213

Merged
Jay-Day merged 2 commits into
Jay-Day:masterfrom
Ownasaurus:0f-fix-remix
Oct 9, 2026
Merged

Jay-Day merged 2 commits into
Jay-Day:masterfrom
Ownasaurus:0f-fix-remix

Conversation

@Ownasaurus

@Ownasaurus Ownasaurus commented Oct 9, 2026 •

Copy link
Copy Markdown

NOTE: These are really two separate fixes in one. This first writeup describes the first problem and fix. The next comment describes a similarly-related problem and fix.

Summary

This fixes a rollback-state serialization bug that could cause incorrect audio to play after a rollback, including Smash Remix unexpectedly playing the “INCREDIBLE!” announcer sound during boot.

Rollback savestates now preserve and restore both AI DMA FIFO addresses instead of reconstructing them from the current AI register state.

Underlying issue

The N64 Audio Interface maintains a two-entry DMA FIFO. Each entry contains several pieces of state:

  • RDRAM source address
  • Transfer length
  • Playback duration

The existing savestate format stored the FIFO lengths and durations, but did not store their corresponding RDRAM addresses.

When loading a savestate, both missing addresses were reconstructed using the current AI_DRAM_ADDR_REG value:

dev->ai.fifo[0].address = dev->ai.regs[AI_DRAM_ADDR_REG];
dev->ai.fifo[1].address = dev->ai.regs[AI_DRAM_ADDR_REG];

That register value is not necessarily the address associated with either saved FIFO entry. In particular, the second queued DMA may point somewhere different from the currently visible register value.

After a rollback, the emulator could therefore retain the saved transfer lengths and timing while reading audio data from the wrong location in RDRAM. This could produce a pop, unrelated PCM data, or—as observed with Smash Remix—a valid but completely unintended announcer sample.

This also explains several characteristics of the failure:

  • Only a peer that actually rolled back would restore the damaged FIFO state.
  • Different peers could hear different audio despite running the same game.
  • A .krec replay would not necessarily reproduce it because ordinary playback does not recreate the same network rollback and savestate-load sequence.
  • The symptom could appear correlated with held inputs or 0-frame delay because those conditions affect rollback timing, without the input itself directly enabling the sound.

Fix

Rollback savestates now store an additional eight bytes:

  • AI FIFO entry 0 RDRAM address: 4 bytes
  • AI FIFO entry 1 RDRAM address: 4 bytes

When restoring a new rollback savestate, both addresses are copied back into their original FIFO entries. This keeps each FIFO entry’s address, length, and duration synchronized across rollback.

A new rollback-state header flag indicates that the saved state contains these addresses.

@Ownasaurus

Copy link
Copy Markdown
Author

Synchronize RDRAM memory mapping after rollback

Underlying issue

Mupen uses memory handlers to determine how reads and writes to each emulated N64 address range should behave.

During boot, the N64 IPL configures the RDRAM chips through their mode registers. Certain configurations cause Mupen to install a special corrupted-RDRAM read handler. The core tracks the currently installed handler separately from the RDRAM register values.

During normal execution, writing an RDRAM mode register updates both:

  • The emulated register value
  • The emulator’s RDRAM memory-handler mapping

Savestate loading restores the registers through direct assignment, bypassing the normal register-write side effects. A rollback could therefore produce an inconsistent state:

Restored RDRAM registers: state from the rollback frame
Installed memory handler: state from the discarded future timeline

This is particularly relevant during early boot, while the IPL is configuring RDRAM. A stale handler could make memory reads behave differently from what the restored registers specify, potentially causing incorrect execution or a black-screen startup stall.

Fix

After all RDRAM registers have been restored, rollback loading now recalculates the required memory mapping from those registers.

If the calculated state differs from the currently installed handler, the correct normal or corrupted-RDRAM handler is installed.

The same synchronization function is also used by normal RDRAM mode-register writes, ensuring that both paths derive the mapping consistently.

Implementation approach

The memory-handler selection is reconstructed rather than serialized because it is derived emulator bookkeeping, not independent N64 hardware state.

This ensures:

  • The installed handler always agrees with the restored RDRAM registers.
  • No pointers or emulator-internal mapping structures are stored in rollback states.
  • No additional bytes are added to rollback-state buffers.
  • The relatively expensive remapping operation runs only when the required handler has changed.

@Ownasaurus Ownasaurus changed the title Preserve AI FIFO addresses in rollback states Preserve AI FIFO addresses and RDRAM memory mapping in rollback states Oct 9, 2026
@Jay-Day
Jay-Day merged commit 316c7c1 into Jay-Day:master Oct 9, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants