Detecting 86/87 GIME and NTSC/PAL

Cloud Kingdoms needs to use very precise timing to know when to switch from graphics mode to text mode for the score area at the bottom of the screen.  If the timing is off by even a little bit, flickering will be visible on the line where it switches from graphics to text mode.  If the timing is off by a lot, it could actually end up displaying the wrong area of text memory instead of the area where we’ve drawn the score text.

We need to know precisely, from the start of VSYNC, when we’ve finished drawing a specific line of the screen (I believe it’s the 143rd line) and switch to text mode at that specific moment.  We do this by setting

the high-speed timer to a specific frequency and resetting at the top of each VSYNC.  What that precise frequency is is very dependent on two factors.  Is it a 1986 GIME or a 1987 GIME?  Is it NTSC or PAL?

The 1986 GIME sets the frequency of the high-speed timer to 2 higher than you set it to, and the 1987 GIME sets the frequency to 1 higher than you set it to.  Neither can do a frequency of 1 (firing every 63.695 µs).  Setting the frequency to 1 will actually set it to 3 on the 86 GIME and 2 on the 87 GIME.  We can use this discrepancy (timer firing slower on the 86 GIME) to detect which GIME we’re running on by counting the number of times it fires in a known time period. (such as VSYNC).

VSYNC happens 60 times per second for NTSC, or 50 times per second for PAL.  So if we fire an IRQ every VSYNC, set the high speed timer to fire an FIRQ with a frequency of 1 (every 63.695 * 3 µs on 86 GIME, 63.695 * 2 µs on 87 GIME), and we count how many FIRQs fire in 60 ticks of the VSYNC IRQ, we can get a count that will tell us whether we’re on an 86 or 87 GIME, and whether we’re on NTSC or PAL.

Number of High-Speed Timer
ticks in 60 VSYNC ticks

           NTSC       PAL
87 GIME    7,851      9,421
86 GIME    5,233      6,279

So, if the count is <= to, say, 7085 (arbitrary number roughly halfway between highest 86 GIME count and lowest 87 GIME count), we’re running on an 86 GIME.  Otherwise, we’re running on an 87 GIME.  For the 86 GIME, if the count is <= 5750, we’re on an NTSC CoCo. Otherwise, we’re on a PAL CoCo.  For an 87 GIME, if the count is <= 8630, we’re on an NTSC CoCo. Otherwise, we’re on a PAL CoCo.

Through a bit of educated estimation, and a lot of trial and error running on the 4

different machines (86 GIME/NTSC, 86 GIME PAL, 87 GIME/NTSC, 87 GIME/PAL), we can find the precise frequency we need for each machine to switch to text mode at the exact right moment.  Using our detection algorithm, we can decide which of those frequency numbers to use.

Below is the routine (6809 assembly) for detecting 86/87 GIME and NTSC/PAL.

    sta     $FFD9       ; Set CPU to 1.78Mhz speed
    ; Grab the current value at $0113 (LSB of Extended Basic's timer) and wait
    ; for it to change
    ldu     #$0112
    ldb     1,u
@WaitForStartOfNextTick
    cmpb    1,u
    beq     @WaitForStartOfNextTick
    ;
    ldd     #$FFC4      ; Start IRQ (60Hz NTSC, 50Hz PAL) counting up from  #%FFC4 (65476).
    std     ,u          ; This will count 60 ticks (1 second on NTSC or 1.2 seconds on PAL).
    ldx     #$FF93
    clr     -2,x        ; $FF91 - Set high speed timer to 63.695 µs
    lda     #$20
    sta     ,x          ; $FF93 - Enable high speed timer FIRQ
    ldd     #1
    stb     2,x         ; $FF95 - Set LSB of high-speed timer value to 1
    sta     1,x         ; $FF94 - Set MSB of high-speed timer value to 0
                        ;         & start timer counting down.
                        ; The 86 GIME will treat 1 as 3 (firing every 63.695 * 3 µsec)
                        ; and the 87 GIME will treat 1 as 2 (firing every 63.695 * 2 µsec).
    ldy     #1          ; Start our count of FIRQs at 1
    ldb     ,x          ; Acknowledge any pending timer FIRQ
    ; Wait for the IRQ timer to roll over to #$0000 and count each FIRQ that fires.
@WaitForIRQTimerHighByteToCycleBackToZero
    lda     #$20
    bita    ,x          ; Test if the timer FIRQ is pending and acknowledge it
    beq     @SkipCount
    leay    1,y         ; Count number of timer FIRQs
@SkipCount
    tst     ,u          ; Has the IRQ timer rolled over to #$0000 yet?
    bne     @WaitForIRQTimerHighByteToCycleBackToZero
    sta     $FFD8       ; Set CPU back to 0.89Mhz speed
    ; At this point, y contains the count of high-speed
    ; timer ticks that occurred in 60 IRQ ticks
    ; <= 7085 = 86 GIME.  <= 5750, it’s NTSC otherwise it’s PAL.
    ; > 7085 = 87 GIME.  <= 8630, it’s NTSC otherwise it’s PAL.
This entry was posted in Uncategorized and tagged , , , , , . Bookmark the permalink.

Leave a comment