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

supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: Why not read controllers in NMI?

Post by supercat »

lidnariq wrote:
supercat wrote:Code which would be ill-prepared to handle an NMI may clear bit 7 of $2000 to prevent it from firing on schedule, such that if vblank happens when the system is unready the handler will either start late within the current vblank or else wait until the next one.
Writing to $2000 during rendering can cause a shoot-through glitch, incorrectly clearing the 256s bit of X scrolling for one scanline. This only happens on some subpixel alignments, and only if the write collides with the correct pixel, but without timed code it's hard to be assured of missing that. As a result, if you're using 4-screen or horizontal layout of nametables, it's best to avoid using the NMI enabled bit to selectively mask NMIs at runtime in the NES.
I don't recall having read of that problem. If one wants to change the B, S, or NN bits mid-frame, what update time must one avoid? And do you see any problems with the "soft-disable approach" shown (which, unlike hardware disabling of NMI, will allow code to know how many frames it missed)?
Fiskbit
Posts: 891
Joined: Sat Nov 18, 2017 9:15 pm

Re: Why not read controllers in NMI?

Post by Fiskbit »

According to previous findings and discussion, the OAM DMA-safe portion of PAL vblank is likely larger than NTSC vblank and the information on the wiki here is likely not accurate to the scanline. If your OAM DMA fits in NTSC vblank, it probably works on PAL.

As far as emulator compatibility for synchronized reads, I tested various emulators in January and found that support among emulators that emulate joypad bit deletion is still very poor, with only Nintendulator passing all the current tests. Compatibility is better if your joypad read code is shorter than the time between two DMA reads (ie you're not reading 4 controllers). Unfortunately, Nestopia UE passes none of them and is widely used because of its libretro core, which has made me uncomfortable with using this in something I want people to be able to reliably play.

For the shoot-through glitch, my understanding based on recent findings is that you can avoid the glitching if you write to $2000 or $2100 depending on whether the screen is currently on the left ($2000) or right ($2100) half of the nametables.

Edit: On the matter of the original topic, I would think that reading joypads in the NMI is fine, but I would only do it on non-lag frames, just as I would also only do OAM DMA and VRAM writes on non-lag frames to avoid drawing partial state. On the NES, I don't know what I would do with fresh joypad information partway through a frame and it definitely adds risk of bugs unless being put into a separate variable. The only real benefit I can see is being able to continue capturing press vs down information at a constant rate even when lagging, but I would not expect to ever see a button be indicated as freshly pressed on two consecutive frames, so this seems like it could also cause bugs.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Why not read controllers in NMI?

Post by Pokun »

Edit: Sorry I didn't see the above two posts before I posted this.
FrankenGraphics wrote:
pokun wrote:and it seems there are limitations of how the actual controller reading routine may look like
hmm... to what ends do you want to alter the example code? Removing 1 of the 2 controllers is simple enough; it still aligns correctly.
I can think of many situations where you can't use the example code. Using other input devices, using a controller reading FDS BIOS call to save disk space, using a multitap etc. Having variable size vblank routines or not wanting to loose vblank time from doing the controller reading in vblank is probably very common as well. The DMC workaround seems to be a valid solution to the bug (especially for things like mouse and keyboard where you may not be able to read it twice), but it is an advanced solution that may require extra thought as soon as you are doing something different from the example code.
rainwarrior wrote:
tepples wrote:
FrankenGraphics wrote:There's the inconvenience that you you get the order
OAMDMA, controller reads, other graphics updates, music.
rather than
OAMDMA, other graphics updates, controller reads, music.

for an update order that works on both systems.
I was thinking this:
  1. if (PAL NES) { OAM DMA }
  2. VRAM updates
  3. if (not PAL NES) { OAM DMA }
  4. controller reading if requested
  5. audio
??? Why would you do this? There is no reason to have two separate orderings. PAL doesn't start its forced OAM refresh until 21 scanlines in. If an order works for NTSC's budget, it will still work for PAL.

"OAM DMA first" is just a rule of thumb, not any kind of requirement.
So the required OAM-DMA timing for NTSC and PAL are the same? I can swear I read somewhere on the wiki that PAL requires an earlier OAM-DMA than NTSC which may even benefit from a late one when doing the mentioned DMC workaround.
In that case, disregard everything I said about the DMC workaround counting cycles not being compatible with PAL. NTSC and PAL can have identical vblank routines.
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 »

pokun wrote:So the required OAM-DMA timing for NTSC and PAL are the same? I can swear I read somewhere on the wiki that PAL requires an earlier OAM-DMA than NTSC which may even benefit from a late one when doing the mentioned DMC workaround.
This article describes most of what you said (link) - though it doesn't have to do with the DMC cycle avoidance.

I read it as such:
1) on NTSC you *might* extend the vBlank period through forced blanking to gain a longer period to update VRAM in, as an approximation of the PAL versions' extended vBlank. But in order to do this, you should put OAMDMA late, lest it decays.

2) Not only is this redundant for the PAL verison in that it already has a longer vBlank period, but also discouraged as some sort of automated OAM refresh takes place on the PAL version, which you don't want to have a conflict with. What the visual result from that confict is, is undescribed.

3) OAM does not decay on the PAL version due to said automatic OAM refresh.

4) So in order to extend the period in which it is suitable to update VRAM on NTSC, you need two different update orderings for the two versions.

So basically, if we only go by the article, OAMDMA shouldn't happen too late (for PAL compatibility), but it doesn't need to be absolutely first either. This not regarding what fiskbit just wrote about any time place within the normal (not-forced) NTSC time window should be safe for PAL as well.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Why not read controllers in NMI?

Post by Pokun »

I don't think it was this page I saw. It explicitly said that NTSC and PAL may need different vblank routines, and not by extending the NTSC vblank with a forced blanking. It might have been edited out when regarded as false though.
User avatar
aquasnake
Posts: 515
Joined: Fri Sep 13, 2019 11:22 pm

Re: Why not read controllers in NMI?

Post by aquasnake »

surely u can, its determined by which period has more spare time to execute keys scanning, in v-blank or not.
Post Reply