Classic Computer Magazine Archive COMPUTE! ISSUE 39 / AUGUST 1983 / PAGE 182

Part VII

Commodore 64 Video — A Guided Tour

Jim Butterfield, Associate Editor

In this, the final installment of our exploration of the Commodore 64's unique video design, we look at a solution to the pesky "hiccup" screen glitch.

Last time, we looked at a simple program to split the screen of the Commodore 64. It was similar, but not identical, to this one:

100 FOR J = 828 TO 862 : READ X
110 T = T + X : POKE J, X
120 NEXT J
130 IF T <> 3929 THEN STOP
200 DATA 173, 25, 208, 41, 1, 240, 25, 141, 25, 208, 162, 146, 160, 6, 173, 18
210 DATA 208, 16, 4, 162, 1, 160, 0, 142, 18, 208, 140, 33, 208, 76, 188, 254, 76, 49, 234
300 POKE 56333, 127
310 POKE 788, 60 : POKE 789, 3
320 POKE 56333, 129 : POKE 53274, 129

Our previous example split the screen into two sections: graphics and text. This one splits the screen into two background color areas. It makes it easier for us to see the glitch — the hiccup that occasionally disturbs our screen split. By the way, it's easier to see the problem when you are using the keyboard.

Why The Problem?

Here's where the problem comes from: the timer interrupt strikes about every 1/60 of a second. The screen display, too, runs at a rate of about 60 times a second. But they are not synchronized. The two processes run at similar, but not identical, speeds.

Now, every once in a while, the timer interrupt hits just before the raster interrupt. The timer interrupt has quite a few jobs to do: update the TI$ clock, check the cassette motor, flash the cursor, and check the keyboard. It takes time to do these jobs, and extra time is required if a key is being pressed.

Suppose we have just started on the timer interrupt, and the raster scan says, "I'm ready!" Sorry, raster, we're already into an interrupt routine, and other interrupts are locked out until we have finished. By that time, the screen scan might have moved along a few lines, and our split screen has crept from its normal position.

Some Possible Fixes

There are several possible approaches to fixing this jitter. The ones that come to mind first are complex; in a moment, we'll move on to an easy one.

When the timer interrupt strikes, we could ask it to look at the raster and see if the scan was close to the interrupt point. If so, we might wait things out, or skip part of the timer interrupt jobs. Messy.

The timer interrupt could "unlock" the interrupt very quickly, using a CLI command. That way, we could interrupt the interrupt program itself to do the split screen job. Better, but some programmers feel it's dangerous to allow this kind of thing to happen.

A Better Way

There is an easier way: shut the timer interrupt off completely, and do its various jobs with our own programs. This seems complex, but it's not. We can call the timer interrupt routines ourselves, whenever it's time.

Let's look a little more closely into the timing of these interrupts. We expect to cause a raster scan interrupt about 120 times a second. That's twice as often as the timer interrupt needs to be handled. So our raster program could occasionally call in the timer interrupt program.

It seems that we could accomplish the task easily by calling the timer interrupt routines every second raster interrupt. That would certainly do the job, but there's a better way.

Even though we've shut off the timer inter-

Table 1: 6566 Video Chip C64 Control and Miscellaneous Registers

Table 2: 6566 Video Chip C64 Sprite Registers

rupt, it's still signaling when the time is ready. Let's review: the timer leaves a signal in hex address $DCOD (56333) whenever it counts down to zero. Normally, this signal triggers the interrupt line (IRQ) and causes the processor to be interrupted. But we may "break" the connection between the timer signal and the interrupt line. In this case, the timer will not cause an interrupt, but the signal bit will still flash when the appropriate time has come.

We can see the plan in Figures 1 and 2. We will disconnect the timer from interrupt, and service it ourselves when it flashes. Easier done than said. Let's look at the machine language coding:

033C A9 01  INTR  	LDA #$01
033E 8D 19  D0	STA $D019

Raster interrupt is now the only game in town, so we don't need to test for it. We must, of course, turn off the raster interrupt flag.

0341		A2 92	LDX #$92
0343		A0 06	LDY #$06

Setup for top of screen. Next interrupt, line 92 hex; new color, number 6.

0345   AD    12    D0  LDA	  $D012
0348   10   	04    BPL MID

If it's really the top of screen, we can skip ahead. Otherwise, we change for mid-screen – line 1, new color, number 0:

034A 	A2	01	LDX  #$01
034C		A0	00	LDY  #$00

Now we're ready to do the job, wherever the screen is:

034E 8E 12 D0 MID	STX $D012
0351 8C 21 D0 		STY $D021

The job is done. Now let's see if the timer interrupt is calling for action:

0354 AD 0D DC		LDA $DC0D
0357 29 01			AND	 #$01
0359 F0 03			BEQ	 SKIP

If we didn't skip, the timer wants attention. Call it in:

035B 4C 31 EA		JMP $EA31

If we did skip, the timer isn't needed. Quit with:

035E   4C   BC FE   SKIP   JMP     $FEBC

We must remember, of course, to: turn off the timer interrupt; set the IRQ vector to our new code; and turn on the raster interrupt. We'll do all that in BASIC. Speaking of which.…

BASIC-ally Yours

Here's the same program in BASIC.

100  FOR J=828  TO  864 : READ  X
110  T = T+X : POKE  J,X
120  NEXT  J
130  IF  T<>4077   THEN  STOP
200  DATA  169, 1, 141, 25, 208, 162, 146, 160, 6, 173, 18, 208, 16, 4, 162, 1
210  DATA  160, 0, 142, 18, 208, 140, 33, 208, 173, 13, 220
220  DATA  41, 1, 240, 3, 76, 49, 234, 76, 188, 254
300  POKE  56333, 127
310  POKE  788, 60 : POKE 789, 3
320  POKE  53274, 129

Now we have a rock-solid color change at the appropriate screen point. No creeping, no jittering, no hiccups.

We've only touched upon the techniques of raster interrupt. A whole host of new possibilities open up with its use.

But we've shown it can be done, and some of the techniques that can be used to do it.

Copyright © 1983 Jim Butterfield.

Figure 1: "Conventional" coding requires the program to distinguish between the two live timing sources. It may also cause timing jitter.

Figure 2: Single interrupt coding gives priority to the time-sensitive raster job.