My emulator's MMC1 giving wrong mirroring values

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
breathermachine
Posts: 20
Joined: Wed Oct 21, 2015 10:28 pm

My emulator's MMC1 giving wrong mirroring values

Post by breathermachine »

Hello,

I am currently currently implementing MMC1 and able to play at least a few of the games without really noticeable glitches.
However when I tried to play Metroid, I found a bug in my emu where it uses an incorrect nametable mirroring for the first tunnel.
The screen just before the bugged tunnel
Image

The bugged tunnel (emu reports that it uses horizontal mirroring)
Image

Nametable view
Image

What could be possible causes for this?


I also added the result from Holy Diver Batman (using M1_P128K.nes) as I believe Metroid has the same ROM layout.
Image
What could the detailed test result "0100" mean?

Legend of Zelda has glitches also but not as bad as the tunnel in Metroid
Image
Image
Image

Thank you!
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: My emulator's MMC1 giving wrong mirroring values

Post by rainwarrior »

That room in metroid should indeed be using horizontal mirroring (which your nametable view seems to be correctly doing). It doesn't change until a few frames before the door opens, I think; the "bottom" tiles that are clearly incorrect should get written before the mirroring switch (when they are still on the "right" nametable under vertical mirroring).

I'm seeing that the writes take place in the $2C00 address area; are you correctly mirroring writes as well as reads? Is your internal VRAM implemented as only 2k of data, mapped into the address space according to the mirroring, or do you have 4k? That "bottom half" nametable in your view there should already be filled with data before the mirroring switch, and immediately after the switch it should still have the same data as the "right side" had before the switch.
breathermachine
Posts: 20
Joined: Wed Oct 21, 2015 10:28 pm

Re: My emulator's MMC1 giving wrong mirroring values

Post by breathermachine »

I think I only use 2K of actual PPU memory by using bitmasks according to the nametable mirroring
$F7FF <- for vertical mirroring (This ensures that $0800 doesnt get decoded)
$FBFF <- for horizontal mirroring (This ensures that $0400 doesnt get decoded)
lidnariq
Posts: 10677
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: My emulator's MMC1 giving wrong mirroring values

Post by lidnariq »

That's not right: it's not 4K of memory that is selectively disabled. Regardless of whether it's laid out horizontally or vertically, accessing PPU memory at $2C00 accesses the same physical memory, which isn't what masking does.
breathermachine
Posts: 20
Joined: Wed Oct 21, 2015 10:28 pm

Re: My emulator's MMC1 giving wrong mirroring values

Post by breathermachine »

So does that mean that physical address = logical address & bitmask is incorrect?
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: My emulator's MMC1 giving wrong mirroring values

Post by tepples »

Correct. There are only 2048 physical addresses. Mirroring controls whether bit 11 or 10 of the video memory address is used as bit 10 of the nametable address.

Notice that the detected mapper number in Holy Diver Batman is wrong: MMC1 is mapper 1 (SxROM), not mapper 2 (UxROM). It turns out Holy Diver Batman detects ASIC mappers through their response to writes to mirroring control registers. This should be your first hint that mirroring is messed up.

The following sequence of tests applies to both MMC1 (mapper 1) and Action 53 (mapper 28):

Set mirroring type to 2 (ABAB, vertical mirroring/horizontal arrangement)
Write $AB to $2000, which writes to $000
Write $CD to $2400, which writes to $400
Reading $2800 should produce $AB
Reading $2C00 should produce $CD

Set mirroring type to 3 (AABB, horizontal mirroring/vertical arrangement)
Write $89 to $2000, which writes to $000
Write $EF to $2800, which writes to $400
Reading $2400 should produce $89
Reading $2C00 should produce $EF
EDIT: A typo in this test has been corrected

Set mirroring type to 3
Write $65 to $2000
Write $43 to $2800
Set mirroring type to 2
Reading $2000 should produce $65
Reading $2400 should produce $43
Reading $2800 should produce $65
Reading $2C00 should produce $43
Set mirroring type back to 3
Reading $2000 should produce $65
Reading $2400 should produce $65
Reading $2800 should produce $43
Reading $2C00 should produce $43

[Do you understand why each value in this sequence is read back? If not, what's the first thing you misunderstood?]
breathermachine
Posts: 20
Joined: Wed Oct 21, 2015 10:28 pm

Re: My emulator's MMC1 giving wrong mirroring values

Post by breathermachine »

Ok I'll try to understand :)
Set mirroring type to 2 (ABAB, vertical mirroring/horizontal arrangement)
Write $AB to $2000, which writes to $000
Write $CD to $2400, which writes to $400
Reading $2800 should produce $AB
Reading $2C00 should produce $CD
I'm okay with this one
Set mirroring type to 3 (AABB, horizontal mirroring/vertical arrangement)
Write $89 to $2000, which writes to $000
Write $EF to $2800, which writes to $400
Reading $2800 should produce $89
Reading $2C00 should produce $EF
"Reading $2800 should produce $89" -> shouldn't this one be $2400 (for horizontal mirroring)?
Set mirroring type to 3
Write $65 to $2000
Write $43 to $2800
Set mirroring type to 2
Reading $2000 should produce $65
Reading $2400 should produce $43
Reading $2800 should produce $65
Reading $2C00 should produce $43
Set mirroring type back to 3
Reading $2000 should produce $65
Reading $2400 should produce $65
Reading $2800 should produce $43
Reading $2C00 should produce $43
So applying masking here (as if I'm my own emulator)
1. Set mirroring type to 3 (mask = $FBFF)
2. Write $65 to $2000
3. Write $43 to $2800
4. Set mirroring type to 2 (mask = $F7FF)
5. Reading $2000 should produce $65 -> Returns $65 ($2000 & $F7FF)
6. Reading $2400 should produce $43 -> Returns $2400 (??) ($2400 & $F7FF == $2400)
.. No need to continue further..

Now I see the problem with masking!
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: My emulator's MMC1 giving wrong mirroring values

Post by rainwarrior »

One way of looking at mirroring is that it's a way of remapping the two highest bits of the address.

Code: Select all

15 bit  8 7  bit  0
--------- ---------
0010 nnaa aaaa aaaa  <  nametable read/write address
The bottom 10 bits are used as is for accessing nametables, but the top 2 bits are used to select which nametable to use. The practice of "mirroring" remaps the 4 possible combinations of those 2 bits to the internal VRAM. For example, if you used those two bits for a lookup table, some common mirroring modes might look like:

Code: Select all

mirroring[4] = { 0, 1, 0, 1 }; // vertical mirroring
mirroring[4] = { 0, 0, 1, 1 }; // horizontal mirroring
mirroring[4] = { 0, 0, 0, 0 }; // single screen 0 mirroring
mirroring[4] = { 1, 1, 1, 1 }; // single screen 1 mirroring
You can replace those two bits "nn" with the value looked up from your mirroring table, before using the address to make a read or write. You don't necessarily have to use a lookup table, but any equivalent implementation should work.

It's a little more complicated with mappers that have 4-screen mirroring, or can otherwise map CHR-ROM or CHR-RAM into the nametable space, but this is a little more obscure, and I'm sure you can figure it out when you get there.

On the cartridge, simple mirroring is implemented by physically connecting the 10th or 11th CHR address bit to bit 10 of the VRAM address. The 10th CHR address gives a 0,1,0,1 pattern (vertical mirroring), and the 11th CHR address line gives a 0,0,1,1 pattern (horizontal mirroring), and connecting that output directly to VRAM's 10th bit address directly selects the 1k page. (Reference: Wiki: Mirroring)
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: My emulator's MMC1 giving wrong mirroring values

Post by tepples »

breathermachine wrote:Ok I'll try to understand :)
Set mirroring type to 3 (AABB, horizontal mirroring/vertical arrangement)
Write $89 to $2000, which writes to $000
Write $EF to $2800, which writes to $400
Reading $2800 should produce $89
Reading $2C00 should produce $EF
"Reading $2800 should produce $89" -> shouldn't this one be $2400 (for horizontal mirroring)?
Oops, my bad. The first read was supposed to be from $2400. I have fixed this above.
rainwarrior wrote:For example, if you used those two bits for a lookup table, some common mirroring modes might look like
And in fact, some mappers let the program fill that lookup table manually. MMC5 is one of them. There are other funky mirroring methods such as diagonal (ABBA) and L-shaped (ABBB) with their own purposes.
breathermachine
Posts: 20
Joined: Wed Oct 21, 2015 10:28 pm

Re: My emulator's MMC1 giving wrong mirroring values

Post by breathermachine »

Finally made it to work (as well as one-screen mirroring for MMC1 and AxROM). Thanks guys!
Post Reply