Blog Projects Contact/Links

Digibeatz

Play or download ROM on itch.io.

After creating Hyperbeatz for the NES, I decided to try making a rhythm game for the Atari 2600 as well. It's similar to Guitar Hero, except with only 3 "frets" that are selected with the joystick. Before a note reaches its target, hold the joystick in the corresponding position. Then press fire when it reaches the target.

DigiBeatz has software-generated audio to split one of the console's 2 audio channels into 5 software channels. It has 7 songs, each with 5 charts. All of this fits in 4KiB, only 10% the size of Hyperbeatz!

The software-generated audio works by having the CPU add 4 square waves together in realtime. The audio update subroutine runs every 152 CPU cycles, and takes 91 (I think?) CPU cycles to run. The rest of the time (about 40%) is spent running game logic and drawing to the screen. The Atari 2600 also has no CPU interrupts, so I needed to manually add in calls to update audio throughout the entire gameplay code. Additionally, the Atari 2600 only has the graphics hardware to display a single row of picture, and the CPU must update this hardware as the picture is sent to the TV in order to show a 2D image, so the game logic can only run in the time between frames. That leaves only about 4000 CPU cycles per frame to do all the game logic and music loading for a frame. And on the Atari 2600, your game cannot lag or the video signal goes out of spec.

Because I wanted the game to fit on a standard 4KiB cartridge, I had to keep the music simple. The 4 software square waves are used for a melody, a countermelody, an arpeggiator and a bass. The 2nd hardware channel is used for white noise to make drum effects. These roles are hard-coded and shared across all tracks to save space. The melody and countermelody have a range of 15 notes plus silence, meaning each takes 4 bits per note, which are combined to make 1 byte per note. 1 more byte is used for the rhythms of the other channels. These are grouped into measures of 16 notes. A song then has up to 8 melody measures, 4 rhythm measures, and 8 chords (which determines the notes the arpeggiator and bass play). Each measure of the song chooses one of each of these, which takes just 1 byte per measure. In total, a song is 16 bytes per distinct measure of melody and rhythm, plus 1 byte for the ID of each chord it uses, plus 1 byte per measure. A typical song is 200 bytes.

The charts are generated randomly using a fixed seed, following the rhythm of a subset of the channels. This means a chart is just 1 byte to indicate which channels should be included. When the melody is used, the chart's patterns will repeat notes when the melody does, so that it is somewhat pitch dependent.

This might be the most technically challenging piece of software I've ever written. And as a game it's...adequate.

You can listen to an enhanced version of the music from DigiBeatz here. Rather than capture the output of the console, I recreated what it would sound like if it had a higher sample rate and stereo.

© 2025 Anthony Blackman. All Rights Reserved.