Why not read controllers in NMI?

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
mikejmoffitt
Posts: 1353
Joined: Sun May 27, 2012 8:43 pm

Re: Why not read controllers in NMI?

Post by mikejmoffitt »

Street Fighter II reads inputs at the start of the game's polling loop. This is troublesome for emulator authors who don't update the virtual inputs frequently. If the game has a "turbo" setting on, it means that the number of game ticks that run per visual frame can vary, and with that, the frequency of input polls.

Dwedit - why would reading the gamepad during the NMI produce controller data changes mid-frame?
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Why not read controllers in NMI?

Post by Dwedit »

Just assuming you store your byte after you did the 8 joypad reads.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Why not read controllers in NMI?

Post by rainwarrior »

Race conditions with a vblank interrupt aren't necessarily a big deal. It depends how often you refer to your input, and what you do with it. If you handle your player control early on in a frame and never later on it'd be pretty unlikely to get clobbered even in a lag situation. There are lots of "convenient" reasons one might end up checking again later on in a frame though...

The main disadvantage is just that you've introduced another situation that can go wrong if you're not aware of the threading / timing. Probably most of the time it wouldn't matter at all, but the kind of errors you get when you forget can be pretty insidious.

That's basically why I'd advocate not doing it by default on the NES, but if you've got a reason you need it then sure go for it.
tepples wrote:Would it be likewise "apples to oranges" between the NES and Super NES?
Ask me when you've got a concrete example for SNES, I don't want to get hypothetical. We're comparing a C games library API on Genesis to what's appropriate for NES, or at least, I was.

Polling in a vblank interrupt is a valid technique on NES, SNES, or Genesis. Polling on demand is also valid on all three of these platforms.

Should one way or the other be "standard" for any of these platforms? I don't care. I think I already stated what purposes it can be used for. If you've got a good use case for it, use it. If you don't, I'd probably recommend not doing it for simplicity's sake. If you're using a library like SGDK, just roll with however it expects you to do things.
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: Why not read controllers in NMI?

Post by calima »

tepples wrote:And which get linked into the executable, occupying ROM and RAM, even if unused.
No, they do not. These are modern tools, with LTO and other such conveniences the ancient platforms can only dream of.

LTO will notice you never call function X. That cascades. If you don't use any SGDK joy functions, they will be optimized out such that only the var update in the vblank func will remain.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Why not read controllers in NMI?

Post by Bregalad »

tokumaru wrote:One reason not to read controllers in the NMI handler is the consistency of controller state within the same logic frame. If a lag frame happens, and an NMI fires in the middle of that logic frame, it's possible that different controller states will be readable in that same logic frame.
I was going to say the exact same thing. This is really the only significant problem with reading the controller in NMI. I can't think of anything else. If the main code is designed robustly, either by making it's local copies during decision-taking routines, or by making sure the potentially slow code is always executed after the code using the controller-read value and taking decisions, it's fine. But the danger of having main codes behaving weirdly, or, in worst cases, even crashing, if the controller changes states during a lag frame, is there. This could also be a thing to exploit for speedruners.

For similar reasons, it would be bad practice to poll the controller multiple times during the same frame (*) - unless the logic is solid, and for example once only the directional pad are used and the other time only the buttons are used.
(*) I'm not including cases where reading the controller multiple times is part of the read routine

Also I disagree with tepples that games usually don't read controller during NMI. This practice might be not recommended, but commercial games still do it, often. Just check the NMI routine of your favourite games.

The only real advantage of reading the controller in NMI I can think of, is that you don't need to call the controller reading routine at many different places across the game's code. This saves a tiny bit of ROM. Other than that I can't think of any advantages.
tokumaru wrote: I don't know about the Mega Drive, but on the NES, where vblank time is at a premium, wasting part of it on a task that could literally be performed at any other time, would be completely nonsensical.
Doing it before the VRAM updates would be completely nonsensical, but doign it in NMI after all VRAM updates, I really don't see the problem. Just like playing the music engine, by the way. And reading controllers in constant-cycle-timed routine is not hard to do, so it even doesn't clash with potential further-raster-effects-that-don't rely-on-sprite-zero-hit.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Why not read controllers in NMI?

Post by Pokun »

Yeah I'm also not sure what Tepples is talking about. It is commonly done in games. I once even thought it was preferable to have input reading in NMI, but Tokumaru taught me about the possible inconsistency it introduces, and I stopped doing it.

Also doesn't the SNES controller auto-reading function read the controllers in vblank or something?
Bregalad wrote:The only real advantage of reading the controller in NMI I can think of, is that you don't need to call the controller reading routine at many different places across the game's code. This saves a tiny bit of ROM. Other than that I can't think of any advantages.
That could be done in the main loop as well. If you have a jump table for the various modes your game has in the main thread, you can just read the controllers before the jump table and jumping to the active mode's logic. As long as all modes are fine with the same controller reading routine it's enough with just one call.
supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: Why not read controllers in NMI?

Post by supercat »

calima wrote:
tepples wrote:And which get linked into the executable, occupying ROM and RAM, even if unused.
No, they do not. These are modern tools, with LTO and other such conveniences the ancient platforms can only dream of.

LTO will notice you never call function X. That cascades. If you don't use any SGDK joy functions, they will be optimized out such that only the var update in the vblank func will remain.
LTO is only good if there is a means of indicating when a function call needs to be regarded as "opaque", and all functions where that is necessary are thus marked. When C was invented, there was no need for such a directive because all or nearly all extant compilers would extend the language by treating cross-module function calls as opaque(in fact such treatment was so universal it wasn't generally thought of as an "extension", but simply part of how the language worked), and thus very little code that relies upon such treatment that is marked to indicate such reliance.

Without such marking, something like:

Code: Select all

   volatile unsigned char data_ready_flag;
   void wait_for_frame(void)
   {
      while(data_ready_flag)
        ;
   }
   ...
   databuff[0] = 123;
   wait_for_frame();
   databuff[0] = 45;
   wait_for_frame();
may get "optimized" to remove one of the stores to databuff[0].
supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: Why not read controllers in NMI?

Post by supercat »

Bregalad wrote:(*) I'm not including cases where reading the controller multiple times is part of the read routine
If one performs an OAM DMA within the NMI routine, and keeps track of whether an even or odd number of cycles have elapsed between then and the code that will read the controller, one can avoid the possibility of DMC clobbering the controller read. Likewise if one reads the controller at a suitable time within a DMC IRQ. While one needs to be mindful of how controller inputs will behave in the presence of lag, and ensure that such behaviors will always be sensible, I think reading then at a consistent point each frame is for many purposes better than just reading them "whenever".
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Why not read controllers in NMI?

Post by Bregalad »

supercat wrote:If one performs an OAM DMA within the NMI routine, and keeps track of whether an even or odd number of cycles have elapsed between then and the code that will read the controller, one can avoid the possibility of DMC clobbering the controller read. Likewise if one reads the controller at a suitable time within a DMC IRQ. While one needs to be mindful of how controller inputs will behave in the presence of lag, and ensure that such behaviors will always be sensible, I think reading then at a consistent point each frame is for many purposes better than just reading them "whenever".
I've edited this note in quickly because when I claimed that reading controller twice per frame could be potentially harmful, I was sure someone came up with an annoying remark noticing how this is useful for DMC. Apparently even though I've edited this in, I still didn't avoid people quibble over that.
supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: Why not read controllers in NMI?

Post by supercat »

Bregalad wrote:
supercat wrote:If one performs an OAM DMA within the NMI routine, and keeps track of whether an even or odd number of cycles have elapsed between then and the code that will read the controller, one can avoid the possibility of DMC clobbering the controller read. Likewise if one reads the controller at a suitable time within a DMC IRQ. While one needs to be mindful of how controller inputs will behave in the presence of lag, and ensure that such behaviors will always be sensible, I think reading then at a consistent point each frame is for many purposes better than just reading them "whenever".
I've edited this note in quickly because when I claimed that reading controller twice per frame could be potentially harmful, I was sure someone came up with an annoying remark noticing how this is useful for DMC. Apparently even though I've edited this in, I still didn't avoid people quibble over that.
My point was that if one is using DMC for video frame timing and reads controllers from the main loop, one will have to read them multiple times to make them reliable, but the necessity of reading them twice suggests that the controllers should be read differently.
Roth
Posts: 401
Joined: Wed Aug 03, 2005 3:15 pm
Contact:

Re: Why not read controllers in NMI?

Post by Roth »

I'm not sure I understand what is bein' posited? I think every NES game I've made strobes the controller in NMI, but not necessarily in vblank. Are we talkin' about readin' the actual inputs that the user... inputs? Like testin' if they pushed the 'A' button and all that jazz?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Why not read controllers in NMI?

Post by tokumaru »

Yeah, we're talking about reading the state of the controller's buttons. The main argument against doing this in the NMI handler is that the state of the controller will change in the middle of lag frames, which could cause problems depending on how the game uses the input data, while the main argument for reading the controllers in the NMI handler appears to be the possibility of using the OAM DMA to avoid controller data corruption caused by DPCM sample fetches.
Roth
Posts: 401
Joined: Wed Aug 03, 2005 3:15 pm
Contact:

Re: Why not read controllers in NMI?

Post by Roth »

haha What a weird debate. Obviously it will depend on the engine bein' used, because if you KNOW there will be no input lag due to lagging frames, then implement it. Alternatively, if you can implement a DMC bug squash with it, then do it.

The way I tend to program though, I would shy away from anything not PPU related during vblank. But that's because everyone has a different way to implement things hehe No one is right or wrong, if I'm reading this correctly. Just all about implementation?
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Why not read controllers in NMI?

Post by Pokun »

It's not about being right or wrong. It's about different possibilities and pros and cons, but yeah it heavily depends on what you are trying to do.

Also it is not about input lag, but rather the opposite (logic lags but not the controller). It's about a possible bug if you have slowdown in your game and have the controller reading in NMI instead of the main thread.
If the main thread lags and an NMI interrupts it, having the controller reading in the NMI will update the controller state again before the main thread has finished the logic. So the first part of the logic is processing one controller state and the second part (after PC has returned from NMI) is processing an updated controller state, which would potentially be the cause of a bug, although possibly rarely.

If you can guarantee you have no lag frames there is no problem in having the controller reading in NMI though, since there will be an equal number of main thread logic frames as NMI frames.

Either way NMI isn't strictly for vblank related things. Your sound driver is best updated in the NMI or the music will not have a consistent beat if you have lag frames (some commercial games messes this up too).


The DMC fix is very advanced, and I'm not sure it's fully PAL compatible either.
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: Why not read controllers in NMI?

Post by FrankenGraphics »

The DMC fix is very advanced, and I'm not sure it's fully PAL compatible either.
The theory behind is in-depth but the implementation is plug and play, provided there's nothing in your game that makes controller reads right after OAMDMA directly unsuitable.

the PAL version doesn't have the dmc bug (it was fixed), so it should work either way you do it, rahsennors' cycle alignment fix or not. There might be problems with several emulators, though - the even/odd observation was only highlighted a few years ago and emulators might not have the bug correctly implemented. Then again, you need games that use the dmc fix to create incentive to fix emulation inaccuracies.
Post Reply