Help regarding MMC1 behavior

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Help regarding MMC1 behavior
by on (#138466)
Hi guys,

I'm seeking your help once more to figure out a couple of things about the MMC1 mapper.

I've gone through the docs in the wiki, as well as the ones in Kevin Horton's site, back and forth. I managed to come up with some crappy implementation in my emulator, enough to run some games flawlessly (for example Mega Man 2, Castlevania II, Goal!, Lolo 3, Metroid), but others fail big time (like Bart vs Space Mutants (runs into a bad opcode, then crashes), Chip n' Dale 2 (crashes at loading), Double Dragon(Freezes at initial scene, before the "mission 1" screen)).

I lock the last PRG bank to 0xC000, making the one at 0x8000 switchable at reset. (Writing 0xC to 0x8000 - 0x9FFF)

On writes to the CHR Switch registers (1 and 2), I immediately switch the 8k / 4K bank into 0x0000 or 0x1000. In 8k Mode, low bit of reg 1 is ignored, and reg 2 is totally ignored.

On Writes to PRG Switch Reg (0xE000-0xFFFF), I immediately switch the 16k switchable bank (depending on the mode), nothing is done to the fixed banks. On 32K mode I use 2 16K Banks, for example, if bank number is 0, I place bank 0 in the upper 16K space and bank 1 in the lower 16K space, same if bank number is 1, making this a 32K block.

I'm pretty sure I've implemented the shift register correctly (only in the fifth write does the address matters, I select the register using bits 13 and 14 of the address, reset the load counter as well as the shift register after the 5th write.), as well as all the register's bits. Also 4k / 8K CHR banks seem to be switched correctly as well. PRG RAM is permanently enabled.

Currently I don't ignore consecutive writes to the mapper registers.

NMI Timing and CPU Instruction tests all pass. Sprite Zero hit tests pass as well. No sprite overflow implemented yet.

My question is, how exactly should I treat writes to the control register 0. Should I update the other registers with the last value written to them whenever PRG / CHR bank switch mode changes. How do I know which PRG banks remain where on a PRG mode change? Am I missing something?

Thank you in advance for your help.
Re: Help regarding MMC1 behavior
by on (#138472)
You got the order wrong for 32k banks.
Re: Help regarding MMC1 behavior
by on (#138491)
You should just remember that the regs 1-3 are basically mapped to the EPROM's address directly through combinational logic. If there is a PRG switching mode change, then the corresponding PRG bank written to reg 3 immediately applies to the new mode. For example, if bank #0 was swapped in $8000-$bfff, and the last bank is in $c000-$ffff and then the program switch to 32k switching mode, then bank #1 is immediately present in $c000-$ffff as a direct consequence.

The exact same for CHR banks, too.
Re: Help regarding MMC1 behavior
by on (#138844)
Thanks a lot guys, I think I've fixed most of my PRG Switching on MMC1.

Now just one more question:

At mapper reset, what should be the status of the CHR Banks? I mean, for PRG it is known that the last bank is hard-wired to the CPU 0xC000-0xFFFF range and the bank at CPU 0x8000-0xBFFF is somehow random / undefined until it's switched or mode changes. But what about CHR? I assume that PPU 0x0000 is just hard-wired to the first 8K of CHR-RAM / ROM in the cart. Is that correct?

My apologies in advance if this is a silly question. I just can't seem to find this info in any doc and wanted to make sure.

Thanks and happy new year everyone!
Re: Help regarding MMC1 behavior
by on (#138845)
The initial CHR banks are also unspecified. A game's init code needs to set them. And games on SUROM or SXROM, which use CHR ROM A16 as PRG ROM A18 to select one of two 256 KiB outer banks, need to have init code in both bank 15 and bank 31.
Re: Help regarding MMC1 behavior
by on (#139227)
I see, that was very informative.

After adding fixes, it appears that my mapper runs all the games I throw to it perfectly except one: "The Simpsons - Bart vs. the Space Mutants (USA)", which runs into unofficial opcode $02 (one of the many KIL's). It's got to be something on the PRG handling, definitely looks like a mapper issue (CPU passes all tests except the interrupt hijacking ones). It's trying to execute code from a system ram range (0x200-0x2FF), Sprite DMA copying takes place at range 0x300-0x3FF, so no corruption that I can spot on that side. Addresses look OK, but the opcodes and arguments are screwed up (Compared logs with FCEUX).

Do you know if there's anything obscure or tricky when trying to emulate this game?

I will keep debugging my core / mapper and see if I catch anything.

Thanks guys, you've helped me big time.