Your total PRG ROM size has to be less than or equal to 512KB. Valid values in the header for PRG banks are 1, 2, 4, 8, 16, 32. The mapper supports 512KB max for PRG, the ROM header specifies how many 16 KB banks there will be. 512/16=32. It should be a power of 2 because physical ROMs are.
Your total CHR ROM size has to be less than or equal to 256KB. Valid values in the header for PRG banks are 1, 2, 4, 8, 16, 32. The mapper supports 256KB max for PRG, the ROM header specifies how many 8KB banks there will be. 256/8=32. It should be a power of 2 because physical ROMs are.
Edit: 0 is valid too if you want CHR RAM.
Your reset label (and vectors) need to be in the last 8KB of your PRG data. MMC3 divides your PRG data into 8KB segments, but only the last 8KB segment (bank) is guaranteed a position on power on so reset code needs to be there. The last 8KB also needs to be mapped to $E000-$FFFF.
Disable IRQs by writing any value to $E000 after reset. (You can reenable them later when you learn about them.) To set vertical mirroring, write #$00 to $A000. To set horizontal mirroring, write #$01 to $A000. You can change this at any time, but definitely set it up to something known at the start.
Writing a value to $8000 affects how the CHR and PRG banks are arranged, as well as setting which bank a write to $8001 will change. The highest 2 bits written control how the CHR and PRG banks are arranged, the lowest 3 bits control which bank a write to $8001 will change.
For now, let's assume the highest bits are all zero. Writing #$06 to $8000 will say, "I want a write to $8001 to change which bank is at $8000-$9FFF now." Writing a 0 to $8001 will then map the first 8KB of your PRG data to $8000-$9FFF. Write a #$07 to $8000 will say, "I want a write to $8001 to change which bank is at $A000-$BFFF now." Write a 1 to $8001 will then map the second 8KB of your PRG data to $A000-$BFFF.
$8000 and $8001 are a bit like the $2006 and $2007 pair, except they can be written at any time and you write the even one once per value instead of twice. First you set what you want to change with the even register, then write the value to the odd register.
So say you're changing from a 32 KB NROM game with 8KB CHR and horizontal mirroring to MMC3.
Code: Select all
sta $E000;Disable IRQs.
sta $A000;Horizontal mirroring
ldx #$00;Not specifically MMC3, but good to do early
stx $2000; Disable NMI
stx $2001; Disable Rendering
lda #$06;We want to change $8000-$9FFF to what it was when we were 32KB NROM
sta $8000;We'll now change $8000-$9FFF when we write to $8001
sta $8001;Now the first 8KB segment of PRG is at $8000-$9FFF just like it was in the 32KB NROM version of the game.
;Now we need to make sure $A000-$BFFF is in the right place
sta $8000;We'll now change $A000-$BFFF when we write to $8001
sta $8001;Now the second 8KB segment of PRG is at $A000-$BFFF just like it was in the 32KB NROM version of the game.
;$E000-$FFFF was already in the last 8KB of PRG, and that's guaranteed for MMC3.
;$C000-$DFFF is also fine. The high bits being clear when we last wrote to $8000 guarantee this.
;Done with PRG!
lda #0; Next write to $8001 will now change the 2KB at $0000-$07FF
sta $8001;We want the first 2KB of our CHR there, so 0.
lda #1;Similar drill. Next write to $8001 will now change the 2KB at $0800-$0FFF
;This is the part that gets a bit confusing! We're selecting the start of a 1KB segment our CHR starts
;Odd numbers essentially become the even number below them.
;Since 0 is the first 1KB, and 1 is the second 1KB, and both were already mapped by changing a 2KB segment
;2 is the proper value for the next 2KB segment.
sta $8000;Next write to $8001 will now change 1KB at $1000-$13FF
lda #4;3 was the second part of the 2KB segment from the write above. So 4...
sta $8000;Next write to $8001 will now change 1KB at $1400-$17FF
lda #5;Since we're writing 1KB segments now, odd numbers are valid.
sta $8000;Next write to $8001 will now change 1KB at $1800-$1BFF
sta $8000;Next write to $8001 will now change 1KB at $1C00-$1FFF
Hopefully with the above, the chart on the wiki
will make more sense. The way it describes CHR banks is pretty technical. But it's basically:
When writing a 1KB CHR bank (2, 3, 4, or 5 was last written to $8000), the value written to $8001 directly corresponds to 1KB in CHR. 0 is first 1KB of CHR, 1 is second 1KB of CHR, 2 is third KB of CHR etc.
When writing a 2KB CHR bank, (0 or 1 was last written to $8000) write the 1KB segment you want to start on. (But... one is subtracted from odd values. So you can only start at 0, 2, 4 etc.)
The value written to $8001 for PRG chooses which 8KB segment, the value written to $8001 for CHR chooses which 1KB segment, basically.
As for how else to setup, it would be helpful to know what assembler you used to build your previous ROMs.
Edit2: As far how does the number of banks affect where to write your code. Hmm...For CHR, so long as you only add banks after the banks that are there, nothing in your code really needs to change to add CHR banks.
PRG gets a little trickier because the very last PRG bank is the fixed bank (where your reset code and vectors need to be.) If you add PRG banks after the last one, you need to move that stuff too. If you add PRG banks before the first one, your writes to $8001 all need to be offset.
If your 8KB banks in order are A, B, C, and D. 0 refers to A, 1, refers to B, 2 refers to C, 3 refers to D. If you add E before A, 0 now refers to E... so any writes you had that wanted to swap in A will now swap in E.
So ideally you add banks before your last two banks (which are fixed at specific places), but after all the other banks.
If you find any of this confusing, by all means ask! This is a general answer, but feel free to ask for a specific one.
Edit3: Swapped mirroring whoops! Changed less than to less than or equal to while I'm here...