This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Best way to detect NTSC or PAL

Best way to detect NTSC or PAL
by on (#163256)
What is the best way to check whether the console is NTSC or PAL?

I'd prefer a method that is used once at startup and then it's done. If it's possible, I'd like to have something that you don't need to put into the NMI where it would takes away CPU time at any frame.

Also, about that Dendy stuff: Do I have to set the music to PAL or to NTSC for that?
Re: Best way to detect NTSC or PAL
by on (#163257)
Check the startup code that comes with Famitone2. I don't remember the details... maybe it counts something between several NMIs.
But, it's able to tell the difference between NTSC and PAL.
Re: Best way to detect NTSC or PAL
by on (#163258)
Here's the run-once routine I wrote for the NROM Driar port; no NMI intrusion necessary.

Code:
;;; use the power-on wait to detect video system-
   ldx #0
   ldy #0
@vwait1:
   bit $2002
   bpl @vwait1  ; at this point, about 27384 cycles have passed
@vwait2:
   inx
   bne @noincy
   iny
@noincy:
   bit $2002
   bpl @vwait2  ; at this point, about 57165 cycles have passed

;;; BUT because of a hardware oversight, we might have missed a vblank flag.
;;;  so we need to both check for 1Vbl and 2Vbl
;;; NTSC NES: 29780 cycles / 12.005 -> $9B0 or $1361 (Y:X)
;;; PAL NES:  33247 cycles / 12.005 -> $AD1 or $15A2
;;; Dendy:    35464 cycles / 12.005 -> $B8A or $1714

   tya
   cmp #16
   bcc @nodiv2
   lsr
@nodiv2:
   clc
   adc #<-9
   cmp #3
   bcc @noclip3
   lda #3
@noclip3:
;;; Right now, A contains 0,1,2,3 for NTSC,PAL,Dendy,Bad
Re: Best way to detect NTSC or PAL
by on (#163259)
It can be done by counting cycles from one NMI to the next. This may mess up on an overclocked NES, so you can either use a more complicated method to detect overclocked systems or just write off overclocking as undefined behavior.

Ninja'd: lidnariq has an interesting way to correct for the $2002 race.
Re: Best way to detect NTSC or PAL
by on (#163260)
Alternative way:
- Poll for VBL
- Wait in timed loop for ~30k cycles
- Check VBL flag in $2002, if set => NTSC
- Wait in timed loop for ~4k cycles
- Check VBL flag in $2002, if set => PAL
- Otherwise => Dendy
Re: Best way to detect NTSC or PAL
by on (#163263)
Does anyone know the music difference of the Dendy, as asked in OP?
Re: Best way to detect NTSC or PAL
by on (#163264)
Dendy sound wants NTSC tuning (at least if you're using DPCM) and PAL speeds.

I have to admit that I like thefox's algorithm better than my "brute force" implementation.
Re: Best way to detect NTSC or PAL
by on (#163265)
thefox wrote:
Alternative way:
- Poll for VBL
- Wait in timed loop for ~30k cycles
- Check VBL flag in $2002, if set => NTSC
- Wait in timed loop for ~4k cycles
- Check VBL flag in $2002, if set => PAL
- Otherwise => Dendy

That's how I do it (it's a good way to do the detection when booting up without interfering with the rest of the program), except I don't have one variable indicate 1 of 3 types of consoles. Instead I have 2 flags, one indicating whether the frame rate is 60Hz (NTSC) or 50Hz (PAL and Dendy), and another indicating whether the PPU vs. CPU clock ratio is 3:1 (NTSC and Dendy) or 3.2:1 (PAL). I do this because of the Dendy, which has some things in common with NTSC consoles and some in common with PAL consoles, and his way I can make decisions by checking a single flag, instead of checking whether the console is this OR that.
Re: Best way to detect NTSC or PAL
by on (#163266)
0=NTSC, 1=PAL, 2=Dendy gives the mapping nonzero=change speed, bit 0 set=change pitch.

In game code and music tempo code:
Code:
  lda tvSystem
  beq @noSpeedCorrection
    ; fixes for PAL NES/Dendy here
  @noSpeedCorrection:


In music pitch code and raster effect code:
Code:
  lda tvSystem
  lsr a
  bcs @noPitchCorrection
    ; fixes for PAL NES here
  @noPitchCorrection:
Re: Best way to detect NTSC or PAL
by on (#163267)
I've used tepples' method (from the wiki) in several releases at this point, so I can say that it works well in my experience.

The other two approaches should work, too, though.
Re: Best way to detect NTSC or PAL
by on (#163273)
I'll check the rest of the answers later.

But now, I'd like to elaborate on the following:
dougeff wrote:
Check the startup code that comes with Famitone2. I don't remember the details... maybe it counts something between several NMIs.
But, it's able to tell the difference between NTSC and PAL.

There is something like that in FamiTone? Because in that library, you have to specify yourself whether FamiTone shall use PAL or NTSC.


Another question about FamiTone: Is that program able to use the correct music for Dendy? Because I can only pass PAL or NTSC to the initialization:

Code:
;------------------------------------------------------------------------------
; reset APU, initialize FamiTone
; in: A   0 for PAL, not 0 for NTSC
;     X,Y pointer to music data
;------------------------------------------------------------------------------

FamiToneInit:


And then there is the FT_PITCH_FIX constant that is set to true when FT_PAL_SUPPORT and FT_NTSC_SUPPORT are both enabled.

So, will FamiTone adjust the music correctly for Dendy when NTSC and PAL support are both enabled?
Re: Best way to detect NTSC or PAL
by on (#163280)
I wonder how many Dendy systems there are out there relative to PAL and NTSC systems? I never see it as a selection in emulators. ...I just started using tepples method from the wiki as well, baked it into the GGSound demos (the library itself, like famitone, doesn't have the detection itself) and used it to correct raster effects in my current game project---works great for me!

*edit* Another thing I had wanted to say was---feedback from beta testers suggests that once a player is used to the pitch and speed of a game on NTSC or PAL, that feels like the "normal version" of the game to them---and the opposite region either feels too fast or too slow. This phenomenon suggests to me it is not necessarily always worth it to go to the trouble to make a game play the same on each region. *edit* I only used it to make the raster effects work correctly in both, on my current project. All other speed and pitch concerns were left alone. I might wind up doing it on the next project though, just "because."
Re: Best way to detect NTSC or PAL
by on (#163282)
As far as I can tell, most systems using a Dendy-style chipset (6527P/6538) were sold in Asia.

There is a patch to enable Dendy emulation in FCEUX.
Re: Best way to detect NTSC or PAL
by on (#163283)
GradualGames wrote:
I wonder how many Dendy systems there are out there relative to PAL and NTSC systems? I never see it as a selection in emulators.

I think at least one emulator calls it "hybrid mode".

Quote:
feedback from beta testers suggests that once a player is used to the pitch and speed of a game on NTSC or PAL, that feels like the "normal version" of the game to them---and the opposite region either feels too fast or too slow.

I guess it was very much like this in the 80's and 90's, when you had absolutely no contact with the other version, but now that we have YouTube and emulators it's very easy to be exposed to alternate versions, and you can immediately tell that something is off and not everyone is having the same experience.

Quote:
This phenomenon suggests to me it is not necessarily always worth it to go to the trouble to make a game play the same on each region.

It really is a lot of trouble. Somethings have to be adjusted up, others down, and the low precision of fixed-point numbers doesn't really allow everything to remain synced properly.

Quote:
I only used it to make the raster effects work correctly in both, on my current project. All other speed and pitch concerns were left alone. I might wind up doing it on the next project though, just "because."

I'll probably just handle raster effects and the music's tempo and pitch, which are simple. I definitely don't feel like messing with physics and animations, because I'm sure I won't be able to perfectly match the gameplay for both refresh rates.
Re: Best way to detect NTSC or PAL
by on (#163285)
Unfortunately I made so many updates to GGSound it didn't make it realistic to integrate into my current project, so the pitch will be different, too, but apparently people get used to that as well. I'll surely correct for pitch in my next project though, it is indeed easy. But this brings me to a question that I haven't yet found an answer to, and that is: How is the speed of envelope execution handled for NTSC versus PAL? Since these require frame by frame fidelity to sound smooth, I would imagine that envelopes remain unchanged on NTSC or PAL for most music engines, and thus will sound subtly different, and maybe even change the affect of certain instruments. Can anyone comment on this? GGSound right now does not do any adjustment for envelopes, only the tempo of playing notes. Does famitone?
Re: Best way to detect NTSC or PAL
by on (#163286)
I know Pently does not adjust envelopes. If FamiTone doesn't either, and I don't think it does, this may pose a problem for composers who like to use "rhythmic" envelopes *cough*Haunted: Halloween '85*cough*.
Re: Best way to detect NTSC or PAL
by on (#163290)
How famitone2 detects NTSC vs PAL...

from demo.asm (included with famitone2)..

Code:
   stx FRAME_CNT  ;x = 0 at this point

detectNTSC:

   jsr waitNMI      ;blargg's code
   ldx #52
   ldy #24
   
@loop:

   dex
   bne @loop
   dey
   bne @loop

   lda PPU_STATUS ;$2002 register
   and #$80
   sta NTSC_MODE   ;$00 PAL, $80 NTSC



Then it uses NTSC_MODE when it initializes the music...

Code:
ldx #<address_of_music_data
ldy #>address_of_music_data
lda NTSC_MODE
jsr FamiToneInit      ;init FamiTone
Re: Best way to detect NTSC or PAL
by on (#163296)
There are two easy options for dealing with envelopes in an NTSC + PAL situation:

1. Don't rely on envelopes to interact with notes rhythmically, and just use them as-is for both. This is fairly easy to do if you kept it in mind when composing.

2. On PAL, tick the music engine twice on every 5th frame. You do miss one frame of the envelope, so a 1-frame blip in an envelope might get skipped if unlucky, but in most circumstances it sounds fine. Since the PAL frame is longer than NTSC, spending extra time on the music every 5th frame shouldn't break the CPU performance budget if it's already fine on NTSC. Gimmick's PAL version actually does this, and I've used it in some music compilation ROMs I've released where needed.
Re: Best way to detect NTSC or PAL
by on (#163301)
GradualGames wrote:
I wonder how many Dendy systems there are out there relative to PAL and NTSC systems? I never see it as a selection in emulators.

Nintendulator has it, it's called "Hybrid".

Quote:
*edit* Another thing I had wanted to say was---feedback from beta testers suggests that once a player is used to the pitch and speed of a game on NTSC or PAL, that feels like the "normal version" of the game to them---and the opposite region either feels too fast or too slow. This phenomenon suggests to me it is not necessarily always worth it to go to the trouble to make a game play the same on each region.

I have the same experience. I have played through several games on PAL NES and they never felt "too slow" to me. It's about the frame of reference (from past experiences), sort of. Also I think people are susceptible to being fooled by the music. If the music sounds slow, they'll feel that the game is slow. But if the music speed has been fixed they won't necessarily notice so easily that the gameplay speed is off.

As for envelopes, the difference is indeed quite noticeable. Originally, in MUSE, I ran envelopes at the system frame rate because I thought it wouldn't matter, but I later changed it so that the speed is compensated for (at the price of choppier updates).

YMMV.
Re: Best way to detect NTSC or PAL
by on (#163303)
thefox wrote:
GradualGames wrote:
I wonder how many Dendy systems there are out there relative to PAL and NTSC systems? I never see it as a selection in emulators.

Nintendulator has it, it's called "Hybrid".


Excellent, this information enabled me to check out how my current project works on Dendy. Raster effects were messed up. I understand the CPU speed is the same on Dendy as on NTSC? I opted for using the same timings as NTSC when Dendy is detected, and the raster effects now look correct for Dendy. I see happy Russian customers in my future. :D
Re: Best way to detect NTSC or PAL
by on (#163305)
Yes. The PAL famiclones are designed for maximum cycle-for-cycle compatibility with Famicom software. They do this by changing the CPU to divide the master clock by 15 instead of 16, which matches the ratio of 3 dots per CPU cycle, and changing the PPU to delay NMI until line 291, which matches the duration of vertical blanking.
Re: Best way to detect NTSC or PAL
by on (#163306)
tepples wrote:
Yes. The PAL famiclones are designed for maximum cycle-for-cycle compatibility with Famicom software. They do this by changing the CPU to divide the master clock by 15 instead of 16, which matches the ratio of 3 dots per CPU cycle, and changing the PPU to delay NMI until line 291, which matches the duration of vertical blanking.

It still impresses me that pirates were able to come up with a better solution for converting the Famicom hardware to PAL than the company that created the console in the first place. Some might say that the timing difference was intended to work as a form of regional lockout, but I have a hard time believing that.
Re: Best way to detect NTSC or PAL
by on (#163335)
dougeff wrote:
How famitone2 detects NTSC vs PAL...

from demo.asm (included with famitone2)..

Alright, so FamiTone itself doesn't do it, just the sample program.


Thanks for all the answers so far. In the near future, I will review all the various methods and then check which one fits best for me. (In the moment, I'm in the process of optimizing the action in the game loop before I implement the missing movement functions for each character type.)

By the way, I decided not to adjust the game itself, i.e. the PAL version will run slower.
I'll just adjust the music. Or rather: I'll let FamiTone do this by enabling PAL and NTSC support as well as pitch fix. And that's why I needed to know how to detect the version because I need to pass this information to FamiTone as a parameter.


I just noticed that Dendy is not a TV norm, but an actual console. And not an official one. And not even one that existed at the time when my game is supposed to have come out (1986).
So, I'll just adjust my game's music to PAL and NTSC.
Re: Best way to detect NTSC or PAL
by on (#164569)
I decided to use blargg's way of detecting PAL and NTSC. It looks like the most simple one.

However, I'd like to know if the following code is correct (the important stuff is at the end):
Code:
Reset:
   SEI
   CLD
   LDX #$40
   STX $4017
   LDX #$FF
   TXS
   INX
   STX PpuCtrl
   STX PpuMask
   STX $4010
   BIT PpuStatus
@waitForVBlank1:
   BIT PpuStatus
   BPL @waitForVBlank1

   LDA #$00
   STA _Pointer
   STA _Pointer + 1
   TAX
   TAY
@initializeRamOuterLoop:
@initializeRamInnerLoop:
   STA (_Pointer), Y
   INY
   BNE @initializeRamInnerLoop
   INC _Pointer + 1
   INX
   CPX #$08
   BNE @initializeRamOuterLoop

@waitForVBlank2:
   BIT PpuStatus
   BPL @waitForVBlank2

   ; Various initializations
   ; ...

   ; NTSC/PAL detection
   LDX #52
   LDY #24
@ntscPalLoop:
   DEX
   BNE @ntscPalLoop
   DEY
   BNE @ntscPalLoop
   LDA PpuStatus
   AND #$80
   STA IsNtsc


The reason why I ask is this: Depending on the code that I saw in other projects, more things are done.
For example, "Zooming Secretary" does this before detecting PAL vs. NTSC:
Code:
   lda #%10000000
   sta <PPU_CTRL_VAR
   sta PPU_CTRL      ;enable NMI
   lda #%00000110
   sta <PPU_MASK_VAR

   lda <FRAMECNT1
@wait:
   cmp <FRAMECNT1
   beq @wait

So, my question is:

Is this necessary for PAL/NTSC detection? Because in my case, I didn't do any of it and it still works: I made a text output to the title screen based on the IsNtsc value and it was always correct regarding the emulator option of PAL vs. NTSC.

I do this while PPUCTRL and PPUMASK are still set to 0.
I.e. in my case, the NMI isn't even enabled yet (this comes in the next step), so I don't understand why the above code enables the NMI before and does frame counting. Is this necessary, and if yes, why does my code work as well despite not doing this?
Re: Best way to detect NTSC or PAL
by on (#164570)
The detection code you have there works by waiting a fixed amount of time from the start of the vertical blank and then checking whether the next vertical blank has started yet (it starts sooner in NTSC because the frame is shorter). It doesn't use NMIs, so you don't need NMIs on at that point (in fact, it's better that they're still disabled), but for it to work reliably, the counting should be in sync with the start of the vertical blank, so you should move those "Various initializations" somewhere else, so they don't interfere with the cycle counting.
Re: Best way to detect NTSC or PAL
by on (#164571)
So, when I change the code like this:
Code:
@waitForVBlank2:
   BIT PpuStatus
   BPL @waitForVBlank2

   ; NTSC/PAL detection
   LDX #52
   LDY #24
@ntscPalLoop:
   DEX
   BNE @ntscPalLoop
   DEY
   BNE @ntscPalLoop
   LDA PpuStatus
   AND #$80
   STA IsNtsc

   ; Various initializations
   ; ...
then I can be sure that everything is fine with PAL/NTSC detection, no matter what?
Re: Best way to detect NTSC or PAL
by on (#164575)
I would also put another BIT PpuStatus before the loop that waits for vblank, exactly like you're doing in the first wait loop, to make sure you won't catch the vblank in the middle.

Other than that, assuming the values loaded into X and Y are correct (I haven't timed it!), yes, the code should work just fine even if you tweak stuff that comes before or after that critical area.
Re: Best way to detect NTSC or PAL
by on (#164577)
Thanks for the information.

In this link:
http://wiki.nesdev.com/w/index.php/Init_code
the BIT PpuStatus/bit $2002 before the vblank is only done once before the first vblank, but not before the second one.
Why is it missing there?
Re: Best way to detect NTSC or PAL
by on (#164578)
As the comment for the bit $2002 before the first wait loop states:
Code:
    ; If the user presses Reset during vblank, the PPU may reset
    ; with the vblank flag still true.  This has about a 1 in 13
    ; chance of happening on NTSC or 2 in 9 on PAL.  Clear the
    ; flag now so the @vblankwait1 loop sees an actual vblank.

The instruction is missing from the second wait loop because it is not possible for the flag to immediately be true again at that point.
Re: Best way to detect NTSC or PAL
by on (#164579)
Not even if an arbitrary number of initialization stuff is done in between?
Code:
; Other things you can do between vblank waits are set up audio
; or set up other mapper registers.
Re: Best way to detect NTSC or PAL
by on (#164580)
If "an arbitrary number of initialization stuff is done in between", then the PPU will have warmed up anyway.
Re: Best way to detect NTSC or PAL
by on (#164581)
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.
Re: Best way to detect NTSC or PAL
by on (#164585)
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.
Re: Best way to detect NTSC or PAL
by on (#164620)
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?