Skip to content

Add support for mapper 9 (MMC2)#559

Merged
bfirsh merged 1 commit intomainfrom
bfirsh/add-mapper-9
Feb 15, 2026
Merged

Add support for mapper 9 (MMC2)#559
bfirsh merged 1 commit intomainfrom
bfirsh/add-mapper-9

Conversation

@bfirsh
Copy link
Owner

@bfirsh bfirsh commented Feb 15, 2026

Summary

  • Adds mapper 9 (MMC2), used exclusively by Mike Tyson's Punch-Out!! and Punch-Out!!
  • Implements tile-triggered CHR bank switching with two independent 4KB latches that swap banks when the PPU fetches specific pattern table addresses ($FD/$FE tiles)
  • Integrates latch monitoring into the PPU rendering pipeline (BG tile fetches, sprite pattern fetches, and unused sprite slot dummy fetches) to match real hardware behavior

Implementation details

Mapper (src/mappers/mapper9.js):

  • PRG: 8KB switchable at $8000, three fixed 8KB banks at $A000-$FFFF
  • CHR: two latches (latch0 for $0000-$0FFF, latch1 for $1000-$1FFF) each selecting between two 4KB banks based on $FD/$FE state
  • Mirroring control, save state serialization

PPU changes (src/ppu/index.js):

  • renderBgScanline: calls latchAccess() after each BG tile fetch with the computed pattern table high-byte address
  • renderSpritesPartially: calls latchAccess() for each sprite's pattern table fetch (both 8x8 and 8x16)
  • Simulates unused sprite slot dummy fetches (tile $FF in 8x16 mode → address $1FE8 resets latch 1 to $FE between scanlines)
  • _inRendering guard prevents recursion when latch bank switches trigger triggerRendering()

All latch access calls are no-ops for non-MMC2 mappers (base class latchAccess is empty). Benchmark shows ~1% overhead (1778 fps vs ~1800 baseline).

Fixes #430

Test plan

  • All existing tests pass (445 pass, 0 fail, 40 skipped)
  • Benchmark shows minimal performance impact (~1778 fps)
  • Manual testing with Mike Tyson's Punch-Out!! ROM — some minor sprite corruption in crowd remains

🤖 Generated with Claude Code

MMC2 is used exclusively by Mike Tyson's Punch-Out!! and features
tile-triggered CHR bank switching with two independent 4KB latches.

The PPU rendering pipeline now calls latchAccess() during BG and sprite
tile fetches so the mapper can monitor pattern table addresses, matching
real hardware behavior. Unused sprite slot dummy fetches (tile $FF in
8x16 mode) are simulated to correctly reset latch 1 between scanlines.

Fixes #430

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bfirsh bfirsh merged commit 31c99dc into main Feb 15, 2026
5 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.

Mike Tyson’s Punch Out MMC2(9) mapper support

1 participant