What came first the chicken or the egg? (Updating v Drawing)

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
BARBEERIAN
Posts: 13
Joined: Sun Jan 02, 2011 9:58 pm

What came first the chicken or the egg? (Updating v Drawing)

Post by BARBEERIAN » Wed Feb 20, 2019 3:05 pm

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

User avatar
rainwarrior
Posts: 7703
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: What came first the chicken or the egg? (Updating v Draw

Post by rainwarrior » Wed Feb 20, 2019 3:46 pm

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.

User avatar
gravelstudios
Posts: 75
Joined: Mon Mar 13, 2017 5:21 pm
Contact:

Re: What came first the chicken or the egg? (Updating v Draw

Post by gravelstudios » Wed Feb 20, 2019 4:53 pm

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.

User avatar
tokumaru
Posts: 11496
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: What came first the chicken or the egg? (Updating v Draw

Post by tokumaru » Wed Feb 20, 2019 5:00 pm

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.

Oziphantom
Posts: 779
Joined: Tue Feb 07, 2017 2:03 am

Re: What came first the chicken or the egg? (Updating v Draw

Post by Oziphantom » Thu Feb 21, 2019 12:34 am

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.

User avatar
Sumez
Posts: 909
Joined: Thu Sep 15, 2016 6:29 am
Location: Denmark (PAL)

Re: What came first the chicken or the egg? (Updating v Draw

Post by Sumez » Thu Feb 21, 2019 2:25 am

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.

BARBEERIAN
Posts: 13
Joined: Sun Jan 02, 2011 9:58 pm

Re: What came first the chicken or the egg? (Updating v Draw

Post by BARBEERIAN » Thu Feb 21, 2019 1:31 pm

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.

User avatar
tokumaru
Posts: 11496
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: What came first the chicken or the egg? (Updating v Draw

Post by tokumaru » Thu Feb 21, 2019 1:55 pm

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.

Post Reply