MMC6

From NESdev Wiki
Revision as of 09:17, 13 June 2009 by Banshaku (talk | contribs)
Jump to navigationJump to search

The Nintendo MMC6 is a mapper ASIC used in Nintendo's NES-HKROM and HVC-HKROM Game Pak boards. This board, along with most common TxROM boards (which use the Nintendo MMC3) are assigned to iNES Mapper 004.

Overview

  • PRG ROM size: Up to 512 KB
  • PRG ROM bank size: 8 KB
  • PRG RAM: 1 KB (internal)
  • CHR capacity: Up to 256 KB ROM
  • CHR bank size: 1 KB and 2 KB
  • Nametable mirroring: Controlled by mapper
  • Subject to bus conflicts: No

Banks

  • CPU $7000-$7FFF: 1 KB PRG RAM, mirrored
  • CPU $8000-$9FFF (or $C000-$DFFF): 8 KB switchable PRG ROM bank
  • CPU $A000-$BFFF: 8 KB switchable PRG ROM bank
  • CPU $C000-$DFFF (or $8000-$9FFF): 8 KB PRG ROM bank, fixed to the second-last bank
  • CPU $E000-$FFFF: 8 KB PRG ROM bank, fixed to the last bank
  • PPU $0000-$07FF (or $1000-$17FF): 2 KB switchable CHR bank
  • PPU $0800-$0FFF (or $1800-$1FFF): 2 KB switchable CHR bank
  • PPU $1000-$13FF (or $0000-$03FF): 1 KB switchable CHR bank
  • PPU $1400-$17FF (or $0400-$07FF): 1 KB switchable CHR bank
  • PPU $1800-$1BFF (or $0800-$0BFF): 1 KB switchable CHR bank
  • PPU $1C00-$1FFF (or $0C00-$0FFF): 1 KB switchable CHR bank

Registers

The MMC6 has 4 pairs of registers at $8000-$9FFF, $A000-$BFFF, $C000-$DFFF, and $E000-$FFFF - even addresses ($8000, $8002, etc.) select the low register and odd addresses ($8001, $8003, etc.) select the high register in each pair.

Bank select ($8000-$9FFE, even)

7  bit  0
---- ----
CPMx xRRR
|||   |||
|||   +++- Specify which bank register to update on next write to Bank Data register
||+------- PRG RAM enable*
|+-------- PRG ROM bank configuration (0: $8000-$9FFF swappable, $C000-$DFFF fixed to second-last bank;
|                                      1: $C000-$DFFF swappable, $8000-$9FFF fixed to second-last bank)
+--------- CHR ROM bank configuration (0: two 2 KB banks at $0000-$0FFF, four 1 KB banks at $1000-$1FFF;
                                       1: four 1 KB banks at $0000-$0FFF, two 2 KB banks at $1000-$1FFF)

Once PRG RAM has been enabled by writing 1 to the specified bit above, it cannot be disabled without resetting the game.

Bank data ($8001-$9FFF, odd)

7  bit  0
---- ----
DDDD DDDD
|||| ||||
++++-++++- New bank value, based on last value written to Bank select register
           0: Select 2 KB CHR bank at PPU $0000-$07FF (or $1000-$17FF);
           1: Select 2 KB CHR bank at PPU $0800-$0FFF (or $1800-$1FFF);
           2: Select 1 KB CHR bank at PPU $1000-$13FF (or $0000-$03FF);
           3: Select 1 KB CHR bank at PPU $1400-$17FF (or $0400-$07FF);
           4: Select 1 KB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF);
           5: Select 1 KB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF);
           6: Select 8 KB PRG bank at $8000-$9FFF (or $C000-$DFFF);
           7: Select 8 KB PRG bank at $A000-$BFFF

Mirroring ($A000-$BFFE, even)

7  bit  0
---- ----
xxxx xxxM
        |
        +- Mirroring (0: vertical; 1: horizontal)

PRG RAM protect ($A001-$BFFF, odd)

7  bit  0
---- ----
HhLl xxxx
||||
|||+------ Enable writing to RAM at $7000-$71FF
||+------- Enable reading RAM at $7000-$71FF
|+-------- Enable writing to RAM at $7200-$73FF
+--------- Enable reading RAM at $7200-$73FF

IRQ latch ($C000-$DFFE, even)

7  bit  0
---- ----
DDDD DDDD
|||| ||||
++++-++++- IRQ latch value

This register specifies the IRQ counter reload value. When the IRQ counter is zero (or a reload is requested through $C001), this value will be copied into the MMC6 IRQ counter at the end of the current scanline.

IRQ reload ($C001-$DFFF, odd)

7  bit  0
---- ----
xxxx xxxx

Writing any value to this register requests that the MMC3 IRQ counter be reloaded at the end of the current scanline.

IRQ disable ($E000-$FFFE, even)

7  bit  0
---- ----
xxxx xxxx

Writing any value to this register will disable MMC3 interrupts AND acknowledge any pending interrupts.

IRQ enable ($E001-$FFFF, odd)

7  bit  0
---- ----
xxxx xxxx

Writing any value to this register will enable MMC3 interrupts.

Hardware

The MMC6 exists in a 64-pin TQFP package. At least two revisions exist, though only MMC6B has been observed.

The MMC6 scanline counter is based entirely on PPU A12, triggered on rising edges (after the line remains low for a sufficiently long period of time).

When the scanline counter is clocked, the value will first be checked. If it is zero, it will be reloaded from the IRQ latch ($C000); otherwise, it will decrement. If the old value in the counter is nonzero and new value is zero (whether from decrementing or reloading), an IRQ will be generated IF IRQ generation is enabled (by writing to $E001).

Important points:

  • The scanline counter cannot be stopped. It will continue to decrement and reload as long as PPU A12 on the PPU bus toggles.
  • There is no direct access to the counter! The best you can do is update the reload value and immediately request a reload.
  • Writing to $E000 will only prevent the MMC6 from generating IRQs - the counter will continue to run.
  • Writing to $E001 will simply allow the MMC6 to generate IRQs - the counter remains unaffected.
  • Writing to $C001 will cause the counter to be reloaded on the NEXT rising edge of PPU A12 instead of being decremented.
  • Writing to $C000 does not immediately affect the value within the counter - this value is only used when the counter is reloaded, whether from reaching 0 or from writing to $C001.
  • Whenever the IRQ counter reaches $00, an IRQ will be generated (if enabled).
  • The exact number of scanlines between IRQs is N+1, where N is the value written to $C000. 1 to 256 scanlines are supported.
  • Writing $00 to $C000 will result in an IRQ being generated at every rising edge of PPU A12. Writing a non-zero value to $C000 will reload the counter the next time it is clocked.
  • The counter will not work properly unless you use different pattern tables for background and sprite data. The standard configuration is to use PPU $0000-$0FFF for background tiles and $1000-$1FFF for sprite tiles, whether 8x8 or 8x16.

Some versions of the Nintendo MMC3 have been observed to have IRQ counters which behave as above when inintialized to zero, while others behave differently, generating a single interrupt and remaining silent until reloaded with a nonzero value.