Does input need to be polled every frame?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

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

Re: Does input need to be polled every frame?

Post by tokumaru »

A lag frame is when the main loop takes too long and is interrupted by the NMI. The problem with reading the controllers the NMI in this case is that the part of the main loop that ran before the NMI will see one controller state, while the part that runs after the NMI will see another state, and this could cause inconsistencies in the game logic (a button might appear both pressed and not pressed in the same logical frame depending on when you check it).

Another thing to worry about in case of lag frames is the correctness of VRAM update buffers and PPU parameters such as the scroll. You must implement some means of not letting the NMI handler use partially filled buffers or new scroll values until all VRAM updates are properly carried out.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Does input need to be polled every frame?

Post by Pokun »

I see, that's what I thought.

The graphics updates each have their own flag (except OAM-DMA) that has to be set before they run (as suggested the article The frame and NMIs) and the flag are only set in the main loop when there are pending updates in the corresponding buffer. But this also means an NMI is not always of the same length every frame, not sure if that is a big problem (music might get out of beat I guess).

The reason why OAM-DMA isn't conditional is because I thought earlier that it had to happen every frame. Maybe I should make that conditional too, to avoid it using a partially filled OAM buffer?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Does input need to be polled every frame?

Post by tokumaru »

Pokun wrote:The graphics updates each have their own flag (except OAM-DMA) that has to be set before they run (as suggested the article The frame and NMIs) and the flag are only set in the main loop when there are pending updates in the corresponding buffer.
I don't know if individual flags for each buffer is the way to go, since the different updates might be correlated in some way that only makes sense if they're all performed at the same time. For example, in a game where the player can change characters on the fly, it makes sense to change the character's patterns, palette and OAM entries all at the same time, otherwise you may end up with miscolored or glitchy-looking sprites for a brief moment. The individual updates should not depend on each other if it there's a chance that only some of them will be carried out.
But this also means an NMI is not always of the same length every frame, not sure if that is a big problem (music might get out of beat I guess).
I don't know as much about audio as I'd like, but I assume this distortion is way too subtle for anyone to notice. At 15720 (262 * 60) scanlines per second, a period of 20 scanlines (the length of vblank) is less than 1.3ms. I hope I did the math right.
The reason why OAM-DMA isn't conditional is because I thought earlier that it had to happen every frame.
OAM starts decaying if the PPU is off for too long. I don't know how long is "too long", but if you aren't using forced blanking, I don't think OAM will decay from one frame to the next.
Maybe I should make that conditional too, to avoid it using a partially filled OAM buffer?
Using a partially filled OAM buffer is pretty bad, but even if it's completely filled, if the rest of the updates aren't carried out along with the OAM DMA, the sprites might look out of sync with the rest of the scene. Objects that switch between background and sprites (such as blocks that can be broken or picked up) might look duplicated or be missing for a frame, scrolling might look jittery, and so on.

Lag frames can cause pretty bad side effects if you aren't fully prepared for them. For example, if you have a status bar along with a scrolling background, you should double buffer the scroll values (along with any other raster effects you might have) and only swap the buffers in the NMI handler. Since raster effects have to be done even during lag frames, there's no such thing as a typical "ready flag" for them, if the NMI interrupts raster effect changes, you're screwed. This is why you should double buffer them, so that there's always a set of consistent raster effects the NMI handler can use. The "ready flag" in this case means that the NMI handler can switch the sets. If you don't have raster effects, you can simply not change the scroll (which means not using $2006 either) during lag frames and the scroll from last time will be used again.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Does input need to be polled every frame?

Post by tepples »

tokumaru wrote:A lag frame is when the main loop takes too long and is interrupted by the NMI. The problem with reading the controllers the NMI in this case is that the part of the main loop that ran before the NMI will see one controller state, while the part that runs after the NMI will see another state, and this could cause inconsistencies in the game logic (a button might appear both pressed and not pressed in the same logical frame depending on when you check it).
True.

But on the other hand, if a lag frame is long enough, not polling controllers at all during lag frames might cause a press and release during a lag frame to be missed. This is the case, for example, with the Vs. coin switches.

Perhaps this is the most robust method: NMI reads the controller, accumulates presses and releases, and writes the current state to a variable. When the next frame begins, it copies the current state, presses, and releases to its own variable, and clears the NMI's copy of presses and releases.
tokumaru wrote:For example, in a game where the player can change characters on the fly, it makes sense to change the character's patterns, palette and OAM entries all at the same time, otherwise you may end up with miscolored or glitchy-looking sprites for a brief moment.
That and if you're using CHR RAM, ensure that the "changing" cel is loaded first.
tokumaru wrote:OAM starts decaying if the PPU is off for too long. I don't know how long is "too long", but if you aren't using forced blanking, I don't think OAM will decay from one frame to the next.
Correct: it won't decay so long as it's refreshed at least every 20-some scanlines. In particular, it won't decay between last line of one frame and the first of the next.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Does input need to be polled every frame?

Post by tokumaru »

tepples wrote:But on the other hand, if a lag frame is long enough, not polling controllers at all during lag frames might cause a press and release during a lag frame to be missed. This is the case, for example, with the Vs. coin switches.
Can humans press a button this fast though? If the coin switch signals are this fast, then you should probably have special code to handle that specific aspect and set a flag that the main loop can check (and clear) when it's most convenient.
Correct: it won't decay so long as it's refreshed at least every 20-some scanlines. In particular, it won't decay between last line of one frame and the first of the next.
If I'm not mistaken, this is also the reason why OAM DMA must happen during the first 20-some scanlines of vblank in PAL consoles: OAM refresh starts after that many scanlines, even though vblank continues for another 50 scanlines or so.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Does input need to be polled every frame?

Post by rainwarrior »

Pokun wrote:Also what is a "lagframe"?
Maybe that was the wrong term to use, but a frame that takes too long and gets displayed twice. Slowdown. 2 NMIs but only one game update.

Edit: oh, sorry. Didn't see the second page, this has already been answered.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Does input need to be polled every frame?

Post by tepples »

tokumaru wrote:
tepples wrote:if a lag frame is long enough, not polling controllers at all during lag frames might cause a press and release during a lag frame to be missed.
Can humans press a button this fast though?
I think I can do 14 presses per second without turbo controller assistance. That's about 2 frames on, 2 frames off. Mix in some Micronics and missed presses become the rule.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Does input need to be polled every frame?

Post by koitsu »

tokumaru wrote:Can humans press a button this fast though? If the coin switch signals are this fast, then you should probably have special code to handle that specific aspect and set a flag that the main loop can check (and clear) when it's most convenient.
Getting off-topic, but I believe it's time to introduce tokumaru to Takahashi Meijin (video). (Random trivia: Hudson's Adventure Island is actually called Takahashi Meijin no Bouken Jima -- yes, Master Higgins is supposed to be Takahashi Meijin)

Whether or not a game needs to be able to handle this kind of "input rate" depends on the game. Choose poorly, however, and you may find angry retro gamers forever loathing you -- nobody likes non-responsive controls.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Does input need to be polled every frame?

Post by Pokun »

Oh this was all so easy before I was aware of all the possible problems. But thanks for all the tips!

OAM only decays (on NTSC PPU) when rendering is off? In other words when both BG and sprites are turned off in $2001? Then I don't see that as much of a problem as I'm mainly turning it off when changing screens and so on.
tokumaru wrote:
Pokun wrote:The graphics updates each have their own flag (except OAM-DMA) that has to be set before they run (as suggested the article The frame and NMIs) and the flag are only set in the main loop when there are pending updates in the corresponding buffer.
I don't know if individual flags for each buffer is the way to go, since the different updates might be correlated in some way that only makes sense if they're all performed at the same time. For example, in a game where the player can change characters on the fly, it makes sense to change the character's patterns, palette and OAM entries all at the same time, otherwise you may end up with miscolored or glitchy-looking sprites for a brief moment. The individual updates should not depend on each other if it there's a chance that only some of them will be carried out.
I see, maybe sprite and sprite palettes should share one flag and the BG buffer and the BG palettes should share another one. That way sprites and nametables will always be updated the same time as their corresponding palettes. Either that or one flag for all graphic updates so that the whole screen is updated consistently when all buffers are filled.

I haven't done any scrolling yet. My main project is a single screen game anyway, so the only scrolling I might do is for certain effects.
I might start a new thread about my particular problems to avoid derailing the thread though.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Does input need to be polled every frame?

Post by rainwarrior »

Pokun wrote:OAM only decays (on NTSC PPU) when rendering is off? In other words when both BG and sprites are turned off in $2001? Then I don't see that as much of a problem as I'm mainly turning it off when changing screens and so on.
I believe it decays on PAL as well. It was my understanding that PAL just has a couple of forced refreshes during the extended vblank so that it doesn't end up decaying before the end of vblank. Outside of vblank it should still decay if rendering is disabled, AFAIK. (Someone with a PAL system might comment on this, though.)

i.e. the practise I understand is that after rendering is off for any length of time longer than an NTSC vblank, OAM must be fully reinitialized. OAM should only be uploaded during vblank, or on PAL specifically during the beginning part of vblank.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Does input need to be polled every frame?

Post by Pokun »

Oh I see, vblank time is longer than 20 scanlines on PAL so they had to refresh it after 20 scanlines, so that it doesn't decay during vblank like it does in a forced blanking.

So if you always makes sure an OAM-DMA is run before you turn on rendering, you will never have this problem.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Does input need to be polled every frame?

Post by thefox »

rainwarrior wrote:
Pokun wrote:OAM only decays (on NTSC PPU) when rendering is off? In other words when both BG and sprites are turned off in $2001? Then I don't see that as much of a problem as I'm mainly turning it off when changing screens and so on.
I believe it decays on PAL as well. It was my understanding that PAL just has a couple of forced refreshes during the extended vblank so that it doesn't end up decaying before the end of vblank. Outside of vblank it should still decay if rendering is disabled, AFAIK. (Someone with a PAL system might comment on this, though.)
OAM does actually seem to maintain its state on PAL NES even when rendering is off. (Presumably this means that if you do OAM DMA when rendering is off, you should do it within a sufficient time after NMI.) This is all hinging solely on my (possibly flawed) tests, so I really hope somebody else with PAL NES eventually tries to duplicate these results.

Reference: viewtopic.php?f=9&t=11041&p=127180
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Does input need to be polled every frame?

Post by tokumaru »

Pokun wrote:So if you always makes sure an OAM-DMA is run before you turn on rendering, you will never have this problem.
You'd think that a fresh OAM DMA would solve all issues, but there's one problem that not even this can fix: if you disable rendering while sprites are being evaluated, the PPU goes batshit crazy when rendering is enabled again and corrupts a few OAM bytes. For this reason, avoid turning rendering off mid-screen, but if you really need to, avoid doing it in scanlines with many sprites, and do it as close to the end of the scanline as possible.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Does input need to be polled every frame?

Post by Pokun »

OK so OAM decay on PAL is still unclear.

Normally I turn off rendering using a subroutine like this:

Code: Select all

ppu_off:
  lda #$00
  sta shadow_2001           ;turn off rendering in buffer
  lda #$01
  sta ppu_flag              ;indicate that there are PPU setting updates
  jsr nmi_wait              ;wait for an NMI to update from buffer
  rts
Then the NMI handler copies the buffer to the real $2001.
Buffering PPU setting updates to $2000 and $2001 is also as suggested from "The frame and NMI". This should make sure rendering is always turned off in vblank if I'm not mistaken.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Does input need to be polled every frame?

Post by tokumaru »

Pokun wrote:This should make sure rendering is always turned off in vblank if I'm not mistaken.
Yes, but does this have anything to do with OAM decay?
Post Reply