Sprite 0 Hit Test ROMs

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA

Sprite 0 Hit Test ROMs

Post by blargg » Wed Oct 05, 2005 5:09 pm

I've just completed a first version of a sprite 0 hit test ROM suite. In total there are almost 70 different tests performed, covering these main areas:

- Basic behavior
- Relative alignment of background and sprite
- Special cases like background off, left-edge clipping, etc.
- Corner cases and off-by-one errors
- Timing of beginning of frame, pixel, scanline, clearing at VBL
- When multiple pixels hit, which counts as the first hit


Refer to other documentation for proper behavior or start a new thread if you are wondering about PPU operation (so this thread doesn't get swamped). Reply to this thread if you'd like a better description of what a particular failure code means.

I've improved the result reporting a bit to show the test name and PASS/FAIL. The test framework has also advanced so I can write this kind of test suite quickly (these have taken about 6 hours, where they usually take me days or weeks). This will help when writing future tests.

After writing these tests I've realized that sprite 0 hit allows all sorts of automated tests of the PPU, so I'm having several ideas for more things I can write solid tests for. With sprite 0 hit one can read the entire screen! (though only 60 pixels per frame)

Feedback welcome.

User avatar
Posts: 1641
Joined: Sun Sep 19, 2004 10:59 pm

Post by Quietust » Wed Oct 05, 2005 7:34 pm

Well, I found one bug in my emulator - basic test #4 was failing when skipping frames, apparently because I somehow removed 2 checks from my frameskip-optimized code (specifically, checking for background rendering and background clipping). After re-adding those checks (and optimizing their order), it works fine again.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

User avatar
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Thu Oct 06, 2005 8:07 am

Yay... my latest passed ^^

My older emu chocked on the timing tests (and the right edge) -- I think I wasn't clearing $2002 until the first rendered scanline or something... and I just didn't bother with checking x=255.

User avatar
Formerly Fx3
Posts: 3221
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil

Post by Zepper » Sat Oct 08, 2005 4:36 am

For some reason, my emu hangs in the timing tests. Basically, it waits for the VBlank flag forever. -_-;;

Any suggestions?

User avatar
Posts: 355
Joined: Thu Mar 24, 2005 3:17 pm

Post by hap » Sat Oct 08, 2005 8:31 am

Mine gets error #9 for basic timing, the rest works fine.

Fx3: if I force a shorter vblank time, timing tests hang. Maybe your vblank time is too short ?

Posts: 1236
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany

Post by WedNESday » Sat Oct 08, 2005 8:42 am

WedNESday's VBlank time is 2269 CC's. This is the most allowed for blargg's VBlanks test allows. Set it any higher or lower and it fails you.

User avatar
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Sat Oct 08, 2005 9:00 am

NTSC VBlank is 20 scanlines:

20 * 341 = 6820 PPU cycles

/ 3 = 2273.333333 CPU cycles

My understanding is you raise the VBlank flag at the very start of VBlank (and trigger an NMI if enabled) -- then you clear all $2002 flags immediately after those 20 scanlines are complete. This is what my emu does and it passes all these tests.

User avatar
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA

Post by blargg » Sat Oct 08, 2005 9:56 am

The timing tests synchronize with the PPU by waiting for the VBL flag in the usual bit $2002 bpl loop, then going into a loop that waits 29781 clocks (about 10 less the first iteration) and checks the VBL flag. Since the PPU frame is slightly less than 29781 clocks, the loop will eventually "cross over" and see the VBL flag set, at which point it's synchronized.

This is probably where it's hanging, if the timing tests never give a result.

As for hap's error #9, this test uses a background filled with solid tiles using color 1 and a sprite with a solid tile of color 2, and expects a hit to occur. This test was to catch an emulator incorrectly ANDing the background and sprite palette indicies and reporting a hit if this was non-zero. This would fail for colors 1 and 2, since 1 AND 2 = 0. (this is the psychology aspect I was talking about in another post -- you have to think of errors human authors might make, and put tests in to catch those)

As for the actual timing, I haven't worked out the exact values. One nice thing about writing the test ROMs is that I can tweak the delays until they pass on a real NES (being sure I have them generally correct, of course). In the timing tests I report too soon/too late to allow similar adjustment of an emulator. I've done tests based on exact synchronization with the PPU clock and found it to be quite complex. There will be a set of test ROMs soon that test accuracy down to the PPU clock, which will probably fail on most emulators (yes, this is possible, even though the CPU clock is 3x the PPU's).

EDIT: oops... bit $2002 bpl loop, not bmi.


Post by Guest » Mon Oct 17, 2005 2:28 pm

Never mind, the scanline #20 was being handled incorrectly (of 340 or 341 cycles behaviour). Now, the timing tests run - but it gives error #5 for test 9 and error #3 on test 10. What am I supposed to do for proper fix? -_-;;

User avatar
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA

Post by blargg » Mon Oct 17, 2005 5:33 pm

Test ROM 9, result 5 occurs if sprite hit flag is set too late with sprite 0 in the upper-right corner (well, one pixel left of that, otherwise it would fall on column 255 and never report a hit). It might mean that PPU pixels are taking too long (that was the intent behind this test). Test ROM 10 probably fails for the same reason. Once test ROM 9 passes, test ROM 10 will give a meaningful result.

User avatar
Posts: 22
Joined: Sat Jun 08, 2019 2:53 am
Location: Portland, OR

Re: Sprite 0 Hit Test ROMs

Post by lukexor » Fri Nov 08, 2019 12:34 pm

I know this post is rather old, but I'm trying to shore up my final few test roms I'm not passing and I found some differences between the various Sprite 0 hit test roms on the wiki.

RustyNES can pass all the tests from the original zip in this post (The one that unzips to sprite_hit_tests_2005.10.05).

However, the Emulator Tests page on the wiki has a link to a different zip which still links to this thread (http://blargg.8bitalley.com/parodius/ne ... te_hit.zip)

And in those tests, I fail #3 - Flag set too soon for upper-left corner on Test 9 (All the rest pass).

Can anyone comment on what changed with the test? I looked at the asm and it seems to be checking $2002 at cycle 7501 into a VBL frame.

I know where in my code the issue is, but I'm having difficulty with the timing because of all these off-by-one errors.

The way I'm emulating the CPU/PPU catch up is to run the PPU 3x before every CPU read/write and then inside the PPU it first increments the current cycle (and possibly the scanline) before doing anything. X then becomes cycle - 1, and Y is the current scanline.

I managed to be able to pass Test 9 by messing with my numbers, but then it starts failing other sprite zero hit tests.

Here's my current implementation:

Code: Select all

            if self.is_sprite_zero(i)
                && self.frame.sprite_zero_on_line
                && self.rendering_enabled()
                && !self.sprite_zero_hit()
                && self.frame.sprites[i].x < 255
                && x < 255
                && self.frame.sprites[i].y < 255
                && bg_opaque
                && sprite_opaque
I can pass #3 if I add a condition for x > 0, but is that correct? Shouldn't sprite 0 be triggered at x == 0?

If I do that, then I get to test #5 for Flag set too soon for upper right-corner. From my trace logs, it seems that cycle 255 occurs as the last PPU cycle during cycle 4 of LDA $2002, which is right before the CPU executes the read cycle to $2002, and so it reads as true when it shouldn't until the next cycle.

Is there any sort of delayed hit logic that I'm missing? Or should I flip my CPU catch up timing around so that it executes the CPU read/write first and then runs the PPU to catch up? I pass all the other IRQ and VBL timing tests, so I'm worried flipping that will break everything.

Post Reply