Detecting NTSC vs PAL

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Detecting NTSC vs PAL

Post by rainwarrior »

Is there any kind of official way to do this? Or if not, is there something reliable? I can't seem to find anything about it in the Nintendo development book.

The method used on NES of counting a loop between 2 NMI events would work, presumably.

Are there any better ideas out there? Or if you've tried this idea, what's your experience with it?
Kingizor
Posts: 24
Joined: Sat Jun 18, 2011 10:50 am

Re: Detecting NTSC vs PAL

Post by Kingizor »

$213F has a bit that indicates NTSC or PAL. Some games use it as a means of region locking. There are some mods and flash carts that can intercept accesses to it to defeat protections like that. Also be aware that there are a handful of older mods that change the refresh without affecting this bit and that supporting such configurations is discouraged...

A loop between successeive NMIs would work. Exact timing is a bit more of a headache here because there is DRAM refresh on each scanline which eats up CPU time, and a few other unpredictable things.

There is a bit in $4212 that indicates when vblank is active, so timing using it could be a bit simpler because PAL vblank is much longer:

Code: Select all

  .8bit
  stz  $00
  stz  $01
  lda  #$80   ; test $4212.7

  ; ensure we're not in vblank
- bit  $4212
  bne  -

  ; wait until we are in vblank
- bit  $4212
  beq  -

  ; start counter and wait for vblank to end
- inc  $00
  bcc  +
  inc  $01
+ bit  $4212
  bne  -

  ; check counter in $00/$01
  ...
There are other approaches though. It's possible to trigger an IRQ when a certain scanline is reached, but that's probably a bit excessive.

Another way would be to check the PPU's vertical position directly. If you read perform a read on $2137, the current horizontal and vertical position of the PPU will be placed into $213C and $213D (read twice).

Code: Select all

  .8bit
  lda  #$80
  sta  $4201    ; enable PPU latching
line_261:
  lda  $213F    ; reset $213C/$213D hi/lo toggle
  lda  $2137    ; latch $213C/$213D
  lda  $213D    ; read the low byte
  cmp  #261.b   ; compare low byte
  bne  line_261
  lda  $213D    ; read the high byte
  and  #1       ; compare high byte
  bne  line_261

post_261:
  lda  $213F
  lda  $2137
  cmp  #261.b
  bne  post_261
  cmp  #262.b
  beq  pal_mode

ntsc_mode:
  ...
pal_mode:
  ...
The idea here is we'd wait for line 261 which will always occur on any system, then we would check what number the next line is. If the next line is line 0, we have an NTSC system, otherwise we would get 262 which would indicate a PAL system.

There are caveats there though. If interlacing is enabled via $2133, there is an extra scanline every other frame. The $4212 method is probably better, although there could be other fun ways too.

I'd typically look at anomie's documentation before anything else, particularly the register and dsp documents. Fullsnes is quite good and has a lot of unique perspectives.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Detecting NTSC vs PAL

Post by rainwarrior »

Thanks very much! I had missed that PPU status register. :) I figured the hardware would have something like that.

Checking the scanline counter is another interesting approach. Thanks for the cool info.
User avatar
jeffythedragonslayer
Posts: 344
Joined: Thu Dec 09, 2021 12:29 pm

Re: Detecting NTSC vs PAL

Post by jeffythedragonslayer »

For the record it is $213f.4 (STAT78) that is set if PAL, clear otherwise:

Code: Select all

;     fl0mvvvv
bit #%00010000
Post Reply