Page 1 of 2

Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 12:20 pm
by rainwarrior
I'm having a really strange thing happen with my attempt to use sprite 0 hit to cause a scroll split at a variable screen position. My code runs fine in every emulator I've tried except Nintendulator, and also appears to run correctly on my NTSC NES. The ROM also autodetects and compensates for PAL but I do not have a PAL NES to run a hardware test on.

In the attached ROM, a two-pixel wide sprite is placed on pixels 253/254 to trigger a sprite 0 hit. $2002 is polled for the hit, and once detected the scroll split is timed to be written during hblank on the following scanline. To demonstrate the variable position, the sprite will be moved from Y=41 to Y=239, one pixel per frame.

For some reason in Nintendulator the $2002 test appears to fail randomly (maybe on 3% of frames?), causing the scroll split to be missed in overlay_test_1.nes. I can't figure out why.

Does Nintendulator emulate something unusual about sprite 0 hits that other emulators do not? Since it's not happening on my hardware test, I'm wondering if it is a bug in Nintendulator, but I'm worried that it's emulating some rare case that I should really be looking out for.


This is the code that waits for the sprite 0 hit and sets the scroll, you can find it at $801F in memory when the last 32k bank is selected (this uses an oversized 256k BNROM mapper).

Code: Select all

render_overlay:
	lda #1
	sta nmi_lock ; disables NMI temporarily in case sprite 0 hit fails
	:
		; sprite 0 hit doesn't clear until the end of vblank, make sure that's happened
		bit $2002
		bvs :-
	:
		bit $2002         ; will hit after dot 253
		bmi @overlay_fail ; if vblank is detected, we completely missed the sprite 0 hit
		bvc :-
	; [ 4 cycles elapsed since sprite 0 hit ]
	; wait for hblank alignment
	; add 3 dots to get from 254 sprite hit to 257 hblank (1 cycle)
	; a line is 341 dots long (113.6 cycles NTSC, 106.6 cycles PAL)
	; thus, this wait needs: NTSC 84 cycles, PAL 77 cycles (+6 cycles above, +27 cycles below)
	lda player_pal          ; [ 3 ]
	bne :+                  ; [ +2 if NTSC, +3 if PAL ]
		nop
		nop
		nop
		nop
	:                       ; [ 13 NTSC, 6 PAL ]
	; 71 cycles to go
	lda player_pal          ; [ +3 ]
	.repeat 34
		nop
	.endrepeat              ; [ +68 ]
	; [ NTSC 84, PAL 77 cycles waited ]
	; wait finished
	lda #%00001010
	sta $2001            ; disable sprite rendering
	lda #%00000100
	sta $2006            ; 2006.1 > nametable %01
	lda overlay_scroll_y
	sta $2005            ; 2005.2 > Y scroll
	and #%00111000
	asl
	asl
	ldx #0
	; [27 cycles elapsed since wait finished]
	; the last two write should fall in hblank (after dot 256, before dot 320)
	stx $2005            ; 2005.1 > X scroll = 0
	sta $2006            ; 2006.2 > Y scroll bits 3-5, X scroll low bits = 0
	lda #0
	sta nmi_lock
	rts
@overlay_fail:
	lda #0
	sta nmi_lock
	rts
If you need the NMI routine, or other source, I can post it.

In overlay_test_2.nes, the fail-safe line bmi @overlay_fail is commented out, which doesn't make a difference, except in Nintendulator. In Nintendulator the overlay position appears to freeze on frames where the test fails, which I don't quite understand. If it's catching the sprite on the next frame, the scroll should not have been executed. Very puzzling...


I apologize that this isn't a simple test program with full source. I made an attempt to produce a "simpler" test ROM, but so far I have been unable to do so. This is excerpted from a larger program I'm working on.

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 12:47 pm
by Quietust
What version are you running? I just tried both ROMs in the latest development build (from April 21, 2013) for several minutes, and I didn't see any glitches.

If you're running an old version, it was probably a bug in the way it emulated OAM overwrite - originally, the sprite fetch logic was using the last value written to $2003 to fetch the first 8 bytes of OAM, but now it overwrites the first 8 bytes of OAM with whatever page the sprite address was pointing at (to more closely match what the real PPU appears to do).

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 1:24 pm
by rainwarrior
This is happening for me with the 0.975 beta binaries from here, both ANSI and unicode versions, and also with the 0.970 release binaries as well.

For me overlay_test_1.nes the scroll split disappears/flickers noticeably for at least a few frames per loop, usually for several frames at a time when it happens. It's very strange because it is not a consistent pattern; if I restart Nintendulator it will flicker at different times.

The sprite itself still renders in the correct position when the sprite 0 hit fails. Also, the NMI routine writes 0 to $2003 before doing the sprite DMA, so I think that should be okay.

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 1:37 pm
by rainwarrior
Hmm, tried it on a different computer and the problem is still there but less frequent. Also seemed to become stable a few seconds after starting execution.

Something really weird, though, if I turn off "auto" frameskip and set frameskip to 1 the scroll flickers on and off at a slow and regular rate, something like 30 frames on, 30 frames off. This is happening on both of my PCs consistently.

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 1:39 pm
by rainwarrior
With a frameskip of 0, the problem appears to be gone. (The default setting for frameskip is "auto", I hadn't tried adjusting it before.)

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 3:37 pm
by Quietust
Okay, now I can confirm that it's a bug in the frameskip logic - when it knows nothing's going to make it to the screen, it skips whatever extra logic it can without affecting behavior, but it's clearly skipping too much.

[edit] Fixed - when I switched over to the detailed sprite evaluation logic, I missed a spot in the frameskip code for determining which sprite scanline to fetch (originally, it got a value from 0-15, but now it gets an absolute scanline number). A new build will be available shortly.

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 5:02 pm
by tepples
Sometime in 2011, I remember having seen similar misbehavior with mid-screen pattern table bankswitching when frameskip is enabled. Should I make a test ROM?

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 5:17 pm
by rainwarrior
I'm curious why frameskipping is on by default. Since Nintendulator seems oriented toward debugging (esp. how the user is required to manually start execution), I was kind of surprised that this was going on. When developing I'd rather see every frame go by than have the speed be kept even by skipping.

A personal preference, of course. Obviously it's easy to make the setting once you know the feature is there, but I would guess more people would want it off.

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 6:50 pm
by tokumaru
rainwarrior wrote:I would guess more people would want it off.
I certainly do. Whenever I run a new copy of Nintendulator (or any other emulator, for that matter) one of the first things I do is turn frame skipping off (as soon as I notice it's on). I find it annoying enough when playing (if my computer can't run it at full frame rate, I'd rather not play it), and completely unacceptable for debugging.

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Thu Mar 06, 2014 7:06 pm
by thefox
I have actually completely forgotten that there even was a frame skipping option in Nintendulator, because I always have it turned off. But I do remember seeing in the sources that there were two separate, almost identical routines (mostly copy&paste) for running the PPU in the skip/non-skip modes (RunSkip() and, RunNoSkip()), and wondering that that must be a hell of a job to maintain. :)

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Tue May 27, 2014 5:59 am
by Ti_
Nintendulator ,975 (build from 29 April) still have bug with frameskip. (game: ducktales2)

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Wed May 28, 2014 5:55 am
by Quietust
Ti_ wrote:Nintendulator ,975 (build from 29 April) still have bug with frameskip. (game: ducktales2)
Could you be more specific?

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Wed May 28, 2014 6:13 am
by Ti_
Quietust wrote:
Ti_ wrote:Nintendulator ,975 (build from 29 April) still have bug with frameskip. (game: ducktales2)
Could you be more specific?
if set to frameskip not 0.

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Wed May 28, 2014 9:30 pm
by Quietust
Found it - on sprite 0 hit during frameskip, it was neglecting to clear the "found sprite 0 in this scanline" flag, causing the first sprite on EVERY subsequent scanline to possibly trigger a hit. Should be fixed now.

Re: Strange sprite 0 hit behaviour on Nintendulator

Posted: Wed May 28, 2014 11:59 pm
by Ti_
Quietust wrote:Should be fixed now.
Same problem. Have you tested rom?