mmc3 and Double Dragon 3

Discuss emulation of the Nintendo Entertainment System and Famicom.
User avatar
Anes
Posts: 717
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

mmc3 and Double Dragon 3

Post by Anes »

After 5 days of chatting with ChatGPT it seems I.A. is not the same as human intelligence.
I write this becouse im constantly getting this picture of Double Dragon 3 in my emu. This means that my MMC3 is not working well enough. I'm using code for MMC3B which is the one that this game uses.
I have checked, re-checked, written and re-written code for my mmc3 emulation.
Nothing gives me the result i want. And what i want is "Pause" in DD3 looks fine. I have checked with nester. Not to mention that i had this game when i was kid.
Anyway, i'm not putting my mmc3 logic code.

If someone knows why this image happens it would be nice to know.
I could put my mmc3 tracking a12 code, but maybe someone know what is going on here.
Thanks in advance.
Captura de pantalla 2025-10-15 201453.png
Investigating a little forward it seems that my "sprite fetch" is bad. I mean, if the emu evaluated 4 sprites to be in the scanline. What does the ppu do with the leftover sprites (the other 4 ones). Maybe there is the error, or maybe its a mmc3 logic error.
Well i post it for help. Thx
You do not have the required permissions to view the files attached to this post.
Last edited by Anes on Thu Oct 16, 2025 2:46 pm, edited 2 times in total.
ANes
User avatar
Gilbert
Posts: 615
Joined: Sun Dec 12, 2010 10:27 pm
Location: Hong Kong

Re: mmc3 and Double Dragon 3

Post by Gilbert »

The image does not show up (for me at least).
You may instead just attach the image file to your post, and it'll be uploaded to the forums.
User avatar
Anes
Posts: 717
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Re: mmc3 and Double Dragon 3

Post by Anes »

Gilbert wrote: Wed Oct 15, 2025 5:42 pm The image does not show up (for me at least).
You may instead just attach the image file to your post, and it'll be uploaded to the forums.
What that would be. I don't know another way to upload and image. I uploaded from Onedrive.
I'll try to find another way
ANes
User avatar
Gilbert
Posts: 615
Joined: Sun Dec 12, 2010 10:27 pm
Location: Hong Kong

Re: mmc3 and Double Dragon 3

Post by Gilbert »

Just click 'Add files' in the Attachment tag below the post edit area and choose a file from your computer:
スクリーンショット 2025-10-17 005902.png
You may click 'Place inline' to make it actually show inside your post.
You do not have the required permissions to view the files attached to this post.
User avatar
Anes
Posts: 717
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Re: mmc3 and Double Dragon 3

Post by Anes »

No answer?? christ!!

Well my a12 "tracking" works as follow:

Code: Select all

void CheckA12(u16 ppuAddr)
{
	bool a12 = (ppuAddr & 0x1000) != 0;
	if (!mmc3.prevA12 && a12) { // rising edge
		if (mmc3.lowTimer >= 8) { // at least ~8 PPU cycles low
			ClockIRQCounter();
		}
		mmc3.lowTimer = 0;
	}
	if (!a12) {
		mmc3.lowTimer++;
	}
	mmc3.prevA12 = a12;
}
This function is called everytime ppu fetchs something, but is limited to < 0x2000. I mean the func looks like:
In few words is called by "ReadPpuMem()" when the cart tries to read data. But i call it this way:

Code: Select all

u8 ReadPpuMem(u16 addr)
{
	if (ppu.mmc3)
		if (addr < 0x2000)
			CheckA12(addr);
	return chr_map.ReadChr[addr >> 10](addr);
}
So the above "CheckA12(ppuAddr) its called when the 16 bit address is lower than 0x2000.
CheckA12 actually waits for 8 >= cycles to "see" if there was and a12 rise and is not so close together between them.
I increment this "lowtimer" if and only if a12 is low.
Clocks the irq counter when prevA12 is false and a12 is true, the "low counter" is reset since a12 is high and the MMC3 irq counter has been clocked.
My mmc3 irq counter looks like:

Code: Select all

void ClockIRQCounter()
{
	if (mmc3.irq_counter == 0 || mmc3.irq_reload) {
		mmc3.irq_counter = mmc3.irq_latch;
		mmc3.irq_reload = false;
	}
	else {
		mmc3.irq_counter--;
	}
	if (mmc3.irq_counter == 0 && mmc3.irq_enable)
		SetIRQ(true);
}
And talking about the mmc3 registers i issue:

Code: Select all

anoter cases here...
else if (addr >= 0xC000 && addr <= 0xDFFF)
{
	if (addr & 0x01)
		mmc3.irq_reload = true;
	else
		mmc3.irq_latch = data;
}
else if (addr >= 0xE000 && addr <= 0xFFFF)
{
	if (addr & 0x01)
		mmc3.irq_enable = 1;
	else
	{
		mmc3.irq_enable = 0;
		SetIRQ(false);
	}
}
Register $4015 acknowlade fine, it stops irq for happening.
That's is everything i have to say. I don't know why "Double Dragon 3" pause screen looks scratched.
ANes
Fiskbit
Site Admin
Posts: 1380
Joined: Sat Nov 18, 2017 9:15 pm

Re: mmc3 and Double Dragon 3

Post by Fiskbit »

Alright, I have several thoughts.

In the image in your original post, there's actually not supposed to be an IRQ on that screen at all. Looking in Mesen, I see that the IRQ reload value is 72, which is approximately when your unexpected raster split occurs. Mesen thinks MMC3 IRQ is enabled, though. What actually prevents the IRQ from happening is the CPU's I flag. The I flag is set, so IRQs are ignored by the CPU. You should make sure that your MMC3 IRQs are respecting the I flag and that the I flag is set here as it should be.

As for A12 handling in general, MMC3 only looks at two things: the A12 bit and M2, the CPU's clock output. If A12 has been low for at least 3 M2 edges in a row and then goes high, then the scanline counter is clocked. A12 doesn't care whether the CPU address is a pattern table address or a nametable address; it's only looking at A12, so it will respect it regardless of the type of address. It also doesn't even care if the PPU is reading or writing; there is a quirk where the PPU puts a background pattern lsbit address on the bus on dot 0, but doesn't read from it, and this is expected to refresh the M2-based filter so that extra clocks don't happen. Furthermore, because addresses are put on the bus a dot before the memory access happens, it's actually the first dot that typically clocks the counter, not the second one.

Some games will also manually toggle A12 during vblank by writing to $2006. Although the PPU isn't reading from or writing to these addresses, the toggles are expected to clock the scanline counter.
User avatar
Anes
Posts: 717
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Re: mmc3 and Double Dragon 3

Post by Anes »

You were right, i had a problem with "Interrupt" flag. My NMI() handler wasnt setting it.
Now it works like a charm.

Thank you very much!! :)
Captura de pantalla 2025-10-22 154155.png
You do not have the required permissions to view the files attached to this post.
ANes