TV Type Detection

Scanline counting

One method is to count how many scanlines there are, by watching how many values the scanline counter runs through between line 0 and the next line 0. You should get 262 on an NTSC (or Brazilian PAL/M) machine and 313 on a PAL machine.

Unfortunately, this is poorly emulated in many emulators and is not recommended.

Frame length counting

An alternative is to simply time (in software) how long a frame takes. A busy loop incrementing a counter can be used so long as the counter doesn't overflow in the time.

The code below is based on World Soccer, with minor modifications to make it generalised. It turns on frame interrupts and disables Z80 interrupts, so the VDP status flags can be used to detect VBlanks. An alternative (but more bulky) method is to use the scanline counter to detect line 0, but this is less reliably emulated.

DetectTVType:; Returns a=0 for NTSC, a=1 for PAL; uses a, hl, dedi; disable interruptslda,%01100000; set VDP such that the screen is onout($bf),a; with VBlank interrupts enabledlda,$81out($bf),aldhl,$0000; init counter-:ina,($bf); get VDP statusora; inspectjp p,-; loop until frame interrupt flag is set-:ina,($bf); do the same again, in case we were unlucky and came in justora; before the start of the VBlank with the flag already setjp p,-; the VDP must now be at the start of the VBlank-:inchl; (6 cycles) increment counter until interrupt flag comes on againina,($bf); (11 cycles)ora; (4 cycles)jp p,-; (10 cycles)xora; reset carry flag, also set a=0ldde,2048; see if hl is more or less than 2048sbchl,deretc; if less, return a=0lda,1ret; if more or equal, return a=1

The main counter loop takes 31 clock cycles per iteration; it should therefore count up to approximately 3579545/60/31 = 1924 on NTSC machines and 3546893/50/31 = 2288 on PAL machines. 2048 is not exactly half-way between these but it probably doesn't matter much.