It is currently Sat Oct 21, 2017 3:40 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: Mon Nov 30, 2015 9:27 pm 
Offline
User avatar

Joined: Wed Nov 19, 2014 9:00 am
Posts: 40
Location: Mexico
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 ***


Top
 Profile  
 
PostPosted: Mon Nov 30, 2015 9:51 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6289
Location: Seattle
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.


Top
 Profile  
 
PostPosted: Tue Dec 01, 2015 7:52 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 710
Location: New York, NY
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.


Top
 Profile  
 
PostPosted: Tue Dec 01, 2015 9:27 am 
Offline
User avatar

Joined: Wed Nov 19, 2014 9:00 am
Posts: 40
Location: Mexico
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 ***


Top
 Profile  
 
PostPosted: Tue Dec 01, 2015 10:39 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19113
Location: NE Indiana, USA (NTSC)
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.


Top
 Profile  
 
PostPosted: Tue Dec 01, 2015 10:59 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 710
Location: New York, NY
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.


Top
 Profile  
 
PostPosted: Tue Dec 01, 2015 11:46 am 
Offline
User avatar

Joined: Sat Jan 22, 2005 8:51 am
Posts: 427
Location: Chicago, IL
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


Top
 Profile  
 
PostPosted: Tue Dec 01, 2015 12:03 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 710
Location: New York, NY
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.


Top
 Profile  
 
PostPosted: Wed Dec 02, 2015 12:38 pm 
Offline
User avatar

Joined: Wed Nov 19, 2014 9:00 am
Posts: 40
Location: Mexico
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:
....
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:

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 ***


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 7:41 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 710
Location: New York, NY
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?


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 9:14 am 
Offline
User avatar

Joined: Wed Nov 19, 2014 9:00 am
Posts: 40
Location: Mexico
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 ***


Top
 Profile  
 
PostPosted: Fri Dec 04, 2015 8:43 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 710
Location: New York, NY
Prior to masking the address, which MMC3 games were failing?


Top
 Profile  
 
PostPosted: Fri Dec 04, 2015 11:32 am 
Offline
User avatar

Joined: Wed Nov 19, 2014 9:00 am
Posts: 40
Location: Mexico
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 ***


Top
 Profile  
 
PostPosted: Sun Dec 06, 2015 5:40 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3064
Location: Brazil
Do they work with IRQs disabled?


Top
 Profile  
 
PostPosted: Sun Dec 06, 2015 9:19 pm 
Offline
User avatar

Joined: Wed Nov 19, 2014 9:00 am
Posts: 40
Location: Mexico
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 ***


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group