What's going on with the MMC5 counter?

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.
Drag
Posts: 1708
Joined: Mon Sep 27, 2004 2:57 pm

What's going on with the MMC5 counter?

Post by Drag »

Might as well have this too. :P
Blargg did some RE work on it
Here's the wiki page for it
Disch's mapper docs are valuable too

So unless there's been some kind of breakthrough that hasn't been posted or documented anywhere, I'm going to assume that, since these sources all say they don't know how the IRQ counter specifically detects scanlines, I'm going to assume nobody knows how it works.

The current theory is that the MMC5 monitors the PPU address lines to detect scanlines. The MMC5 already has to monitor the address lines so that it knows when to inject its own extended tile/attribute data into the PPU.

The current theory is that the MMC5 watches for the two dummy nametable reads that occur at the end of each scanline. The easiest way I can think of to get this to work is to just check to see if the PPU fetches the same address twice in a row.

In theory, the PPU will never fetch from an address twice in a row. (This is unless the garbage nametable fetches during sprite fetches can be the same, but if the sprite fetches use the same circuit as the bg fetch, wouldn't it be a garbage nametable fetch, and then a garbage attribute fetch? That would always be two different addresses) The only time it does fetch from the same address twice is during those two dummy fetches at the end of the scanline.



However, there's also another potential way to get this to work:

Conveniently, A13 toggles for each tile, because the PPU fetches nametable/attribute data, and then pattern table data. A13 is high during the nametable fetch and the attribute fetch, and it's low during the pattern table fetches.

Since the MMC5 is likely already monitoring A13 to detect tiles, maybe it's also counting how many times A13 rises per scanline? A13 will rise exactly 43 times each scanline: 32 times for the BG tiles, 8 times for the sprites, 2 times for the two tiles of the next scanline, and then once for the two dummy nametable reads at the end of the scanline.

This probably isn't how it's done though, because the MMC5 seems to know exactly when a scanline starts, such that it can set the in-frame flag on the next scanline, when the PPU rendering is activated mid-scanline that is.
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Post by qbradq »

I have to agree that watching for those two consecutive read accesses to the $2000-$2FFF address range seems to be how it is done. Thinking from the hardware side I can see a very convenient (and low pin-count) way of detecting this.

You will need to capture the CHR A11, CHR A12 and CHR /RD signals. This should only add two input pins as CHR A11 is already used for name table mirroring.

Here is what the MyHDL code might look like:

Code: Select all

@always(chr_rd_n.negedge)
def irq_clock():
	if chr_a12 == 0 or chr_a11 == 1:
		flags_irq_nt_fetch_last_frame.next = 0
	elif flags_irq_nt_fetch_last_frame == 0:
		flags_irq_nt_fetch_last_frame.next = 1
	else:
		flags_irq_nt_fetch_last_frame.next = 0
		flags_irq_in_frame.next = 1
		irq_counter.next = irq_counter + 1
		if irq_counter + 1 == irq_target:
			flags_irq_pending.next = 1
			out_irq_n.next = 0
I actually like this better than the MMC3 IRQ counter's implementation :D
Drag
Posts: 1708
Joined: Mon Sep 27, 2004 2:57 pm

Post by Drag »

qbradq wrote:You will need to capture the CHR A11, CHR A12 and CHR /RD signals. This should only add two input pins as CHR A11 is already used for name table mirroring.
Why CHR A11? That's the vertical nametable select bit.

I was thinking you'd need to latch A6-A9 when A13 is high and A12 is low, then check to see if A6-A9 is the same for two consecutive fetches. A6-A9 is 1111 during attribute fetches, and less than 1111 during "normal" nametable fetches. However, if you set the internal PPU registers improperly (as in, set the Y scrolling >= $F0, or set the scrolling by writing $03C0 to $2006), then the nametable could fetch attribute data as nametable data, in which case, the MMC5 would see a whole bunch of double %xxxxx1111xxxxxx fetches. Depending on how the MMC5 compares the reads, this could either cause 34 extra scanline clocks (if the MMC5 simply checks to see if A6-A9 is the same) for up to 16 scanlines, or the scanline counter would be delayed by up to 16 scanlines (if the MMC5 specifically checks for two reads where A6-A9 != 1111)

However, if the MMC5 checks the entire PPU address to see if it access the exact same byte twice, then improperly setting the scrolling as I've stated above will cause exactly one extra scanline clock on up to 8 scanlines, as the ppu accesses %10xx1111111111 twice during visible scanline rendering (once as a nametable fetch, and the other as an attribute fetch)

This is pretty cool, because these are all situations that are easily testable on an MMC5 cart, using just software, and if any of those quirks occur, then we know for certain that it looks for duplicate sequential reads. :D
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Post by qbradq »

Ah, now I see why folks have been saying it looks for three consecutive reads from the $2000-$2FFF range. We can use the same method if we revise the code to clock on the third consecutive read to that address range.

This does not address the issue of setting the in_frame flag, but I am not worried about that for my purposes :D
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Post by qbradq »

I've hit a snag. How does the MMC5 detect the end of the frame? Perhaps by listening for the idle bus during scanline 241? If so, how would this be accomplished? Some sort of counter maybe? Clocked by M2?
User avatar
tokumaru
Posts: 12668
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Do you really have to stick to the exact same technique used by an actual MMC5? As long as the scanline counter is reliable and the same registers are used to interface with it, the exact internal workings shouldn't matter, right?

Can anyone think of a decent way to count scanlines that will not break with different pattern table and sprite sizes configurarions? I don't think it has to be the exact same solution used by the MMC5, specially considering the MMC5 doesn't work on clones (not sure if the scanline counter has anything to do with this, but still).
tepples
Posts: 22993
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)

Post by tepples »

tokumaru wrote:Do you really have to stick to the exact same technique used by an actual MMC5?
If we want programs to be testable in existing emulators during development, we have to use either A. the same technique or B. another technique where all behavioral differences between the techniques are documented. That's one reason why we want to know exactly how the MMC5 behaves: so we can document the differences between it and a subset clone. Otherwise, the maker of these cartridge boards will have to arrange for mapper plug-ins to be made available for some emulator on each major PC platform. We don't want to develop programs that rely on emulator behaviors that differ from the actual hardware.
User avatar
tokumaru
Posts: 12668
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

What I mean is that as long as the same regirsters are used to interface with the mapper, and the overall timing is the same (i.e. interrupts fire at the same time in the scanline) the actual scanline counting method doesn't matter. Emulators will not be able to tell the difference... as far as they are concerned the software will appear to be using an MMC5.
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Post by qbradq »

I didn't know the MMC5 does not work on clone systems. Now I finally have an excuse to grab a copy of Laser Invasion or Uncharted Waters and try it :D

Anyhow, I am open to trying different scan line detection methods. My major problem is I do not have a logic analyzer or scope, so I have to guess at what the NOAC is actually doing. Perhaps it does not make the dummy NT reads at the end of the scan line?
User avatar
Bregalad
Posts: 8181
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

I have a Gemfire card I was planning to sacrifice one day anyways, so if someone can make test ROMs for the scanline counter but can't test them because of the lack of the possibility to test them on a MMC5, I could handle that.
What I mean is that as long as the same regirsters are used to interface with the mapper, and the overall timing is the same (i.e. interrupts fire at the same time in the scanline) the actual scanline counting method doesn't matter. Emulators will not be able to tell the difference... as far as they are concerned the software will appear to be using an MMC5.
If both methods are extremely accurate and works every time, and give an IRQ on the same cycle, then yes. Otherwise....

For example, at first glance you could say that with the MMC3's counter. However :
- it will count if you do $2006 writes that will clock it
- it will screw up if you use sprites from the BG pattern table
- it will screw up if you enter into forced blanking mode
etc... etc...

That's why it's important to get the exact behavior of the mapper.
I didn't know the MMC5 does not work on clone systems.
I think most clone systems have CIRAM /CE and CHR /A13 wired together internally. So any cart who tries to do something fancy with nametables, such as 4-screen mirroring or using VROM for nametables, or adding an extra nametable will not work.

In addition to that the MMC5 might use the CHR A13 or CHR /A13 lines for counting because it toggles accurately between each pattern and nametable reads, no matter how the chip is programmed (the only condition for this is that the PPU is not in forced VBlank mode).
Useless, lumbering half-wits don't scare us.
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Post by qbradq »

Bregalad wrote:I have a Gemfire card I was planning to sacrifice one day anyways, so if someone can make test ROMs for the scanline counter but can't test them because of the lack of the possibility to test them on a MMC5, I could handle that.
I can write up the test ROM. I am working on one anyway :D Do you have a clone system to test on as well? That would help me out a ton.

What exactly do you want tested?
Bregalad wrote:In addition to that the MMC5 might use the CHR A13 or CHR /A13 lines for counting because it toggles accurately between each pattern and nametable reads, no matter how the chip is programmed (the only condition for this is that the PPU is not in forced VBlank mode).
Yuck, that really bites if you're a fan of CV3. The sub-set I am interested in does not do anything of the sort though, so I might be OK on that front. Thanks for the info.
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Post by qbradq »

Speculation on Detecting PPU Idle Time

Ok, so here's the revised plan of checking for CPU idling. I'll use HDL pseudo-code as that seems appropriate.

Code: Select all

On the falling edge of CHR /RD:
	Set flag_ppu_reading True
	If CHR A11 == 0 and CHR A12 == 1: // Reading from $2000-$2FFF, or $6000-$6FFF, etc.
		Increment ppu_nt_read_count
	Else:
		Set ppu_nt_read_count to 0
	If ppu_nt_read_count >= 3:
		// CLOCK IRQ COUNTER HERE

On the rising edge of PRG M2:
	If flag_ppu_reading is False:
		If flag_ppu_not_reading_last_clock is True:
			Set flag_ppu_idle True
		Else:
			Set flag_ppu_not_reading_last_clock False
			// RESET IRQ STATE MACHINE HERE
	Set flag_ppu_reading False
With this logic we would detect the PPU idle state in a minimum of 6 PPU cycles (NTSC) or a maximum of 9 (I think). This should skip over single idle PPU cycles flawlessly.

Can someone find the flaw here?

As for testing if this is how the MMC5 detects the end of frame, I don't think we can.
Drag
Posts: 1708
Joined: Mon Sep 27, 2004 2:57 pm

Post by Drag »

tokumaru wrote:Do you really have to stick to the exact same technique used by an actual MMC5? As long as the scanline counter is reliable and the same registers are used to interface with it, the exact internal workings shouldn't matter, right?
No, we don't have to use the absolutely exact implementation as the real MMC5. However, if we know what the real hardware implementation of the MMC5 is, it's helpful for how we approximate it. For example, if we know the exact workings of the MMC5, we know exactly which pixel the IRQ fires on (versus a rough estimate), we know about any oddball quirks (such as the 3 I mentioned in my previous post), and just stuff like that.
tokumaru wrote:Can anyone think of a decent way to count scanlines that will not break with different pattern table and sprite sizes configurarions?
Yeah, use the Gameboy. ;)
haha, I'm kidding. However, once again, I'd say the MMC5's scanline counter is probably the best we'll get for the time being. I mean, it avoids the exact problems you just mentioned. :P From the sounds of it, the MMC5 is very robust.
tokumaru wrote:I don't think it has to be the exact same solution used by the MMC5, specially considering the MMC5 doesn't work on clones (not sure if the scanline counter has anything to do with this, but still).
Even if we don't know how the MMC5 counter really works, we have a number of hypotheses as to how it could work, and any of those theories could be implemented in a custom mapper right now and work just fine.
Drag
Posts: 1708
Joined: Mon Sep 27, 2004 2:57 pm

Post by Drag »

Disch's Mapper Doc wrote:The IRQ will trip at the *start* of the desired scanline. Or, more precisely, near the very end of the previous scanline (closest I can figure is dot 336). That is... if the trigger line is set to 1, the IRQ will trip on dot 336 of scanline 0.
PPU cycle 336 is when the first dummy nametable fetch is made, 339 is when the second dummy fetch ends. 340 is the last cycle of the scanline.
If this is the case, then there's no way the MMC5 can be looking for 3 duplicate fetches (as in, the two dummy nametable fetches, and then the first nametable fetch of the next scanline).

So if the MMC5 looks for duplicate fetches, it'd only be looking for the two at the end of the scanline.
tepples
Posts: 22993
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)

Post by tepples »

MMC5 has to count horizontal fetches to tell sprite banks from background banks and figure out at what point on the scanline to vertically split.