μMC1 - Tech docs
← Back to μMC1 general
This section contains technical information for developers and hardware enthusiasts.
The cartridge is composed of three basic components:
- A SST39SF040 512 KiB PLCC NOR FLASH IC, acting as PRG-ROM.
- A IS61C256 32 KiB SRAM IC, acting as CHR-RAM for the PPU.
- A SLG46824 Dialog GreenPAK, acting as a mapper IC.
Although the SRAM for CHR-RAM has 32 KiB space, only 8 KiB of the SRAM are exposed. The reason why 4-screen was not implemented is because this mode is not commonly supported in Famiclones, and was never commercially used in MMC1 or UNROM games.
The PRG-ROM supports a socket, but it only makes sense for development cartridges. As such, the FLASH can be optionally soldered straight to the PCB.
For CPU reads, the mapper divides the memory in two banks, just like UxROM and MMC1 in mode 3:
$BFFF: 16 KiB read+write switchable bank
$FFFF: 16 KiB read-only bank, fixed to last in ROM
$1FFF: 8 KiB fixed CHR-RAM
The lower bank is writable, and thus this allows self-writability to store the current progress, or to update the current running program during development.
Just like the MMC1, and unlike all other mappers, the registers are written bit by bit, LSB-first on D0 of the CPU. They are implemented by two shift registers with no buffering (ie changes apply immediately, not only when all bits have been written), and writes go to one or the other depending on the CPU address:
$DFFF: 2-bit mirroring control
$FFFF: 5-bit PRG bank selection
The mirroring is controlled by a 2-bit shift register, which shifts the D0 bit of the CPU on any write from
The 2-bit mirroring control value to mode mapping is:
||Single screen A|
||Single screen B|
While it might look silly and arbitrary, it is not. These values have been carefully chosen to allow both easy porting of MMC1 games, and glitch-less swaping mid-render of single screen modes, without requiring the double buffering the MMC1 had.
; Sets vertical mirroring setvmirr: LDA #$01 STA $C000 STA $C000 RTS ; Sets horizontal mirroring sethmirr: LDA #$00 STA $C000 STA $C000 RTS ; Sets mirroring to single screen A setmirrscra: LDA #$01 STA $C000 ; LSR to make it zero LSR A STA $C000 RTS ; Swap single screen A with single screen B swapscratob: LDA #$01 STA $C000 RTS
The reason why single screen A is
01 and B is
10 should be evident by the code above: swapping one for the other requires feeding the shift register a single bit.
Any other 2-bit combination would’ve required to feed two bits for swapping single screen, and thus it would’ve caused visible glitches after feeding the first bit but before feeding the second.
PRG bank (
The PRG bank register is implemented by a 5-bit register, which is fed by the D0 during any writes to any address between
$FFFF. It allows addressing up to 512 KiB of FLASH memory.
For changing the bank, the code is pretty similar to that of the MMC1:
; Sets the current switchable bank ; Parameters: ; - A: desired bank setbank: STA $E000 LSR A STA $E000 LSR A STA $E000 LSR A STA $E000 LSR A STA $E000 RTS