How to get started with MMC3?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
pinkpuff
Posts: 22
Joined: Mon Nov 26, 2012 6:12 am

How to get started with MMC3?

Post by pinkpuff »

So far I've only been using the default mapper, but I want to try using MMC3. I read the relevant wiki articles but I can't get anything to work. It will compile, but the resulting rom just produces a blank screen in the emulator. The identical code works just fine with the default mapper. It's not doing anything fancy, just writing some colors to the palette to make sure it works.

So I guess what I'm looking for is a sort of "quick setup template" for getting something (anything) running using MMC3. For example:
  • What do I put in the header?
  • Where should my code start?
  • Is there something special I need to do at the start of the reset code to get things set up? If so, does that need to happen before or after the usual initialization code (waiting to power up etc)?
Thanks!
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: How to get started with MMC3?

Post by lidnariq »

Have you tried using a debugging emulator (FCEUX on Windows, Nintendulator, Mesen)? It should help you narrow down what's going wrong.

Guessing, the most likely reason something doesn't work when MMC3 is that your reset function isn't in the very last 8 KiB of PRG; the specific banks mapped to $8000-$DFFF aren't guaranteed on power-up.
User avatar
pinkpuff
Posts: 22
Joined: Mon Nov 26, 2012 6:12 am

Re: How to get started with MMC3?

Post by pinkpuff »

lidnariq wrote:Have you tried using a debugging emulator (FCEUX on Windows, Nintendulator, Mesen)? It should help you narrow down what's going wrong.

Guessing, the most likely reason something doesn't work when MMC3 is that your reset function isn't in the very last 8 KiB of PRG; the specific banks mapped to $8000-$DFFF aren't guaranteed on power-up.
I'm using FCEUX, though I'm not sure where to look to find out what's going wrong; all I can tell from that is that there is something going wrong since it's not setting the palettes.

I put the code at $C000.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: How to get started with MMC3?

Post by lidnariq »

Yeah, move the code to $E000 instead. Or, insert a stub that writes 0 to $8000 (so that $C000 is the fixed bank)
User avatar
pinkpuff
Posts: 22
Joined: Mon Nov 26, 2012 6:12 am

Re: How to get started with MMC3?

Post by pinkpuff »

lidnariq wrote:Yeah, move the code to $E000 instead. Or, insert a stub that writes 0 to $8000 (so that $C000 is the fixed bank)
Moving the code to $E000 had no effect. :(
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: How to get started with MMC3?

Post by lidnariq »

How big is your PRG? What happens when you open the FCEUX debugger, reset, and take the first couple steps? Does it do what you think it should?

What assembler are you using? When you say you moved the code from $C000 to $E000, did it actually move where it was in the file?
User avatar
pinkpuff
Posts: 22
Joined: Mon Nov 26, 2012 6:12 am

Re: How to get started with MMC3?

Post by pinkpuff »

lidnariq wrote:How big is your PRG? What happens when you open the FCEUX debugger, reset, and take the first couple steps? Does it do what you think it should?

What assembler are you using? When you say you moved the code from $C000 to $E000, did it actually move where it was in the file?
Here's my header:

Code: Select all

   .db "NES", $1a ;identification of the iNES header
   .db $04 ;number of 16KB PRG-ROM pages
   .db $08 ;number of 8KB CHR-ROM pages
   .db $40 ;MMC3
   .dsb 9, $00 ;clear the remaining bytes
When I opened the debugger and reset, the first instruction was 0101 then it was a bunch of 00s followed by a bunch of FFs followed by a bunch of 00s again in a repeating pattern like that. Seems very incorrect...

The assembler I'm using is ASM6. It's served me perfectly well with the default mapper.

Upon opening the file in a hex editor, it appears to be only $2000 in size to begin with, and everything after about $00A8 or so is just completely filled with 00s.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: How to get started with MMC3?

Post by lidnariq »

For that header, the file you load should be exactly 16+4*16384+8*8192=131088 bytes. Since your file is only 8 KiB, it seems safe to assume that FCEUX is loading garbage for the remainder of the file. Maybe try starting off with just your known-working NROM bit and just change the mapper number to 4 so that you can reduce the number of variables.

Since you now specify 64 KiB of PRG, you need to put the reset handler starting at 56 KiB into the file. I'm not sufficiently versed in ASM6 to know how to do that...
User avatar
pinkpuff
Posts: 22
Joined: Mon Nov 26, 2012 6:12 am

Re: How to get started with MMC3?

Post by pinkpuff »

lidnariq wrote:For that header, the file you load should be exactly 16+4*16384+8*8192=131088 bytes. Since your file is only 8 KiB, it seems safe to assume that FCEUX is loading garbage for the remainder of the file. Maybe try starting off with just your known-working NROM bit and just change the mapper number to 4 so that you can reduce the number of variables.

Since you now specify 64 KiB of PRG, you need to put the reset handler starting at 56 KiB into the file. I'm not sufficiently versed in ASM6 to know how to do that...
Taking a program that was working as an NROM and changing it to MMC3 and nothing else... works!
Changing the existing MMC3 program to have only 1 PRG page... works!

Thanks!

Although interestingly, even the working NROM rom is only $6000 in size and appears to have no vectors at the end indicating NMI, IRQ, and reset, which makes me wonder how that's even capable of working. The code seems to start right after the header.
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: How to get started with MMC3?

Post by dougeff »

$6010 bytes is a valid size for "NROM 128" boards. $10 header+$4000 PRG + $2000 CHR.

If there is only 1 bank of PRG ROM, it is loaded to $8000-bfff and mirrored at $c000-ffff.

I would expect it to work.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: How to get started with MMC3?

Post by dougeff »

To answer your original question.

If you are using asm6, you need to fill banks (if there isn't code yet) with zeros using

pad and base statements.

And to initialize the MMC3, you should explicitly set every PRG and CHR bank and set the PPU mirroring.

Your init code should be in the last $2000 bytes of your PRG ROM, which will map as the fixed bank at $e000-ffff. Your vectors will also be in this bank.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
pinkpuff
Posts: 22
Joined: Mon Nov 26, 2012 6:12 am

Re: How to get started with MMC3?

Post by pinkpuff »

dougeff wrote:To answer your original question.

If you are using asm6, you need to fill banks (if there isn't code yet) with zeros using

pad and base statements.

And to initialize the MMC3, you should explicitly set every PRG and CHR bank and set the PPU mirroring.

Your init code should be in the last $2000 bytes of your PRG ROM, which will map as the fixed bank at $e000-ffff. Your vectors will also be in this bank.
Thanks! Although I don't really understand how to use those .base or .pad statements. When I did this:

Code: Select all

   .base $6000

   .base $8000

   .base $A000

   .base $C000

   .base $E000
The rom was $4000 in size with the reset vectors at $200A-$200F. When loaded in an emulator, it doesn't function. When I did this:

Code: Select all

   .base $6000
   .pad $2000

   .base $8000
   .pad $2000

   .base $A000
   .pad $2000

   .base $C000
   .pad $2000

   .base $E000
The compiler said "Value out of range" at all the lines corresponding to the .pad statements. It wouldn't produce a rom at all.
Through trial and error, the only thing I could get to produce a functioning rom was this:

Code: Select all

   .base $8000
Which is fine until the time comes when I'll need more memory.
User avatar
never-obsolete
Posts: 411
Joined: Wed Sep 07, 2005 9:55 am
Location: Phoenix, AZ
Contact:

Re: How to get started with MMC3?

Post by never-obsolete »

For ram I use enums:

Code: Select all

.enum $6000
SomeVar:    .db 0
SomeWord:   .dw 0
SomeArray:  .dsb SIZE_OF_ARRAY
.ende
For an 8k bank:

Code: Select all

   .base $8000
   ; code/data
IF $ > $9FFF
ERROR "Bank overflow"
ENDIF
  .org $A000
Repeat for however many banks you have, changing the addresses as needed.
. That's just like, your opinion, man .
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: How to get started with MMC3?

Post by dougeff »

So, let's talk about what the assembler is trying to do.

As it goes line by line, it's counting bytes. This is so, when it sees a label, it knows what address it will have, in case it needs to use it in your code.

(Default starting address = 0)

Lda #0 (it counts 2 bytes)
Label: (this label now has the value 0002)
Sta 0 (it counts 2 bytes)
Label2: (this label has the value 0004)
Jmp Label (this will translate to jump to 0002)

Since it's a 6502, there is a max of ffff for the count, if it rolls over that, error.

You can change the assembler's count with base statements.

Base $8000

Lda #0 (it counts 2 bytes)
Label: (this label now has the value 8002)
Sta 0 (it counts 2 bytes)
Label2: (this label has the value 8004)
Jmp Label (this will translate to jump to 8002)

You can use 'org' or 'pad' statements, to tell the assembler to start counting UP to a certain address. It has to be larger than (or equal to) the current count.

Base $8000

Some code here

Pad $a000
(Will fill with zero from the end of the code till reaches $a000)

Base $8000
(Resets the count back to $8000)
Pad $a000
(Fills $2000 bytes of zeros)

Etc.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
pinkpuff
Posts: 22
Joined: Mon Nov 26, 2012 6:12 am

Re: How to get started with MMC3?

Post by pinkpuff »

I get it now. That's working.

Thanks so much for your help! That was not at all clear from the ASM6 documentation.

I've poked around with NES programming a tiny bit many years ago but this is the first time I've sat down to actually attempt to make a full game from start to finish; we'll see how far I get.
Post Reply