Commodore 64 Video — A Guided Tour
Jim Butterfield, Associate Editor
This month we explore a fairly advanced technique: split screens on the Commodore 64. It's a new aspect of the computer, combining things we have already learned into a new set of capabilities. We'll demonstrate, via a BASIC program, an amazing visual display.
We'll need to venture into more technical waters now, but with a little effort, we can perform some minor miracles on the Commodore 64 screen. All the limitations we have learned may be set aside with a little creative "cheating." We'll have to venture into machine language; but even if you're not a ML tyro, it's worth knowing that the job can be done.
We have learned a number of limitations, largely based on the idea that the screen can do a lot of things, but only one at a time:
- We can have only one background color, unless we are in multicolor mode; and even in that case, we're restricted to our choice of colors.
- We can obtain information only from one 16K memory quadrant.
- We can use only one character set.
- We can be in character mode or bit map (hi-res) mode, but not both.
- We may have only eight sprites on the screen at one time.
In fact, we have a more general set of rules. We may be in only one mode at a time – multicolor is either on or off; extended color is either on or off; and so on. It seems impossible to mix screen modes and have the best of both worlds, but we can do it.
Here's the trick: the "Raster Register," address D012 together with the high bit of D011, can do more than tell us where the screen is being painted at this instant. We may store an "interrupt" value there, and tell the computer: "Advise me when you get to this part of the screen." At this point, we can switch screen characteristics: color mode, high resolution, background color, character set, memory bank – whatever you want. Of course, we need to put it all back when we return to the top of the screen.
We're going to write a quick program to split the screen into two parts, each with a different characteristic. It won't be perfect; we're just trying to show the technique, not to polish up all the loose ends. The fine points will come later. First, let's plan.
If we set a new "interrupt" into our machine, we'll need to make some careful distinctions. First, when an interrupt happens, we must establish: who caused this one? Was it the raster, or the traditional interrupt source of 1/60 second timing? Second, if it was a raster, which part of the screen is involved – the top or the "switch" point?
Let's start to lay out the machine language program. All interrupts will come here, and we'll need to sort them out. We'll put the program into the cassette buffer.
033C AD 19 DO INT LDA $D019 033F 29 01 AND #$01 0341 F0 19 BEQ REGULR
The interrupt has happened and has come here. Check the Raster Interrupt Bit in D019 – was this one caused by the raster? We'll need to mask out the bit we want with an AND. If we get nothing, it's a regular interrupt – go there.
0343 8D 19 DO STA $D019
It is indeed a raster interrupt, and we must shut off the alarm. We do this by storing the bit back where it came from (there's a 1 in the A register right now). Amazingly, this turns the bit off.
0346 A2 92 LDX #$92 0348 A0 15 LDY #$15
We'll prepare the registers, assuming we are doing the top-of-screen work. The hex 92 is decimal 146 — the scan line that hits about mid-screen; that's where we will want the next interrupt to take place. Note that hex 92 is considered a "negative" byte; we will use this fact in just a moment. Now, let's see if we are correct about being at mid-screen:
034A AD 12 D0 LDA #$D012 034D 10 04 BPL MID
We look at the raster scan. If it's less than 127, we're near the top of the screen, and we don't see the "negative" byte. So we skip ahead. If, however, we are at the middle of the screen, we'll see a "negative" value. We won't branch; instead, we'll fix up the registers for mid-screen work:
034F A2 01 LDX #$01 0351 A0 17 LDY #$17
Both streams join again at this point. X contains the raster location where we will want the next interrupt: if we're at the top, we want to be interrupted at the middle (hex 92); if we're at the middle, we will want to be interrupted at the top (hex 01). Y contains information on the character set we want to choose: graphics or text. Let's proceed:
0353 8E 12 D0 MID STX $D012
Place the next interrupt point into the raster register. The next interrupt will now hit at the right time.
0356 8C 18 D0 STY $D018
Place the "character set" value — hex 15 for graphics, hex 17 for text — into the appropriate register.
0359 4C BC FE JMP $FEBC
We've done our job. We may now exit. Don't give an RTI; instead, go to a routine that cleans things up nicely, at FEBC. And what of our regular interrupt?
035C 4C 31 EA REGULR JMP $EA31
It goes to the normal address, to which regular interrupts go.
We have more to do after we get this program into memory. We must also detour the interrupt vector to our new program, and fire up the raster interrupt control.
Back To BASIC
Ready to put all this in BASIC? Here we go:
100 FOR J = 828 TO 862 : READ X 110 T = T + X : POKE J, X 120 NEXT J 130 IF T < > 3958 THEN STOP 200 DATA 173, 25, 208, 41, 1, 240, 25, 141, 25, 208, 162, 146, 160, 21, 173, 18 210 DATA 208, 16, 4, 162, 1, 160, 23, 142, 18, 208, 140, 24, 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
Let's look at the last three lines. Line 300 kills the interrupt for a moment, so that we can mess with the interrupt vector without running into disaster. Line 310 changes the interrupt vector to point at our newly POKEd program. Line 320 restores the interrupt, and adds an extra one: the raster interrupt.
An Amazing Split
When the program is run, an amazing thing happens: the screen becomes graphic at the top and text at the bottom. Impossible, you say? Not for us clever — and careful — people. The effect is permanent: you may NEW the program and start something else and the split screen will still be there.
You shouldn't use cassette tape with this program in place — it's there in the buffer. And you may find that LOAD and SAVE don't work quite right. RUN-STOP/RESTORE will put everything back to its former state.
The Unsolved Problem
But it's not perfect (I warned you). Every once in a while, the barrier seems to creep slightly, and then correct itself. Maybe it's computer hiccups. It seems worse when you are using the keyboard. What's happening? And how can we fix it? Stay tuned.
Copyright © 1983 Jim Butterfield