Mapper File: MMC3

MMC3

  • iNES mapper IDs: 004, 118, 119
  • PRG ROM capacity: 512K
  • PRG ROM page size: 8 KiB
  • PRG RAM: 8 KiB
  • CHR capacity: 256 KiB ROM
  • CHR page size: 1 KiB
  • Nametable mirroring mode: Programmable, vertical or horizontal mirroring

PRG ROM memory map

Form explanation:

+-------------+-------------------+
|             |  Bank Selection   |
|   CPU MEM   |-------------------|
|    ADDR.    | Mode 0  | Mode 1  |
+-------------+---------+---------+
| $8000-$9FFF |    R6   |   (-2)  |
+-------------+---------+---------+
| $A000-$BFFF |    R7   |    R7   |
+-------------+---------+---------+
| $C000-$DFFF |   (-2)  |    R6   |
+-------------+---------+---------+
| $E000-$FFFF |   (-1)  |   (-1)  |
+-------------+---------+---------+

Code explanation:

constexpr const unsigned A14 = 0x4000;
int bank_no = 0;

if (prg_bank_mode1)
	addr ^= A14; // $0800 <--> $0c00

switch ((addr & 0x7fff) / 8192) {
    
    
case 0: bank_no = R[6]; break;
case 1: bank_no = R[7]; break;
case 2: bank_no = -2; break;
case 3: bank_no = -1; break;
}

prg_addr = bank_no < 0 ? prg_rom.size() : 0;
prg_addr += bank_no * 8192 + addr & 8191;

Graphical explanation:

Mode 0
------
                              ...
      +--------+           |--------|
$8000 |  8 KB  |~~~~~~~~~~>|  8 KB  |
      |--------|           |--------|
$A000 |  8 KB  |~~~~~~~~~~>|  8 KB  |
      |--------|           |--------|
$C000 |  8 KB  |------.    |  8 KB  |
      |--------|      |    |--------|
$E000 |  8 KB  |---.  |       ...
      +--------+   |  |    |--------|
                   |  `--->|  8 KB  |
                   |       |--------|
                   `------>|  8 KB  |
                           +--------+


Mode 1
------
                              ...
      +--------+           |--------|
$8000 |  8 KB  |------.    |  8 KB  |
      |--------|      |    |--------|
$A000 |  8 KB  |~~~~~~|~~~>|  8 KB  |
      |--------|      |    |--------|
$C000 |  8 KB  |~~~~~~|~~~>|  8 KB  |
      |--------|      |    |--------|
$E000 |  8 KB  |---.  |       ...
      +--------+   |  |    |--------|
                   |  `--->|  8 KB  |
                   |       |--------|
                   `------>|  8 KB  |
                           +--------+

CHR ROM memory map

Form explanation:

+-------------+---------------------+
|             |   Bank Selection    |
|   PPU MEM   |---------------------|
|    ADDR.    | A12 Inv. | A12 Inv. |
|             |   = 0    |   = 1    |
+-------------+----------+----------+
| $0000-$03FF |          |    R2    |
+-------------+    R0    +----------|
| $0400-$07FF |          |    R3    |
+-------------+----------+----------+
| $0800-$0BFF |          |    R4    |
+-------------+    R1    |----------|
| $0C00-$0FFF |          |    R5    |
+-------------+----------+----------+
| $1000-$13FF |    R2    |          |
+-------------+----------+    R0    |
| $1400-$17FF |    R3    |          |
+-------------+----------+----------+
| $1800-$1BFF |    R4    |          |
+-------------+----------+    R1    |
| $1C00-$1FFF |    R5    |          |
+-------------+----------+----------+

The lowest bits of R0 and R1 are treated as 0, so R0 and R1 can only select even memory pages. The size of each page is 1KB, so R0 and R1 can actually map 2KB of memory respectively

code explanation

constexpr const unsigned A12 = 0x1000;
int bank_no = 0;
int offset = addr & 0x03ff;

if (A12_inv)
	addr ^= A12;
	
if (addr < 0x1000) {
    
    
	offset = addr & 0x07ff;
	bank_no = R[addr / 2048] & ~1;
} else {
    
    
	bank_no = R[2 + (addr & 0x0fff) / 1024];
}

chr_addr = bank_no * 1024 + offset;

Graphical explanation:

A12 Inversion = 0
-----------------

      +--------+
$0000 |  2 KB  |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.
      |        |                                              |
      |--------|                                              |
$0800 |  2 KB  |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.   |
      |        |                         ...              |   |
      |--------|                 |--------+--------|      |   |
$1000 |  1 KB  |~~~~~~~~~~~~~~~~>|  1 KB  |        |      |   |
      |--------|                 |--------+  2 KB  |<~~~~~'   |
$1400 |  1 KB  |~~~~~~~~~~~~~~~~>|  1 KB  |        |          |
      |--------|                 |--------+--------|          |
$1800 |  1 KB  |~~~~~~~~~~~~~~~~>|  1 KB  |        |          |
      |--------|                 |--------+  2 KB  |<~~~~~~~~~'
$1C00 |  1 KB  |~~~~~~~~~~~~~~~~>|  1 KB  |        |
      +--------+                 |--------+--------|
                                         ...

A12 Inversion = 1
-----------------

                                         ...
      +--------+                 |--------+--------|
$0000 |  1 KB  |~~~~~~~~~~~~~~~~>|  1 KB  |        |
      |--------|                 |--------+  2 KB  |<~~~~~~~~~.
$0400 |  1 KB  |~~~~~~~~~~~~~~~~>|  1 KB  |        |          |
      |--------|                 |--------+--------|          |
$0800 |  1 KB  |~~~~~~~~~~~~~~~~>|  1 KB  |        |          |
      |--------|                 |--------+  2 KB  |<~~~~~.   |
$0C00 |  1 KB  |~~~~~~~~~~~~~~~~>|  1 KB  |        |      |   |
      |--------|                 |--------+--------|      |   |
$1000 |  2 KB  |                         ...              |   |
      |        |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'   |
      |--------|                                              |
$1800 |  2 KB  |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
      |        |
      +--------+

reference

Guess you like

Origin blog.csdn.net/ZML086/article/details/129194420