Nintendo Power Game Boy Memory cartridge documentation
Here I document as much as I know about the white NP GB Memory flash cartridges that were available in Japan:
Game selection menu of cartridge containing three games. |
I used the information from here as a starting point for my investigation:
https://github.com/sanni/cartreader/blob/master/Cart_Reader/GBM.ino
I don't know where they got their information from, though.
I also found a datasheet for a flash that has a command set that looks similar to the commands used by the flash in
the cartridge:
http://support.technologicalarts.ca/docs/Components/Am29F400.pdf
Please report any errors I made here:
https://github.com/msinger/gbreveng/issues
Also, I would be happy if you have any additional information. Just create an issue or a discussion in this repository.
Of course, feel free to ask questions there if anything is unclear, maybe I can answer.
If you need the schematics or a replacement PCB, RWeick has made a KiCad project for that here.
I noticed the MBC6 game Net de Get - Mini-Game@100 has a flash chip with very similar part number. The Nintendo Power cartridges have 29F008ATC, Net de Get has 29F008TC. I tested the flash chip in Net de Get and I couldn't find any difference to the NP flash chips that I documented here. They have the same erase sector size and even the same 256 byte hidden region. I don't know if this region was used in Net de Get, because I only have cartridges with empty flashes. The part of this documentation about the flash can also be used for Net de Get. For a documentation about the MBC6 chip, I'd recommend Pan Docs.
- Overview
- MMC commands
- MMC registers
- Map layout
- Map entry format
- Flash commands
- MMC power up and reset behavior
- Pseudocode procedures for Nintendo Power cartridges
- Pseudocode procedures for Net de Get (MBC6) cartridges
- MMC chip pinout
- Flash chip pinout
- Calculating output address from input address
- Random stuff
Overview
For an explanation of what this cartridge is, please read the Wikipedia article. This article states that the cartridge is partitioned into 8 flash blocks and 16 RAM blocks. This partitioning is purely artificial, though. It is only implemented by the menu. The hardware allows a more fine-grained partitioning of the two memory chips. The mapping definitions for the flash are actually quantized in 32 KiB steps. So you could partition the 1 MiB flash into 32x32 KiB blocks. You would have to implement a game selection menu software that fits into one of those 32 KiB blocks, since the original menu requires 128 KiB and only supports up to seven game entries.
The MegaChips MX15002 chip on the cartridge PCB is labeled "G-MMC1". I don't know what this stands for, but for the sake of a short name, I will just call this chip "MMC" in this documentation. The MMC chip is able to emulate different MBC chip versions.
The flash chip not only stores 1 MiB of data, it also contains a much smaller hidden sector that stores an additional 256 bytes. We call this hidden sector the "map", because it is used to store the memory mapping configuration that gets read by the MMC chip to configure itself.
If you build your own hardware for reading the NP GB Memory cartridge, you must take care that the /WR signal is high during power up. Otherwise, the MMC chip is in some kind of lockdown. When in lockdown, you can only access the first 32 KiB of the flash and the MMC chip doesn't react to any commands. I don't know if this is some kind of protection or if it is an unintentional bug. I haven't found a way to exit this lockdown mode, other than power cycling the cartridge with the /WR pin held high. The /RST signal doesn't fix this state.
The following image roughly shows the topology of the cartridge:
There are three "entities" you can send commands to or access registers of: The MMC, the emulated MBC and the flash. In order to send commands to the flash, you need to be able to control A0-A14 of the flash. A14 is controlled by the emulated MBC, though. Before issuing a command to the flash, you first have to select an odd bank in the MBC, so that A14 actually goes high when you access the address range 0x4000-0x7fff.
Just to be clear: In this entire document, when I talk about "writing to the flash", I mean the memory bus access itself, which is just a way of communicating with the flash chip. No non-volatile storage elements within the flash chip are meant to be changed when using the term "write". When I use the terms "programming" and "erasing", that's when the actual flash content is modified.
MMC commands
Commands sent to the MMC chip have the following structure:
- Command ID is written to address 0x0120.
- Some commands require arguments, which are written to addresses 0x0121-0x0127.
- Command is terminated by writing 0xa5 to address 0x013f.
Take note, that if an MBC chip is being emulated and if MBC registers are enabled, issuing MMC commands will always cause the RAM access to be disabled, because MMC commands are written to addresses 0x0120-0x013f, which triggers MBC register 0x0000.
The following table contains all known MMC commands:
Command ID | Sequence (ADR <‑ DATA) | Description |
---|---|---|
0x02 | 0x0120 <‑ 0x02 0x013f <‑ 0xa5 |
Disable flash write protection Disables the flash write protection. For this command to have an effect, bit 0 of MMC register 0x0121 needs to be set. MMC command 0x0a can be used to set bit 0 of register 0x0121. The MMC has one of its outputs connected to a WP (write protect) input of the flash. This command (and its counterpart 0x03) control the state of this WP signal. MMC's FLASH_WP pin and bit 1 of MMC register 0x0121 will go high when the write protection is disabled. |
0x03 | 0x0120 <‑ 0x03 0x013f <‑ 0xa5 |
Enable flash write protection Enables the flash write protection. For this command to have an effect, bit 0 of MMC register 0x0121 needs to be set. MMC command 0x0a can be used to set bit 0 of register 0x0121. The MMC has one of its outputs connected to a WP (write protect) input of the flash. This command (and its counterpart 0x02) control the state of this WP signal. MMC's FLASH_WP pin and bit 1 of MMC register 0x0121 will go low when the write protection is enabled. If the flash write protection is enabled, flash sector 0 and the hidden map region can't be erased or programmed. Also, the state of the sector 0 protection can't be changed, if the flash write protection is enabled. Flash sectors 1-7 can always be erased and programmed, even if the flash write protection is enabled. |
0x04 | 0x0120 <‑ 0x04 0x013f <‑ 0xa5 |
Disable memory mapping Disables the memory mapping and allows you to access the entire flash and RAM within the cartridge. An MBC will be emulated that behaves like the MBC5, except that it doesn't allow you to switch the banked ROM area (0x4000-0x7fff) to ROM bank 0, like an MBC5 chip would allow you to do. In this file, they talk about "MBC4". I don't know where they have this information from and if it is true. I find it unlikely, because MBC4 chips don't exist in real life. If you have seen one, please tell me. MBC registers will be reset to their defaults (ROM bank 1 is selected, RAM bank 0 is selected, RAM access is disabled). The previous content of the MBC registers is backed up. Whether MBC registers are enabled is not changed by this command. Command 0x05 can be used to re-enable/restore the memory mapping and to restore the backed up content of the MBC registers. Commands 0x80-0xbf or 0xc0-0xff can be used to re-enable the memory mapping using a different mapping configuration than before. |
0x05 | 0x0120 <‑ 0x05 0x013f <‑ 0xa5 |
Enable memory mapping Enables the memory mapping that was active before disabling it with command 0x04. Bits 2-7 of MMC register 0x0121 store the index of the selected mapping entry. This index is used to restore the mapping. The content of the MBC registers is restored with backed up values from the last time the command 0x04 was called. If command 0x04 was never called before, then the MBC registers are zeroed: ROM and RAM bank 0 is selected, and RAM access is disabled. Unlike commands 0x80-0xbf or 0xc0-0xff, this command (0x05) doesn't disable MMC registers and commands after restoring the mapping, nor does it enable MBC registers. |
0x08 | 0x0120 <‑ 0x08 0x013f <‑ 0xa5 |
Disable MMC registers and commands Disables the MMC registers and commands that you can access through addresses 0x0120-0x013f. You need to disable MMC registers to be able to see the flash content at addresses 0x0120-0x013f. Also, if you are writing the flash, you need to disable MMC commands to be able to write to flash addresses 0x0120-0x013f. While MMC commands are enabled, write access to this address range will not go through to the flash. However, if MBC emulation is active, writing to this address range will always trigger a write event to MBC register 0x0000, no matter if MMC commands are enabled or not. Writing to MBC register 0x0000 disables RAM access (except if 0x0a is written, of course). On power up, MMC registers and commands are disabled. |
0x09 | 0x0120 <‑ 0x09 0x0121 <‑ 0xaa 0x0122 <‑ 0x55 0x013f <‑ 0xa5 |
Enable MMC registers and commands Enables the MMC registers and commands that you can access through addresses 0x0120-0x013f. This is the only command that the MMC reacts to while MMC commands are disabled. On power up, MMC registers and commands are disabled, so you have to send this command (0x09) first, before any other MMC commands can be used. When this command is being written while MMC commands are disabled, all writes will still go through to the flash. This is normally not an issue, because the flash is normally read-only. You have to be aware of this though, when you try to program the flash, it will taint the write buffer at addresses 0xXX20, 0xXX21, 0xXX22 and 0xXX3f. (For more information about that, read further below.) |
0x0a | 0x0120 <‑ 0x0a 0x0125 <‑ 0x62 0x0126 <‑ 0x04 0x013f <‑ 0xa5 |
Unlock changing flash write protection This command sets bit 0 of the MMC register 0x0121. The bit gets cleared when MMC command 0x08 is sent. The bit must be set in order for MMC commands 0x02 and 0x03 to have an effect. |
0x0f | 0x0120 <‑ 0x0f 0x0125 <‑ <ADR_H> 0x0126 <‑ <ADR_L> 0x0127 <‑ <DATA> 0x013f <‑ 0xa5 |
Perform write access on flash Triggers the MMC to perform a write memory access on the flash with address <ADR_H><ADR_L> and data <DATA>. Normally when MBC registers are enabled, regular write accesses to addresses 0x0000-0x7fff, which are not performed by command 0x0f, will not go through to the flash. This command can be used to bypass MBC registers, even when they are enabled. The higher address lines are still controlled by the emulated MBC. The ROM offset configured by the current memory mapping is applied the same way, as if you write to the flash directly. Also, the bank number is applied the same way if you use this command to write to address range 0x4000-0x7fff. This command is bugged, though: You can't use it to write to the MMC command address range 0x0120-0x013f. When you try, the address applied to the flash will be 0x000XX, where XX is <ADR_L>, and the chip enable signal is suppressed. If you write to address range 0x8000-0xffff, it behaves the same way; the output address is 0x000XX and chip enable is suppressed. In both of these cases, the write signal gets asserted normally, but it has no effect due to the missing chip enable. The host system (Game Boy) must not issue any memory access to the cartridge or work RAM directly after this command, otherwise the data on the bus will get scrambled. It has to wait for at least one cycle, better two to make sure, since the oscillator the MMC uses is not synced with the Game Boy clock. |
0x10 | 0x0120 <‑ 0x10 0x013f <‑ 0xa5 |
Disable MBC registers Disables access to MBC registers. MBC registers need to be disabled when you want to write to the flash chip. If you don't disable MBC registers, then you may accidentally switch the memory banks and the writes will be intercepted by the MBC registers and never reach the flash. Even if no MBC emulation is enabled in the current memory mapping, write access to the flash is blocked when MBC registers are enabled. Disabling MBC registers does not disable the MBC's function and its control over the higher address lines. Their content just can't be changed anymore. Alternatively, you can use the MMC command 0x0f to bypass the MBC registers without disabling them. |
0x11 | 0x0120 <‑ 0x11 0x013f <‑ 0xa5 |
Enable MBC registers Enables access to MBC registers. When MBC registers are enabled, write access to the flash is blocked. This is even the case when the current memory mapping has no MBC selected. |
0x80-0xbf | 0x0120 <‑ 0x80|<IDX> 0x013f <‑ 0xa5 |
Switch memory mapping while resetting host Switches to memory mapping entry <IDX> while the host (Game Boy) gets reset. <IDX> can be in the range 0-63; it is given in the lower six bits of the command ID itself, not as an argument. The host reset gets pulled low directly after this command was issued. Normally when the host reset gets pulled low by external means, the MMC sends a reset command to the flash directly after the falling edge; however, when the MMC itself causes this falling edge, it ignores it and doesn't send this reset command. The host reset is held low (asserted) for about 900 µs before the MMC starts reading the mapping entry from the flash chip. Reading the entry takes about 22 µs. These are the read and write accesses the MMC performs on the flash chip: host_reset_out(0); /* Assert reset on Game Boy. */ usleep(900); /* Wait ~900 µs. */ write(0x07fff, 0xf0); /* Flash reset command. */ write(0x05555, 0xaa); /* Read map command sequence (1/6). */ write(0x02aaa, 0x55); /* Read map command sequence (2/6). */ write(0x05555, 0x77); /* Read map command sequence (3/6). */ write(0x05555, 0xaa); /* Read map command sequence (4/6). */ write(0x02aaa, 0x55); /* Read map command sequence (5/6). */ write(0x05555, 0x77); /* Read map command sequence (6/6). */ var tmp = read(0x0007f); if (tmp != 0x00) { /* If map is invalid... */ write(0x07fff, 0xf0); /* Flash reset command. */ host_reset_out(1); /* Deassert reset on Game Boy. */ return { 0x00, 0x00, 0x00 }; } var byte0 = read(IDX * 3); if ((byte0 & 0xe0) == 0xc0 || (byte0 & 0xe0) == 0xe0) { /* If MBC type is invalid... */ write(0x07fff, 0xf0); /* Flash reset command. */ host_reset_out(1); /* Deassert reset on Game Boy. */ return { 0x00, 0x00, 0x00 }; } var byte1 = read(IDX * 3 + 1); var byte2 = read(IDX * 3 + 2); write(0x07fff, 0xf0); /* Flash reset command. */ host_reset_out(1); /* Deassert reset on Game Boy. */ return { byte0, byte1, byte2 };This command is used by the Game Boy Color variant of the game selection menu. On Game Boy Color, the Game Boy always gets reset and runs the boot ROM when a game was selected in the menu. Read further below for an explanation about the format of the mapping entries stored in the map region. This command automatically enables memory mapping, disables MMC registers and commands, enables MBC registers, and resets MBC register contents to their defaults (ROM bank 1, RAM bank 0, RAM access disabled). |
0xc0-0xff | 0x0120 <‑ 0xc0|<IDX> 0x013f <‑ 0xa5 |
Switch memory mapping without host reset Switches to memory mapping entry <IDX> without resetting the host (Game Boy). <IDX> can be in the range 0-63; it is given in the lower six bits of the command ID itself, not as an argument. The mapping entry gets read from the flash chip directly after this command was issued. Reading the entry takes about 22 µs, so the host system must not issue any memory accesses to the cartridge or the work RAM during that time, otherwise the data on the bus will get scrambled. These are the read and write accesses the MMC performs on the flash chip: write(0x07fff, 0xf0); /* Flash reset command. */ write(0x05555, 0xaa); /* Read map command sequence (1/6). */ write(0x02aaa, 0x55); /* Read map command sequence (2/6). */ write(0x05555, 0x77); /* Read map command sequence (3/6). */ write(0x05555, 0xaa); /* Read map command sequence (4/6). */ write(0x02aaa, 0x55); /* Read map command sequence (5/6). */ write(0x05555, 0x77); /* Read map command sequence (6/6). */ var tmp = read(0x0007f); if (tmp != 0x00) { /* If map is invalid... */ write(0x07fff, 0xf0); /* Flash reset command. */ return { 0x00, 0x00, 0x00 }; } var byte0 = read(IDX * 3); if ((byte0 & 0xe0) == 0xc0 || (byte0 & 0xe0) == 0xe0) { /* If MBC type is invalid... */ write(0x07fff, 0xf0); /* Flash reset command. */ return { 0x00, 0x00, 0x00 }; } var byte1 = read(IDX * 3 + 1); var byte2 = read(IDX * 3 + 2); write(0x07fff, 0xf0); /* Flash reset command. */ return { byte0, byte1, byte2 };This command is used by the DMG variant of the game selection menu. On monochrome Game Boys, the Game Boy never gets reset when a game is selected in the menu. Read further below for an explanation about the format of the mapping entries stored in the map region. This command automatically enables memory mapping, disables MMC registers and commands, enables MBC registers, and resets MBC register contents to their defaults (ROM bank 1, RAM bank 0, RAM access disabled). |
MMC registers
While MMC registers are enabled (see MMC command 0x09), the MMC registers can be read in address range 0x0120-0x013f. All MMC registers are read-only. The following table describes all the MMC registers:
Address | Description |
---|---|
0x0120 | Always reads as 0x21. |
0x0121 | Mapping entry index and flash write protection status
|
0x0122-0x0124 | Memory mapping configuration Three bytes read from the currently selected memory mapping entry. Read the map entry format description below for more information about its format. On power up, these registers are filled with the three bytes read from address 0x00-0x02 (mapping entry index 0) of the map region. If the mapping entry is invalid, or if the entire map region is invalid (because it is missing the zero byte at the end, see below), then these registers are 0x00 0x00 0x00. When MMC command 0x04 is called, these registers read 0x9a 0x80 0x00, which is a mapping that makes all flash and RAM accessible. MMC command 0x04 does not overwrite the contents of these registers, the values 0x9a 0x80 0x00 are just overlaid. Issuing MMC command 0x05 will show the previous mapping entry again, even if command 0x04 was issued more than once. This behavior is different from the MBC register backups. The MBC register backups are overwritten each time command 0x04 is issued. |
0x0125 | Always reads as 0x87. |
0x0126 | Always reads as 0x78. |
0x0127 | Always reads as 0x5a. |
0x0128-0x013e | Always read as 0x00. |
0x013f | Always reads as 0xa5. |
Map layout
The map is located in a hidden region of the flash. For information how to access it, see flash command 0x77 0x77 further below. The map region is 256 bytes in size. When the map is made visible, it is mapped to all addresses dividable by 256 across the whole address space. For example, it starts at address 0x0000, address 0x0100, 0x0200, ...
This is an example map of a cartridge containing three games (Kirby no Kirakira Kids, Yoshi no Cookie and Momotarou Densetsu Jr.):
00000000 a8 00 00 2d 04 00 28 0c 04 31 10 04 ff ff ff ff |...-..(..1......| 00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000030 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000060 ff ff ff ff ff ff ff ff ff ff ff ff ff ff 0d 00 |................| 00000070 30 19 99 10 30 12 37 17 ff ff ff ff ff ff 00 00 |0...0.7.........| 00000080 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000090 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000b0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000d0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000e0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
The red, green, blue and magenta bytes are mapping entries. The red one (entry #0) is for the menu. The green, blue and magenta ones (entries #1, #2 and #3) are for the three games. Entry #0 is automatically loaded during power up, so it must be the menu. Each entry is three bytes. The yellow bytes are similar, but not equal, on each cartridge. I don't know what it contains, but it is not relevant for the hardware and the menu. From a hardware perspective, the yellow bytes will be interpreted as mapping entries number ~36 to ~42, when commands 0xe4-0xea were used to switch to those mappings. The menu only uses entries 1-7 (commands 0xc1-0xc7), though. The byte at address 0x7f with the gray background must be set to 0x00. If it is not zero, then the MMC will ignore the mapping region completely and will treat it as if each byte in the mapping region was 0xff.
On cartridges that contain a 1 MiB game, they store additional information in the map region. Here is an example from Super Mario Bros. Deluxe:
00000000 b5 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000010 ff ff ff ff ff ff ff ff 08 00 40 00 43 47 42 20 |..........@.CGB | 00000020 2d 41 48 59 4a 2d 20 20 82 4f 82 57 82 60 83 58 |-AHYJ- .O.W.`.X| 00000030 81 5b 83 70 81 5b 83 7d 83 8a 83 49 83 75 83 89 |.[.p.[.}...I.u..| 00000040 83 55 81 5b 83 59 83 66 83 89 83 62 83 4e 83 58 |.U.[.Y.f...b.N.X| 00000050 20 20 20 20 30 31 2f 30 31 2f 32 30 30 31 31 39 | 01/01/200119| 00000060 3a 32 37 3a 33 36 4c 41 57 30 37 30 38 35 01 00 |:27:36LAW07085..| 00000070 30 1e 00 03 31 08 42 37 ff ff ff ff ff ff 00 00 |0...1.B7........| 00000080 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000090 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000b0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000d0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000e0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
The red bytes contain the mapping entry for the game. Since all space is used up for the game itself, this cartridge doesn't have a menu. The green bytes contain information about the game. Like the yellow ones, these are not relevant for the hardware. The MMC would interpret them as mapping entries.
Functionally, the following map would be exactly the same as the previous one:
00000000 b5 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000030 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000060 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000070 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 |................| 00000080 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000090 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000b0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000d0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000e0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 000000f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
My guess is that these green and yellow bytes are just read by the Kiosk devices that were used to program the cartridges. What can be seen in the green area is the ROM identifier (CGB -AHYJ- in this example), a date and time (probably time of purchase of the game), and other data. Maybe transaction ID or something. The yellow area could be a cartridge serial number, maybe. Again, none of it is relevant.
In short, the map looks like this: Map entry n, where 0 ≤ n ≤ 63, starts at address n * 3. Byte at address 0x7f must be 0x00. Map entry #42 is not fully usable, because it overlaps with the byte at address 0x7f. So, if you want to use entry #42, you have to use a mapping that works with its middle byte being 0x00.
Map entry format
Each entry is three bytes in size. It is divided into five fields:
Byte 0 | Byte 1 | Byte 2 | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
MBC type | ROM size | RAM size | - | ROM offset in 32 KiB steps | - | RAM offset in 2 KiB steps |
Byte #1 bit #6 and byte #2 bits #6 are ignored and can have any value.
MBC type can be one of the following:
Value | Description |
---|---|
0 | No MBC A cartridge without any MBC chip is emulated. Writing to MBC registers has no effect, memory banks can't be changed. |
1 | MBC1 A cartridge with MBC1 chip is emulated. The emulated MBC1 chip does not allow to map address range 0x0000-0x3fff to another bank in mode 1. |
2 | MBC2 A cartridge with MBC2 chip is emulated. This emulated version of the MBC2 chip allows reading and writing of full bytes in RAM. A "real" MBC2 chip only has the lower four data lines connected and stores only half-bytes in each RAM location. It is possible to have 8 KiB of RAM with this emulated version. Even more RAM could be selected, but MBC2 doesn't have registers for RAM bank switching, so more than 8 KiB is not accessible. |
3 | MBC3 A cartridge with MBC3 chip is emulated. The RTC registers of the emulated MBC3 chip do nothing and are undefined when read. |
4 | MBC5-ish A cartridge with MBC5-ish chip is emulated. "-ish", because in contrast to MBC5, this MBC doesn't allow you to select ROM bank 0 on address range 0x4000-0x7fff. Another difference between this and MBC5 is, when you enable RAM access by writing 0x0a to register 0x0000, this MBC5-ish MBC ignores bits 4-7, so you can write 0xfa instead. MBC5 requires bits 4-7 to be 0. This setting is used when the MMC command 0x04 is called. I have never seen this in the map region of any cartridge. Use value 5, if you want an MBC5 chip. |
5 | MBC5 A cartridge with MBC5 chip is emulated. |
6, 7 | Invalid entry Invalidates the mapping entry and causes the MMC to load a null entry (00 00 00) instead. So, basically it emulates a cartridge without MBC chip and ignores all the other fields of the entry, setting them to 0: 32 KiB ROM, no RAM, no offsets. |
ROM size can be one of the following:
Value | Description |
---|---|
0 | 32 KiB ROM |
1 | 64 KiB ROM |
2 | 128 KiB ROM |
3 | 256 KiB ROM |
4 | 512 KiB ROM |
5 | 1 MiB ROM |
6 | 1 MiB ROM This setting is used when the MMC command 0x04 is called. I have never seen this in the map region of any cartridge. Use value 5, if you want 1 MiB ROM size. I think that they had initially intended to support 2 MiB flash chips and this would have been the option for 2 MiB. I explain further below, in the paragraph about ROM offset. |
7 | 16 KiB ROM This maps the same 16 KiB block at address 0x0000-0x3fff and again at address 0x4000-0x7fff. I don't think this setting was ever used, since there is no game with less than 32 KiB ROM. |
RAM size can be one of the following:
Value | Description |
---|---|
0 | No RAM A cartridge without any RAM is emulated. Writing to addresses 0xa000-0xbfff has no effect, reading them is undefined. |
1 | 2 KiB RAM (or 512 bytes with MBC2) This maps the same 2 KiB block four times within the 8 KiB cartridge RAM address space, at addresses 0xa000, 0xa800, 0xb000 and 0xb800. When MBC2 is selected as MBC type, then it is 512 bytes repeated 16 times. |
2 | 8 KiB RAM |
3 | 32 KiB RAM |
4 | 64 KiB RAM |
5 | 128 KiB RAM |
6, 7 | No RAM I have never seen this in the map region of any cartridge. Use value 0, if you don't want any RAM. |
ROM offset is given in 32 KiB steps. For example, an offset of 1 means that address 0x0000 from the Game Boy's perspective is mapped to address 0x8000 of the flash (which is 1 times 32768). Keep in mind, the cartridges that got programmed by the official Kiosks are partitioned in 128 KiB blocks, so they will have offsets of 0, 4, 8, 12, etc. (The lower two bits are 0.) The mapping wraps around at the end of the flash. For example, if ROM offset is set to 1 and the ROM size is set to value 5 (1 MiB), then ROM banks 62 and 63, which would be outside the 1 MiB range after applying the offset, are actually mapped to flash addresses 0x0000 and 0x4000. Of course, such wrapped around mappings are not done by the official Kiosks.
You may have noticed that the ROM offset has six bits; and that 2^6 times 32 KiB is 2 MiB. I suspect that they had initially planned to support 2 MiB flash chips, but then decided to limit it to 1 MiB. This is the reason I come to this conclusion: When you create the mapping bf ff ff and switch to it, then what gets actually loaded into the MMC registers 0x122-0x124 is bf bf 3f. Bit #6 in the middle byte is cleared, and bits #6 and #7 are cleared in the last byte. Bit #5 of the middle byte gets transferred to the registers, even though it is completely useless if the flash is only 1 MiB. Also, there are two ROM size options for 1 MiB. I think they initially used the second one to select 2 MiB ROM size, and the bit #5 of the ROM offset was needed to be able to define offsets across the whole 2 MiB flash. Later they may have scrapped this and those are two leftovers.
RAM offset is given in 2 KiB steps. It works the same way as the ROM offset, just with a smaller step size, and it wraps around at 128 KiB.
Flash commands
Except for the reset command, commands sent to the flash chip have the following structure:
- 0xaa is written to address 0x5555.
- 0x55 is written to address 0x2aaa.
- Command ID is written to address 0x5555.
Most commands consist of two command IDs. For those commands, steps 1-3 are repeated. Only address lines A0-A14 are relevant for commands. Address lines A15 and higher are ignored. There is an exception to this: The erase flash sector command (0x80; 0x30). To erase a sector, the second command ID (0x30) needs to be written to an address that lies within that sector, instead of address 0x5555.
For these commands to work properly when an MBC chip is emulated, you need to select an odd ROM bank first. Otherwise, A14 won't be high when writing to address 0x5555. Also, you have to disable MBC registers using the MMC command 0x10. If MBC registers are enabled, then write accesses won't go through to the flash.
The following table contains all known flash commands:
Command ID(s) | Sequence (ADR <‑ DATA) | Description |
---|---|---|
0xf0 | 0xXXXX <‑ 0xf0 |
Reset Can be written to any address. Used to exit from read ID (0x90) and read map (0x77; 0x77) commands. Also used to exit from any commands that provide status bits to communicate the completion of the operation, like program and erase commands. (Yes, I have just listed all known flash commands. So in short: The reset command is used to exit all the other commands.) After issuing a reset command, you will be able to read the array data (the contents stored in the flash) again. It may be good practice to always issue a second reset command to the same address, if the chip is in an unknown state. This safely exits the program flash command (0xa0) or the program map command (0x60; 0xe0) without triggering the program operation. |
0x90 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x90 |
Read ID After issuing this command, the array data (flash contents) can't be read anymore. Instead, you will be able to read the manufacturer and device ID. The following four bytes are read across the whole address space repeatedly: 0xXXX0 ‑> 0xc2 (manufacturer ID: Macronix) 0xXXX1 ‑> 0x89, if device ID is 29F008ATC (NP GB Mem); 0x81, if device ID is 29F008TC (Net de Get) 0xXXX2 ‑> 0xc2, if read from sector 0; 0x00, if read from sectors 1-7 0xXXX3 ‑> 0xffUse the reset command (0xf0) to exit this mode. Source: I found a file listing 0xc2 as the ID for Macronix, the vendor of this flash chip. So we know that the 0xc2 is the manufacturer ID and the 0x89 must be the device ID for this specific chip. You can also google for any datasheet of Macronix chips listed in this file. They all document 0xc2 as Macronix' ID. |
0xa0 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0xa0 |
Program flash Programs 128 bytes of flash memory at any 128 byte aligned address. See further below for an explanation on how to transfer the 128 bytes for the programming operation. The programming operation can only change bits from 1 to 0. Use the mass erase flash command (0x80; 0x10) or the erase flash sector command (0x80; 0x30) first to change bits back to 1. Flash sector 0 can only be programmed if the flash write protection is disabled and if the sector 0 protection is removed (see command 0x60; 0x40). The status of the operation can be read from the flash chip. See below for a description of the status bits. Use the reset command (0xf0) to exit this operation after status bit 7 went high. The reset command has no effect while the operation is still in progress. |
0x60; 0x04 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x60 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x04 |
Erase map Erases the hidden 256 byte map region. The status of the operation can be read from the flash chip. See below for a description of the status bits. Use the reset command (0xf0) to exit this operation after status bit 7 went high. The reset command has no effect while the operation is still in progress. This command sequence is ignored if the flash write protection is enabled. When ignored, no status stage is entered afterward. |
0x60; 0x20 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x60 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0xXXXX <‑ 0x20 |
Protect sector 0 Restores the erase and program protection of sector 0. If sector 0 is protected, it can't be erased or programmed, and status bit 1 is permanently high. The mass erase flash command (0x80; 0x10) will still erase sectors 1-7, if the protection of sector 0 is enabled. The last byte of this command sequence must be written to any address within sector 0. The status of the operation can be read from the flash chip. See below for a description of the status bits. Use the reset command (0xf0) to exit this operation after status bit 7 went high. The reset command has no effect while the operation is still in progress. This command sequence is ignored if the flash write protection is enabled. When ignored, no status stage is entered afterward. |
0x60; 0x40 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x60 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0xXXXX <‑ 0x40 |
Unprotect sector 0 Normally, sector 0 of Nintendo Power GB Memory cartridges is protected. It needs to be unprotected by this command before it can be erased or programmed. Once sector 0 is unprotected, it will stay unprotected, even after power cycling the cartridge. Use the protect sector 0 command (0x60; 0x20) to re-enabling the protection of sector 0. If sector 0 is protected, status bit 1 is permanently high. The last byte of this command sequence must be written to any address within sector 0. The flash chips in Net de Get cartridges do not seem to have this protection enabled. I only own ones with empty flash, so maybe the protection would have been set when someone had downloaded some DLCs. The status of the operation can be read from the flash chip. See below for a description of the status bits. Use the reset command (0xf0) to exit this operation after status bit 7 went high, or directly issue an erase operation next. The reset command has no effect while the operation is still in progress. This command sequence is ignored if the flash write protection is enabled. When ignored, no status stage is entered afterward. |
0x60; 0xe0 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x60 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0xe0 |
Program map Programs 128 bytes of the the hidden map. See further below for an explanation on how to transfer the 128 bytes for the programming operation. The programming operation can only change bits from 1 to 0. Use the erase map command (0x60; 0x04) first to change bits back to 1. The status of the operation can be read from the flash chip. See below for a description of the status bits. Use the reset command (0xf0) to exit this operation after status bit 7 went high. The reset command has no effect while the operation is still in progress. This command sequence is ignored if the flash write protection is enabled. When ignored, no status stage is entered afterward. |
0x77; 0x77 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x77 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x77 |
Read map After issuing this command, the array data (flash contents) can't be read anymore. Instead, you will be able to read the hidden 256 byte map. Read the map layout section above for more information. Use the reset command (0xf0) to exit this mode. |
0x80; 0x10 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x80 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x10 |
Mass erase flash Erases the whole 1 MiB flash. The hidden 256 byte map region is preserved. Sector 0 will also be preserved, if the flash write protection or the sector 0 protection is enabled. Disable the flash write protection and use the unprotect sector 0 command (0x60; 0x40) before mass erasing the flash, if you want to erase sector 0 too. The status of the operation can be read from the flash chip. See below for a description of the status bits. Use the reset command (0xf0) to exit this operation after status bit 7 went high. The reset command has no effect while the operation is still in progress. |
0x80; 0x30 | 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 0x5555 <‑ 0x80 0x5555 <‑ 0xaa 0x2aaa <‑ 0x55 <ADR> <‑ 0x30 |
Erase flash sector Erases one flash sector selected by the address <ADR>. The flash is divided into eight individually erasable sectors, each 128 KiB. The last written byte in the sequence of this command must be written to an address within the sector that should be erased. This means for the last byte in the sequence, address lines A17-A19 contain the sector number 0-7; address lines A0-A16 are ignored. If you want to erase sector 0, make sure that you first disable the flash write protection and remove the sector 0 protection using the unprotect sector 0 command (0x60; 0x40). The status of the operation can be read from the flash chip. See below for a description of the status bits. Use the reset command (0xf0) to exit this operation after status bit 7 went high. The reset command has no effect while the operation is still in progress. |
Status bits of flash program/erase operations
During and after any program or erase operation, status bits can be read from the flash chip; the address being read doesn't matter. These are the status bits:
- Bit 7
- Low, while a program or erase operation is in progress. High, when the operation is complete, even if the operation failed. In case of program operations, it is also high when the actual operation hasn't been triggered yet by writing to the same buffer location twice. So, it can be seen as a ready bit.
- Bit 6
- undriven/undefined
- Bits 5-4
- driven/unknown; only seen as low
- Bits 3-2
- undriven/undefined
- Bit 1
- Low, if sector 0 is unprotected. High, if sector 0 is protected. If this bit is high, then sector 0 can't be erased or programmed. Sectors 1-7 can still be erased or programmed, even if this bit is high, so it doesn't really indicate an error.
- Bit 0
- undriven/undefined
Flash program operations
Programming the flash contents and programming the map works both in the same way. The only difference is the flash command you use to initiate the procedure. In both programming procedures, you have to write up to 128 bytes into a buffer in the flash chip and then trigger the actual programming. These are the steps to take:
- Issue the flash command: Either program flash (0xa0) or program map (0x60; 0xe0).
- After issuing the command, reading from the flash chip will return status bits instead of flash contents. There is no need to read the status bits now, but if you would read them, then status bit 7 will be set, which means that no operation is going on yet.
- The 128 byte buffer that you have to fill will be initialized with 0xff. So if you skip writing into this buffer and trigger the programming, then flash contents won't be changed, because the programming operation can only change bits from 1 to 0, not from 0 to 1.
- Write data to the buffer.
- The lower seven address lines (A6-A0) select the byte position inside the buffer that is being written to. The other address lines (A19-A7) will be ignored.
- You can write the bytes into the buffer in any order you want, but don't write to the same location twice in a row, because this will trigger the programming operation. Since the upper address lines are ignored, writing to address 0x0181 and then to 0x0201 would be considered the same location, and therefore trigger the programming. (0x0181 & 0x7f == 0x0001 and also 0x0201 & 0x7f == 0x0001) You can overwrite bytes that you have already written into the buffer if you want as long as you don't write to the same location consecutively without writing to another location in between.
- You don't have to write to all locations. If you just want to change one single byte in the flash, then just write that single byte.
- Trigger programming operation.
- Triggering the operation is done by writing to the same buffer location that you have written to last. For example, if you filled the buffer by writing to addresses 0x0000, 0x0001, 0x0002, ..., 0x007f in that order, then writing to address 0x007f again will trigger the operation. During this repeated write access to the same location, the data written doesn't matter (with one small exception). You can write 0x00, you can write 0xff, or whatever, it won't change the data in the buffer, as long as A6-A0 stay the same as in the previous write access. The small exception is: Writing 0xf0 will be interpreted as a reset command and abort the programming procedure.
- When writing the trigger, address lines A19-A7 determine the address to which the 128 buffer will be programmed to. For example, if you write to address 0x127f to trigger the operation, then the buffer will be programmed to address 0x1200, because 0x127f & ~0x7f == 0x1200.
- When programming the map, A19-A8 are also ignored when triggering the operation, because the map only consists of two 128 byte blocks. A7 selects which of the two halves of the map gets programmed.
- Wait for operation to complete.
- After triggering the operation, status bit 7 will be low until the operation completes.
Afterward, you can issue another flash command to write the next 128 bytes, or any other command, like the reset command (0xf0), to make the flash contents visible again.
MMC power up and reset behavior
On power up, the MMC reads mapping entry 0 from the flash. While doing that, it holds the Game Boy's reset signal low, so that the Game Boy CPU doesn't start running before the mapping entry got read. The reading process is actually triggered by the release of the reset signal at MMC's pin 55. These are the read and write accesses the MMC performs to read the mapping entry:
host_reset_out(0); /* Assert reset on Game Boy. */ usleep(910); /* Wait ~910 µs. */ write(0x07fff, 0xf0); /* Flash reset command. */ write(0x05555, 0xaa); /* Read map command sequence (1/6). */ write(0x02aaa, 0x55); /* Read map command sequence (2/6). */ write(0x05555, 0x77); /* Read map command sequence (3/6). */ write(0x05555, 0xaa); /* Read map command sequence (4/6). */ write(0x02aaa, 0x55); /* Read map command sequence (5/6). */ write(0x05555, 0x77); /* Read map command sequence (6/6). */ var unknown = read(0x00030); /* I don't know why it reads this address on power up. */ var tmp = read(0x0007f); if (tmp != 0x00) { /* If map is invalid... */ write(0x07fff, 0xf0); /* Flash reset command. */ host_reset_out(1); /* Deassert reset on Game Boy. */ return { 0x00, 0x00, 0x00 }; } var byte0 = read(0x00000); if ((byte0 & 0xe0) == 0xc0 || (byte0 & 0xe0) == 0xe0) { /* If MBC type is invalid... */ write(0x07fff, 0xf0); /* Flash reset command. */ host_reset_out(1); /* Deassert reset on Game Boy. */ return { 0x00, 0x00, 0x00 }; } var byte1 = read(0x00001); var byte2 = read(0x00002); write(0x07fff, 0xf0); /* Flash reset command. */ host_reset_out(1); /* Deassert reset on Game Boy. */ return { byte0, byte1, byte2 };
I don't know why it reads address 0x00030. The value at that location doesn't seem to affect anything. When issuing MMC commands 0x80-0xbf or 0xc0-0xff, a very similar sequence is run to read the mapping entry, but it is missing this particular read from address 0x00030.
If at any time after the power up sequence, the reset signal on the cartridge bus gets pulled low, the MMC chip reacts to the falling edge event with the following actions:
- Flash reset command (0xf0) gets written to the flash on address 0x07fff. The MMC doesn't pull the reset signal low while it issues the reset command to the flash, unlike it does on power up.
- MMC commands and registers get disabled.
- MBC registers get enabled and reset to their defaults.
- Memory mapping gets enabled. The mapping entry is not re-read from flash.
The currently selected mapping is not reset to index 0. This means, it doesn't switch back to the menu. Also worth mentioning is, the current state of the flash write protection is not changed during reset.
Pseudocode procedures for Nintendo Power cartridges
Writing to the flash can get very complicated, because the state of the MMC and the MBC will impact if and how write accesses reach the flash chip. To make things simpler, I provide a few procedures here that consider all three devices (MMC, MBC and flash) and provide explanation in comments.
In this pseudocode, I use read() and write() functions. Those depict memory accesses on the cartridge bus from the perspective of the Game Boy or your custom hardware.
/* Sends command to MMC chip. */ procedure mmc_command(command, [optional] address, [optional] data) { /* Write command ID. */ write(0x0120, command); /* Some commands require additional data. */ switch (command) { case 0x09: /* Command 0x09 needs an unlock sequence. */ write(0x0121, 0xaa); write(0x0122, 0x55); break; case 0x0a: /* Command 0x0a needs an unlock sequence. */ write(0x0125, 0x62); write(0x0126, 0x04); break; case 0x0f: /* Command 0x0f needs two arguments: address and data. */ write(0x0125, address >> 8); write(0x0126, address & 0xff); write(0x0127, data); break; } /* Write termination. */ write(0x013f, 0xa5); } /* Restores the state that the flash chip will have on power up. */ procedure reset_flash() { /* Enable MMC commands. */ mmc_command(0x09); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Issue reset command to flash. * We issue two reset commands to the same address in direct succession, * just in case the flash chip is currently receiving data into its write * buffer prior to a program operation. Two reset commands issued to the * same address will cause exiting from this mode without starting the * program operation. */ write(0x0000, 0xf0); write(0x0000, 0xf0); /* Wait for 100 milliseconds. * Due to my measurements, the longest program or erase operation takes around * 6 milliseconds, so 100 milliseconds will be on the safe side. */ sleep(0.1); /* We try resetting the flash a third time after 100 ms, just in case * there was a program or erase operation ongoing the first and second * time. Reset has no effect during such an operation. */ write(0x0000, 0xf0); } /* Restores the state that the cartridge will have on power up. */ procedure reset_cartridge() { /* Enable MMC commands. */ mmc_command(0x09); /* Enable flash write protection. */ mmc_command(0x0a); mmc_command(0x03); /* Make flash chip exit any special mode and make flash contents accessible. */ reset_flash(); /* Select mapping entry 0. This automatically disables MMC commands, * enables MBC registers, and resets MBC register contents. */ mmc_command(0xc0); } /* Returns true, if sector 0 is protected; false, if it is unprotected. */ function is_sector0_protected() { /* Enable MMC commands. */ mmc_command(0x09); /* Disable mapping so that we can access the whole flash. * This also selects ROM bank 1, which is also what we want, so that A14 is * high if accessing address 0x4000-0x7fff, when issuing the command sequence * below. */ mmc_command(0x04); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Make sure flash write protection is enabled. * We don't want to accidentally overwrite something. */ mmc_command(0x0a); mmc_command(0x03); /* Issue program flash command sequence, so we can read the status byte * from the flash. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0xa0); /* Being in program mode allows us to read the status byte. */ var status = read(0x0000); /* Abort the program flash command. */ reset_flash(); return (status & 0x02) != 0x00; } /* Makes the hidden map accessible for reading. */ procedure read_map() { /* Enable MMC commands. */ mmc_command(0x09); /* Disable mapping so that we can access the whole flash. * This also selects ROM bank 1, which is also what we want, so that A14 is * high if accessing address 0x4000-0x7fff, when issuing the command sequence * below. */ mmc_command(0x04); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Issue read map command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x77); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x77); /* Now, the 256 byte map can be read from the flash chip. * Issue the flash reset command (0xf0) when done reading. */ } /* Erases the whole 1 MiB of flash. */ procedure mass_erase_flash() { /* Enable MMC commands. */ mmc_command(0x09); /* Disable mapping so that we can access the whole flash. * This also selects ROM bank 1, which is also what we want, so that A14 is * high if accessing address 0x4000-0x7fff, when issuing the command sequence * below. */ mmc_command(0x04); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Disable flash write protection. */ mmc_command(0x0a); mmc_command(0x02); /* Issue unprotect sector 0 flash command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x40); /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } /* Issue mass erase flash command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x80); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x10); /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ mmc_command(0x03); /* Issue reset command to flash to make contents accessible again. */ write(0x0000, 0xf0); } /* Erases one 128 KiB flash sector. * sector_idx: Sector index 0-7. */ procedure erase_flash_sector(sector_idx) { /* Enable MMC commands. */ mmc_command(0x09); /* Disable mapping so that we can access the whole flash. */ mmc_command(0x04); /* Enable MBC registers. */ mmc_command(0x11); /* Write to MBC register 0x2000 (ROM bank select). * Select bank ((sector_idx * 0x20000 [<- sector size]) / 0x4000 [<- bank size]) + 1. * +1, because address needs to be odd, so that A14 is high if accessing address 0x4000-0x7fff. */ write(0x2000, sector_idx * 8 + 1); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Disable flash write protection. */ mmc_command(0x0a); mmc_command(0x02); if (sector == 0) { /* Issue unprotect sector 0 flash command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x40); /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } } /* Issue sector erase flash command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x80); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x30); /* We could use any address here that is in the range 0x4000-0x7fff. */ /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ mmc_command(0x03); /* Issue reset command to flash to make contents accessible again. */ write(0x0000, 0xf0); } /* Erases the 256 byte map. */ procedure erase_map() { /* Enable MMC commands. */ mmc_command(0x09); /* Disable mapping so that we can access the whole flash. * This also selects ROM bank 1, which is also what we want, so that A14 is * high if accessing address 0x4000-0x7fff, when issuing the command sequence * below. */ mmc_command(0x04); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Disable flash write protection. */ mmc_command(0x0a); mmc_command(0x02); /* Issue erase map command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x04); /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ mmc_command(0x03); /* Issue reset command to flash to make contents accessible again. */ write(0x0000, 0xf0); } /* Programs the 1 MiB flash with data from an array. */ procedure program_flash(data[1048576]) { var index = 0; var address = 0; /* Enable MMC commands. */ mmc_command(0x09); /* Disable mapping so that we can access the whole flash. */ mmc_command(0x04); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Disable flash write protection. */ mmc_command(0x0a); mmc_command(0x02); for (var bank = 1; bank < 64; bank++) { if (bank > 1) address = 0x4000; for (; address < 0x7fff; address += 128) { /* We exploit the "disable MMC commands" command here, because it * has the side effect of selecting ROM bank 1. We want ROM bank 1 to be * selected, so that A14 is high if accessing address 0x4000-0x7fff. * Repurposing MMC command 0x04 for that saves us some time, because * otherwise we would have to enable MBC registers, switch bank, and * then disable MBC registers. */ mmc_command(0x04); /* Issue program flash command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0xa0); /* Enable MBC registers. */ mmc_command(0x11); /* Write to MBC register 0x2000 (ROM bank select). * Select current bank number for programming data into the flash. */ write(0x2000, bank); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Fill the 128 byte write buffer with data from the array. * We always begin writing at address 0x0000, so we will never get into the * address range 0x0120-0x013f, which is used for MMC commands. Therefore, we * don't need to bother with disabling the MMC commands and reenabling them * all the time, which makes things much easier. */ for (var i = 0; i <= 128; i++) { write(i, data[index++]); } /* Write to the last written buffer location twice, but apply the target * address this time. This triggers the actual programming operation. The * written data doesn't matter as long as it isn't the reset command 0xf0. */ write(address + 127, 0); /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } } } /* Again, we use the "disable MMC commands" command to select ROM bank 1. * The "protect sector 0" command needs to be written to an address within sector 0. */ mmc_command(0x04); /* Issue protect sector 0 flash command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x20); /* We could use any address here that is in the range 0x4000-0x7fff. */ /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ mmc_command(0x03); /* Issue reset command to flash to make contents accessible again. */ write(0x0000, 0xf0); } /* Programs the 256 byte map with data from an array. */ procedure program_map(data[256]) { /* Enable MMC commands. */ mmc_command(0x09); /* Disable mapping so that we can access the whole flash. * This also selects ROM bank 1, which is also what we want, so that A14 is * high if accessing address 0x4000-0x7fff, when issuing the command sequences * below. */ mmc_command(0x04); /* Disable MBC registers. * We need to disable MBC registers, otherwise write accesses won't go * through to the flash. */ mmc_command(0x10); /* Disable flash write protection. */ mmc_command(0x0a); mmc_command(0x02); /* Issue program map command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0xe0); /* Fill the 128 byte write buffer with first half of data * from the array. */ for (var i = 0; i <= 128; i++) { write(i, data[i]); } /* Write to the last written buffer location twice. * This triggers the actual programming operation. The written * data doesn't matter as long as it isn't the reset command 0xf0. */ write(0x007f, 0); /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } /* Issue program map command sequence. */ write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x2aaa, 0x55); write(0x5555, 0xe0); /* Fill the 128 byte write buffer with second half of data * from the array. */ for (var i = 0; i <= 128; i++) { write(i, data[i + 128]); } /* Write to the last written buffer location twice. * This triggers the actual programming operation. The written * data doesn't matter as long as it isn't the reset command 0xf0. */ write(0x00ff, 0); /* Poll status and wait until operation completes. */ while (!(read(0x0000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ mmc_command(0x03); /* Issue reset command to flash to make contents accessible again. */ write(0x0000, 0xf0); }
Pseudocode procedures for Net de Get (MBC6) cartridges
Getting the commands through to the flash on a Net de Get cartridge is maybe as confusing as on a Nintendo Power cartridge. You have two address ranges that you can select a flash bank to be mapped to. And you have only 13 address lines (A12-A0) that you can control directly, instead of 14. A19-A13 are determined by the selected flash banks in the MBC6 chip.
/* Configure MBC6 so that flash is visible. */ procedure enable_flash() { write(0x0c00, 1); write(0x2800, 8); write(0x3800, 8); } /* Restores the state that the flash chip will have on power up. */ procedure reset_flash() { enable_flash(); /* Issue reset command to flash. * We issue two reset commands to the same address in direct succession, * just in case the flash chip is currently receiving data into its write * buffer prior to a program operation. Two reset commands issued to the * same address will cause exiting from this mode without starting the * program operation. */ write(0x4000, 0xf0); write(0x4000, 0xf0); /* Wait for 100 milliseconds. * Due to my measurements, the longest program or erase operation takes around * 6 milliseconds, so 100 milliseconds will be on the safe side. */ sleep(0.1); /* We try resetting the flash a third time after 100 ms, just in case * there was a program or erase operation ongoing the first and second * time. Reset has no effect during such an operation. */ write(0x4000, 0xf0); } /* Restores the state that the cartridge will have on power up. */ procedure reset_cartridge() { /* Make flash chip exit any special mode. */ reset_flash(); /* Restore state of all MBC6 registers to their defaults. */ write(0x0000, 0); write(0x0c00, 0); write(0x1000, 0); write(0x2800, 0); write(0x3800, 0); write(0x0400, 0); write(0x0800, 1); write(0x2000, 2); write(0x3000, 3); } /* Returns true, if sector 0 is protected; false, if it is unprotected. */ function is_sector0_protected() { enable_flash(); /* Make sure flash write protection is enabled. * We don't want to accidentally overwrite something. */ write(0x1000, 0); /* Select flash banks so that * accessing address 0x5555 results in flash address 0x05555; and * accessing address 0x6aaa results in flash address 0x02aaa. */ write(0x2000, 2); write(0x3000, 1); /* Issue program flash command sequence, so we can read the status byte * from the flash. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0xa0); /* Being in program mode allows us to read the status byte. */ var status = read(0x4000); /* Abort the program flash command. */ reset_flash(); return (status & 0x02) != 0x00; } /* Makes the hidden map accessible for reading. */ procedure read_map() { enable_flash(); /* Select flash banks so that * accessing address 0x5555 results in flash address 0x05555; and * accessing address 0x6aaa results in flash address 0x02aaa. */ write(0x2000, 2); write(0x3000, 1); /* Issue read map command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x77); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x77); /* Now, the 256 byte map can be read from the flash chip. * Issue the flash reset command (0xf0) when done reading. */ } /* Erases the whole 1 MiB of flash. */ procedure mass_erase_flash() { enable_flash(); /* Select flash banks so that * accessing address 0x5555 results in flash address 0x05555; and * accessing address 0x6aaa results in flash address 0x02aaa. */ write(0x2000, 2); write(0x3000, 1); /* Disable flash write protection. */ write(0x1000, 1); /* Issue unprotect sector 0 flash command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x40); /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } /* Issue mass erase flash command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x80); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x10); /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ write(0x1000, 0); /* Issue reset command to flash to make contents accessible again. */ write(0x4000, 0xf0); } /* Erases one 128 KiB flash sector. * sector_idx: Sector index 0-7. */ procedure erase_flash_sector(sector_idx) { enable_flash(); /* Select bank ((sector_idx * 0x20000 [<- sector size]) / 0x2000 [<- bank size]) + 2. * +2, because bank number needs to end in 0b10, so that A14 is high and A13 is low * if accessing address 0x4000-0x5fff. This way, we have the sector number in A19-A17 * and we can still use 0x5555 for the command sequence. */ write(0x2000, sector_idx * 16 + 1); /* Select the second flash bank so that accessing address 0x6aaa results * in flash address 0x02aaa. */ write(0x3000, 1); /* Disable flash write protection. */ write(0x1000, 1); if (sector == 0) { /* Issue unprotect sector 0 flash command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x40); /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } } /* Issue sector erase flash command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x80); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x30); /* We could use any address here that is in the range 0x4000-0x5fff. */ /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ write(0x1000, 0); /* Issue reset command to flash to make contents accessible again. */ write(0x4000, 0xf0); } /* Erases the 256 byte map. */ procedure erase_map() { enable_flash(); /* Select flash banks so that * accessing address 0x5555 results in flash address 0x05555; and * accessing address 0x6aaa results in flash address 0x02aaa. */ write(0x2000, 2); write(0x3000, 1); /* Disable flash write protection. */ write(0x1000, 1); /* Issue erase map command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x04); /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ write(0x1000, 0); /* Issue reset command to flash to make contents accessible again. */ write(0x4000, 0xf0); } /* Programs the 1 MiB flash with data from an array. */ procedure program_flash(data[1048576]) { var index = 0; enable_flash(); /* Select the second flash bank so that accessing address 0x6aaa results * in flash address 0x02aaa. */ write(0x3000, 1); /* Disable flash write protection. */ write(0x1000, 1); for (var bank = 0; bank < 128; bank++) { for (var address = 0x4000; address < 0x5fff; address += 128) { /* Select the first flash bank so that accessing address 0x5555 * results in flash address 0x05555. */ write(0x2000, 2); /* Issue program flash command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0xa0); /* Select first flash bank for programming data into the flash. */ write(0x2000, bank); /* Fill the 128 byte write buffer with data from the array. */ for (var i = 0; i <= 128; i++) { write(0x4000 + i, data[index++]); } /* Write to the last written buffer location twice, but apply the target * address this time. This triggers the actual programming operation. The * written data doesn't matter as long as it isn't the reset command 0xf0. */ write(address + 127, 0); /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } } } /* Select the first flash bank so that accessing address 0x5555 * results in flash address 0x05555. */ write(0x2000, 2); /* Issue protect sector 0 flash command sequence. */ /* TODO: I'm not sure if Net de Get cartridges have a protected * sector 0 when their flash contains dowloaded content. * Maybe this step shouldn't be done. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x20); /* We could use any address here that is in the range 0x4000-0x5fff. */ /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ write(0x1000, 0); /* Issue reset command to flash to make contents accessible again. */ write(0x4000, 0xf0); } /* Programs the 256 byte map with data from an array. */ procedure program_map(data[256]) { enable_flash(); /* Select flash banks so that * accessing address 0x5555 results in flash address 0x05555; and * accessing address 0x6aaa results in flash address 0x02aaa. */ write(0x2000, 2); write(0x3000, 1); /* Disable flash write protection. */ write(0x1000, 1); /* Issue program map command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0xe0); /* Fill the 128 byte write buffer with first half of data * from the array. */ for (var i = 0; i <= 128; i++) { write(0x4000 + i, data[i]); } /* Write to the last written buffer location twice. * This triggers the actual programming operation. The written * data doesn't matter as long as it isn't the reset command 0xf0. */ write(0x407f, 0); /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } /* Issue program map command sequence. */ write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0x60); write(0x5555, 0xaa); write(0x6aaa, 0x55); write(0x5555, 0xe0); /* Fill the 128 byte write buffer with second half of data * from the array. */ for (var i = 0; i <= 128; i++) { write(0x4000 + i, data[i + 128]); } /* Write to the last written buffer location twice. * This triggers the actual programming operation. The written * data doesn't matter as long as it isn't the reset command 0xf0. */ write(0x40ff, 0); /* Poll status and wait until operation completes. */ while (!(read(0x4000) & 0x80)) { /* do nothing; just wait */ } /* Enable flash write protection. */ write(0x1000, 0); /* Issue reset command to flash to make contents accessible again. */ write(0x4000, 0xf0); }
MMC chip pinout
The following table lists all pins of the MMC chip (MegaChips MX15002):
Pin# | Description | Pin# | Description |
---|---|---|---|
1 | VDD* | 41 | A1_OUT Address output to flash and SRAM. |
2 | GND* | 42 | A14_OUT Address output to flash and SRAM. |
3 | WR_IN Write signal input from Game Boy. |
43 | A15_OUT Address output to flash and SRAM. |
4 | RD_IN Read signal input from Game Boy. |
44 | A16_OUT Address output to flash and SRAM. |
5 | CS_IN RAM chip select signal input from Game Boy. |
45 | A17_OUT Address output to flash and SRAM. |
6 | A0_IN Address input from Game Boy. |
46 | A18_OUT Address output to flash and SRAM. |
7 | A1_IN Address input from Game Boy. |
47 | A19_OUT Address output to flash and SRAM. |
8 | A2_IN Address input from Game Boy. |
48 | GND* |
9 | A3_IN Address input from Game Boy. |
49 | FLASH_CE Chip enable output to flash. |
10 | A4_IN Address input from Game Boy. |
50 | FLASH_WP Write protect output to flash. This pin is controlled by MMC commands 0x02 and 0x03. |
11 | A5_IN Address input from Game Boy. |
51 | OE_OUT Read signal to flash and SRAM. |
12 | GND* | 52 | WE_OUT Write signal to flash and SRAM. This signal is blocked if flash is accessed while MBC registers are enabled. |
13 | A6_IN Address input from Game Boy. |
53 | VDD* |
14 | A7_IN Address input from Game Boy. |
54 | Unknown. Connected to MMC pin 58 and nothing else. Probably NC. ** |
15 | A8_IN Address input from Game Boy. |
55 | RESET_IN Reset input. Connected to MMC's pin 60. If pulled low, it resets the whole MMC chip and causes it to read mapping entry 0 from the flash as described here. If you disconnect this pin from pin 60 and pull it high during power up, then mapping entry 0 won't be read from flash. So this reset input is actually the trigger for that reading process. It doesn't seem to have any internal pull-up or pull-down resistors. If it is floating, it constantly triggers the reading process. |
16 | A9_IN Address input from Game Boy. |
56 | GND* |
17 | A10_IN Address input from Game Boy. |
57 | GND* |
18 | A11_IN Address input from Game Boy. |
58 | Unknown. Connected to MMC pin 54 and nothing else. Probably NC. ** |
19 | A12_IN Address input from Game Boy. |
59 | Unknown. Connected to capacitor C2 (120 nF), which is connected to GND. |
20 | A13_IN Address input from Game Boy. |
60 | RESET_OUT Reset output. MMC drives this pin low on power up for ~50 ms. After that, it stays high forever. It is used for resetting the flash and the MMC itself, since it is also connected to MMC's pin 55. |
21 | A14_IN Address input from Game Boy. |
61 | SRAM_CE Chip enable output to SRAM. This signal can be blocked by MBC register 0x0000, or if an invalid RAM bank was selected in MBC3 mode. It is also blocked when the current memory mapping has SRAM disabled. The MMC only maps host system memory accesses to/from address range 0xa000-0xbfff to the cartridge SRAM; the so-called "echo area" 0xe000-0xf??? does not assert this chip enable signal. |
22 | A15_IN ROM chip select signal input (active low) from Game Boy aka. A15. |
62 | BAT_VIN Battery input. |
23 | HOST_RESET_IN Host system reset input. Like pin 24, this pin is connected to the RST signal of the cartridge connector. If pulled low by the host system, some parts in the MMC are reset and the MMC sends a reset command (0xf0) to the flash. For details, see here. |
63 | VDD* |
24 | HOST_RESET_OUT Open-drain host system reset output. Like pin 23, this pin is connected to the RST signal of the cartridge connector. It gets pulled low by the MMC while it reads mapping entry 0 from flash during power up, as described here. It is also pulled low by the MMC when MMC command 0x80-0xbf gets called. |
64 | SRAM_VOUT Power supply for SRAM. If cartridge is powered by the host system, this is 5V; otherwise this is the battery voltage from pin 62. There is no voltage drop for either of those two input voltages. |
25 | A0_OUT Address output to flash and SRAM. |
65 | GND* |
26 | A13_OUT Address output to flash and SRAM. |
66 | GND* |
27 | A12_OUT Address output to flash and SRAM. |
67 | INTERNAL_OSC Connected to resistor R5 (10 k), which is connected to VDD. Also connected to unpopulated resistor R4, which would be connected to GND. If connected to VDD via R5, the internal digital oscillator is enabled and the external crystal oscillator on pins 79 and 80 is disabled. If connected to GND via R4, the external crystal oscillator is enabled and the internal digital oscillator is disabled. |
28 | GND* | 68 | GND* |
29 | A11_OUT Address output to flash and SRAM. |
69 | VDD* |
30 | A9_OUT Address output to flash and SRAM. |
70 | D7 Data I/O from/to Game Boy, flash and SRAM. |
31 | A8_OUT Address output to flash and SRAM. |
71 | D6 Data I/O from/to Game Boy, flash and SRAM. |
32 | A7_OUT Address output to flash and SRAM. |
72 | D5 Data I/O from/to Game Boy, flash and SRAM. |
33 | VDD* | 73 | D4 Data I/O from/to Game Boy, flash and SRAM. |
34 | A6_OUT Address output to flash and SRAM. |
74 | D3 Data I/O from/to Game Boy, flash and SRAM. |
35 | A5_OUT Address output to flash and SRAM. |
75 | D0 Data I/O from/to Game Boy, flash and SRAM. |
36 | A4_OUT Address output to flash and SRAM. |
76 | D1 Data I/O from/to Game Boy, flash and SRAM. |
37 | A10_OUT Address output to flash and SRAM. |
77 | D2 Data I/O from/to Game Boy, flash and SRAM. |
38 | GND* | 78 | GND* |
39 | A3_OUT Address output to flash and SRAM. |
79 | OSC_OUT Oscillator output. Crystal is not populated. If pin 67 is high, this output is always high. If pin 67 is low, this oscillator output is the inverse of the oscillator input pin 80. If you enable the external crystal oscillator by pulling pin 67 low, you need to populate X1 with a 2 MiHz crystal to archive the same timings as with the internal oscillator. Also, R3 needs to be removed and R2 needs to be populated with 1 M or 1.5 M, I'm not sure. |
40 | A2_OUT Address output to flash and SRAM. |
80 | OSC_IN Oscillator input. Crystal is not populated, instead this input is pulled high by resistor R3 (10 k). |
* I'm not sure about VDD and GND pins. Some of them could be pulled-up or pulled-down inputs.
** Pin 54 and 58 are probably NC. They are both connected with each other, and they would be connected to GND if there wasn't a hole drilled to disconnect them from GND. So, the reason they are connected to each other might just be because of that undone GND connection.
Flash chip pinout
The following table lists all pins of the flash chip (Macronix 29F008ATC):
Pin# | Description | Pin# | Description |
---|---|---|---|
1 | A16 Address input. |
21 | A0 Address input. |
2 | A15 Address input. |
22 | CE Chip enable input. |
3 | A14 Address input. |
23 | GND |
4 | A13 Address input. |
24 | OE Output enable input. |
5 | A12 Address input. |
25 | D0 Data I/O. |
6 | A11 Address input. |
26 | D1 Data I/O. |
7 | A9 Address input. |
27 | D2 Data I/O. |
8 | A8 Address input. |
28 | D3 Data I/O. |
9 | WE Write enable input. |
29 | NC |
10 | RESET Reset input. Flash needs to be reset after power up, otherwise it returns only garbage. |
30 | VDD |
11 | NC | 31 | VDD |
12 | WP Write protect input. If low, then flash sector 0 and the hidden map region can't be erased or programmed, and sector 0 protection can't be changed. Has no effect on sectors 1-7. |
32 | D4 Data I/O. |
13 | A18 Address input. |
33 | D5 Data I/O. |
14 | A7 Address input. |
34 | D6 Data I/O. |
15 | A6 Address input. |
35 | D7 Data I/O. |
16 | A5 Address input. |
36 | A10 Address input. |
17 | A4 Address input. |
37 | A19 Address input. |
18 | A3 Address input. |
38 | NC |
19 | A2 Address input. |
39 | GND |
20 | A1 Address input. |
40 | A17 Address input. |
This table could also be correct for the Macronix 29F008TC (Net de Get), but that's not tested.
Calculating output address from input address
The following two functions describe how the addresses for the flash and SRAM are calculated by the MMC chip. When the SRAM gets accessed, the upper three address lines (which are not connected to the SRAM) are always 0.
/* Calculate flash address from input address, MBC type, ROM size, ROM offset * and ROM bank number. * adr_in: 16-bit input address from host (Game Boy). * mbc_type: MBC type value (0-5) selected by current memory mapping. * rom_size: ROM size value (0-7) selected by current memory mapping. * rom_offset: ROM offset in 32 KiB steps (0-63), selected by current memory mapping. * rom_bank: ROM bank number (0-63) selected by emulated MBC; or 0 if MBC type is 0 * or if input address is in range 0x0000-0x3fff. * Returns 20-bit address applied to the flash chip. */ function rom_address(adr_in, mbc_type, rom_size, rom_offset, rom_bank) { switch (mbc_type) { case 0: /* no MBC */ adr_in &= 0x7fff; rom_bank = 0; break; case 2: /* MBC2 */ adr_in &= 0x3fff; rom_bank &= 0x0f; break; default: /* MBC1, MBC3, MBC5 (and value 4) */ adr_in &= 0x3fff; rom_bank &= 0x3f; break; } switch (rom_size) { case 0: /* 32 KiB */ rom_bank &= 0x01; break; case 1: /* 64 KiB */ rom_bank &= 0x03; break; case 2: /* 128 KiB */ rom_bank &= 0x07; break; case 3: /* 256 KiB */ rom_bank &= 0x0f; break; case 4: /* 512 KiB */ rom_bank &= 0x1f; break; case 5: /* 1 MiB */ case 6: /* other 1 MiB option */ rom_bank &= 0x3f; break; case 7: /* 16 KiB */ adr_in &= 0x3fff; rom_bank = 0; break; } var adr_out = adr_in + (rom_offset << 15) + (rom_bank << 14); adr_out &= 0xfffff; return adr_out; } /* Calculate SRAM address from input address, MBC type, RAM size, RAM offset * and RAM bank number. * adr_in: 16-bit input address from host (Game Boy). * mbc_type: MBC type value (0-5) selected by current memory mapping. * ram_size: RAM size value (0-7) selected by current memory mapping. * ram_offset: RAM offset in 2 KiB steps (0-63), selected by current memory mapping. * ram_bank: RAM bank number (0-15) selected by emulated MBC; or 0 if MBC type is 0. * Returns 17-bit address applied to the SRAM chip. */ function ram_address(adr_in, mbc_type, ram_size, ram_offset, ram_bank) { switch (mbc_type) { case 0: /* no MBC */ adr_in &= 0xffff; ram_bank = 0; break; case 1: /* MBC1 */ case 3: /* MBC3 */ adr_in &= 0x1fff; ram_bank &= 0x03; break; case 2: /* MBC2 */ adr_in &= 0x1fff; ram_bank = 0; break; default: /* MBC5 (and value 4) */ adr_in &= 0x1fff; ram_bank &= 0x0f; break; } switch (ram_size) { case 1: /* 2 KiB */ adr_in &= 0x07ff; if (mbc_type == 2) /* 512 bytes if MBC2 */ adr_in &= 0x01ff; ram_bank = 0; break; case 2: /* 8 KiB */ adr_in &= 0x1fff; ram_bank = 0; break; case 3: /* 32 KiB */ adr_in &= 0x7fff; ram_bank &= 0x03; break; case 4: /* 64 KiB */ ram_bank &= 0x07; break; case 5: /* 128 KiB */ ram_bank &= 0x0f; break; default: /* no RAM (0 bytes) */ adr_in &= 0x00ff; ram_bank = 0; ram_offset = 0; /* When RAM size is 0 bytes (value 0, 6, or 7), the chip enable signal * won't be asserted. */ break; } var adr_out = adr_in + (ram_offset << 11) + (ram_bank << 13); adr_out &= 0x1ffff; return adr_out; }
Random stuff
This is completely useless, but MMC commands can have any number of arguments. They just get ignored. Even command 0x09. You can do the following sequence for command 0x09, and it still works:
0x0120 <- 0x09 0x0121 <- 0xaa 0x0122 <- 0x55 0x0123 <- 0x42 0x0125 <- 0x87 0x013d <- 0x23 0x0122 <- 0xcd 0x0121 <- 0xab 0x013f <- 0xa5
The first three bytes must be written in direct succession for the command to work. After that, you can write any number of bytes. You can even write to 0x0121 and 0x0122 again with different data and the command still works.
You can insert stuff before and after the unlock sequence of command 0x0a, but not between 0x0125 and 0x0126. After the unlock sequence, you can write to 0x0125 and 0x0126 again with different data, but not before the unlock sequence. This is a valid 0x0a command:
0x0120 <- 0x0a 0x0121 <- 0xdd 0x0133 <- 0x55 0x0123 <- 0x42 0x0125 <- 0x62 0x0126 <- 0x04 0x013d <- 0x23 0x0125 <- 0xcd 0x0126 <- 0xab 0x013f <- 0xa5
I tried to exploit the MBC register backup/restore mechanism of MMC commands 0x04/0x05. I failed, but I think this is still interesting if you want to emulate this cartridge precisely. I tried to select a ROM and RAM bank for MBC2 mappings with a higher index than allowed by the MBC2. This is the method I used:
/* PRE-REQUIREMENT: Program a map that has an MBC2 mapping at index 0. * In this example I use 56 80 00. */ /* Make sure MMC commands and MBC registers are enabled. */ mmc_command(0x09); mmc_command(0x11); /* Call command 0x04. This switches to an MBC5 like emulation and * creates a backup of all MBC registers. */ mmc_command(0x04); /* Unlock RAM, select ROM and RAM banks that are normally not * accessible with MBC2 chip. */ write(0x0000, 0x0a); write(0x2000, 63); write(0x4000, 15); /* Call command 0x04 again. This overwrites the backup with the * MBC registers we've just set. */ mmc_command(0x04); /* Call command 0x05 to switch back to MBC2 mode and to restore * the backups. */ mmc_command(0x05);
After that, the RAM is unlocked, but RAM bank 0 is selected, instead of RAM bank 15. ROM bank 15 is selected, instead of ROM bank 63. ROM bank 15 is the maximum for MBC2. So the registers are getting masked sometime after restoring the backups.
In another test, I tried to exploit the fact that the MBC register backups are initialized with zeroes on power up. I tried to select ROM bank 0 for addresses 0x4000-0x7fff for an MBC1 mapping. This also failed, I used this method:
/* PRE-REQUIREMENT: Program a map that has an MBC1 mapping at index 0. * In this example I use 35 80 00. Also, the cartridge * must be freshly power cycled to make sure that the * backup registers are zero. */ /* Make sure MMC commands are enabled. */ mmc_command(0x09); /* Call command 0x05 without ever having called command 0x04. This * loads the zero initialized backup registers into the live MBC registers. */ mmc_command(0x05);
The selected ROM bank is still 1 after this, so it must be adjusted sometime after restoring the backups. You can try this method with an MBC5 mapping instead. There you will see that ROM bank 0 will be selected afterward.
I did a lot more tests not shown here. I can say with certainty that the backup and restore operations of MMC commands 0x04 and 0x05 do indeed not mask the MBC registers. The MBC registers are ANDed with specific masks only when they are set, and when they are used to calculate an address for memory accesses. The following table contains all the MBC registers that exist. They exist in two sets: The currently used ones, and the backup set.
Register | Width | Description |
---|---|---|
rom_bank | 6 bits | Stores the ROM bank number. This is what you set when writing MBC register 0x2000 for most MBCs or 0x2100 for MBC2. |
ram_bank | 4 bits | Stores the RAM bank number. This is what you set when writing MBC register 0x4000 for most MBCs. |
ram_enable | 1 bit | Enables/disables RAM access. This is what you set when writing MBC register 0x0000 for most MBCs. |
mbc1_mode | 1 bit | Selects mode of MBC1. This is what you set when writing MBC register 0x6000 for MBC1. |
mbc3_invalid_bank | 1 bit | Set when you select a RAM bank for MBC3 by writing to MBC register 0x4000 with bits 2 or 3 set. Writing values 0-3 would set ram_bank to that value and mbc3_invalid_bank to 0. Writing values like 4, 7, 8, 15 will not change ram_bank but set mbc3_invalid_bank to 1. |
All these registers will be backed up and restored without being modified in the process when using MMC commands 0x04 and 0x05. When you switch memory mappings, they will be set to the following default values, independent of the used MBC type or ROM size etc.:
Register | Default value |
---|---|
rom_bank | 1 |
ram_bank | 0 |
ram_enable | 0 |
mbc1_type | 0 |
mbc3_invalid_bank | 0 |
The backup set for these registers is not modified when you switch memory mappings. It is initialized all zero one time, when the MMC is powered up (or more precisely, when the MMC gets reset by pin 55).
When you write to any of the MBC registers, the written value will be ANDed with a mask before it is written into the register. This mask depends on the currently selected MBC type. The ROM/RAM sizes don't have an effect on the mask. This table shows the masks used when setting registers:
Register | no MBC | MBC1 | MBC2 | MBC3 | Type 4 | MBC5 |
---|---|---|---|---|---|---|
rom_bank | n/a* | 0x3f** | 0x0f | 0x3f | 0x3f | 0x3f |
ram_bank | n/a* | 0x03*** | n/a* | 0x03 | 0x0f | 0x0f |
ram_enable***** | n/a* | 0x0f | 0x0f | 0x0f | 0x0f | 0xff |
mbc1_type | n/a* | 0x01 | n/a* | n/a* | n/a* | n/a* |
mbc3_invalid_bank | n/a* | n/a* | n/a* | 0x0c**** | n/a* | n/a* |
* MBC type doesn't have this register mapped to any address, therefore you can't change it.
** Yes, MBC1 allows you to set 6 bits of the rom_bank register, even though the real MBC1 chip has only 5 bits in this register. However, the highest bit (bit 5) isn't being used. When determining the actual ROM bank number for memory accesses, the lowest bit of ram_bank is used as ROM bank bit 5, just like the real MBC1 does it.
*** When setting the ram_bank register for MBC1, the value in the rom_bank register isn't changed, even though, the lowest bit of the ram_bank register affects the ROM bank number later, when it is used to access memory range 0x4000-0x7fff.
**** The mask 0x0c is applied when writing to register 0x4000. The emulated MBC3 doesn't implement any RTC registers, so it just marks the RAM bank as invalid when applying this mask results in a value that is not 0.
***** The masks 0x0f or 0xff are applied to the value 0x0a that needs to be written to register 0x0000 to enable the RAM. Only MBC5 requires you to write 0x0a exactly. All other MBCs accept values like 0xfa, 0x5a, 0xaa, ...
The following pseudocode functions describe how the actual ROM and RAM bank numbers are calculated based on the MBC register contents, which are passed to the address calculation functions shown above:
/* Calculate ROM bank number that is passed to rom_address function, based * on MBC type and MBC register content. * mbc_type: MBC type value (0-5) selected by current memory mapping. * rom_bank: ROM bank number (0-63) stored in the current rom_bank register. * ram_bank: RAM bank number (0-15) stored in the current ram_bank register. */ function final_rom_bank(mbc_type, rom_bank, ram_bank) { var r; switch (mbc_type) { case 0: /* no MBC */ r = 1; break; case 1: /* MBC1 */ r = rom_bank & 0x1f; if (r == 0) r = 1; r |= (ram_bank & 1) << 5; break; case 2: /* MBC2 */ r = rom_bank & 0x0f; if (r == 0) r = 1; break; case 3: /* MBC3 */ case 4: r = rom_bank & 0x3f; if (r == 0) r = 1; break; case 5: /* MBC5 */ r = rom_bank & 0x3f; break; } return r; } /* Calculate RAM bank number that is passed to ram_address function, based * on MBC type and MBC register content. * mbc_type: MBC type value (0-5) selected by current memory mapping. * ram_bank: RAM bank number (0-15) stored in the current ram_bank register. * mbc1_mode: MBC1 mode (0 or 1) stored in the current mbc1_mode register. */ function final_ram_bank(mbc_type, ram_bank, mbc1_mode) { var r; switch (mbc_type) { case 0: /* no MBC */ case 2: /* MBC2 */ r = 0; break; case 1: /* MBC1 */ r = ram_bank & 0x03; if (mbc1_mode == 0) r = 0; break; case 3: /* MBC3 */ r = ram_bank & 0x03; break; case 4: case 5: /* MBC5 */ r = rom_bank & 0x0f; break; } return r; }
Scans of the empty PCB: