MMC3 RevA vs. RevB IRQ question

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
jwdonal
Posts: 719
Joined: Sat Jun 27, 2009 11:05 pm
Location: New Mexico, USA
Contact:

MMC3 RevA vs. RevB IRQ question

Post by jwdonal »

Which type of IRQ counter reload (i.e. "natural" / "reset") has priority if the IRQ counter is 0, the user sets the reset request flag (via $C001) before the next A12 rise, _and_ the reload value ($C000) is 0.

So the scenario is:
- the IRQ counter is 0
- the $C001 reset flag is set
- the value in $C000 is 0
- when the next A12 rise comes along the IRQ controller has 2 choices
1) Perform a "natural" reload since the IRQ counter is 0
2) Perform a "reset" reload since the $C001 reset flag is set


It matters because the 2 mappers react differently for a "natural" reload. If the answer is (1) then it's different depending on the mapper revision. If the answer is (2) then it's the same for both revisions.

Here is a quote from Disch on the 2 types of reloads that can occur and the difference in mapper revisions (with minor mods by me for clarity - I hope):
There are two ways the IRQ counter can be reloaded:
1) "natural" reload caused by an A12 rise when the IRQ counter is 0
2) "reset" reload caused by an A12 rise after $C001 has been written to.

If $C000 is set to 0...

...in a RevA mapper, then...
--> a "natural" reload does not trigger IRQ
--> a "reset" reload triggers IRQ

OR

...in a RevB mapper, then...
--> a "natural" reload triggers IRQ
--> a "reset" reload triggers IRQ
Anyone know the answer?

Pz
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

I don't have the MMC3 behavior in my mind to answer the question. Have you tried just implementing both and seeing if the MMC3 tests rule one out?

In a private message you asked how I tested these things. It's pretty simple:
  • Using some other devcart, start code in internal NES RAM.
  • Remove cartridge while code still runs (CIC is disabled in NES).
  • Insert unmodified MMC3/whatever cartridge to test on.
  • Instruct my code to perform tests.
My NES communicates with my PC via a serial power emulated with the second controller port, so I easily keep uploading new code to test while the normal, unmodified cartridge is inserted. That's the basic scheme. I recently made a modification to my NES that will map $E000-$FFFF reads to $6000-$7FFF in the cartridge, but not affect writes. With that enabled, the MMC3 cart's WRAM is mapped to $E000, allowing me to set my own IRQ vector and have the code think it's running from ROM.

Oh, and let's help correct my erroneous naming of revisions. What I called MMC3A and MMC3B were really both MMC3B, at least as marked on the chips. Better terminology seems to be MMC3 and MMC6; this matches kevtris' documentation. So, (my) Crystalis game uses an MMC3B that has MMC6-style IRQ counter behavior. I've used this newer naming scheme in the new MMC3 tests I put up. Sorry for the confusion my older, incorrect naming has caused.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Post by thefox »

blargg wrote:[*] Remove cartridge while code still runs (CIC is disabled in NES).
Let me hijack this thread for a second since I was thinking about this couple of days ago. Is disabling CIC all that is required to do to be able to "hotswap" cartridges (with code in RAM)?
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Yeah, just disable CIC (same for SNES, can swap there after that as well). Here's some code to run while doing the swapping:

Code: Select all

        ; Play tone for 6 seconds while
        ; continuously doing sprite DMA
        ldy #6 * 13
loop:   sta $4011
        sta $4014
        eor #$10
        dex
        bne loop
        dey
        bne loop
It makes a tone as long as the code hasn't crashed, and constantly does sprite DMA, so that most of the time the CPU isn't executing any instructions, and thus won't crash if garbage gets on the bus momentarily.

I tried to test the code as compared to one that doesn't do sprite DMA, but I couldn't get anything to crash, even when constantly inserting and removing a couple of cartridges.
User avatar
jwdonal
Posts: 719
Joined: Sat Jun 27, 2009 11:05 pm
Location: New Mexico, USA
Contact:

Post by jwdonal »

blargg wrote:I don't have the MMC3 behavior in my mind to answer the question. Have you tried just implementing both and seeing if the MMC3 tests rule one out?
Good question. So I just tried reversing the priorities and I can still get both your MMC3 and MMC6 ROMs to pass (by flipping a DIP-switch on my board). So your current tests do not answer this question.
blargg wrote:So, (my) Crystalis game uses an MMC3B that has MMC6-style IRQ counter behavior.
Wow, that's weird. So is there any way to know which games have an MMC3 chip with MMC6 style IRQs?

Also, that's a really sweet test setup you have blargg. nice. thanks for the info
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

OK, I got the MMC3 model back in my mind and indeed, the case you describe wasn't tested. I put up newer MMC3 tests on the wiki that test this. In the case you describe, the clear takes precedence, so you DO get an interrupt on MMC3_alt. Here is code that passes in my emulator for both versions of MMC3:

Code: Select all

bool mmc3_alt_behavior;
bool irq;
bool enabled;
bool clear;
int latch;
int counter;

void write_mmc3( int addr, int data )
{
    switch ( addr & 0xE001 )
    {
    case 0xC000:
        latch = data;
        break;
    
    case 0xC001:
        if ( mmc3_alt_behavior )
            clear = true;
        counter = 0;
        break;
    
    case 0xE000:
        irq     = false;
        enabled = false;
        break;
    
    case 0xE001:
        enabled = true;
        break;
    }
}

void clock_counter()
{
    int old = counter;
    
    if ( counter == 0 || clear )
        counter = latch;
    else
        counter = counter - 1;
    
    if ( (!mmc3_alt_behavior || old != 0 || clear) && counter == 0 && enabled )
        irq = true;
    
    clear = false;
}
And I give up on naming these MMC3 versions. I just tested on my MMC6 Startropics and it behaves like all my other MMC3 carts, but NOT like Crystalis. Now in the tests I just call it MMC3_alt. I'l leave it to someone else to make sense of...
User avatar
jwdonal
Posts: 719
Joined: Sat Jun 27, 2009 11:05 pm
Location: New Mexico, USA
Contact:

Post by jwdonal »

Wow!! Thanks Blargg! I wasn't expecting that. Very much appreciated. I think we can now officially say that every possible scenario/case/priority of the MMC3 IRQ output has been documented (and tested).

Pz!
User avatar
James
Posts: 431
Joined: Sat Jan 22, 2005 8:51 am
Location: Chicago, IL
Contact:

Post by James »

blargg - I've found that setting the irq counter to zero on writes to $C001 causes problems for Gauntlet II (granted, it could be some other bug, but most other mmc3 titles are working well). Specifically, when the player crosses in/out of the lower ~10% of the map, the background will glitch (will upload a pic if you want it). Can you recreate this with your implementation?
get nemulator
http://nemulator.com
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

How would a $C001 write in the above code cause anything to happen when mmc3_alt_behavior is false? Without knowing how your code works, I don't know what effect not clearing the counter would have. Care to distill yours into something similar to the above, for comparison?
User avatar
James
Posts: 431
Joined: Sat Jan 22, 2005 8:51 am
Location: Chicago, IL
Contact:

Post by James »

disregard... stupid bug :roll:

edit: ok, maybe not terribly stupid. I was combining the behavior of both MMC3 versions because I didn't really understand what was going on there. After re-reading this thread, and some previous posts, I think I have a handle on it now.
get nemulator
http://nemulator.com
User avatar
jwdonal
Posts: 719
Joined: Sat Jun 27, 2009 11:05 pm
Location: New Mexico, USA
Contact:

how to tell

Post by jwdonal »

Okay, so my last question on this is: Is there anyway to tell which game uses which style of IRQ? Aside from someone like Blargg manually checking each game??? As far as I understand it is not based on revision. What about MMC3 IC date codes? Maybe something like, "All games manufactured after such and so date have IRQ style B (alt) behavior."?

BootGod's NES cart database seems to have real nice hi-res images of the PCBs that maybe we can make out date codes from. Or are we all just sol?
BootGod
Posts: 359
Joined: Wed Jul 13, 2005 3:14 pm

Post by BootGod »

BootGod's NES cart database seems to have real nice hi-res images of the PCBs that maybe we can make out date codes from. Or are we all just sol?
Well date code info is already available for most profiles (right side of detailed chip info), no need to squint at images to find them. If it's not MMC revision and not based on date, one other possibility is the chip maker, both NEC and Sharp made them. Seems unlikely, but keep it in mind I guess.

If anyone has a list of some games that use a specific IRQ type, it shouldn't be too hard to figure out the common ground between them using the DB info.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

In a posting a while back, I noted how the MMC3B chips in Crystalis and SMB3 were manufactured a few weeks apart.

Aha! the MMC3B in SMB3 has a bold, short S before the date code. It seems the S stands for Sharp, because some other Sharp IC pictures on the web have the same S. This chip is also really thin. The MMC3B chips in Mega Man 3 and MC Kids, which also pass the "non-alt MMC3" test, are also the same, with the S. The MMC3B in Crystalis has no S, uses a different font, and is a lot thicker. Same pinout and package, and I also went through with a meter to see if the same pins were grounded and pulled up, which they are.

I notice on BootGod's database (awesome site!), Mega Man 3 doesn't have an S on the MMC3B, MC Kids does, and Crystalis DOES. In my NES emulator, I had put in a check for games which trigger the behavior that differs, and I don't think any did. So either behavior is fine, though it seems the Sharp version is more common, so that seems the best behavior to emulate (reload=0 keeps triggering an IRQ every line).

EDIT: Pretty much confirmed. I gathered all my MMC3 carts, opened them, and tested which behavior they had. The presumably-Sharp chips have normal, non-Sharp have alt behavior, and Sharp seems more common:

MMC3
Conquest of the Crystal Palace (MMC3B S 9039 1 DB)
Kickle Cubicle (MMC3B S 9031 3 DA)
M.C. Kids (MMC3B S 9152 3 AB)
Mega Man 3 (MMC3B S 9046 1 DB)
Super Mario Bros. 3 (MMC3B S 9027 5 A)
Startropics (MMC6B P 03'5)

MMC3_alt:
Batman (MMC3B 9006KP006)
Golgo 13: The Mafat Conspiracy (MMC3B 9016KP051)
Crystalis (MMC3B 9024KPO53)
Legacy of the Wizard (MMC3A 8940EP)

The MMC3A (lucky I have one of those) suggests that the non-Sharp chips are based on an earlier revision of MMC3B. The normal MMC3 behavior makes more sense, generating an IRQ on every scanline when reload is zero, rather than just stopping altogether.
BootGod
Posts: 359
Joined: Wed Jul 13, 2005 3:14 pm

Post by BootGod »

NEC and Sharp both made all 3 revisions of the chip, is this how you believe they work?:

IRQ alt: MMC3A (both), MMC3B (NEC)
IRQ normal: MMC3B (Sharp), MMC3C (both)

I could test all 6 chips to verify, assuming I can test them with CopyNES anyways. I've never done any kind of IRQ tests so I'm not exactly sure how to go about it.

The XML currently doesn't export chip maker, I guess I'll have to work that in sometime.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Yeah, I'm thinking maybe all MMC3A have alt behavior, but I don't have any other MMC3A carts to verify that with.

I could make versions of the tests that work with CopyNES, though I'm not sure how it's set up. If you put an unmodified MMC3 cart in, what all extra does CopyNES add? Any extra RAM? Any way to modify the IRQ vector? For testing my carts, I had to connect a wire from /IRQ to the D3 input on the first controller port, so I could monitor it, as I couldn't change the IRQ vector. :)
Post Reply