A couple of questions about MMC3

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
Fumarumota
Posts: 49
Joined: Wed Nov 19, 2014 9:00 am
Location: Mexico

A couple of questions about MMC3

Post by Fumarumota »

Hi everyone,

I came up with the first implementation of MMC3 for my emulator. Right now it has a buggy IRQ counter and can run a few games decently.

The emu passes all CPU Instructions tests, PPU vbl_nmi tests (except for the NMI_on_timing one) and PPU Vram access.

I have the following questions tough:

1. Is there any initial PRG / CHR bank setup that games expect? I can run for example Mega Man 3, SMB3, Double Dragon II, SMB2, Nintendo WC... but other games like Tiny Toon Adventures, Batman Returns and Flintstones crash on bad opcodes....

My mapper starts synced with PRG mode 0 (0x8000-0x9FFF and 0xA000-0xBFFF swappable, last bank fixed to 0xE000-0xFFFF and second-last bank in 0xC000-0xDFFF) and PPU A12 inversion bit 0 as well.

2. I tried to run Blargg's MMC3 tests, but it seems to use CHR RAM along with CHR ROM (my emu crashes on writes to the CHR area because it thinks it has only CHR ROM), how can I tell? What is the best way to implement this?

Thank you very much in advance.
*** O-Nes-Sama emulator team ***
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: A couple of questions about MMC3

Post by lidnariq »

Fumarumota wrote:1. Is there any initial PRG / CHR bank setup that games expect?
No. A game should only rely on the contents of the last 8 KiB ($E000-$FFFF); the other 24 KiB could be as though the registers (R6, R7, and $8000 & 64) have random contents.
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: A couple of questions about MMC3

Post by zeroone »

Fumarumota wrote:2. I tried to run Blargg's MMC3 tests, but it seems to use CHR RAM along with CHR ROM (my emu crashes on writes to the CHR area because it thinks it has only CHR ROM), how can I tell? What is the best way to implement this?
I would have to review Blargg's MMC3 tests, but as far as CHR RAM, a value of 0 in byte 5 of the iNES header indicates that the board uses CHR RAM. Does your emulator halt on writes to ROM to enable you to detect problems? Generally, a write to ROM just does nothing.
User avatar
Fumarumota
Posts: 49
Joined: Wed Nov 19, 2014 9:00 am
Location: Mexico

Re: A couple of questions about MMC3

Post by Fumarumota »

Guys,

I got the MMC3 IRQ counter tests running, I fail all of them tough... Could this be causing errors that look like a PRG mapping issue, by jumping to the IRQ routine at the wrong time? (I think that some games working almost perfectly and others don't even starting by crashing or freezing is totally weird).

I think I've got some work to do in that regard.

Also, I have gone through the MMC3 available docs in the wiki pages and I think I have a confusion with the term "acknowledge IRQ" when writing to register E000. Does it mean that whenever the MMC disables IRQs by writing to E000, it clears its IRQ flag and pulls the CPU IRQ line back up (not touching the CPU I flag), so the MMC has to re-enable interrupts by writing the E001 register in order for IRQ to fire later, in case CPU I flag allows it?

Thanks a lot for your valuable help!
*** O-Nes-Sama emulator team ***
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: A couple of questions about MMC3

Post by tepples »

Fumarumota wrote:I think I have a confusion with the term "acknowledge IRQ" when writing to register E000. Does it mean that whenever the MMC disables IRQs by writing to E000, it clears its IRQ flag and pulls the CPU IRQ line back up (not touching the CPU I flag), so the MMC has to re-enable interrupts by writing the E001 register in order for IRQ to fire later, in case CPU I flag allows it?
Yes. From Chapter 12: Interrupts:
If a trigger flag is set, but the interrupts are disabled (I=1), [...] the request is not dismissed. Rather the request is held pending, postponed until a later time, when the system deems it convenient to handle the requests. In other words, once the trigger flag is set, under most cases it remains set until the software clears it.
[...]
Clearing a trigger flag is called acknowledgement, which occurs only by specific software action. Each trigger flag has a specific action software must perform to clear that flag.
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: A couple of questions about MMC3

Post by zeroone »

Fumarumota wrote:Also, I have gone through the MMC3 available docs in the wiki pages and I think I have a confusion with the term "acknowledge IRQ" when writing to register E000. Does it mean that whenever the MMC disables IRQs by writing to E000, it clears its IRQ flag and pulls the CPU IRQ line back up (not touching the CPU I flag), so the MMC has to re-enable interrupts by writing the E001 register in order for IRQ to fire later, in case CPU I flag allows it?
The MMC3 board interacts with the 2A03 through the processor pins. It does not have direct access to the flag registers. The board attempts to interrupt the processor by setting /IRQ to 0. And, the board keeps /IRQ at 0 until the processor acknowledges that the interrupt is being handled. The acknowledgement takes place in software; a write to $E000-$FFFE::even will cause the MMC3 board to restore /IRQ to 1.

It should be noted that the MMC3 board is linked to the /IRQ pin through additional logic. Essentially, an OR-gate is required to allow other components, such as the APU, to also have an opportunity to attempt to interrupt the processor.

When the interrupt-disable flag (I) is 1, the processor ignores the /IRQ pin value. If the I-flag is 0 and /IRQ is 0, then the processor sets the I-flag to 1 and jumps to the address in $FFFE/$FFFF. As noted above, the code that responds to the interrupt is responsible for acknowledging the interrupt.
User avatar
James
Posts: 431
Joined: Sat Jan 22, 2005 8:51 am
Location: Chicago, IL
Contact:

Re: A couple of questions about MMC3

Post by James »

zeroone wrote: It should be noted that the MMC3 board is linked to the /IRQ pin through additional logic. Essentially, an OR-gate is required to allow other components, such as the APU, to also have an opportunity to attempt to interrupt the processor.
There is a pull-up resistor attached to /IRQ that normally keeps the line high. Any device can assert an IRQ by grounding this line; no additional logic is required.
get nemulator
http://nemulator.com
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: A couple of questions about MMC3

Post by zeroone »

James wrote:There is a pull-up resistor attached to /IRQ that normally keeps the line high. Any device can assert an IRQ by grounding this line; no additional logic is required.
Thanks. I did not know the wiring details. Logically, it's like an OR-gate.
User avatar
Fumarumota
Posts: 49
Joined: Wed Nov 19, 2014 9:00 am
Location: Mexico

Re: A couple of questions about MMC3

Post by Fumarumota »

Wow, nice info I got from you guys. Now I pass all MMC3 tests except the 4-scanline_timing and 6-MMC3-alt.

The bad news are that those games I mentioned earlier and (possibly more) wont even start, crashing into bad opcodes. So I wonder if there's any gotchas about PRG mapping. Here's how i'm doing it:


On writes to $8000, I sync PRG and CHR banks according to the mode in bits 6 and 7, on writes to $8001 y update the register indicated by previous value written to $8000 & 7, then re-sync PRG and CHR:

Code: Select all

....
switch (addr & 0xE001){
        case 0x8000:
            CHRMode = val & 0x80;
            PRGMode = val & 0x40;
            regAddr = val & 0x7;
            prgProtect = val & 0x20;
            syncPRG();
            syncCHR();
            return;
        case 0x8001:
            swapRegs[regAddr] = val;
            syncPRG();
            syncCHR();
            return;
...
And here is my banks sync code:

Code: Select all


void MMC3::syncPRG(){
    if (PRGMode){
        cData.prgPtr[2] = prg[prgSize8K - 2];
        cData.prgPtr[3] = prg[swapRegs[7]];
        cData.prgPtr[4] = prg[swapRegs[6]];
        cData.prgPtr[5] = prg[prgSize8K - 1];
    } else {
        cData.prgPtr[2] = prg[swapRegs[6]];
        cData.prgPtr[3] = prg[swapRegs[7]];
        cData.prgPtr[4] = prg[prgSize8K - 2];
        cData.prgPtr[5] = prg[prgSize8K - 1];
    }
}

void MMC3::syncCHR(){
    if (CHRMode)
        {
            cData.chrPtr[0] = chr[swapRegs[2]];
            cData.chrPtr[1] = chr[swapRegs[3]];
            cData.chrPtr[2] = chr[swapRegs[4]];
            cData.chrPtr[3] = chr[swapRegs[5]];
            cData.chrPtr[4] = chr[swapRegs[0] & 0xFE];
            cData.chrPtr[5] = chr[swapRegs[0] | 1];
            cData.chrPtr[6] = chr[swapRegs[1] & 0xFE];
            cData.chrPtr[7] = chr[swapRegs[1] | 1];
            for (int i=0; i < 4; i++)
                ppu.changeCache1KBank(i, swapRegs[i+2]);
            ppu.changeCache2KBank(2, swapRegs[0]);
            ppu.changeCache2KBank(3, swapRegs[1]);
        }
        else
        {
            cData.chrPtr[0] = chr[swapRegs[0] & 0xFE];
            cData.chrPtr[1] = chr[swapRegs[0] | 1];
            cData.chrPtr[2] = chr[swapRegs[1] & 0xFE];
            cData.chrPtr[3] = chr[swapRegs[1] | 1];
            cData.chrPtr[4] = chr[swapRegs[2]];
            cData.chrPtr[5] = chr[swapRegs[3]];
            cData.chrPtr[6] = chr[swapRegs[4]];
            cData.chrPtr[7] = chr[swapRegs[5]];
            for (int i=4; i < 8; i++)
                ppu.changeCache1KBank(i, swapRegs[i-2]);
            ppu.changeCache2KBank(0, swapRegs[0]);
            ppu.changeCache2KBank(1, swapRegs[1]);
        }
}

Thanks a lot for your help. Hope I don't waste your time by missing obvious things... :S
*** O-Nes-Sama emulator team ***
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: A couple of questions about MMC3

Post by zeroone »

Fumarumota wrote:The bad news are that those games I mentioned earlier and (possibly more) wont even start, crashing into bad opcodes.
Does your emulator pass all the op code tests?
User avatar
Fumarumota
Posts: 49
Joined: Wed Nov 19, 2014 9:00 am
Location: Mexico

Re: A couple of questions about MMC3

Post by Fumarumota »

Guys, I think I solved it. It certainly was a very easy fix....

The problem was that I wasn't "ANDing" the bank number with the total number of prg rom banks in the game minus one. This was an issue because not every game has 64 8K prg banks.... For example, if my game has 32 8K PRG banks (i.e. 256 KB PRG), and the game writes bank number 48 in the PRG swap registers, bank number should be 48 & 31 = 16.

In other words, bank number needs to wrap around the total number of PRG banks. Pfff, I was getting headache with this one.

I learned a lot about IRQs and I even managed pass all IRQ tests by reading your posts :) . Thank you for your help!
*** O-Nes-Sama emulator team ***
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: A couple of questions about MMC3

Post by zeroone »

Prior to masking the address, which MMC3 games were failing?
User avatar
Fumarumota
Posts: 49
Joined: Wed Nov 19, 2014 9:00 am
Location: Mexico

Re: A couple of questions about MMC3

Post by Fumarumota »

zeroone wrote:Prior to masking the address, which MMC3 games were failing?
Several games were failing:

- Tiny Toon Adventures
- Batman Returns
- The Flintstones, The rescue of dino...
- Super C

probably others...

In the other hand, others were working:
- Super Mario Bros. 2 / 3
- Mega Man 3
- Captain America & The Avengers
- Double Dragon 2
- Nintendo World Cup

probably others as well...
*** O-Nes-Sama emulator team ***
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: A couple of questions about MMC3

Post by Zepper »

Do they work with IRQs disabled?
User avatar
Fumarumota
Posts: 49
Joined: Wed Nov 19, 2014 9:00 am
Location: Mexico

Re: A couple of questions about MMC3

Post by Fumarumota »

Zepper wrote:Do they work with IRQs disabled?
Well,

Mario 3 works but status bar is glitched. Batman Returns hangs at the first "Intro" screen. Double Dragon 2's status bar does not stay in its place. Mega Man 3 screen splits look weird, gemini man stage does not scroll at all, weapon menu does not show correctly. Capitain America & Avengers graphics appear all garbled.

Mario 2 & Super C seem to work perfectly without the IRQ enabled.

So yeah, apparently there are some games that don't use the IRQ, i guess.
*** O-Nes-Sama emulator team ***
Post Reply