It is currently Mon May 20, 2019 7:42 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Wed Feb 20, 2019 3:05 pm 
Offline

Joined: Sun Jan 02, 2011 9:58 pm
Posts: 13
I'm wondering what the pro's and con's of two ways of approaching updating and drawing are, or if it even makes a difference.

Right now I'm doing:

NMI sets a 'need to update' flag to TRUE for game logic to update -> MAIN updates game logic if flag is TRUE -> MAIN sets flag false when it's done updating -> NMI draws stuff and resets the flag to TRUE

But I'm curious if the following offers any benefits (outside of the first frame where NMI basically does nothing):

MAIN runs game logic and sets a 'draw' flag to TRUE when it's done -> NMI checks if game logic is ready to draw. If FALSE it does nothing and waits until the next frame, if TRUE it sets up rendering stuff and sets the flag false


Top
 Profile  
 
PostPosted: Wed Feb 20, 2019 3:46 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7459
Location: Canada
The main thread needs to wait for the NMI to finish the update before it can begin a new one, so both of those communications need to happen (or both of them are equivalent, I'm not sure exactly what you're describing.). Something like this:
  • 1. Main generates data to send as an update, sets a flag to say it's ready. Waits until flag clears.
  • 2. Nmi eventually happens again and sees the flag, does update, clears flag.
  • 3. Main sees the flag is clear, go back to 1.

It's important that the NMI does nothing if the main thread hasn't finished a frame yet, otherwise you can get the NMI trying to push half finished data if you have a "slow" frame that took the main thread longer than expected.

The point is, the NMI has to do nothing if the frame is not ready yet, and then the main thread needs to wait until the NMI is finished uploading the new data. Both of those synchronization points need to occur.


Top
 Profile  
 
PostPosted: Wed Feb 20, 2019 4:53 pm 
Offline
User avatar

Joined: Mon Mar 13, 2017 5:21 pm
Posts: 58
The only way I can think about it that makes sense to me is that the game state has to be determined first, and then the NMI updates the PPU and APU based on the game state. Thinking about it the other way around just doesn't make sense. You can't display stuff that hasn't happened yet.

I think the 'all in the NMI' style of organizing code can be confusing, because it seems as if the NMI exclusive stuff (like updating the PPU) is happening first. it's not really. the CPU is just spinning in the main loop waiting for an NMI to happen. So when the first NMI occurs, there are no legitimate updates to do. Those first PPU updates don't do anything meaningful until the code that follows them creates a game state. it's just one frame though, so who cares. It took me a while to figure out that what is actually happening is that updating the PPU is the last thing, not the first thing. the bulk of the code figures out the game state, then (assuming this isn't a lag frame) the CPU enters into a holding pattern of some sort waiting for NMI, then when NMI occurs the PPU and APU get updated. If there is more game logic code in the NMI routine after that, it's really part of the code that's updating the state. The fact that it's inside the NMI routine is inconsequential.


Top
 Profile  
 
PostPosted: Wed Feb 20, 2019 5:00 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11345
Location: Rio de Janeiro - Brazil
The way you worded things made it seem like the NMI is calling the shots, but the way I see it, the main thread is, as the name implies, the main part. The NMI doesn't get to say that a redraw is needed, it's the main thread that continuously produces content and signals when the content is ready for the NMI to consume. Of course the main thread has to wait for the content to be consumed so that new content can be written to the various buffers, seeing as there's normally only one set of buffers.


Top
 Profile  
 
PostPosted: Thu Feb 21, 2019 12:34 am 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 711
Well the Update happens first. As you need to enable NMI( :roll: ) it can't happen until it is allowed to happen, thus updating happens first.

Typically the NMI "follows" your game, so you game updates, then the NMI happens to present the updated state. Small games can just be "NMI" though so it neither chases nor follows.


Top
 Profile  
 
PostPosted: Thu Feb 21, 2019 2:25 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 896
Location: Denmark (PAL)
tokumaru wrote:
The way you worded things made it seem like the NMI is calling the shots, but the way I see it, the main thread is, as the name implies, the main part. The NMI doesn't get to say that a redraw is needed, it's the main thread that continuously produces content and signals when the content is ready for the NMI to consume. Of course the main thread has to wait for the content to be consumed so that new content can be written to the various buffers, seeing as there's normally only one set of buffers.


Yeah, this is how I see it.
To me, the NMI is a process that's being called completely independently of my actual videogame logic. It's a dumb task that makes things happen, so the player will see an output on the screen.
Even though I have a pretty good idea of when it's going to happen, I try to think of it as a completely random process out of my control, that could occur at any time. And when it does, it simply looks at some variables I have defined to indicate which tasks it should carry out, after which it indicates that it has done it. And as other people have pointed out, whenever the main thread is done processing a frame, it just chooses to wait for the next NMI to be done as a way of syncing.


Top
 Profile  
 
PostPosted: Thu Feb 21, 2019 1:31 pm 
Offline

Joined: Sun Jan 02, 2011 9:58 pm
Posts: 13
Thanks for the input everyone. I'll try to start reorganizing things in the program.

gravelstudios wrote:
The only way I can think about it that makes sense to me is that the game state has to be determined first, and then the NMI updates the PPU and APU based on the game state. Thinking about it the other way around just doesn't make sense. You can't display stuff that hasn't happened yet.

I think the 'all in the NMI' style of organizing code can be confusing, because it seems as if the NMI exclusive stuff (like updating the PPU) is happening first. it's not really. the CPU is just spinning in the main loop waiting for an NMI to happen. So when the first NMI occurs, there are no legitimate updates to do. Those first PPU updates don't do anything meaningful until the code that follows them creates a game state. it's just one frame though, so who cares. It took me a while to figure out that what is actually happening is that updating the PPU is the last thing, not the first thing. the bulk of the code figures out the game state, then (assuming this isn't a lag frame) the CPU enters into a holding pattern of some sort waiting for NMI, then when NMI occurs the PPU and APU get updated. If there is more game logic code in the NMI routine after that, it's really part of the code that's updating the state. The fact that it's inside the NMI routine is inconsequential.


I know what you mean. I'm still a noob at NES (and a crap programmer to begin with) and the tutorials I've been going through are 'all in NMI' which makes it seem like the NMI is the boss of things not the main loop. I'm still bad enough that it's hard for me to 'think outside the box' of what tutorials teach me.


Top
 Profile  
 
PostPosted: Thu Feb 21, 2019 1:55 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11345
Location: Rio de Janeiro - Brazil
BARBEERIAN wrote:
the tutorials I've been going through are 'all in NMI' which makes it seem like the NMI is the boss of things not the main loop.

I guess that "all in NMI" is simpler for beginners because it means only one thread to care about, which does away with all those synchronization issues. The problem with using a single thread, be it "all in NMI" or "all in main", is the poor handling of lag frames... if you simply ignore the occurrence of vblank during lag frames, there may be a number of side effects, like the music slowing down or raster effects breaking.

It is actually possible to handle lag frames when doing "all in NMI" if you allow reentrant NMIs, but I don't see why anyone would prefer that over using the main thread.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 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