Simple sprite 0 questions and advice

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Simple sprite 0 questions and advice

Post by battagline »

So I'm looking into sprite 0 to do my status bar. I just want to make sure I'm understanding correctly how this works.

So when the first sprite in your chr file is rendered on top of a non transparent tile bit 6 in $2002 get's set to 1

So do I need to sit and monitor $2002 at the beginning of my game loop?

If so, doesn't this waste a lot of cycles that could be used for other things?

Also, it's my understanding that you only have about 20 cycles to work with while the hblank is running, is that right?

So in my little asteroid game I was going to render the score and level status stuff as background tiles. I'm using horizontal mirroring so I was going to render it at the top of Nametable 0. I'm using background tiles for the largest asteroids because they are 32x32 and I'd like to prevent flickering. Those asteroids will only be able to move horizontally and all of them will move at the same speed.

So if I'm understanding what I need to do it's basically the following.

1. At the end of the NMI, change the $2000 register to point to PPU $2000 memory location (Nametable 0)
2. At the beginning of the game loop, loop until the sprite 0 hit appears in the $2002 register
3. When sprite 0 hit appears in $2002 register, change the $2000 register to point to PPU $2800 memory location (Nametable 2)
4. Change the PPU Scroll Register ($2005) to have Y=0 and X to asteroid move value. (also during the hblank)

Am I understanding what needs to happen correctly? Are there any gotchas I need to look out for?

Any advice or suggestions are appreciated.

Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
tokumaru
Posts: 12536
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Simple sprite 0 questions and advice

Post by tokumaru »

battagline wrote:So do I need to sit and monitor $2002 at the beginning of my game loop?
The beginning of your game loop may get delayed by the sound engine, lag frames and other things, so the sprite zero hit check is normally done near the end of the vblank handler, to make sure that no other task will cause you to miss the hit.
If so, doesn't this waste a lot of cycles that could be used for other things?
Yes, but you can do useful things before waiting for the hit, as long as you're sure that any tasks you do won't ever take longer than the time it takes to reach the sprite. A good thing to do during that time is run the audio engine.
Also, it's my understanding that you only have about 20 cycles to work with while the hblank is running, is that right?
Depends on what you need to do. Even though the PPU is not generating a picture during hblank, it's still doing stuff in preparation for the next scanline, so how long you have to change something and what the exact time to change that thing is depends on whether your changing the scroll (and what portions of the scroll), switching patterns, changing palettes, and so on.
2. At the beginning of the game loop, loop until the sprite 0 hit appears in the $2002 register
Before waiting for for the flag to get set, you have to wait for it to be *cleared*. The PPU only clears the sprite zero flag at the end of vblank, so if by any chance your vblank handler ends too soon (due to not having much to do), you may mistakenly detect the last frame's hit. To prevent that, make sure the flag is clear before waiting for it to get set.
4. Change the PPU Scroll Register ($2005) to have Y=0 and X to asteroid move value. (also during the hblank)
The Y scroll can't be changed mid-frame via normal $2005 writes, only the X scroll will change, while the Y changes will be ignored until the next frame. To Change the Y scroll mid-frame you need to do a combination of $2006/$2005 writes.
User avatar
pubby
Posts: 587
Joined: Thu Mar 31, 2016 11:15 am

Re: Simple sprite 0 questions and advice

Post by pubby »

It's the first sprite in OAM memory, not the first sprite in CHR.
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Simple sprite 0 questions and advice

Post by battagline »

Ok, I think I'm going to have more questions soon. I appreciate the help.

Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
tepples
Posts: 22861
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Simple sprite 0 questions and advice

Post by tepples »

In a post that somehow disappeared, dougeff wrote:Which is why you should try to do something to waste a little time from the start of vblank, such as run the music code.
Provided your audio driver has a provable maximum cycle count. Penguin does (it's constant time in fact) but I'm not aware of others that do. I guess a driver could be separated into a "top half" where sequences are processed and a "bottom half" where instruments are processed, and only one half gets run while waiting for the sprite 0 hit.
User avatar
tokumaru
Posts: 12536
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Simple sprite 0 questions and advice

Post by tokumaru »

I don't know how complex sound engines typically are, but I believe that status bars are often 32 pixels high or more, and I personally consider that a fairly generous amount of time to dedicate to sound. If I was working on a game to find out that more than 13% of the total frame time was spent just on sounds, even if occasionally, I wouldn't think twice about ditching the sound engine and going for something simpler/lighter/faster.
tepples
Posts: 22861
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Simple sprite 0 questions and advice

Post by tepples »

tokumaru wrote:I personally consider [3600 cycles] a fairly generous amount of time to dedicate to sound. If I was working on a game to find out that more than 13% of the total frame time was spent just on sounds, even if occasionally, I wouldn't think twice about ditching the sound engine and going for something simpler/lighter/faster.
A full-featured audio driver playing a track with all effects turned on might peak at 3900 cycles for one frame as all tracks switch to a new pattern, even if it's only 1500 sustained. That's one reason why I mentioned a split between "top half" and "bottom half". How would I go about getting a code review to help fix code that my profiler determines is uniformly slow?
User avatar
dougeff
Posts: 3080
Joined: Fri May 08, 2015 7:17 pm

Re: Simple sprite 0 questions and advice

Post by dougeff »

post that somehow disappeared
I deleted it. Tokumaru covered what I wanted to say.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Simple sprite 0 questions and advice

Post by battagline »

More troubles. So at the end of the NMI, I set the scroll registers to 0

Code: Select all

        set PPU_SCROLL, #0
        set PPU_SCROLL, #0
At the beginning of my game loop I wait for the sprite 0 hit then change the scroll register to move the asteroid

Code: Select all

        jsr sprite0_wait

        set PPU_SCROLL, scroll_x
        set PPU_SCROLL, #0
What's weird is half of the frames, the background for my status bar moves with the asteroid and the other half it doesn't move. I can step through it in Mesen and every other frame it changes between using the scroll and not using the scroll.

I've attached the rom. You have to actually start playing the game to see it because I'm not doing the sprite 0 thing on the title screen.

I'd really appreciate any thoughts as to what I'm doing wrong.

Thanks
Attachments
nesteroids.nes
Sprite 0 fail
(40.02 KiB) Downloaded 324 times
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
lidnariq
Site Admin
Posts: 11623
Joined: Sun Apr 13, 2008 11:12 am

Re: Simple sprite 0 questions and advice

Post by lidnariq »

battagline wrote: set PPU_SCROLL, scroll_x
set PPU_SCROLL, #0
Access to $2005 during rendering is full of gotchas.

#1- You have to have reset the first byte/second byte toggle by reading from $2002, or know that it has the right value already, to make sure that you're updating the X coordinate (first write) and not the Y coordinate (second write)
#2 - The exact time you set the replacement X scroll can cause visible glitches
#3- Your current implementation here insinuates that you think you could get away with just setting some other value for the replacement Y scrolling value. Sadly, that's not true; this write has no function at all here.

https://wiki.nesdev.com/w/index.php/PPU_scrolling has all the exhausting details.
User avatar
pubby
Posts: 587
Joined: Thu Mar 31, 2016 11:15 am

Re: Simple sprite 0 questions and advice

Post by pubby »

How'd you implement 'sprite0_wait'? You should have two loops in it:

1) Wait for sprite0 flag to be cleared. This signifies the end of VBLANK time.
2) Wait for sprite0 flag to be set.

You'll have problems if you skip step 1.
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Simple sprite 0 questions and advice

Post by battagline »

Is that the reason I'm getting a second sprite0 hit at scanline 247? Or is that unrelated?

Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
tokumaru
Posts: 12536
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Simple sprite 0 questions and advice

Post by tokumaru »

That's probably it. Like I said before, if the vblank/NMI handler finishes its job too soon due to not having much to do, you'll begin polling the sprite zero flag *before it gets cleared*, and since that only happens at the end of vblank, you'll get an immediate hit. Waiting for a sprite 0 hit should consist of two loops, one waiting for the flag to be cleared, and another waiting for it to get set.
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: Simple sprite 0 questions and advice

Post by battagline »

That was it. I put a wait for sprite0 clear subroutine at the beginning of my gameloop and it's working now.

Thanks for your help everyone
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
Post Reply