MMC1 Memory Mapping

NES Programming Tutorial

Published 11/25/2009 - Download Example ROM at Bottom

INTRO

I had a request for MMC1 mapper information, so I thought everyone might like to read what I have to say.

This will help you figure out MMC1 memory mapping. It assumes that you have a working knowledge
of NES programming and can understand my messed up little mind. Most of the information on this
mapper can be found on:

http://wiki.nesdev.com/w/index.php/MMC1

MMC1 will allow you to use up to 256 kb of PRG ROM and 128 kb of CHR ROM. I think that you can use
SUROM to expand up to 4 MB of PRG ROM, but this is not covered here.


First, you have to decide on what kind of configuration you want to use. MMC1 will support PRG bank
switching in either 16kb mode or 32kb mode. And with the 16, you can choose whether you want
the memory at $C000 or the memory at $8000 to be switched.

Second, you have to decide on the CHR ROM switching. MMC1 supports switching of 4kb (background or
sprite tiles separately) or 8kb (switching them together).


After you decide this, you are ready to start.


INES HEADER

Notes:

-You can only have even numbers of PRG banks. NESASM uses 8kb “banks”, I’m talking about 16kb banks.
i.e. 02 (32kb),04 (64kb),06 (96kb),08 (128kb),0A (160kb),0C (192kb),0E (224kb),10 (256kb)

-CHR banks are in multiples of 8kb banks. (important if you are using 4kb swapping.)
i.e. 01 (8kb),02 (16kb),03 (24kb),04 (32kb),05 (40kb), 06 (48kb), etc., 10 (128kb)

-MMC1 mapper number is “1” …creative!

-Mirroring should match that used below in the initiation routine.

In this exercise, we will use:

.inesprg $10 ; 16x 16KB PRG code
.ineschr $10 ; 16x 8KB CHR data
.inesmap $01 ; mapper 1 = MMC1, 4KB CHR bank swapping
.inesmir 0 ; background mirroring


MAPPER CONTROL HEADER

This is one bite that has all the information for the mapper. Observe:

76543210

Bits 7,6,5 – Not sure what these do.
Bit 4 – CHR ROM bank mode – (0 means switch 8kb at a time, 1 means switch the two separate 4kb banks independently)
Bit 3 – PRG ROM bank mode – (0 means switch all 32kb at once, ignores bit 2)
(1 means switch ONLY the 16kb specified in bit 2)
Bit 2 – PRG ROM location – (0 means switch 16kb at $C000, 1 means switch 16kb at $8000)
Bits 1,0 – Mirroring – (0 means one screen, lower bank; 1 means one screen, upper bank
2 means vertical; 3 means horizontal)

Here we will use LDX #%00011000

BITCH WORK! Look above and figure out what this means.


INITIATE MAPPER

Here we load the information required by the system to run the mapper as well as the initial banks.
You have to do the 5 writes to make it work…for whatever reason.

initMMC1Mapper:
LDA #$80 ;don’t know what this does.
STA $8000

TXA ;uses our header to initiate the mapper
JSR setMMC1ControlMode

LDA #$02 ;sets the CHR information for the sprites
JSR setCHRPage0000

LDA #$01 ;sets the CHR information for the background
JSR setCHRPage1000

LDA #$03 ;sets the PRG information
JSR setPRGBank

RTS

setMMC1ControlMode:
STA $8000
LSR A
STA $8000
LSR A
STA $8000
LSR A
STA $8000
LSR A
STA $8000
RTS

setCHRPage0000:
STA $A000
LSR A
STA $A000
LSR A
STA $A000
LSR A
STA $A000
LSR A
STA $A000
RTS

setCHRPage1000:
STA $C000
LSR A
STA $C000
LSR A
STA $C000
LSR A
STA $C000
LSR A
STA $C000
RTS

setPRGBank:
STA $E000
LSR A
STA $E000
LSR A
STA $E000
LSR A
STA $E000
LSR A
STA $E000
RTS

Congrats….your program should work.

USING THE MAPPER

You can swap out banks whenever you want, even several times per NMI. Just load the bank number you want to
use into A and call the appropriate subroutine. Just be sure that you don’t switch away information that
your program needs to run or it will die.

Weird bank numbering notes:

-CHR data is stored in 8kb for NESASM. If you want to call the first 4kb of data from the 6th 8kb chunk,
you would use bank #$0C. Observe, call number for 4kb chunk vs. 8kb bank number:

00-0
01-0
02-1
03-1
04-2
05-2
06-3
07-3
08-4
09-4
0A-5
0B-5
0C-6
0D-6
0E-7
0F-7
10-8
11-8
12-9
13-9
14-10
15-10
16-11
17-11
18-12
19-12
1A-13
1B-13
1C-14
1D-14
1E-15
1F-15

Clear?

-PRG info is stored in 8kb chunks in NESASM, but you call and switch 16kb banks. If you want to call bank
26, use call number #$0D. Observe, call number vs. bank number:

0-0,1
1-2,3
2-4,5
3-6,7
4-8,9
5-10,11
6-12,13
7-14,15
8-16,17
9-18,19
A-20,21
B-22,23
C-24,25
D-26,27
E-28,29
F-30,31

Clear?

-At the end of each 16kb bank, you have to have vectors in place or it will die.

.org $FFFA ;first of the three vectors starts here
.dw NMI ;when an NMI happens (once per frame if enabled) the
;processor will jump to the label NMI:
.dw RESET ;when the processor first turns on or is reset, it will jump
;to the label RESET:
.dw 0 ;external interrupt IRQ is not used in this tutorial

-Bank numbering is successive. i.e. if you have PRG banks numbered 0-23, you would start numbering your
CHR banks at 24.

-If you have, for example, a 16kb CHR file, you only have to include the starting place and NESASM will
split the banks properly. i.e. in 4kb mode:

.bank 32
.org $0000
.incbin “MMC1.chr” ;includes 16KB graphics file

This will include 4 – 4kb (or 2-8kb) banks in the assembly process. Be sure to account for the 2 banks
in your numbering. (see the attached ASM file.)


PRACTIAL APPLICATION

This is a little inefficient. To use all this nonsense in something real, an example would be:

LoadBackground:

;find room info

;switch to room info table bank

;load bankground pointer

;switch to bank where background information is stored

;load background

;switch back to room info table bank

;load attribute and palette pointers

;switch to attribute/palette information bank

;load attributes/palettes

;switch back to room info table bank

;load collision detection pointer

;switch to collision detection bank

RTS


WORKING EXAMPLE

Here we use the controller to switch banks for both CHR banks and the PRG bank.

A and B – swap out CHR information for the sprites
Select and Start – nothing
Up and Down – load a background located in different banks (the flashing is cause you are holding the button
down for more than one frame. Just tap it. I was too lazy to add stuff in to fix this.)
Left and Right – swap out the CHR information for the backgrounds

Download the attached file and assemble the program. Mess around with it and try to switch out the
various buttons and banks. Fix the flashing. Add new backgrounds and characters…etc.

The little DOS assembler file might not work, you may have to edit it to your drive.


THE END!

I’m sure I totally screwed this up, but don’t worry! Someone will help me out if there are any mistakes.

Download Example Stuff