I have been reading this forums for quite some time and never go the courage to ask for help, but i have been working a couple months trying to fix a problem with the MMC 3 and cant figure it out.
I would normally find help on this forums by searching for it but after reading many posts and unable to find the solution and anyone else who had the same problem i finally gave in and now im asking for your opinion on the issue.
Download this emulator and play SMB3 and you will see the problem asap.
webplayer.kryptonware.com/prototype/Vonsole.jar
for forum searching purposes, ill explain it here...
When loading Super Mario Bros. 3 (SMB3) i get a error. The screen loads the curtain and when it does its IRQ to start drawing the floor it freaks out. It seems to draw the screen over with black. it does this over and over and never gets out of this loop. I need help what could be the problem?
The CPU seems to be okay, it passes the instruction tests.
In Super Mario 3, the writes should look like this:
scanline 248 (vblank time):
C000 = C1 ;next value for latch
C001 = xx ;value C1 will be reloaded into the scanline counter at dot 260 of the prerender scanline
E001 = xx ;allow MMC3 interrupts
Interrupt should trigger at scanline 192, dot 260. CPU will be at the address of the IRQ handler at about dot 284-295.
scanline 193, 194:
E001 = xx ;allow MMC3 interrupts
E000 = xx ;acknowledge and disable MMC3 interrupts
All I can say is also make sure that you keep the CPU's interrupt disable bit completely separate from the MMC3 interrupts. Also make sure other possible sources of interrupts (like APU Frame IRQs or DMC) are separate too. Also make sure that instructions like CLI or PLP check for interrupts too.
You may also want to fix scrolling. Slalom is a very easy test case to see if you are updating the X scroll correctly or not.
Dwedit wrote:
Also make sure other possible sources of interrupts (like APU Frame IRQs or DMC) are separate too.
What do you mean by separate? I have a flag at the CPU to detect interrupts when starting a new cpu opcode either NMI, IRQ etc.
Dwedit wrote:
Also make sure that instructions like CLI or PLP check for interrupts too.
Just like i check a interrupt before i start a new cpu opcode?
CPU has its interrupt disable flag, and the interrupting device has its own interrupt flag. Changing the CPU's interrupt disable flag shouldn't affect the interrupting device, nor the other way around. Some people have made that mistake.
By the way, when an Interrupt or NMI happens, the CPU's interrupt disable flag is turned on automatically.
As for mentioning that CLI and PLP change the interrupt flag, and to check for interrupts at that time, checking for interrupts at the start of every instruction works too. I'm just used to writing really fast emulators that don't check those things constantly.
But I think it's really strange that Megaman 3 works fine, but Super Mario 3 fails.
Dwedit wrote:
But I think it's really strange that Megaman 3 works fine, but Super Mario 3 fails.
EDIT :
What i find even odder is that Megaman 3 does not have those messed up scanlines like the wiki says should have when selecting a boss.As for the rest, do you think i could be the PRG not being mapped correctly? seems to have something wrong with the way it reads PRG. this is just speculation because i have reviewed that part countless times and still unable to find an error.
Edit 2nd time:
Dwedit wrote:
Also make sure that instructions like CLI or PLP check for interrupts too.
Do you think that is all i need to check for interrupts is while in opcode for CLI and PLP only?
I check for interrupts after CLI, PLP, RTI, and after any event that would cause an interrupt to happen. Interrupts could still possibly happen at any time, I just wrote my code differently. Forget I ever said anything, that advice only applies to catch-up systems that keep executing instructions until the "cycles remaining" counter reaches 0, then it handles an event.
But in general, when you're having problems matching other emulators, compare logs. If you don't have logging in your emulator, add it in.
If you don't want to use logging, just watch specific events in the other emulator's debugger and see how your emulator does it differently.
For logging, try FCEUX. For watching things in a debugger, try Nintendultor or FCEUX.
Here is a log of output that i gathered from the emu, hope it helps. Maybe you can see something i cant? i removed a lot of the same thing like most of the CPU output. but did leave some in so you get a picture of what its like. Any comments is welcome. If its not enough let me know and i can post the entire log as a download file?
Code:
------------ NES Header -----------
CRC32 : 192162611
iNES Mapper Number : 4
Mirroring : Horizontal
Four Screen Mirroring : False
Number PRG Banks : 16 (262144 Bytes)
Number CHR Banks : 16 (131072 Bytes)
RAM Battery : False
-----------------------------------
END LINE : 189
A12 High : IR_counter : 3
END LINE : 190
A12 High : IR_counter : 2
END LINE : 191
A12 High : IR_counter : 1
END LINE : 192
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
A81E 10 A:00 X:00 Y:00 P:22 SP:FB
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
A81E 10 A:00 X:00 Y:00 P:22 SP:FB
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
A81E 10 A:00 X:00 Y:00 P:22 SP:FB
A12 High : IR_counter : 0
IRQ Fired
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
F795 78 A:00 X:00 Y:00 P:26 SP:F8
F796 08 A:00 X:00 Y:00 P:26 SP:F8
F797 48 A:00 X:00 Y:00 P:26 SP:F7
F798 8A A:00 X:00 Y:00 P:26 SP:F6
F799 48 A:00 X:00 Y:00 P:26 SP:F6
F79A 98 A:00 X:00 Y:00 P:26 SP:F5
F79B 48 A:00 X:00 Y:00 P:26 SP:F5
F79C AD A:00 X:00 Y:00 P:26 SP:F4
F79F C9 A:00 X:00 Y:00 P:26 SP:F4
A12 High : IR_counter : 5
END LINE : 188
A12 High : IR_counter : 4
END LINE : 189
A12 High : IR_counter : 3
END LINE : 190
A12 High : IR_counter : 2
END LINE : 191
A12 High : IR_counter : 1
END LINE : 192
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
A81E 10 A:00 X:00 Y:00 P:22 SP:FB
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
A81E 10 A:00 X:00 Y:00 P:22 SP:FB
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
A81E 10 A:00 X:00 Y:00 P:22 SP:FB
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
A81E 10 A:00 X:00 Y:00 P:22 SP:FB
A81C A5 A:00 X:00 Y:00 P:22 SP:FB
A12 High : IR_counter : 0
IRQ Fired
Try to also write down timestamps (scanline and dot) for the writes to c000-c001 and e000-e001 to see if they look good.
Also, is the code after the RTI at F8DA correct? Should jump to A81C or A81E, which is a tiny spin loop.
This Super Mario Bros 3 problem sounds vaguely familiar to me. Unfortunately if I had this problem with my emulator, I can't remember what caused it. I'd recommend checking out your IRQ behavior. Make sure acknowledging IRQs works correctly and the conditions for an IRQ are correct. You may have a problem that looks like a PRG mapping issue but it's actually caused by IRQs firing when they shouldn't.
I'm suspecting that you are running the MMC3 scanline counter during VBlank or while the background and sprites are using the same pattern table, or you have the PRG bank switching wrong for MMC3.
Batman and Tiny Toon Adventures are two other MMC3 games that crash.
There's also several things wrong with the sound code that I can hear (length counter seems to mute the note instantly no matter what length is set), so the problem could be an unwanted frame counter interrupt as well.
I would recommend extending your instruction logger to show a disassembly so that comparing with other emulators is easier.
I would also suggest looking at my emulator code at
http://code.google.com/p/halfnes since it's open source and written in Java and should be a decent reference for you. (The PPU code is not the most accurate but it is generally functional.)
Would it help if i output very detailed information into a file and have you guys analyze it? For example, I would write a class to output all given string to a file on the HD and output all of the execution step by step into that. Maybe run it until i see it flash and restart drawing again, that way its not that big of a file and i still capture the bug? Im sure if you guys search for fire and follow it from there you can immediately see what i cant see.
Edit : can someone explain to me how Blargg tests for mmc3 detect the counter clocking even when the IRQ has been disabled? My mmc 3 does not pass test 1 error 3.