Slight timing(?) issue
Moderator: Moderators
Slight timing(?) issue
This scanline test is showing some corruption in my emu:
I think it's a problem with timing, but I have a hard time finding the cause. Maybe you experienced guys have some pointers?
I suspect/hope it's also the cause for this glitch in SMB that only occurs when a sprite is near the top of the screen. It renders perfectly otherwise.
I think it's a problem with timing, but I have a hard time finding the cause. Maybe you experienced guys have some pointers?
I suspect/hope it's also the cause for this glitch in SMB that only occurs when a sprite is near the top of the screen. It renders perfectly otherwise.
Re: Slight timing(?) issue
Are you checking for collision with sprites that aren't Sprite #0?
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: Slight timing(?) issue
I have the same problem with scanline test, but no shaking.
Zepper
RockNES author
RockNES author
Re: Slight timing(?) issue
I have triple checked, I'm only testing sprite #0.
It passes these tests, except for the timing test #9. That one fails with "Flag set too soon for upper-left corner". If I add a one-cycle delay, it fails with "Flag set too late for upper-right corner" instead
Re: Slight timing(?) issue
Are you absolutely certain? There's a big difference between "the first sprite rendered on the scanline" and "the sprite located at OAM address 0", and I strongly suspect your emulator is doing the former rather than the latter.
In fact, I'm almost 99% certain that that's what you're doing, because when I edited my own emulator to drop the "scanline contains sprite #0" check from its sprite 0 hit logic, it began behaving exactly the same as depicted in your first post.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.
Re: Slight timing(?) issue
Yes, I am certain. I'm iterating over a copy of the secondary OAM starting at index 0 and the flag can only get set during the first iteration. There is no "sort by x coordinate" anywhere in the code.
Code: Select all
// just the basic logic, not the literal code
int hitFlag = 0x40 * min(1, bgPattern);
for(int i = 0; i < numSpr; ++i) {
// range check, etc...
if(sprPattern[i] > 0)
status |= hitFlag;
hitFlag = 0;
}
Re: Slight timing(?) issue
If you look at the first sprite from secondary OAM, you'll find the first sprite rendered on the line, which is not necessarily Sprite #0. It needs to actually be sprite #0.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: Slight timing(?) issue
So Sprite #0 is the one at index 0 in the primary OAM, not the one at index 0 in the secondary OAM? Really? Where does the PPU get this information from?
The first sprite rendered on the current line is the first one in secondary OAM that is in range of the current pixel's x position - that's not necessarily the first one in the secondary OAM. The sprite at OAM2[0] can be at x = 200 and the one at OAM2[4] can be at x = 10. They're not sorted by x coordinate. I'm only checking the one at OAM2[0], but I gotta check again if I misunderstood something about this.
Re: Slight timing(?) issue
It would take a total of one bit of storage to indicate that Sprite 0 in secondary OAM is the same as Sprite 0 in primary OAM. You don't need anything fancy like expanding secondary OAM to include things like 'original sprite number' or 'is this sprite 0' on each sprite.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: Slight timing(?) issue
Sure, but I haven't seen anything about this flag in the docs, that's why I'm asking. Maybe I missed it.Dwedit wrote: ↑Mon May 17, 2021 9:11 am It would take a total of one bit of storage to indicate that Sprite 0 in secondary OAM is the same as Sprite 0 in primary OAM. You don't need anything fancy like expanding secondary OAM to include things like 'original sprite number' or 'is this sprite 0' on each sprite.
Re: Slight timing(?) issue
Using a flag is just one possible way to implement it, so that flag doesn't really formally exist anywhere, so it wouldn't be in any documentation.
The only part that matters is if it's Primary OAM Sprite #0 or not.
I don't know if the actual PPU uses a single bit of storage to define this relation, but the actual decapped chip is available to look at. It's very hard to read it.
The only part that matters is if it's Primary OAM Sprite #0 or not.
I don't know if the actual PPU uses a single bit of storage to define this relation, but the actual decapped chip is available to look at. It's very hard to read it.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: Slight timing(?) issue
The PPU actually has two internal registers for this: one to denote that sprite #0 was detected during evaluation for the next scanline ("[/]sprite_0_on_next_scanline", nodes #5934/#5907), and another one to denote that sprite #0 is being rendered on the current scanline ("[/]sprite_0_on_cur_scanline", nodes #5834/#1105), where the first gets copied to the second during cycles 256-319 (i.e. during the sprite CHR fetches). The signal names and node numbers refer to the Visual 2C02 simulator.
The actual logic is surprisingly simple - if the PPU tries to write to secondary OAM on cycle 66* (i.e. immediately after evaluating the Y-coordinate of sprite 0), then it sets the flag because it just evaluated Primary OAM slot #0 as a valid sprite; if the first matched sprite was primary OAM slot #1, then the write would've happened at cycle 68, and other sprites would be found at correspondingly later times.
(* the relevant signal in Visual 2C02 is actually named "++hpos_eq_65_and_rendering_and_pclk1", but it's delayed by several clock cycles so it doesn't trigger until hpos=66)
Last edited by Quietust on Mon May 17, 2021 10:15 am, edited 2 times in total.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.
Re: Slight timing(?) issue
I am now a proud user of this flag and the glitch in SMB went away. Thank you!
However, the scanline test doesn't care about sprite 0 hit at all, or sprites in general. It's still flickering.
However, the scanline test doesn't care about sprite 0 hit at all, or sprites in general. It's still flickering.
Re: Slight timing(?) issue
It's been a while since I've tested scanline.nes on real hardware, but the flickering you're seeing might be a result of performing your VRAM address "vertical increment" at the wrong time.
What that ROM does is write $04->$2006/$04->$2006 just to the right of the vertical bar and then write to $2006+$2005+$2005+$2006 (to prepare the VRAM address for the next scanline) at the very right edge of the screen, so if the timing is even slightly off, it could result in the jittering you're seeing.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.
Re: Slight timing(?) issue
I'm struggling with IRQ timing in general. Bunch of test are failing, all related to interrupts. I'm not really sure how long the delay between request and execution should be. Some sources say execute as soon as the current instruction ends, others (and failing tests) say after the next instruction, plus a bunch of special cases whose implementation is gonna be pretty hacky