A Deep Dive Into 8-Bit Audio

SKATE OR DIE!

How three square waves and a noise channel became a masterpiece on the Tandy 1000

Year
1988
Composer
Rob Hubbard
Sound Chip
SN76489
Channels
3 + Noise
Publisher
Electronic Arts
01 / The Game

Skate or Die!

Released by Electronic Arts in October 1987 for the Commodore 64 and ported to IBM PC compatibles in 1988, Skate or Die! was EA's first internally developed game. Conceived by producer Don Traeger and inspired by Atari's arcade classic 720°, it dropped players into a multi-event skateboarding tournament with five distinct events:

Freestyle Ramp Half-pipe tricks
High Jump Half-pipe height
Downhill Race Park setting
Downhill Jam Street combat
Pool Joust 1v1 in a pool

The PC port was handled by Sculptured Software (programmer Arti Haroutunian), with sound and music for the Tandy 1000 version crafted by Rob Hubbard himself. Up to eight players could compete sequentially, facing off against memorable characters like Rodney Recloose (the purple-mohawked shop owner), Poseur Pete, Aggro Eddie, and Bionic Lester.

But it wasn't the gameplay that made the Tandy version legendary. It was the sound.


02 / The Composer

Rob Hubbard

Born in 1955 in Kingston upon Hull, England, Rob Hubbard started playing music at age seven. After school, he moved to Newcastle upon Tyne for three years of music college. His influences ranged from Mozart and Stravinsky to Jean Michel Jarre and Jerry Goldsmith—a classical foundation fused with electronic ambition.

In the late 1970s, he worked as a professional studio musician. Then, in 1983, he read about the Commodore 64 in Electronic & Music Maker magazine and bought one when the price dropped to £230. He taught himself BASIC and 6502 assembly language. His reasoning was simple: "The buzz that was around at the time was that musicians are gonna have to get into computers."

The SID Chip Years (1985–1988)

Between 1985 and 1989, Hubbard composed or converted music for over 75 Commodore 64 games. He became the undisputed master of the MOS 6581 SID chip, inventing techniques that other composers would study for decades. His most iconic trick: altering the SID's volume register thousands of times per second to produce digitized sample playback—exploiting what was essentially a hardware bug to create sounds the chip was never designed to make.

The original Skate or Die! title music for the C64, composed in August 1987, featured sampled electric guitar chords and organ sounds that stunned the chiptune world. The samples were actually recorded on an Amiga and then played back through the SID chip's volume register trick.

Joining Electronic Arts (1988)

Trip Hawkins personally recruited Hubbard to join EA in the United States. He chose EA over Microsoft—"Microsoft had no gaming platform" at the time. Hubbard became the first person at Electronic Arts solely dedicated to sound and music, handling everything from low-level driver programming to composition.

One of his first tasks at EA: writing the sound drivers for the Tandy 1000. He didn't just compose the music—he wrote the actual code that talked to the hardware.

"Not having a bug on the SN chip was no hindrance to doing samples."
— On getting 4-bit PCM sample playback working on the Tandy's SN76489

Kyle Granger

While Rob Hubbard composed the iconic title screen theme (and track 7), the in-game event music was composed by Kyle Granger, who wrote tracks 2–6 and 8–12 for the C64 original. These compositions carried over to the Tandy port, making the game's soundtrack a collaboration between two composers working within the same brutal hardware constraints.


03 / The Hardware

The Texas Instruments SN76489

At the heart of the Tandy 1000's audio was a chip that Texas Instruments originally designed for their TI-99/4A home computer in 1979. Officially called the Digital Complex Sound Generator (DCSG), the SN76489 was a simple, cheap, and surprisingly capable piece of silicon.

3 Square Wave Channels
1 Noise Channel
10-bit Frequency Registers
4-bit Volume per Channel
16 Pins (DIP package)
3.58 MHz Clock Speed (NTSC)

The Lineage: TI-99 → PCjr → Tandy 1000

1979
Texas Instruments creates the TMS9919 for the TI-99/4. Later offered as the standalone SN76489 chip.
1983
IBM includes the SN76496 (a variant with an audio-in pin) in the IBM PCjr, giving it 3-voice sound far superior to the standard PC's beeper.
1984
Tandy/Radio Shack releases the Tandy 1000, a PCjr-compatible clone that keeps the SN76496 sound chip. Unlike the PCjr (which IBM abandoned), the Tandy 1000 becomes a massive success.
1985–89
The Tandy 1000 series becomes the de facto standard for PC gaming audio before the AdLib and Sound Blaster era. Hundreds of DOS games ship with "Tandy/PCjr" sound support.

Chip Pinout

SN76489
DCSG
D2 1 16 VCC
D1 2 15 D3
D0 3 14 CLK
READY 4 13 D4
/WE 5 12 D5
/CE 6 11 D6
AUDIO OUT 7 10 D7
GND 8 9 N/C

What the Chip Could Do

Three independent square wave generators, each with a 10-bit frequency divider and 4-bit volume control (16 levels from full volume to silence). Plus one noise channel that could produce either periodic (buzzy) noise or white noise at three fixed frequencies or tuned to the frequency of channel 3.

The frequency formula is elegant in its simplicity:

// SN76489 Frequency Calculation
f = CLOCK / (32 × N)

// Where:
// CLOCK = 3,579,545 Hz (NTSC colorburst frequency)
// N = 10-bit value (1–1023) in the frequency register

// Examples:
// N = 1 → 111,861 Hz (ultrasonic)
// N = 254 → 440 Hz (concert A4)
// N = 1023 → 109 Hz (lowest tone, ~A2)

What the Chip Could NOT Do

No filters. No ring modulation. No programmable waveforms. No envelopes. Just square waves. Every note was a harsh, buzzy square wave at a fixed 50% duty cycle. Volume could only be set to one of 16 levels—there was no hardware envelope generator to shape the attack, decay, sustain, or release of a note.

All of that had to be done in software.

SN76489 vs. the MOS 6581 SID

To understand what Hubbard was working with on the Tandy, compare it to the C64's SID chip he had mastered:

Feature SN76489 (Tandy) MOS 6581 SID (C64)
Tone Channels 3 (square only) 3 (saw, triangle, pulse, noise)
Noise Channel 1 (separate) Per-channel selectable
Waveforms Square wave only 4 waveforms + combinations
Frequency Resolution 10-bit 16-bit
Volume Control 4-bit (per channel) 4-bit global + per-channel ADSR
Hardware Envelopes None Full ADSR per channel
Filters None Low/High/Band-pass, resonant
Ring Modulation No Yes
Pulse Width Control No (fixed 50%) 12-bit PWM
Sample Playback Via rapid volume writes Via volume register hack

The SID was a synthesizer on a chip. The SN76489 was a beeper with three voices. And yet, Hubbard made both of them sing.


04 / Programming the Chip

Talking to the SN76489

The SN76489 has eight internal registers but no way to read them back. It's a write-only chip. You send it bytes through I/O port 0xC0 on the Tandy 1000, and those bytes either latch a register and write data, or send additional data to the previously latched register.

The Register Map

Register  R2 R1 R0   Function
────────  ── ── ──   ────────────────────
   0 0 0            Tone 1 Frequency
   0 0 1            Tone 1 Attenuation
   0 1 0            Tone 2 Frequency
   0 1 1            Tone 2 Attenuation
   1 0 0            Tone 3 Frequency
   1 0 1            Tone 3 Attenuation
   1 1 0            Noise Control
   1 1 1            Noise Attenuation
    

The Two Byte Types

Every byte written to the chip is one of two types:

LATCH/DATA byte (bit 7 = 1):

  ┌───┬───┬───┬───┬───┬───┬───┬───┐
  │ 1 │R2 │R1 │R0 │D3 │D2 │D1 │D0 │
  └───┴───┴───┴───┴───┴───┴───┴───┘
   7   6   5   4   3   2   1   0

  1  = "This is a LATCH byte"
  R  = Register select (see table above)
  D  = Data bits (low 4 of frequency, or full attenuation)


DATA byte (bit 7 = 0):

  ┌───┬───┬───┬───┬───┬───┬───┬───┐
  │ 0 │ X │D5 │D4 │D3 │D2 │D1 │D0 │
  └───┴───┴───┴───┴───┴───┴───┴───┘
   7   6   5   4   3   2   1   0

  0  = "This is a DATA byte"
  D  = High 6 bits of frequency for last latched register
    

Setting a Frequency: Two Writes

To play concert A (440 Hz) on channel 1, you need to calculate N = 3,579,545 / (32 × 440) ≈ 254, which is 0x0FE in hex, or 0011111110 in binary (10 bits).

; Play A4 (440 Hz) on Channel 1 — Tandy 1000
; N = 254 = 0x0FE = 0011111110 (binary)
;
; Split into: low 4 bits = 1110 (0xE)
; high 6 bits = 001111 (0x0F)

mov dx, 0C0h ; Tandy sound port
mov al, 10001110b ; Latch: reg 000 (Tone 1), data = 1110
out dx, al
mov al, 00001111b ; Data: high 6 bits = 001111
out dx, al

; Set Channel 1 to full volume (attenuation = 0)
mov al, 10010000b ; Latch: reg 001 (Tone 1 vol), data = 0000
out dx, al

Volume Attenuation

Volume isn't "volume"—it's attenuation. The 4-bit value represents how much to reduce the signal, in 2 dB steps. Lower numbers are louder:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

0 = Full volume (0 dB)   |   14 = −28 dB   |   15 = OFF

Noise Channel Configuration

Noise Control Register (110):

  ┌───┬───┬───┬───┬───┬───┬───┬───┐
  │ 1 │ 1 │ 1 │ 0 │ X │FB │NF1│NF0│
  └───┴───┴───┴───┴───┴───┴───┴───┘

  FB  = Feedback type:
        0 = Periodic noise (buzzy, metallic)
        1 = White noise (hissy, full spectrum)

  NF  = Noise frequency:
        00 = Clock / 512   (high pitch)
        01 = Clock / 1024  (medium pitch)
        10 = Clock / 2048  (low pitch)
        11 = Tone 3 output (variable pitch!)
    

That last mode—tuning the noise to channel 3's frequency—was crucial for sound effects and percussion. Composers could "sacrifice" the third tone channel to get a pitched noise source for snare drums, hi-hats, and other percussive sounds.

I/O Port Addresses

System I/O Port Chip Variant
IBM PCjr 0xC0–0xC7 TI SN76496
Tandy 1000 / 1000A / 1000HD 0xC0–0xC7 TI SN76496
Tandy 1000EX/SX/HX/TX 0xC0–0xC7 NCR 8496 (in PSSJ ASIC)
Tandy 1000RSX/2500/Sensation 0x1E0–0x1E7 Relocated for AT bus
Hardware Quirk

Neither IBM nor Tandy ever wrote BIOS routines for the sound chip. Every game had to program it directly via port I/O. When Tandy moved the chip to 0x1E0 in later AT-compatible models, it broke compatibility with virtually every game that had been written to hit port 0xC0. This is why "Tandy sound support" in games was always a fragile thing.


05 / The Music

The Tracklist

The DOS/Tandy version of Skate or Die! contains seven distinct pieces of music, split between the SN76489 (Tandy 3-voice) for the title screen and—in a bizarre design choice—the PC internal speaker for the in-game events.

The Great Absurdity

After the title screen on a Tandy 1000, the game switches to using the PC internal speaker for music and the SN76489 for sound effects only. This means the beautiful 3-voice chip that Hubbard lovingly programmed gets demoted to beeps and boops during actual gameplay, while the single-voice PC speaker handles the music. Why? Nobody knows for certain. The most likely explanation: the in-game music code was written for vanilla PCs first, and adding full Tandy support for every event track wasn't prioritized.

The Title Screen: 4 Minutes and 4 Seconds of Magic

The title screen music is where the Tandy version shines. Rob Hubbard's driver pushes the SN76489 to its absolute limits: rapid arpeggios simulating chords, software-driven volume envelopes faking attack and decay, and—most impressively—4-bit PCM sample playback creating the illusion of digitized guitar and percussion sounds.

The Tandy rendition actually plays at a faster tempo than the C64 original, which suffered from a speed bug in the European PAL version. The Tandy version better reflects Hubbard's intended tempo—driving, aggressive, and unmistakably punk.


06 / The Magic

How to Make a Beeper Sound Like a Band

The SN76489 gives you three square waves. That's it. No filters, no envelopes, no effects. Everything that makes the music sound musical is happening in software, driven by Hubbard's custom sound engine running on the CPU.

Software Volume Envelopes

The chip has no ADSR. So the sound driver rapidly updates the volume registers many times per second via a timer interrupt. A note might start at full volume (attenuation 0), drop to 3 within a few milliseconds, then slowly fade to 8 over the next 100ms. This creates the illusion of percussive attacks and natural decay—all done in code.

; Simplified envelope tick (runs on timer interrupt)
; Called ~60-120 times per second

envelope_tick:
  mov al, [envelope_ptr] ; read next envelope value
  cmp al, 0FFh ; end marker?
  je .sustain
  or al, 10010000b ; set latch bit + channel 1 vol
  out 0C0h, al ; write to SN76489
  inc [envelope_ptr]
  ret

Rapid Arpeggios (Fake Chords)

With only three channels, you can't play a six-note chord. But you can cycle through the notes of a chord faster than the ear can distinguish—typically at 50–60 Hz. Play C, then E, then G, each for one frame (1/60th of a second), and the human ear perceives a C major chord. This technique, borrowed from the C64 demoscene, was essential for creating rich harmonies on the SN76489.

Vibrato via Frequency Modulation

By oscillating a channel's frequency register by ±1 or ±2 on each interrupt tick, Hubbard's driver creates a subtle pitch wobble—vibrato. This adds warmth and expressiveness to what would otherwise be a sterile square wave. The depth and speed of the vibrato can be varied per-note.

4-Bit PCM Sample Playback

This is the crown jewel. The SN76489 was never designed to play samples. But Hubbard discovered that by rapidly writing successive volume values to a channel's attenuation register, you could effectively use the chip as a crude 4-bit DAC (digital-to-analog converter).

The technique works like this:

  1. Set a channel's frequency to a very high value (ultrasonic, above human hearing) so the square wave itself is inaudible
  2. Store your audio sample as a stream of 4-bit values (0–15)
  3. Write each sample value to the volume register at a fixed rate (typically 8–15 kHz)
  4. The output pin's voltage now traces the shape of your audio waveform

The result is low-fidelity but unmistakable: digitized guitar, drums, and vocal-like sounds coming from a chip that only knows how to make square waves. On the C64, Hubbard exploited a similar trick with the SID's global volume register. On the Tandy, he adapted the technique to the SN76489's per-channel attenuation, and as he noted: "not having a bug on the SN chip was no hindrance to doing samples."

The samples in the Tandy version were the same ones from the C64 version—originally recorded on an Amiga and downsampled to 4-bit resolution.

The Interrupt-Driven Engine

All of this runs on a reprogrammed timer interrupt (INT 08h / IRQ 0). The PC's 8253 Programmable Interval Timer is set to fire at a much higher rate than the default 18.2 Hz—typically 60 to 120 Hz for music sequencing, and potentially up to 15 kHz or more during sample playback.

On each interrupt:

  1. Advance the music sequence (read next note/command if it's time)
  2. Update frequency registers for any channels with new notes
  3. Tick volume envelopes for each active channel
  4. Apply vibrato/pitch effects
  5. If playing a sample: write next PCM value to attenuation register
  6. Handle the original INT 08h (system timer) at the correct rate

The CPU is doing all the work that the SID chip does in hardware. Every envelope shape, every tremolo, every arpeggio is eating CPU cycles. On a 4.77 MHz 8088, that's a significant chunk of processing power dedicated to making three square waves sound like music.


07 / Legacy

Why This Still Matters

The Skate or Die! title screen on the Tandy 1000 is a masterclass in creative constraint. Rob Hubbard didn't just write music for the hardware—he wrote the driver that made the hardware capable of playing it. Composer and engineer in one person, pushing a $2 chip past every limit its designers imagined.

Hubbard went on to become Audio Technical Director at EA, making technology decisions that shaped game audio for years. He left EA in 2002 and returned to England, where his classic compositions have been performed in orchestral concerts and continue to be covered, remixed, and celebrated by the chiptune community.

The Tandy 1000's SN76489 was a dead-end branch of audio technology—obsoleted by the AdLib in 1987 and the Sound Blaster in 1989. But for a brief window, it was the best sound a PC could make. And in the hands of someone like Rob Hubbard, "best" was more than enough.

Three square waves and a noise channel. That's all it took.


Sources & Further Reading

References