Making a mapper that detects BG vs Sprite tiles
Moderator: Moderators
Making a mapper that detects BG vs Sprite tiles
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)
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)
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: Making a mapper that detects BG vs Sprite tiles
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.
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.
Re: Making a mapper that detects BG vs Sprite tiles
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.
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.
Re: Making a mapper that detects BG vs Sprite tiles
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.
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.
Re: Making a mapper that detects BG vs Sprite tiles
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.
Re: Making a mapper that detects BG vs Sprite tiles
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".
Re: Making a mapper that detects BG vs Sprite tiles
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.
Re: Making a mapper that detects BG vs Sprite tiles
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?
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?
- infiniteneslives
- Posts: 2102
- Joined: Mon Apr 04, 2011 11:49 am
- Location: WhereverIparkIt, USA
- Contact:
Re: Making a mapper that detects BG vs Sprite tiles
That's a pretty elegant solution. I've always considered counting CHR A13.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)
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.
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:You'll probably want to latch on PPU /RD falling; otherwise I vaguely suspect some kind of timing problem will creep in.
You can always opt to use discrete logic for help with something like that if pins are at a premium.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".
If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers
Re: Making a mapper that detects BG vs Sprite tiles
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.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.
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.
Re: Making a mapper that detects BG vs Sprite tiles
According to ulfalizer's post above, which cites Visual 2C02, the signal to fetch attributes is active only during 0-255 and 320-335.Drag wrote:Did someone actually discover and/or document this behaviorlidnariq 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.
Re: Making a mapper that detects BG vs Sprite tiles
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.
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.
Re: Making a mapper that detects BG vs Sprite tiles
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.tepples wrote:According to ulfalizer's post above, which cites Visual 2C02, the signal to fetch attributes is active only during 0-255 and 320-335.Drag wrote:Did someone actually discover and/or document this behaviorlidnariq 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.
Edit: Or a half-dot delay rather, but it works out like that anyway I think. Timing stuff in circuits is tricky to follow.