It is currently Tue Nov 13, 2018 9:21 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 14 posts ] 
Author Message
PostPosted: Sat Oct 27, 2018 12:40 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 141
Location: Colorado
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


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 6:15 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10959
Location: Rio de Janeiro - Brazil
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.

Quote:
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.

Quote:
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.

Quote:
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.

Quote:
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.


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 6:34 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 415
It's the first sprite in OAM memory, not the first sprite in CHR.


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 7:53 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 141
Location: Colorado
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


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 7:59 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20762
Location: NE Indiana, USA (NTSC)
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.


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 8:32 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10959
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 9:37 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20762
Location: NE Indiana, USA (NTSC)
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?


Top
 Profile  
 
PostPosted: Sat Oct 27, 2018 10:16 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2329
Location: DIGDUG
Quote:
post that somehow disappeared


I deleted it. Tokumaru covered what I wanted to say.

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


Top
 Profile  
 
PostPosted: Sun Oct 28, 2018 3:30 pm 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 141
Location: Colorado
More troubles. So at the end of the NMI, I set the scroll registers to 0

Code:
        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:
        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:
File comment: Sprite 0 fail
nesteroids.nes [40.02 KiB]
Downloaded 24 times

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
Top
 Profile  
 
PostPosted: Sun Oct 28, 2018 3:50 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7714
Location: Seattle
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.


Top
 Profile  
 
PostPosted: Sun Oct 28, 2018 9:16 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 415
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.


Top
 Profile  
 
PostPosted: Mon Oct 29, 2018 8:37 am 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 141
Location: Colorado
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


Top
 Profile  
 
PostPosted: Mon Oct 29, 2018 8:45 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10959
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Mon Oct 29, 2018 8:53 am 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 141
Location: Colorado
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


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: Nioreh and 2 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