It is currently Fri May 24, 2019 1:58 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: sprite0 problem
PostPosted: Tue Nov 13, 2018 12:33 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 514
I have a loop which repeatedly finds the sprite0 hit and colors the screen green after it occurs:

Code:
loop:
    ; Wait until sprite0 is cleared
:
    bit PPUSTATUS
    bvs :-

    ; Wait until sprite0 is set
:
    bit PPUSTATUS
    bvc :-

    ; Color the screen
    lda #PPUMASK_EMPHASIZE_G | PPUMASK_GREYSCALE
    sta PPUMASK
    jmp loop


When I test this in Nestopia and Nintendulator, it works for some frames, but other frames the screen is 100% green with rendering disabled. This seems to occur randomly.

What's going on?

I've tried setting breakpoints on PPUMASK, but I see absolutely no difference between frames. The split seems to occur at the same time each frame, but for some reason it doesn't display that way.

(If you're wondering, my NMI does nothing but set the PPU registers and returns)


Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Tue Nov 13, 2018 12:52 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7462
Location: Canada
My guess is that reading $2002 on the onset cycle of the NMI skips the NMI entirely? It's probably a conflict here to spin on a $2002 read loop while waiting for a pending NMI. Wait for a signal from the NMI to proceed first before you enter the wait loop for sprite 0 clear.

Might be worth posting the ROM for testing if you can, though, would maybe be interesting to compare this niche behaviour against emulators and hardware?


Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Tue Nov 13, 2018 1:29 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 514
rainwarrior wrote:
My guess is that reading $2002 on the onset cycle of the NMI skips the NMI entirely? It's probably a conflict here to spin on a $2002 read loop while waiting for a pending NMI.

Hm, this seems likely, because if I pad the loops with NOPs, the glitch happens less frequently. But I don't think it's from the NMI handler being skipped (can that even happen?).

The documentation on that page says that if you read $2002 on the frame NMI starts, 0 is returned in bit 7. It doesn't mention bit 6, but if bit 6 also appears as 0 on that cycle then that could explain the behavior.

Quote:
Wait for a signal from the NMI to proceed first before you enter the wait loop for sprite 0 clear.

Cool I found a way to make it work:

Code:
    ; Wait until sprite0 is cleared
    bit PPUSTATUS
    bvc clear
    jsr wait_for_nmi
:
    bit PPUSTATUS
    bvs :-
clear:

    ; Wait until sprite0 is set
:
    bit PPUSTATUS
    bvc :-

It's a bit tricky, because I only wait for a NMI signal if the sprite0 bit is set to begin with. Waiting for a signal every time would incur lag frames (which is why I didn't do it to begin with).


Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Tue Nov 13, 2018 5:07 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2507
Location: DIGDUG
If that's the code, then I'm suspicious of it.

wait for NMI should actually wait till the nmi code happens, and not be skipped for any reason.

The NMI code should set a flag or increase a counter, and "wait for NMI" should wait for that change.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Last edited by dougeff on Tue Nov 13, 2018 6:57 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Tue Nov 13, 2018 5:54 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 514
Ok here's a test ROM. I'd be interested to know what a real NES does, and if it differs on PAL vs NTSC.

Flashing screen = bad
No flashing = good


Attachments:
sprite0_test.nes [40.02 KiB]
Downloaded 93 times
Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Tue Nov 13, 2018 7:19 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2507
Location: DIGDUG
I had trouble playing it in several emulators, due to the illegal opcodes. I'm not sure which one to use.

On hardware it is flashing very quickly... perhaps skipping every other frame. And there is some text on the screen, which I think you did not intend.

CRT with original NES.
Attachment:
20181113_090920_resized.jpg
20181113_090920_resized.jpg [ 974.56 KiB | Viewed 2941 times ]


Flatscreen with toploader NES.
Attachment:
20181113_091043_resized.jpg
20181113_091043_resized.jpg [ 767.94 KiB | Viewed 2941 times ]



EDIT - Mesen emulates the flickering fairly well, but didn't emulate the random text on the screen.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Tue Nov 13, 2018 11:54 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 514
Hey thanks Doug! :beer:

Now to figure out why this is behaving this way. . .


Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Tue Nov 13, 2018 12:24 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11348
Location: Rio de Janeiro - Brazil
Looking at the ROM, it seems that after the split, you immediately go back to polling $2002 waiting for the sprite hit flag to be cleared. Those $2002 reads are probably suppressing NMIs from time to time. Try not going back to polling right after the split. Instead, wait for the frame to end, for the NMI to run, and only then you should start polling again.


Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Wed Nov 14, 2018 5:45 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 514
Hmm so the glitch actually causes the handler to be skipped?

I had no idea. I thought it just affected the value read.


Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Wed Nov 14, 2018 7:23 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2507
Location: DIGDUG
If NMIs are on, the signal will still fire regardless of what the program does. It will jump to the NMI code. I don't believe it will skip jumping to NMI by reading from 2002.

The vblank flag (bit 7 of 2002) clears when read. Sometimes it clears on the same cycle it is set, giving a false read of zero. Which is why you shouldn't rely on 2002 reads to time the start of vblank.

Use a flag that YOU set in the NMI handler to know when vblank has occurred.

Then poll for Sprite zero flag clear.

Then poll for Sprite zero flag set.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
 Post subject: Re: sprite0 problem
PostPosted: Wed Nov 14, 2018 11:54 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11348
Location: Rio de Janeiro - Brazil
dougeff wrote:
If NMIs are on, the signal will still fire regardless of what the program does. It will jump to the NMI code. I don't believe it will skip jumping to NMI by reading from 2002.

That's not correct. From the wiki (https://wiki.nesdev.com/w/index.php/PPU_frame_timing):

Quote:
Reading $2002 within a few PPU clocks of when VBL is set results in special-case behavior. Reading one PPU clock before reads it as clear and never sets the flag or generates NMI for that frame. Reading on the same PPU clock or one later reads it as set, clears it, and suppresses the NMI for that frame. Reading two or more PPU clocks before/after it's set behaves normally (reads flag's value, clears it, and doesn't affect NMI operation). This suppression behavior is due to the $2002 read pulling the NMI line back up too quickly after it drops (NMI is active low) for the CPU to see it. (CPU inputs like NMI are sampled each clock.)

So yeah, if you read $2002 too close to the time the vblank flag gets set, the CPU doesn't pick up the change in the NMI line and the NMI doesn't fire. In short: don't poll $2002 while waiting for vblank, even if you're testing the sprite hit flag rather than the vblank flag.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group