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.
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
mmc3 and Double Dragon 3
-
Anes
- Posts: 717
- Joined: Tue Dec 21, 2004 8:35 pm
- Location: Mendoza, Argentina
mmc3 and Double Dragon 3
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
-
Gilbert
- Posts: 615
- Joined: Sun Dec 12, 2010 10:27 pm
- Location: Hong Kong
Re: mmc3 and Double Dragon 3
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.
You may instead just attach the image file to your post, and it'll be uploaded to the forums.
-
Anes
- Posts: 717
- Joined: Tue Dec 21, 2004 8:35 pm
- Location: Mendoza, Argentina
Re: mmc3 and Double Dragon 3
What that would be. I don't know another way to upload and image. I uploaded from Onedrive.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.
I'll try to find another way
ANes
-
Gilbert
- Posts: 615
- Joined: Sun Dec 12, 2010 10:27 pm
- Location: Hong Kong
Re: mmc3 and Double Dragon 3
Just click 'Add files' in the Attachment tag below the post edit area and choose a file from your computer:
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.
-
Anes
- Posts: 717
- Joined: Tue Dec 21, 2004 8:35 pm
- Location: Mendoza, Argentina
Re: mmc3 and Double Dragon 3
No answer?? christ!!
Well my a12 "tracking" works as follow:
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:
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:
And talking about the mmc3 registers i issue:
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.
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;
}
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);
}
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);
}
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);
}
}
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
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.
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.
-
Anes
- Posts: 717
- Joined: Tue Dec 21, 2004 8:35 pm
- Location: Mendoza, Argentina
Re: mmc3 and Double Dragon 3
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!!
Now it works like a charm.
Thank you very much!!
You do not have the required permissions to view the files attached to this post.
ANes