Simple sprite 0 questions and advice
Moderator: Moderators
- battagline
- Posts: 152
- Joined: Wed Sep 05, 2018 11:13 am
- Location: Colorado
- Contact:
Simple sprite 0 questions and advice
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
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
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
Re: Simple sprite 0 questions and advice
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.battagline wrote:So do I need to sit and monitor $2002 at the beginning of my game loop?
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.If so, doesn't this waste a lot of cycles that could be used for other things?
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.Also, it's my understanding that you only have about 20 cycles to work with while the hblank is running, is that right?
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.2. At the beginning of the game loop, loop until the sprite 0 hit appears in the $2002 register
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.4. Change the PPU Scroll Register ($2005) to have Y=0 and X to asteroid move value. (also during the hblank)
Re: Simple sprite 0 questions and advice
It's the first sprite in OAM memory, not the first sprite in CHR.
- battagline
- Posts: 152
- Joined: Wed Sep 05, 2018 11:13 am
- Location: Colorado
- Contact:
Re: Simple sprite 0 questions and advice
Ok, I think I'm going to have more questions soon. I appreciate the help.
Thanks
Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
Re: Simple sprite 0 questions and advice
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.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.
Re: Simple sprite 0 questions and advice
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.
Re: Simple sprite 0 questions and advice
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?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.
Re: Simple sprite 0 questions and advice
I deleted it. Tokumaru covered what I wanted to say.post that somehow disappeared
nesdoug.com -- blog/tutorial on programming for the NES
- battagline
- Posts: 152
- Joined: Wed Sep 05, 2018 11:13 am
- Location: Colorado
- Contact:
Re: Simple sprite 0 questions and advice
More troubles. So at the end of the NMI, I set the scroll registers to 0
At the beginning of my game loop I wait for the sprite 0 hit then change the scroll register to move the asteroid
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
Code: Select all
set PPU_SCROLL, #0
set PPU_SCROLL, #0
Code: Select all
jsr sprite0_wait
set PPU_SCROLL, scroll_x
set PPU_SCROLL, #0
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
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
Re: Simple sprite 0 questions and advice
Access to $2005 during rendering is full of gotchas.battagline wrote: set PPU_SCROLL, scroll_x
set PPU_SCROLL, #0
#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.
Re: Simple sprite 0 questions and advice
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.
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.
- battagline
- Posts: 152
- Joined: Wed Sep 05, 2018 11:13 am
- Location: Colorado
- Contact:
Re: Simple sprite 0 questions and advice
Is that the reason I'm getting a second sprite0 hit at scanline 247? Or is that unrelated?
Thanks
Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
Re: Simple sprite 0 questions and advice
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.
- battagline
- Posts: 152
- Joined: Wed Sep 05, 2018 11:13 am
- Location: Colorado
- Contact:
Re: Simple sprite 0 questions and advice
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
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
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com