Jump to content

NTSC vs PAL detection


Recommended Posts

ZackAttack had an interesting idea of using one of the timer's on the Harmony/Melody to see if we could detect if the console was NTSC or PAL based on slightly different clock speeds. Per this they're:


Video Color Clock: 3.579545 MHz (NTSC), 3.546894 MHz (PAL)

CPU Machine Clock: 1.193182 MHz (NTSC), 1.182298 MHz (PAL)



I've done some experiments with the Harmony and believe I've figured out how the timer works. I then built a test ROM that times how long it takes to draw a single 262 scanline frame. Using it I can already see that my 7800 has a slightly faster master clock than my 2600.

The 2600 ranges from 11d326 to 11d32e:

The 7800 ranges from 11d311 to 11d313:

So please run this ROM on your Harmony cart.

and post the results along with console (2600, 7800, Coleco Gemini, etc) and TV format (NTSC, PAL, SECAM) it was built for. Be sure to run it a few times and make note of the range of values returned.


Also note the 2600/7800 detection won't work unless your Harmony has at least the 1.06 beta 2 bios.

If this pans out I'll set up Draconian to preselect the TV-Type option.




  • Like 2
Link to comment
Share on other sites

Awesome! I'll work up an update tonight to set the TV-Type and colors. I'll use the middle of the extremes, (11d311+11fd20)/2 = 0x11E818 as the comparison point.

Interesting that the PAL 7800 is slightly slower, opposite of the NTSC consoles.

Link to comment
Share on other sites

But I suppose the timing is not reliable enough to safely decide between 2600 and 7800?


Shouldn't the timing be the same for both since the 7800 is operating in the backward compatible mode where it intentionally slows down the clock to match the 2600 spec? Also, what would be the practical application of detecting it's 7800 vs 2600?

Link to comment
Share on other sites

While there are variations in results, there appears to be a minimum difference of 16 timer ticks between 2600 vs 7800. We'll need more results to know for sure. We could also time over multiple frames if needed to increase the difference.


Made some changes during lunch and the Vertical Blank logic for the detection is now this:

void SplashVerticalBlank()
    if (MODE == 0x81)
        T1TC = 0;           // make sure timer starts at 0
        T1TCR = 1;          // turn on timer
    else if (MODE == 0x82)
        T1TCR = 0;          // turn off timer
        if (T1TC < 0x11E818)
            gTVtype = NTSC;
            gTVtype = PAL;
    else // if (MODE == (0x80 + 60))   // 1 second delay for testing splash screen line count
        // eventually this will be the time the AtariAge splash screen is displayed
        MODE = 1;   // menu


For MODE Game=0, Menu=1, Splash>=0x80, it's set to 0x80 during init. The titlescreen should now colorize based on the detect value, though I haven't yet implemented the text change so it'll still say NTSC.



I also made some revisions to the routine which might affect the time returned. I was originally saving T1TC, but realized I didn't need to as it maintains value when the timer's turned off.

Link to comment
Share on other sites

Also, what would be the practical application of detecting it's 7800 vs 2600?

Yep - the 7800 changed the TV Type into a pause key, and it's a momentary button instead of a toggle switch. I used this to handle pause/resume in Stay Frosty 2:


int PauseChanged(){    int changed = 0;    if (IS_2600)    {        if (COLOR_SWITCH_STATE != (SWCHB & )        {            changed = 1;        }	COLOR_SWITCH_STATE = (SWCHB & ;    }    else    {        if (SWCHB &  // color selected, pause not pressed        {            if (COLOR_SWITCH_STATE)            {                changed = 1;            }            COLOR_SWITCH_STATE = 0;        }        else            COLOR_SWITCH_STATE = 1; // bw selected, pause pressed    }    return changed;}

IS_2600 is set based on the contents of Zero Page RAM as it's random on the 2600 but in a known state on the 7800.

Start:;        CLEAN_START; detect 2600 or 7800 for pause routines        ldy #1        ldx $d0        cpx #$2c        bne .is2600        ldx $d1        cpx #$a9        bne .is2600        dey             ; 7800: y=0.is2600                 ; 2600: y=1        ;CLEAN_START - use our own so 2600/7800 result in Y is not lost          cld        ldx #0        txaCLEAR_STACK:        dex        txs        pha        bne CLEAR_STACK     ; SP=$FF, X = A = 0
Link to comment
Share on other sites

Thanks atari2600land! That result shows we probably cannot use the timer for 2600/7800 detection, so we'll have to stick with the ZP RAM method.


Is there a drawback to the ZP RAM method? If it's not reliable enough, you could try to do the 2600 vs 7800 detection at power on when the 7800 is still clocked at a much higher rate. Of course, that's going to have to be supported in the harmony firmware since it happens before the DPC+ file is loaded.

Link to comment
Share on other sites

I posted the lastest build of Draconian in my blog, the menu's been reimplemented and it's now using the timer results to set the initial value for TV-Type.


I've also added preliminary timer support in Stella. It doesn't implement all of the features of the timer, just enough to support this detection routine.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...