Commodore‎ > ‎C128‎ > ‎

VIC-IIe Interlace

The Commodore 128 is known to produce interlaced video with the VDC (80-column) video chip, but the memory-mapped and sprite-featured VIC-II chip is not known for this neat feature. I have created a new video 'mode' which enables a real interlaced display (320x400 hi-res or 160x400 multi-color bitmap or 40x50 text).


This page describes the new NTSC/PAL version of the interlace demo software (the original page is here). You can download the new demo, Comments, good or bad, can be left. The download contains a D64 disk image, a ReadMe file, the assembly source files, the General Public License version 2, and an unsupported freeware utility 'splitbmp.exe'. The D64 contains:

  • DEMO 2; the BASIC demonstration program
  • CODE 5; the main machine language support program
  • BM LOADER; a tiny machine language program to load bitmaps
  • FLI TEXT; data for a 40x50 text display (text and color)
  • Four interlaced bitmaps: two hi-res and two multi-color (8 files)
RUN "DEMO 2" on a real Commodore 128!
(current emulators do not support 400+ VIC rasters)

The images of the standard bitmaps were taken using the VICE so they are very sharp. I had to use a video capture card for the interlaced images. I appologize that they do not appear here as nice as they appear on my TV. This is due to several factors, mainly my video capture card does not grab both fields when taking snapshots. Update: Now included are some PAL screen shots provided by wte.


After reading about how the Atari 2600 can do interlaced video, I began wondering if it could be or has been done for the C64. After reading many articles, it appears it is not possible... the closest thing I read about is called IFLI a video mode for the VIC-II (C64 or C128) that alternates bitmaps every field for the purpose of blending colors and smoothing pixels. This does not create an interlaced (400+rasters) video image. Figure of an NTSC even field or PAL odd field

In consumer video, interlacing is achieved by sending a non-integer number of rasters each field. There are 2 fields per frame usually called even and odd. I sometimes use the terms 'top' field and 'bottom' field on this page to avoid confusion with the terms 'odd field' and 'even field' because these are opposite between NTSC and PAL video!!

The 'top' fields (NTSC even / PAL odd) start in the middle of a raster, which is to say, the first raster is a half-raster then all remaining rasters in the field are complete, full rasters. The 'bottom' fields (NTSC odd / PAL even) start with a full raster, but they end with a half-raster -- all ready to start again with the next field/frame. The even/odd nature is determined by timing of the vertical synchronization (v-sync) pulses that mark the start of a new field.

Figure of an NTSC odd field or PAL even field After reading (in an article of Commodore Hacking probably) about how the C128's undocumented test bit of the VIC-IIe works (it makes VIC skip rasters!), I wondered if that could be used to produce interlaced video. Well, I got a Commodore 128 recently and decided to test the idea. First I needed to know when the VIC produces the v-sync pules (i.e., on which raster according to VIC). After doing more research on the WWW, I was unable to uncover any information. This again leads me to believe this has never been done before.


Picture of the VIC-IIe display rolling on the screen By playing with the test bit, I was able to completely eliminate the v-sync. This produces a rolling video display. With a rolling display, I was able to see (by changing border color with an interrupt routine) when the v-blank starts and when it ends. V-sync occurs in the middle of v-blank so I can't be sure of its location, but by deduction (which rasters I needed to kill to roll the screen) I developed a theory. Through these experiments and references to the NTSC standard and the Atari TIA chip documentation, I have made several conclusions (NTSC):

  • VIC-IIe probably produces odd fields (first raster looks full)
  • V-Blank starts on raster 13 ($0d) and lasts 4 (blank + 3 equalizing) rasters
  • V-Sync starts on raster 17 ($11) and lasts 3 rasters
  • V-Blank resumes on raster 20 ($14) and lasts 4 (3 equalizing + blank) rasters
  • Video starts on raster 24 ($18) and lasts 252 rasters
Figure of the VIC-IIe NTSC screen, showing v-blank and v-sync rasters With this information, I wrote a single-cycle-exact interrupt routine (using a double interrupt technique) that has two parts. These can be found in 'interrupt.src'. 'ivirq' enables the interrupt routine and 'ikirq' disables it. 'eField' contains the code for even fields and 'oField' contains the code for odd fields. Also there is common code at 'ixit' to finish the interrupts, 'iField' to initialize the next field, and 'dblirq' to perform the double-interrupt synchronization.

The technique used is to 'cut' rasters from the VIC's output at the appropriate time (before/during v-sync) to produce an even field. This is done simply by setting the undocumented 'test bit' located in bit 1 of register 48 (memory mapped to $d030 in the Commodore 128). In essence,

LDA #2 ;value for bit 1 on
LDX #0 ;value for bit 1 off
STA $D030 ;test bit on, skip a raster for each clock cycle
STX $D030 ;test bit off, resume normal operation

This can NOT be done on every field because then all fields would be even fields and you would have an image almost identical with VIC's normal odd-only output. To create interlaced images, we must alternate between even and odd fields. But we can not simply ignore the test bit during (VIC's normal) odd field because this would result in an odd field that is 3 or 4 rasters 'taller' than an even field and the two fields would not interlace (fit together) properly. So for odd fields we also cut some rasters, but we are careful to avoid the v-sync area.

Then I experimented with different 'cut times' to create an interlaced effect. When I got an 'interlaced' image I was really exited! In hindsight, it may not have been true interlacing. Since then, I have conducted further experiments, done more research, refined the method, and developed a theory of how this works. Now I am quite confident this is producing a real interlaced image. For comparison, I first present a normal vertical sync (normal for NTSC VIC).

Figure of NTSC VIC-IIe generation of vertical sync showing blanking intervals, equalizing pulses, and v-sync pulses.

Notice the v-sync starts at the beginning of a raster. This indicates to a TV/monitor the start of an odd field. Next is an illistration of my method of creating an even field.

Figure of method used to generate NTSC even field with VIC-IIe showing blanking intervals, cut rasters, v-sync pulses, and equalizing pulses.

By briefly turning on the test bit in the middle of the pre-equalization pulses, VIC skips rasters only to resume with a vertical sync pulse in the middle of a raster. Starting v-sync in the middle of a raster indicates to a TV/monitor the start of an even field.

There are two primary consequences of this method. First, since VIC is skipping rasters, fewer rasters are generated per field resulting in a faster than normal field rate. Approximately an increase from 59.83Hz to 60.63Hz (1.34% faster, NTSC). Second, the 'cut' rasters are those containing pre-sync equalizing pulses. These are not needed by modern equipment, but may cause trouble for very old equipment. In particular, the 1980's saw the introduction of digital tuners (anyone remember the mechanical knobs before that?) and presumambly digital control of synchronization occurred about the same time.

CIRCLE0, the 'top' field of the interlaced circle.

  My first 320x400 bitmap: a circle  

My first bitmap was a BIG circle. I started with the BASIC command

CIRCLE 1,160,199,159,199

This made a standard 320x200 bitmap of (the top) half of a circle. Through some copying, mirroring, and stripping, I eventually ended up with two standard bitmaps that are the odd and even fields for the 320x400 interlaced bitmap. These are on the disk image as CIRCLE0 and CIRCLE1.

CIRCLE0 contains what I call 'top' rasters, representing 0,2,4,6...398 (but it's a normal bitmap so these appear as rasters 0...199 with missing segments). The first raster has a segment in the middle and the last raster has a gap in the middle. CIRCLE1 contains what I call 'bottom' rasters, representing 1,3,5...399. The first raster has a gap in the middle while the last raster has a segment in the middle.

Update: The numbering of rasters 0...399 was developed with NTSC and is appropriate since raster 2, for example, appears in an NTSC even field. PAL users may want to number the rasters as 1...400 so that the same raster, number 3 for the example, corresponds with a PAL odd field.

CIRCLE1, the 'bottom' field of the interlaced circle. Neither bitmap by itself could be called a circle because of missing segments. Each bitmap alone constitutes a video field. Both bitmaps, when interlaced together, form a complete frame. The frame is 400 rasters tall and forms a true circle.

With the bitmaps, I went back to the interrupt code and made it switch VIC video banks for each half of the interrupt code. With the bitmap(s) on screen, it was obvious that my 'interlacing' was wrong so I continued experimenting. I finally found a method that produced a good result and announced my invention on the C128 Alive! forums. I said I would make a demo so that's what I did next.

Picture of NTSC VIC-IIe screen displaying 320x400 interlaced bitmap of a circle.

  Update for PAL  

Unfortunately, the original demo wouldn't permit 'cutting' rasters past 255 so it could not work for PAL. After releasing the first demo I discovered, thanks to mysticshadows, that a document by Christian Bauer mentions the start raster of video blanking. Although this is not the raster for vertical sync (needed for interlace), it is close and the value given is also correct for the NTSC VIC-IIe.

So based on the article's statement of PAL blanking, and the assumption that PAL vertical sync / equalization is 6 rasters (instead of NTSC's 9), I guessed the following:

  • V-Blank starts on raster 300 ($12c) and lasts 3 rasters (blank + 2 equalization)
  • V-Sync starts on raster 303 ($12f) and lasts 2 rasters
  • V-Blank resumes on raster 305 ($131) and lasts 3 rasters (2 equalization + blank)
  • Video starts on raster 308 ($134) and lasts 304 rasters

Figure of PAL VIC-IIe generation of vertical sync theory showing blanking intervals, equalizing pulses, and v-sync pulses.

This made me update the code to handle rasters past 255. The PAL implementation of interlace is the same principle as NTSC: three and half rasters before the vertical sync (in the middle of raster 299), enable the VIC-IIe test bit for 4 cycles to 'cut' four rasters so that VIC resumes in the middle of the vertical sync. For PAL, this should change the field rate from 50.12Hz to 50.69Hz (a 1.14% increase).

Picture of PAL VIC-IIe screen displaying 320x400 interlaced bitmap of a circle.

Update 1: AmiDog from the Commodore 128 Alive! Forums has reported success on a PAL system using a C1084 monitor with a cut starting in raster 300 (instead of 299 as stated above). This is probably related to the fact that PAL should use 7.5 rasters for v-sync (including pre- and post-sync equalization pulses) when I thought it was only 6 and because VIC probably uses the same non-interlace method of other consoles (8 rasters of sync instead of 7.5). I have updated the diagram for you.

Update 2: Other forum members, bacon and wte, have also reported success with a raster value of 300. Due to their confirmation, I have updated the demo to use raster 300 for PAL video. A C1084 monitor was used by bacon. A C1901 monitor was used by wte and provided the PAL screen shots seen here.

While I was updating the code, I decided to try a true text display in interlace mode. The original demo only used bitmaps and the 'text' demo display (a directory listing) was really a bitmap. To get 50 lines of text this time, I used FLI (flexible line interpretation).

Picture of PAL VIC-IIe screen displaying 40x50 interlaced text.

  Real Interlace FLI  

Not to be confused with IFLI (which claims to be but is not interlaced)! In normal FLI, we force the VIC to update its pointers more often than the usual (once per 8 rasters). The interlace demo uses FLI this way:

  1. The screen starts normal and VIC fetches text row 0 (raster 51)
  2. Four rasters later FLI is activated and VIC fetches text row 1 (raster 55)
  3. Immediately after VIC is set back to normal
  4. Four rasters later the process repeats (normal VIC fetch for row 2)
In other words, every 8 rasters FLI is invoked to fetch odd rows then VIC is reset to automaticaly fetch even rows, which results in new text rows every 4 rasters.

Doing this for the entire visible (inside the borders) part of the screen creates 50 rows of text, 4 rasters each (in each field). Since this is used in combination with interlacing, the result (a complete frame) is 50 text rows of 8x8-pixel characters.

The code for this is in 'text-fli.src'. FLI requires precise timing and for variety (and efficiency) I used Timer B of CIA#1 to achieve cycle-exact execution. There is actually two different code sets. The first is 'without ROM' which has an interrupt 1 raster before every badline and the second, 'with ROM', has an interrupt 2 rasters before only the FLI badlines. The demo uses the 'with ROM' version since the interrupt code works in conjunction with a BASIC program.

FLI does have a bug of fetching 3 bad pointers. This results in 3 garbage characters at the start of every odd text row. Because I'm lazy, I did not hide the bug. Normally FLI is used with bitmaps and sprites are used to cover-up the bug. For FLI text mode, another option is to define character 255 as a blank.

Another minor bug (really a detail) is that VIC does not update its row-in-character counter when FLI is activated, so the bottom half of the font must duplicate the top half. Also a normal font must be split into 2 sets for interlace mode (even and odd fields). The routine 'makeFont' creates 2 such sets from the Commodore character ROM for the demo.

Finally note that I only implemented Real Interlace FLI for the text mode demonstration. Feel free to combine this with bitmap mode instead, and if you do, please share!

An interlaced VIC-IIe image of a lady in a bikini at the beach.

  Demo 2 Bitmaps  

After releasing the first demo, I wanted to see something more exciting with my new video mode than a circle or directory. Since there are no bitmap editors for my new video mode and I'm too lazy to write one, I decided to simply split a hi-res image into two files and then convert them to Commodore bitmaps.

To get two files of even and odd fields, I wrote a Windows command-line program. I've included the binary 'splitbmp.exe' and it is unsupported freeware. It requires a 24-bit, unpalettized, uncompressed, BMP (Windows Bitmap) for input and produces two files as output (for the even and odd fields). The image height doesn't matter, but the width must be less than 4000 pixels.

Then I used Timanthes to convert the BMP files into Commodore multi-color bitmaps (if that link is bad you might try C64 Scene Database.). It's important when transforming the colors to the VIC-II pallette that each field has opposite dithering options. It doesn't matter if you select even or odd dither for your even field, but, be sure to select the opposite for your odd field. The output from that program seems like a Koala file without the 'KK' prefix and missing the background color. I simply used a hex editor to append the correct background color.

I've included two of these bitmaps (four files) on the disk image. Although much nicer to look at than a circle, they really do not take full advantage of the interlace mode -- a talented 64 pixeler could do better with a normal multi-color bitmap. But I think they show potential.

Also included is DITHER, a set of bitmaps provided by Nikoniko. This image is designed to show harsh contrast and as a consequence, it flickers terribly! Note this flicker is not a fault of the program, but is a consequence of interlace video. There is an entire science called anti-aliasing designed to prevent/reduce these unwanted effects.

Finally I wrote 'bmload.src' to load the bitmaps. It determines if the bitmap is multi-color or hi-res based on filesize (load end address). Once it knows, it moves the data to appropriate spots in Bank 1 depending also if it is an even or odd field.

  BASIC Program Description  

The actual demo program (DEMO 2 on the disk image) is a (uncompiled) BASIC program. At start-up, it allocates the BASIC bitmap and displays a message on the VDC screen. It sets BASIC's start of variables to $c000 and then loads a few files:

  • Interrupt code (CODE 5 into $1300)
  • Bitmap loader (BM LOADER into $b00)
  • Circle bitmap (CIRCEL0 to $1c00 and CIRCLE1 to $9c00, Bank 1)
  • FLI text and color screens (FLI TEXT to $2000, Bank 0)

It creates the FLI fonts at $3000 and $3800, and shows the copyright and a notice. On a PAL system, a message is displayed that the demo is untested by me although reported to work by others. If you press RETURN to continue, it checks the VIC-IIe test bit and reports if it does not work (such as in an emulator). Finally you get the main menu.

Picture of PAL VIC-IIe screen displaying Interlaced Demo menu.

  Interlace Menu  

When first displayed, the interlace interrupt code will be off. You can turn it on/off by pressing the space bar. If it works correctly on your display, you will hardly notice it on the menu screen! If the display does not look correct, see the Customizing section.

The two main viewing options are V to view an interlaced bitmap or T to view an interlaced text screen. I recommend V first since the circle is monochrome and very simple (easy to see if the settings work correctly for you). When viewing either a bitmap or FLI text, you have these options:

  • Press M to go back to the main menu
  • Press R to reverse the even and odd fields
  • Press + or - to change background color (not all bitmaps)
  • Press Space to turn interlace on/off (bitmap only)

You can load another bitmap by pressing L. When asked for a name, you can type $ to see the directory. Enter the name without the zero or one. For example, the disk contains DITHER0 and DITHER1 files; type DITHER to load the interlaced image set.

If you don't have this text handy, you can press H or Help for a very brief review. Press Q to quit the interlace demo.

Still on the main menu, you will see a section labeled 'Presets'. These will set various parameters for the interlace code. You can restore the default settings by pressing A. Preset B will 'cut' the vertical sync and will probably cause the entire screen to roll (if interlace is enabled). And option C is for testing/comparison: it will 'cut' nothing so there will be no interlace! This is essentially the same as IFLI. Try viewing the bitmap or FLI text screen again with this setting to see the difference between IFLI and real interlace. Note the PAL screen shot shows option D which is not in the demo (it is a customization added by wte).


Picture of VIC-IIe screen displaying a supposed circle, however the fields are wrong (odd coming first); try the Reverse (R) option if you have this problem. If there is no difference in the bitmap or FLI-text between Preset A and Preset C, then interlace mode is not working for your display. You can customize three different settings of the interlace code for each field. The current settings and some statistics for each field are shown at the bottom of the menu screen. Below the field statistics are the statistics for a complete frame. In either case, the statistics are:

  • Number of cycles in frame (or field). A cycle is approximately 1 microsecond.
  • Duration of frame (or field). Given in milliseconds.
  • Frame (or field) rate. Given in Hertz (Hz). Equal to 1/duration.

Press 0 (zero) to edit the even field settings or 1 (one) to edit the odd field settings. This erases the statistics and adds editing options. Note that all options are still accessible while editing, but you can remove the editing options and restore the statistics by pressing the ESCape key.

The editing options allow you to change 3 items:

  • Cut Raster is the VIC raster (vertical position) where the test bit is enabled.
  • Cut Cycle is the cycle (horizontal position) where the test bit is enabled.
  • Cut is the amount of rasters to be cut, if any.

Use the cursor keys UP and DOWN to change the Cut Raster. Use the cursor keys LEFT and RIGHT to change the Cut Cycle. Press 3 or 4 to change the number of rasters to be cut or press N to cut no rasters.

The way the interrupt code is written, the Cut Cycle can only be changed in increments of 2, normally restricting you to even cycles, but you can wrap around to the next raster which allows cutting on odd cycles. For my TV (if the raster is correct), any cycle between 21 and 35 will work.


While experimenting, I found several settings that were almost right, which is why having the bitmap is very handy. The bitmap should have thin, distinct rasters, and of course should look like a circle. The rasters should not overlap. If the display seems stable but the circle looks 'wrong', try reversing the fields by pressing R. Certain settings, on my TV anyway, produce a stable but 'crazy' interlace effect where half (top or bottom) of the screen appears correct but the other half appears reversed.

I suggest experimenting with the settings for even fields because VIC produces odd fields naturally. You should also cut 1 raster more for even fields.

You may be curious why the code 'cuts' 4 rasters for even fields and only 3 rasters for odd fields. This is because the 'cut' crosses from the end of the odd field into the start of the even field and because the code for even field occurs at the end of an odd field (and vice versa).

In other words, 4 rasters are 'cut' to create the even field, but 3.5 are at the end of the odd field and 0.5 at the start of the even field. So the even field starts 0.5 rasters short and at the end 3 more rasters are 'cut' before starting the odd field (this should not cross over). In summary, each field has 3.5 rasters cut but the program displays 3 and 4 because that is the way the VIC-IIe test bit works (it skips 1 complete raster for every cycle it is 'on').

Some settings produce a color artifact I call rainbowing. I believe this may be due to the generation of even fields and the fact that VIC does not reverse the phase of the color burst. Note all screen shots I made show this effect, even without interlace enabled! It must be due to my video capture card. On my TV, the rainbow effect is not present with the right settings. It's hard to describe since the background is still dark gray and the characters/pixels are still (mostly) light green, but in the screen-shots you should notice some color shifting of various amounts resulting in a rainbow effect.

Update:AmiDog reports an even more fantastic color distortion on PAL systems with the appropriate (wrong for proper interlace) settings. It seems a good PAL hack could produce a new color pallette for the VIC-IIe!

Hopefully you'll find a nice setting that shows a super-smooth circle with very little flicker. If you do, the final test is FLI text mode. It should show little flicker and the text should be very legible (small but legible). The amount of flicker is based on a number of factors such as the persistence of your monitor, your personal persistence of vision, and ambient lighting. But probably most important is contrast. Thus black text on a white background is probably the worst. With a medium gray background, I do not notice any flicker on my TV for either black or white text and the other text colors look good too.

© H2Obsession, 2007