Today I am releasing a new C64 Demo: Galactic Rasterbar Power.
I coded this demo in my spare time to accomplish a few goals:
- Broaden my understanding of 6502/6510 assembly and the C64 memory map
- Learn more about the VIC-II and how it works along with the CPU
- Create some interesting multicolor bitmap graphics for my C64
- Master the raster bar demo effect that I have always really enjoyed
- And by extension, understand and implement cycle-exact code
- Make a demo that works equally well on PAL and NTSC hardware.
- Write some music for the SID chip, and make it work on both major revisions of the SID
- As a bonus: make the raster bar effect look absolutely perfect in VICE debug borders.
Although I have written many C64 programs (mostly when I was very young), this is only my second C64 program written with assembly. My first was an invitation/intro several years ago.
The book Racing the Beam describes in great detail the work that went into making the Atari VCS display game graphics. The title comes from the fact that the CPU was barely fast enough to keep up with the raster beam, and the programmer had to be aware of where on the screen the beam was in order to affect color output properly, and to use the few spare cycles during the blanking time to write actual game logic. The Commodore 64 added sound and video processors to offload a lot of that work from the CPU, but accomplishing anything fancy still requires you to be aware of where on the screen the raster beam is and how much time you have before something becomes visible.
For my demo, I wanted to draw “raster bars” — bars of color that get their name from the aforementioned “beam” in cathode ray tubes.
I have always found this effect to be visually interesting. (Unfortunatly, it loses some of its appeal on LCD monitors. Thankfully, I still use a Commodore CRT monitor for my real-hardware setup.) A C64 has a single register for the background color and a single register for the border color. There is no “third line” color setting. So the coder must “race the beam” and set the registers at just the right time so that when the line is drawn, it is the desired color. And then you have to do it again before the next line becomes visible.
If you use hardware on North America (NTSC), you get 65 CPU cycles per line to make these changes. If you’re in Europe (PAL), you get 63 cycles.
Until you start working under these limitations it is hard to really understand how incredibly slow the 6510 CPU in a C64 actually is.
In addition to the raster bars, I wanted to learn more about how the VIC worked with its graphics modes and with memory banking, so that I could combine the raster bars with simulated “layers” in a bitmap graphic. Add to that animation, so that the bars could move and morph. Juggling memory banks, graphics modes, background color, and border color on a per-line basis fills up the CPU line time pretty quick. But just when it seems easy, the VIC-II steals 40 cycles from the CPU on every 8th line. It does this to read ahead some data it needs to figure out what colors to display. And as it does that, your code sits there and does nothing. This leaves you with 25 (or 23) cycles to do what you need to do on every 8th line– these are called “badlines.” And, you never know exactly how many cycles into that line you are, unless you set things up beforehand and get your code cycle exact.
Cycle exact just means that wherever you are in a particular routine, you know exactly how many CPU cycles you have used, and in the case of video effects, you are also aware of where on the screen the raster beam is at that point.
Moving on. Once I managed to get all of that working, I decided to add to my challenge a bit by structuring my code so that the line color would change at exactly the time the VIC advances to the next line. This isn’t actually necessary, because there is a blanking area that is not visible on real hardware. This is a good place to get a few things done in prep for the next line.
VICE has a display mode called debug borders that lets you see what goes on in this area. Here is what my first demo looks like in debug borders:
The arrows point to the spots where you can see the background/border colors being changed. These are normally invisible. In that demo, updating the line color was easy because I never did it fast enough to care about those badlines mentioned above.
So the new challenge was to do all the stuff I needed to do to achieve my effects, and make it look absolutely perfect in VICE’s debug borders. I almost gave up on this, because I managed to get a routine that looked just fine in normal borders. But in the blanking area, there was a checkered effect due to the “prep” work I had to do for the badlines (setting things up so that I could change the banks, background, and border colors in those shorted cycle times…). But I kept at it and reorganized some things, so on every line — even the badlines — the color switches at exactly the point the line advances. Here are some screen shots:
Making the raster bar routine work on NTSC and PAL required carefully placed delays that are modified on startup for the different hardware. Remember, you have a different number of cycles on NTSC than you do on PAL, so cycle-exact color changes have to take this into account.
Some things that are imperfect and unfinished:
- NMIs are not suspended so hitting the restore key will freeze the demo. (Who does that anyway?) I wrote the entire demo and started to add the code to do this, and realized it was no longer possible without significantly redesigning the initialization code. But by the time I got here, my init code was exactly 512 bytes (two pages of RAM) and right up against some other data. I decided that if someone wants to watch the demo they can refrain from hitting the restore key.
- The music really needs some more production work. For example, the pulse width modulation on the bass goes too narrow if the note is held for a while. I should have made a new instrument for that. However, I am mostly satisfied with it as it is and I feel “done” with it.
- The animation tables should be longer so that the raster bar movement doesn’t seem so repetitive. But, there are four effects that loop, so hopefully the changes will make up for the short sequences.
- No custom character set. I actually designed one. But by the time I had set up my “layers” in the different VIC banks, I realized I had neglected to make sure I left a spot open on the bank I was using for text to store the character set. At this point I was beyond caring enough about the character set to go move things around again!
- The galaxy image is imperfectly adapted. I should have spent more time tweaking the pixels especially where the logo overlaps the galaxy image. Honestly, I got a little tired of working on the graphics and I wanted to work on a different aspect of the demo for a while, and I just didn’t get back to it.
I did precisely zero development on an actual C64. Just testing and watching the final result. These days it’s all about cross-development. I use a Windows 10 PC for all the work.
- The code was written and compiled with CBM Prg Studio. This is a great IDE and a lot more comfortable than using a more generic text editor and ACME like I did last time. The only down side is that most of the sample code on the internet uses a slightly incompatible syntax for the labels, but that is easy enough to fix.
- The graphics started in Adobe Photoshop — the galaxy and star field images are actually taken from some space-scapes I designed with Apophysis 7x and Photoshop during bouts of insomnia some years ago. I took these elements, along with a basic mask for the logo, and brought them into Timanthes. Timanthes has some really helpful tools for color reduction and editing specifically for C64 graphics formats. Once you dig through enough forum posts you can actually figure out how to save a bitmap that can be used in a C64. I tweaked the image as three layers — one without the logo, one with, and one with only the logo. Those bitmaps, in addition to a “blank” layer cleared in RAM, allow for the layered rasterbar effect.
- The music was composed using Cheesecutter. Since the “old” SID sounds very different from the “new” SID, I have two versions of the song data in the demo that use different filter settings. The SID model is detected at startup so the correct one is played. I composed the tune with the 8580, so that is where it sounds best, but it will at least play acceptably on a 6581.
- The tune was composed with PAL timings. NTSC displays at 60 frames per second, where PAL is 50 per second. This means that on NTSC hardware I have to skip every 6th frame to keep the tempo close enough to the way it was composed. The pitch is also higher, but nothing can be done about that.
- A 1541U-II+ for getting the program on to real hardware.
- Several custom one-off utilities. Using Delphi (my real-world work IDE), I wrote a tool to help me design the raster bar color patterns, and another one to generate the animation tables from easing algorithms. This was a lot faster than trying to do it all by hand in the assembler.
I hope you enjoy. There are no new fancy here-to-fore unexplored graphics modes coaxing 16 million colors out of the VIC-II, but does every new demo have to contain totally new effects or modes? I don’t think so. At least not for my second C64 program written in assembly.
And here is a YouTube video of the demo running in VICE with debug borders.