How do I set up 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
BioMechanical Dude
Formerly AlienX
Posts: 137
Joined: Fri Apr 18, 2014 7:41 am
Location: Bulgaria

How do I set up MMC3?

Post by BioMechanical Dude »

So far I've been writing programs with no mapper (UNROM). I wanted to try out something with MMC3, but it turns out that simply setting up the mapper is more confusing than I thought.
Now, I do realize there's already a thread like this, but there they simply focused on fixing the problem that the person, who tried to use the mapper had, so a lot of things remain unexplained to me.
What I ask is for someone to write a step-by-step guide, that details what to put into the header, how many PRG and CHR banks are correct to use, how does the number of banks affect where to write your initial code and any special code that might be necessary to set things up. If it's simple enough, you can also add bank-switching.
I ask this, not only to get a clear idea of how to do things, but for any user, who is just starting out with this mapper and would like to know how to work with it.

Thanks!
Greetings! I'm That Bio Mechanical Dude and I like creating various stuff like movies, games and of course chiptunes!
You can check out my YouTube Channel.
You can also follow me on Twitter.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I set up MMC3?

Post by tepples »

For one thing, "UNROM" isn't "no mapper". It's a mapper that switches PRG ROM A17-A14 based on the contents of a 74HC161, OR'd with CPU A14 to provide a fixed bank at $C000.

Asking "how many PRG and CHR banks are correct to use" is is like asking "how long is a piece of string?". I can provide the minimum and maximum sizes, but I'm not going to make an exhaustive list of 16-byte headers for every possible combination of PRG ROM size, CHR ROM size, CHR RAM size, WRAM size, and mirroring behavior. Cartesian products get really big really fast.

MMC3 PRG ROM can be 16 KiB to 512 KiB in powers of two.
MMC3 WRAM is either unpopulated, 8 KiB, or 8 KiB with battery.
MMC3 CHR ROM can be unpopulated, 8 KiB to 256 KiB, or 8 KiB to 64 KiB if CHR RAM is also used, in powers of two.
MMC3 CHR RAM is either unpopulated, 8 KiB, or 32 KiB. At least one of CHR ROM or CHR RAM must be populated. A battery is not available.
MMC3 nametable mirroring can be either normal (switchable H/V) or based on the bit 7 of the CHR ROM bank (which allows oddball things like 1-screen, diagonal, or L-shaped mirroring).
TQROM rule: If a board has both CHR ROM and CHR RAM, then CHR ROM is limited to 64 KiB, and the more flexible mirroring is not available. A board containing both CHR RAM and WRAM doesn't exist officially. If it did, it would probably be as expensive as Koei's SOROM boards, as it'd need four memories.

The iNES mapper for MMC3 depends on the chosen options.
  • CHR ROM and CHR RAM: mapper 119 (byte 6: $7x, byte 7: $7x)
  • Oddball mirroring: mapper 118 (byte 6: $6x, byte 7: $7x)
  • Neither: mapper 4 (byte 6: 4x, byte 7: $0x)
Choose one combination of the above, and I can give you the remainder of the correct header for this particular combination.

In all cases, startup code must be in the very last 8 KiB bank of PRG ROM, which is fixed to $E000-$FFFF.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: How do I set up MMC3?

Post by Kasumi »

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

.org $E000
reset:
sta $E000;Disable IRQs.
lda #$01
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
lda #0
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
lda #$07
sta $8000;We'll now change $A000-$BFFF when we write to $8001
lda #1
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 $8000
lda #0
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
sta $8000
;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.
lda #2
sta $8001

lda #2
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 $8001

lda #3
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 $8001

lda #4
sta $8000;Next write to $8001 will now change 1KB at $1800-$1BFF
lda #6
sta $8001

lda #5
sta $8000;Next write to $8001 will now change 1KB at $1C00-$1FFF
lda #7
sta $8001
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...
Last edited by Kasumi on Mon Dec 04, 2017 3:48 am, edited 3 times in total.
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: How do I set up MMC3?

Post by Bregalad »

tepples wrote: MMC3 CHR RAM is either unpopulated, 8 KiB, or 32 KiB. At least one of CHR ROM or CHR RAM must be populated. A battery is not available.
Didn't know it could have 32kb of CHR-RAM. Well obviously it can, but I don't think it's Nintendo-standard to do this.
Same for battery, definitely not used on CHR-RAMs by Nintendo-standard carts, but technically nothing prevents one to do exactly that.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I set up MMC3?

Post by tepples »

Bregalad wrote:
tepples wrote:MMC3 CHR RAM is either unpopulated, 8 KiB, or 32 KiB.
Didn't know it could have 32kb of CHR-RAM. Well obviously it can, but I don't think it's Nintendo-standard to do this.
One unlicensed game published by Retrotainment Games in 2016 uses (a clone of) MMC3 with 32 KiB of CHR RAM. I posted an explanation of how it lays out CHR RAM.
User avatar
BioMechanical Dude
Formerly AlienX
Posts: 137
Joined: Fri Apr 18, 2014 7:41 am
Location: Bulgaria

Re: How do I set up MMC3?

Post by BioMechanical Dude »

Wow, thanks for your replies! Kasumi's guide was especially detailed and it cleared up a lot of stuff for me. I still have a few questions, though.

I am using ASM6 to compile my programs, and this made me wonder... how do you define the different banks that aren't mapped to any particular address? Given that there are gonna be a lot of PRG banks that simply won't fit into the address range, how do I declare them? NESASM3 has a .bank command, but ASM6 doesn't. What do I do here?

Also, when bankswitching a certain area, where code is being run from, will the CPU continue reading from the address it was on, when the bankswitch happen? For example, let's say I'm running some code from a bank in $8000-$9FFF, I bankswitch that area and the instruction that causes the switch happens at $817F. After the switch, will the CPU continue reading from $8180 or will it somehow reset to $8000?

Thanks!
Greetings! I'm That Bio Mechanical Dude and I like creating various stuff like movies, games and of course chiptunes!
You can check out my YouTube Channel.
You can also follow me on Twitter.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: How do I set up MMC3?

Post by Kasumi »

I guess the simplest answer to your address question is there are two types of address.

Even with NROM, the first byte after your header could go into $8000 in NES Memory, or it could go into $C000 in NES memory.

The NES doesn't really care where things are in your rom, only where they'll be mapped in NES' own memory.

What .org does is specify where things should be mapped in NES memory for that particular block of code. (I'll explain why I said should instead of will later.)

Code: Select all

	.org $8000
main:;endless loop
	jmp main

gets assembled as $4C (jmp) $00 $80

Code: Select all

	.org $A000
main:;endless loop
	jmp main
gets assembled as $4C (jmp) $00 $A0

Without the .org, jmp main couldn't work. There'd be no way for the assembler to know WHERE to put the jump. (Well, it could use some arbitrary starting location to assemble bytes at.)

Now, say you have the second example (.org $A000) in your first bank (bank 0).

And you did this:

Code: Select all

	lda #$06;
	sta $8000;We'll now change $8000-$9FFF when we write to $8001
	lda #0
	sta $8001;Now the first 8KB segment of PRG is at $8000-$9FFF
	jmp main
You've just put code designed to be at $A000 at $8000. So that jmp main would jmp to $A000, but that's not where you just bank swapped in the infinite loop bank. So your program would probably crash. If you did this instead:

Code: Select all

	lda #$06;
	sta $8000;We'll now change $8000-$9FFF when we write to $8001
	lda #0
	sta $8001;Now the first 8KB segment of PRG is at $8000-$9FFF
	jmp $8000
You would jmp to where you put the main loop in memory. But then immediately after, it would still jmp to $A000 and crash. ("main" is replaced with $A000 when assembled)

This is why I said "where things should be mapped" rather than "will be mapped." You can totally put blocks of code in memory where they're not designed to be, but you shouldn't.

I don't use much asm6, but as far as I can tell, you use .base and .pad

For example:

Code: Select all

;bank 0
	.base $8000;Assemble the next byte to be mapped at $8000
	nop;Now the next byte will be mapped at $8001
	.pad $A000;Fills from $8001 to $9FFF. (Will assemble the next byte at $A000)
;bank 1
	.base $A000
	;code here
	.pad $C000
	
;banks 2 and 3
	.base $8000
	;code here
	.pad $C000
;bank 4
	.base $A000
	;code here
	.pad $C000
;bank 5
	.base $A000
	;code here
	.pad $C000
;bank 6
	.base $8000
	;code here
	.pad $A000
;bank 7
	.base $8000
	;code here
	.pad $A000
.org is usually equivalent to .pad in asm6. The above demonstrates a few things. That it's possible to have two $A000-$BFFF banks in a row. That it's possible to have two $8000-$9FFF banks in a row. That it's possible to define two 8KB banks together as one 16KB bank so long as their addresses would have been contiguous. ("banks 2 and 3") A lot of people treat MMC3 as if it has 16KB banking and just swap both 8KB banks every time.
will the CPU continue reading from the address it was on, when the bankswitch happen?
The simplest answer is the bank switch is basically completely invisible to the CPU. So yes, it will totally still try to run the instruction at the address following the current instruction. The bank switch might change what's there, of course. ;) (It wouldn't specifically be one byte greater, though. Different instructions are different sizes.)

Don't do this, but what follows is a detailed example:

Say this is bank zero.

Code: Select all

	.org $8000
	lda #$06;
	sta $8000;We'll now change $8000-$9FFF when we write to $8001
	lda #1
	sta $8001;Now the second 8KB segment of PRG is at $8000-$9FFF
	jmp $8000
And this is bank one

Code: Select all

	.org $8000
	nop;a byte for lda
	nop;a byte for #$06
	
	nop;a byte for sta
	nop;a byte for $00
	nop;a byte for $80
	
	nop;a byte for lda
	nop;a byte for #1
	
	nop;a byte for sta
	nop;a byte for $01
	nop;a byte for $80
	;We are now at the same address
	;as jmp $8000 in bank zero
	lda #$00;disable rendering
	sta $2000
	sta $2001
If the code was running at $8000 in bank zero:
Mapped at $800A is jmp $8000. But at $8007 is sta $8001 that changes what's mapped at $800A. (Really, what's mapped in the whole region from $8000-$9FFF)
So it continues from $800A in bank 1 rather than bank 0. In other words, rendering will get disabled, rather than looping by jumping back to $8000.

I've attached a test ROM that demonstrates this. (Note that it doesn't do a lot of initialization it probably should, but it's good enough to show the concept in the current version of FCEUX.)

Put a breakpoint for execution at $8000, reset or power on, then step through it. You can see the next instruction change.
mmc3bankswaptest.nes
(32.02 KiB) Downloaded 479 times
I'd recommend never swapping the bank you're currently in, though. (At least not with MMC3) A good practice is having your main loop in $E000-$FFF9. You can swap in a data bank into $8000-$9FFF from there. You can swap in a bank with subroutines to read that data in $A000-$BFFF. You jsr to the subroutine, when it returns you can swap both banks again from the safety of the fixed bank.

Even if some of this goes over your head, so long as you understand the recommendation, how to "make banks" in asm6, and the "two types of address" you're fine to continue. The bank switching the bank you're in question is more theoretical than practical. At least with MMC3. AxROM swaps all of $8000-$FFFF at once. Even then, I'd probably opt for code in RAM that does the swap and jmps to the right location in the new bank.
User avatar
BioMechanical Dude
Formerly AlienX
Posts: 137
Joined: Fri Apr 18, 2014 7:41 am
Location: Bulgaria

Re: How do I set up MMC3?

Post by BioMechanical Dude »

Thank you very much! That really cleared up a lot. I will now try to compile a program, using MMC3. I'll ask, if I encounter any issues.
Greetings! I'm That Bio Mechanical Dude and I like creating various stuff like movies, games and of course chiptunes!
You can check out my YouTube Channel.
You can also follow me on Twitter.
sdm
Posts: 410
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

Re: How do I set up MMC3?

Post by sdm »

I do not want to write about MMC3 in the topic about MMC1.
https://forums.nesdev.com/viewtopic.php ... 0&start=15

That is why I continue my previous questions about MMC3 here:

I am trying to initialize the MMC3 code, but I think I got lost in everything.


I try to write an MMC3 code with 256KB PRG and CHR RAM:

Code: Select all


	.inesprg 16		;256kb prg
	.ineschr 0		;chr ram
	.inesmap 4
	.inesmir 0

Reset Code moved to E000:

Code: Select all


RESET:
	sta $e000

	sei
	cld
 
	lda #$40
	sta $4017
 
	ldx #$FF
	TXS
 
	ldx #$07
mmc3initloop:
	stx $8000
	lda mmc3tbl,x
	sta $8001
	dex
	bpl mmc3initloop
	sta $A000

	stx $2000
	stx $2001

VBlankWait1:
	BIT $2002
	BPL VBlankWait1

VBlankWait2:
	BIT $2002
	BPL VBlankWait2

	TXA
ClearMemory:
	STA $0000, x
	STA $0100, x
	STA $0200, x
	STA $0300, x
	STA $0400, x
	STA $0500, x
	STA $0600, x
	STA $0700, x

	INX
	BNE ClearMemory

	JSR CopyCHR			;copy chr data to CHR ROM

	;loadscreen, loadsprite etc

Forever:

	JSR VBWait

	JMP Forever

mmc3tbl:
	.db $0,$2,$4,$5,$6,$7,$0,$1

At the beginning, switching the bank $ 8000- $ 9FFF to the new one (0E) in which the graphics data are located (8kb chr).

Code: Select all

CopyCHR:                                 ;in e000

	LDA %00000110		;6: Select 8 KB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF)
	STA $8000
	LDA #$0E		;switch to bank 0E
	STA $8001

	;copychr data to cart chrram code

	LDA %00000110
	STA $8000
	LDA #$00		;back to bank 00
	STA $8001

	RTS
User avatar
Quietust
Posts: 1918
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: How do I set up MMC3?

Post by Quietust »

sdm wrote:

Code: Select all

	ldx #$07
mmc3initloop:
	stx $8000
	lda mmc3tbl,x
	sta $8001
	dex
	bpl mmc3initloop
	sta $A000

	stx $2000
	stx $2001

...
mmc3tbl:
	.db $0,$2,$4,$5,$6,$7,$0,$1

Remark: that code is writing #$FF to $2000 and $2001, which is not what you want it to do - you should change those to STA and insert an "LDA #$00" above the "sta $A000" just to make it absolutely clear what you're writing (even though it's already getting that value from the beginning of mmc3tbl, it's unclear and confusing and you will forget about that little detail at some point).
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
sdm
Posts: 410
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

Re: How do I set up MMC3?

Post by sdm »

ok, everything seems to work, the problem was a small trifle - before LDA% 00000110, there was no "#" character (of course, nesasm3 did not display an error and I missed the problem).

I changed the reset code. Works, but is it correct?

Code: Select all

RESET:

	sta $E000;Disable IRQs.
	lda #$01
	sta $A000;Horizontal mirroring

	sei
	cld
 
	lda #$40
	sta $4017
 
	ldx #$FF
	TXS
 
	inx
	stx $2000
	stx $2001

	lda #$06
	sta $8000
	lda #0
	sta $8001
	lda #$07
	sta $8000
	lda #1
	sta $8001

VBlankWait1:
	BIT $2002
	BPL VBlankWait1

VBlankWait2:
	BIT $2002
	BPL VBlankWait2

	TXA
ClearMemory:
	STA $0000, x
	STA $0100, x
	STA $0200, x
	STA $0300, x
	STA $0400, x
	STA $0500, x
	STA $0600, x
	STA $0700, x

	INX
	BNE ClearMemory

	JSR CopyCHR			;copy chr data to cart (

(...)

Code: Select all

CopyCHR:

	LDA #%00000110		;6 / 8000-9fff
	STA $8000
	LDA #2			;switch 0 to bank 2
	STA $8001

	LDA #$00
	STA $2006
	LDA #$00
	STA $2006

	LDX #$20		;32x 256 bytes / 8kb

	LDA #low(TileSet)
	STA <NTloadLO
	LDA #high(TileSet)
	STA <NTloadHI

	LDY #$00
CopyCHRLoop:
	LDA [NTloadLO], y
	STA $2007
	INY
	BNE CopyCHRLoop
	INC <NTloadHI
	DEX
	BNE CopyCHRLoop

	LDA #%00000110
	sta $8000
	LDA #0			;back to bank 0
	STA $8001

	RTS

Code: Select all

	.bank 2			;mmc3 bank 2
	.org $8000

TileSet:

	.incbin "demo.spr"
	.incbin "demo.chr"
Test code, 16 banks prg (256kb), chr ram, chr data in bank 2 (switched bank 8000), sound at START BUTTON in bank 17 (switched bank 8000),
a/b also switch mirroring (h/v).

I only want to switch bank 0 (address 8000-9FFF). Banks A000, C000 and E000 will not be changed. It seems that everything works, but not tested on hardware.
Attachments
demo_mmc3_d2.nes
(256.02 KiB) Downloaded 378 times
Last edited by sdm on Tue Sep 18, 2018 5:45 am, edited 2 times in total.
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: How do I set up MMC3?

Post by Bregalad »

Quietust wrote: Remark: [...] you should change those to STA and insert an "LDA #$00" above the "sta $A000" just to make it absolutely clear what you're writing (even though it's already getting that value from the beginning of mmc3tbl, it's unclear and confusing and you will forget about that little detail at some point).
A good practice when doing this kind of optimisation is to leave the instruction here, but comment it. That way you won't waste the 2 bytes of an useless "LDA #$00" instruction where you know A is already always $00, but the intent of loading #$00 into A is still here, and if you ever modify the code you can uncomment it to make it activate again.
sdm
Posts: 410
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

Re: How do I set up MMC3?

Post by sdm »

In the previous reset code I inserted the MMC3 init code, which I was thinking is some standard init code for this mapper. Maybe I did something wrong, I do not know.

viewtopic.php?f=10&t=12030&start=30#p225789

But I see, you do not need any special mmc3 initialization? Because the code I did works. As I wrote above, I only care about switching the 8000-9FFF bank without using advanced MMC3 functions (IRQ etc).
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I set up MMC3?

Post by tepples »

If you don't initialize CHR windows 0-5, you'll display wrong CHR banks. This is true even if you use CHR RAM because the MMC3 can bankswitch CHR RAM.
sdm
Posts: 410
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

Re: How do I set up MMC3?

Post by sdm »

Ok, but if I do not initiate mmc3 CHR banks at the beginning, but I will use chr banks in the standard order for NROM, then the code will work and mmc3 will read everything in the standard order? ($ 0000 4kb spr $ 1000 4kb bgr, 8kb all for one bank).

I did the test code 256KB PRG + 16KB CHR. It works, but I did not test it on the console and card with mmc3.

Code: Select all


	.bank 32
	.org $0000

TileSet0:

	.incbin "demo.spr0"		;lda 0 sta 8000, lda 0 sta 8001 = spr bank 0
	.incbin "demo.spr1"		;lda 0 sta 8000, lda 3 sta 8001 = spr bank 1
	.incbin "demo.chr0"		;lda 2 sta 8000, lda 4 sta 8001 = bgr bank 0
	.incbin "demo.chr1"		;lda 2 sta 8000, lda 5 sta 8001 = bgr bank 1
	.incbin "demo.chr2"		;lda 2 sta 8000, lda 6 sta 8001 = bgr bank 2
	.incbin "demo.chr3"		;lda 2 sta 8000, lda 7 sta 8001 = bgr bank 3

	.bank 33
	.org $0000

TileSet1:

	.incbin "demo.spr2"		;lda 0 sta 8000, lda  8 sta 8001 = spr bank 2
	.incbin "demo.spr3"		;lda 0 sta 8000, lda 10 sta 8001 = spr bank 3
	.incbin "demo.chr4"		;lda 2 sta 8000, lda 12 sta 8001 = bgr bank 4
	.incbin "demo.chr5"		;lda 2 sta 8000, lda 13 sta 8001 = bgr bank 5
	.incbin "demo.chr6"		;lda 2 sta 8000, lda 14 sta 8001 = bgr bank 6
	.incbin "demo.chr7"		;lda 2 sta 8000, lda 15 sta 8001 = bgr bank 7

;etc

Attachments
test_mmc3_e_chrom.nes
(272.02 KiB) Downloaded 374 times
Last edited by sdm on Fri Sep 21, 2018 3:02 am, edited 6 times in total.
Post Reply