Best way to detect NTSC or PAL

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

tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Best way to detect NTSC or PAL

Post by tepples »

If "an arbitrary number of initialization stuff is done in between", then the PPU will have warmed up anyway.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Best way to detect NTSC or PAL

Post by tokumaru »

It might not make a difference when warming up, but the PAL/NTSC detection won't work properly if the timed code starts in the middle of vblank, so that extra BIT $2002 is necessary in this case.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Best way to detect NTSC or PAL

Post by rainwarrior »

DRW wrote:Not even if an arbitrary number of initialization stuff is done in between?
If you make sure the cycles spent on this initialization are always the same, the end-state timing will always be the same, either always within vblank on a given platform, or always not.

More practically speaking, though: just put the dang BIT $2002 in there. There's little reason not to, and it protects you against accidentally mucking it up later.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Best way to detect NTSC or PAL

Post by DRW »

rainwarrior wrote:If you make sure the cycles spent on this initialization are always the same, the end-state timing will always be the same, either always within vblank on a given platform, or always not.
Sure, but I'd like my initialization code to be valid for every game so far. So, yeah, I will put the BIT instruction there to make sure that I can put everything in between and it still works.

In my specific case, that's the location where I will check for specific Reset-safe RAM values before setting the RAM to 0, so that for example the highscore doesn't get deleted when pressing Reset. Who knows what other stuff will be there in future games?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
gravelstudios
Posts: 159
Joined: Mon Mar 13, 2017 5:21 pm
Contact:

Re: Best way to detect NTSC or PAL

Post by gravelstudios »

Apologies for bumping this ancient thread, but I'm curious about this topic. I'm on the fence about whether I want to automatically detect the system a game is running on, or let the player toggle it for themselves. On one hand, I like the idea of it being handled automatically without the player having to worry about it. But I'm curious about situations in which the timing might be off. My code currently works in Mesen, but I don't have a PAL or Dendy system to test on. And what about less accurate emulators? What about clone consoles like the RetroN 5, etc.? My desire to make the game work in the widest possible number of situations makes me want to lean in the direction of making it a user defined setting.

For those of you who have released games that automatically detect the region and adjust timing accordingly, how do you think it turned out? did you get any feedback from players about it?
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Best way to detect NTSC or PAL

Post by Dwedit »

I bet that with the exception of NESticle or other ancient emulators, everything will probably follow the 341 * 262 dots rule for NTSC.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Re: Best way to detect NTSC or PAL

Post by Individualised »

gravelstudios wrote: Thu Feb 16, 2023 3:20 pm Apologies for bumping this ancient thread, but I'm curious about this topic. I'm on the fence about whether I want to automatically detect the system a game is running on, or let the player toggle it for themselves. On one hand, I like the idea of it being handled automatically without the player having to worry about it. But I'm curious about situations in which the timing might be off. My code currently works in Mesen, but I don't have a PAL or Dendy system to test on. And what about less accurate emulators? What about clone consoles like the RetroN 5, etc.? My desire to make the game work in the widest possible number of situations makes me want to lean in the direction of making it a user defined setting.

For those of you who have released games that automatically detect the region and adjust timing accordingly, how do you think it turned out? did you get any feedback from players about it?
You shouldn't worry too much about older emulators, it will be a headache trying to support inaccurate and incomplete emulators. If something doesn't work in an older emulator but it's easily fixable without hindering functionality, the readability of your code, compatibility with accurate emulators/real hardware etc then sure, but if it requires you to make major refactoring to your code or use bad practice then there's no point. If you really must support inaccurate emulators then an option is the way to go here.

Retron 5 isn't a real Famiclone, it's a glorified emulator box with a built in cartridge dumper, so what I just said also applies there (and good luck getting your game to run on it if it uses an even slightly exotic mapper, hell, I've heard aftermarket games have trouble running on it at all). Actual hardware clone consoles will use third party clones of the NES chipsets, or "NES-on-a-chip" solutions, manufactured by companies like UMC. For NTSC hardware clones you will likely not have to worry about much (except in some very specific circumstances involving timing), things should work the same as Nintendo hardware for the most part, though many clones have swapped duty cycles on the APU (50% and 25% are swapped around), so you could have an option for that. PAL clones are what is known as the "Dendy" region in Mesen (which is a misnomer; Dendy is an old brand of Famiclones that use this type of chipset. A better name would be "Clone PAL" as opposed to "Ricoh PAL", or "Hybrid" region due to it being like a hybrid between NTSC and PAL chipsets), and operate quite differently from Ricoh PAL chipsets, so as long as your game takes that into account then you should be good to go there too.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Best way to detect NTSC or PAL

Post by tokumaru »

Letting players change this directly is pretty pointless IMO, since console detection is something we do to compensate for timing and other differences to prevent the game from breaking... Allowing players to change this manually will only cause things to break (music at the wrong speed, raster effects on the wrong scanlines, etc.).

Even if you don't have PAL or Dendy consoles to try your game on, Mesen (and many other emulators) allow you to emulate those consoles, which should be good enough for development purposes. It'd still be a good idea to test on actual hardware before manufacturing cartridges and selling them, though, just in case.

AFAIK, the Retron 5 is an emulator and relies on a database in order to be able to dump and emulate the cartridge, since it doesn't have access to iNES headers like most emulators do. If your game isn't on the database, it probably won't run.
User avatar
gravelstudios
Posts: 159
Joined: Mon Mar 13, 2017 5:21 pm
Contact:

Re: Best way to detect NTSC or PAL

Post by gravelstudios »

Thank you all for the advice. The only thing I want to do is run my music engine twice on every 5th frame on PAL machines to compensate for the slower framerate. So if the region doesn't get set properly, it's not the end of the world. I'm using the method of counting cycles between v-blanks during the PPU warmup period by incrementing X and Y, but since I have NMI disabled during this part of the program, I'm using BIT $2002 and I know that can occasionally miss a frame. Just out of curiosity, does Mesen (or any other emulator for that matter) emulate the behavior in which that occurs?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Best way to detect NTSC or PAL

Post by tokumaru »

I'm not sure if this behavior is emulated correctly, but missing a frame can definitely throw things off if you're counting the time between vblanks. Fortunately, there are ways to do region detection that don't require NMIs or reading $2002 in a loop.

My favorite method is based on synchronizing the CPU with the start of vblank, and waiting the amount of cycles until the next frame for each console type (NTSC is 29780.5, PAL is 33247.5 and Dendy is 35464) in succession and verify whether vblank has indeed started:

1- Wait for vblank via $2002 polling. It doesn't matter if you miss vblanks at this time, because the test only starts when a vblank is detected.

2- Use timed code to wait ~30,000 cycles, then read $2002. If the vblank flag is set, this is an NTSC console.

3- Use timed code to wait ~4,000 cycles, then read $2002. If the vblank flag is set, this is a PAL console.

4- If vblank hasn't started yet, you can just assume that this is a Dendy console, but if you want to be sure, wait ~2,000 cycles and read $2002 again.

Since you're reading $2002 several cycles after the vblank flag gets set, there's no risk of triggering the bug that clears the flag and causes vblanks to not be detected.

I don't even test the vblank flag when I read it, I just save the values directly to variables that I can test whenever needed using BIT. It goes something like this:

Code: Select all

  ;synchronizes the CPU with the start of vblank
  bit $2002 ;makes sure the vblank flag is clear
: bit $2002
  bpl :-

  ;waits for the NTSC vblank to detect NTSC console
  ;[code to wait ~30,000 cycles goes here]
  lda $2002
  sta ConsoleIsNTSC

  ;waits for the PAL vblank to detect PAL console
  ;[code to wait ~4,000 cycles goes here]
  lda $2002
  sta ConsoleIsPAL

  :waits for the Dendy vblank to detect Dendy console
  ;[code to wait ~2,000 cycles goes here]
  lda $2002
  sta ConsoleIsDendy
Then you can just BIT any of those 3 variables at any point when you need to make a decision based on the console type.
Fiskbit
Posts: 891
Joined: Sat Nov 18, 2017 9:15 pm

Re: Best way to detect NTSC or PAL

Post by Fiskbit »

To detect the region, in my init code, I do the first poll on $2002, then clear memory as usual, and then measure the remainder of that frame with a $2002 poll. Because $2002 polling may miss a frame, I compare the resulting number against 5 thresholds to figure out which of the 6 possible ranges it falls within, telling me the region without taking any extra time. This method should be reliable, so I lean against having an option.

There are three caveats. First, the Hong Kong Famicom and clones using the MK5060 are actually NTSC systems that are converted to PAL by halting the PPU for 50 scanlines before NMI, and their timing hasn't seen much research. That halt definitely happens when rendering is enabled, and PPU accesses during the halt briefly wake the PPU up to respond, shortening the frame. The halt also may not happen at all if rendering is disabled. As far as I can tell, though, systems using this method seem to be pretty rare, so I wouldn't be worried about supporting them. They're probably best thought of as Dendy.

Second is that automatic detection doesn't work properly in emulators that are 'overclocking' by adding extra pre- or post-render scanlines. I don't know how often players actually use these features; if your game doesn't tend to lag, they're probably less likely to use them, and these extra scanlines certainly break some real games. This feels to me like the strongest reason to consider providing the player an option.

Third isn't related to detection, but rather compatibility: Dendy has a quirk where 8-cycle $2002 poll loops (or any length that evenly divides the 35464 cycle frame) can hang forever on some CPU/PPU alignments. This happens, for example, when a 7-cycle poll loop crosses a page boundary, making it take 8 cycles. Be sure to avoid these $2002 poll loop lengths.
User avatar
gravelstudios
Posts: 159
Joined: Mon Mar 13, 2017 5:21 pm
Contact:

Re: Best way to detect NTSC or PAL

Post by gravelstudios »

Fiskbit wrote: Fri Feb 17, 2023 5:58 am To detect the region, in my init code, I do the first poll on $2002, then clear memory as usual, and then measure the remainder of that frame with a $2002 poll. Because $2002 polling may miss a frame, I compare the resulting number against 5 thresholds to figure out which of the 6 possible ranges it falls within, telling me the region without taking any extra time. This method should be reliable, so I lean against having an option.

There are three caveats. First, the Hong Kong Famicom and clones using the MK5060 are actually NTSC systems that are converted to PAL by halting the PPU for 50 scanlines before NMI, and their timing hasn't seen much research. That halt definitely happens when rendering is enabled, and PPU accesses during the halt briefly wake the PPU up to respond, shortening the frame. The halt also may not happen at all if rendering is disabled. As far as I can tell, though, systems using this method seem to be pretty rare, so I wouldn't be worried about supporting them. They're probably best thought of as Dendy.

Second is that automatic detection doesn't work properly in emulators that are 'overclocking' by adding extra pre- or post-render scanlines. I don't know how often players actually use these features; if your game doesn't tend to lag, they're probably less likely to use them, and these extra scanlines certainly break some real games. This feels to me like the strongest reason to consider providing the player an option.

Third isn't related to detection, but rather compatibility: Dendy has a quirk where 8-cycle $2002 poll loops (or any length that evenly divides the 35464 cycle frame) can hang forever on some CPU/PPU alignments. This happens, for example, when a 7-cycle poll loop crosses a page boundary, making it take 8 cycles. Be sure to avoid these $2002 poll loop lengths.
I'm doing the exact same method of region detection in my code too. I compare my result against the expected value for both PAL and Dendy, with and without the extra frame included. If it doesn't match any of those 4 values, I assume NTSC timing.

The custom emulator that I made for releasing my game on Steam actually has overclocking set by default to eliminate lag, but since I programmed it myself I can make it work regardless. And this discussion is making me realize that I can't account for every possible custom setting that an emulator user may have in place.

I was aware of the 8-cycle Dendy quirk from reading about this topic on the Wiki. My first wait loop doesn't cross a page boundary, and the second one where I count iterations takes either 12 cycles or 13 depending on whether it's an iteration in which Y is incremented. I did a little math and I'm almost certain that will never end up in an 8-cycle alignment.
Fiskbit
Posts: 891
Joined: Sat Nov 18, 2017 9:15 pm

Re: Best way to detect NTSC or PAL

Post by Fiskbit »

Are you comparing against a specific value? I'd be concerned about things being slightly off due to emulation issues, different CPU/PPU alignments, or different alignments relative to vblank. I use thresholds, instead, to allow wiggle room.

Regarding overclocking, there is also a method of overclocking where the CPU is sped up relative to the PPU, though this is the least compatible way to overclock and probably isn't done much. It'll cause issues for region detection, as well.

And regarding the 8-cycle thing, it gets harder to reason about when having loops of inconsistent length. If you have a loop that was always 13 cycles, that would trigger it, but 12 and 13 combo like what you've got should work fine. I'm really glad this stuff is visible enough on the wiki for people to notice it!
User avatar
gravelstudios
Posts: 159
Joined: Mon Mar 13, 2017 5:21 pm
Contact:

Re: Best way to detect NTSC or PAL

Post by gravelstudios »

Not a specific value, no. I'm incrementing X as a low byte, and then Y as a high byte on iterations where X=0. Then I only check the value of Y. So it gives a range but there's plenty of wiggle room:

Code: Select all

	LDX #0
	LDY #0 
	PPUWait2:
		INX 
		BNE .NoYInc
		INY
		.NoYInc:
		BIT $2002	
		BPL PPUWait2
I did my math based on the idea that it would take 12 cycles for 255 iterations, then on every 256th iteration it would take 13.
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Re: Best way to detect NTSC or PAL

Post by Individualised »

Fiskbit wrote: Fri Feb 17, 2023 5:58 am . First, the Hong Kong Famicom and clones using the MK5060 are actually NTSC systems that are converted to PAL by halting the PPU for 50 scanlines before NMI, and their timing hasn't seen much research.
Is the Hong Kong Famicom the only official Famicom/NES system that can be described as Dendy region?
Post Reply