I was once again thinking about a hypothetical mapper that would tell whether BG tiles or Sprite tiles were being displayed, and automatically do bankswitching so sprites get two whole pattern tables.
Let me know if I have this right. It seems like the way to detect such a transition is to look for two consecutive reads to the nametable, and that enters "Sprite Mode", and then when you have a read of the attribute table, return to "Background Mode". According to the Nintendulator source code, the Garbage AT fetch is the same address as the Garbage NT fetch, so if they are both reads to the nametable instead of the attribute table, you know you're rendering sprites. Likewise, if anything gets fetched from the attribute table, you know you're rendering background tiles. I'll assume nobody's doing any negative scrolling.
The end of a scanline also has two consecutive nametable fetches, and that might trigger a bankswitch to Sprite Mode, but then there's an attribute table fetch right after that, so you'd switch back to Background Mode.
Is this the simplest way to detect BG vs Sprite tiles?
edit: Looks like you don't even need two consecutive reads, just switch to "sprite mode" on any nametable read, and "bg mode" on any attribute table read.
Or in address line notation:
A13 & A9 & A8 & A7 & A6 (reading attribute table)
A13 & !(A9 & A8 & A7 & A6) (reading nametable)
The last thing you suggest is consistent with what I noticed when I was playing with Visual2C02.
You'll probably want to latch on PPU /RD falling; otherwise I vaguely suspect some kind of timing problem will creep in.
The MMC5 clearly did this some other way; otherwise it wouldn't have the flaw where it would stick to whichever of $5120-$5127 or $5128-$512B you wrote to last when in 8x8 sprites mode.
An interesting note is that the MMC5 can determine the absolute screen position of fetched BG tiles, as that's how the split position is specified in vertical split mode. The coarse x and y scroll can be set to whatever, and the split still ends up in the same location.
That alone would make me suspect that it's simply counting nametable or tile fetches to determine when BG and sprite tiles are being fetched, but it seems odd that 8x8 vs 8x16 sprites would make any difference in that case. It would also need some way to synchronize to the frame.
Poked around a bit in Visual 2C02, and it looks like attribute fetches are indeed only done for BG tiles. The "fetch attribute byte" signal is
+hpos_eq_0-255_or_320-335_and_hpos_mod_8_eq_2_or_3_and_rendering, i.e. "fetching background tile and in the attribute byte position". Need to fix this is in my emu too, as I had assumed one of the dummy NT fetches for sprites would be an AT fetch.
The "fetch nametable byte" signal is "NOT fetching attribute byte AND NOT fetching the high or low tile byte", so for sprites it should be two consecutive NT fetches like you said.
I'm wondering if it'd be easiest to count how many times PPU A13 cycles. It seems like it'd be very reliable because it's a guarantee that A13 will cycle on and off for each tile that needs to be fetched, including sprites, and it will always cycle the same amount of times for each scanline. As a bonus, this can also drive a scanline counter, because you'd need to be able to detect new scanlines anyway, whether it be through counting how many tiles were fetched, or using the multiple-read marker that MMC5 uses.
Purely for determining whether it's fetching BG or sprite tiles? No, your final suggestion in your first post is definitely minimal in terms of everything but pin count. It'd be something like "Latch AND(A9,A8,A7,A6) when A13 is high on a falling transition of /RD".
Well, the other thing is, I don't know if we can trust the two garbage fetches that occur with the sprite tile fetches. Technically, the behavior of them is undefined. If the garbage fetches are indeed because the nametable fetching circuitry is being reused for fetching the sprite tiles, then I would assume that the first and second fetches are not going to be the same, because it makes sense to me that the second fetch is always going to be an "attribute" fetch, and going to be computed from the current X and Y, and it's always going to fall in the range of an attribute table.
Certainly for the real NES PPU, the second fetch is always from the not-attribute-part of the nametables, and not from the attribute tables.
I guess if you're aiming for maximal clone compatibility, I'm not certain just how much you can rely on. Evidently there's enough consistency such that MMC3 PPU A12 interrupt sources work, but who knows if A13 even goes high during clone sprite fetches?
Dwedit wrote:
: Looks like you don't even need two consecutive reads, just switch to "sprite mode" on any nametable read, and "bg mode" on any attribute table read.
Or in address line notation:
A13 & A9 & A8 & A7 & A6 (reading attribute table)
A13 & !(A9 & A8 & A7 & A6) (reading nametable)
That's a pretty elegant solution. I've always considered counting CHR A13.
There is a low pin count method of sensing the 2NT fetches-idle cycle-tile #3 fetch. You can latch CHR A13 with CHR /RD and then use that to reset a CHR A13 counter.
I'd say 4 pins are more costly than a 4-5bit counter, but both seem reasonable options.
lidnariq wrote:
You'll probably want to latch on PPU /RD falling; otherwise I vaguely suspect some kind of timing problem will creep in.
I saw issues when implementing MMC2 that agree with your suspicions. I found CHR A12 wasn't always valid on rising edges of CHR /RD. So latching on falling edges and then switching on rising edges resolved the issue.
lidnariq wrote:
your final suggestion in your first post is definitely minimal in terms of everything but pin count. It'd be something like "Latch AND(A9,A8,A7,A6) when A13 is high on a falling transition of /RD".
You can always opt to use discrete logic for help with something like that if pins are at a premium.
lidnariq wrote:
Certainly for the real NES PPU, the second fetch is always from the not-attribute-part of the nametables, and not from the attribute tables.
Did someone actually discover and/or document this behavior? It just looked liked Nintendulator's source code was being used as reference for a behavior I've yet to see documented anywhere, which sets off red flags in my head, regardless that this is Nintendulator.
If it's legitimate, then I'll shush, but I wanted to chime in before a previously unknown (to me at least) behavior was relied on too much and later proved untrue or inconsistent.
Drag wrote:
lidnariq wrote:
Certainly for the real NES PPU, the second fetch is always from the not-attribute-part of the nametables, and not from the attribute tables.
Did someone actually discover and/or document this behavior
According to ulfalizer's post above, which cites Visual 2C02, the signal to fetch attributes is active only during 0-255 and 320-335.
Wow, I'm a moron who can't read. Thanks for pointing that out to me. :S
So in that case, checking for two identical PPU fetches would be viable in differentiating between BG and sprite fetches. In addition, if you detect three identical PPU fetches, you could use it to increment a scanline counter.
Sorry about my shenanigans, I wasn't seeing this information on the wiki.
tepples wrote:
Drag wrote:
lidnariq wrote:
Certainly for the real NES PPU, the second fetch is always from the not-attribute-part of the nametables, and not from the attribute tables.
Did someone actually discover and/or document this behavior
According to ulfalizer's post above, which cites Visual 2C02, the signal to fetch attributes is active only during 0-255 and 320-335.
Btw - the '+' at the beginning at the name signifies a one-dot delay, so it's really active during dots 1-256 and 321-336 like you'd expect. Internally the PPU thinks of the frame as starting from 0.
Edit: Or a half-dot delay rather, but it works out like that anyway I think. Timing stuff in circuits is tricky to follow.