skip navigation

Adding SOUND to your ATARI 2600 game


In this episode we talk about how sound is generated on the Atari 2600 using the Control, Frequency and Volume registers, along with a couple of examples in 6502 assembly language!

April 10, 2023

Original Link:


Your support is greatly appreciated!

Welcome to 8-Blit, a channel covering all the tips, tricks, and everything in between for programming your own games for the Atari 2600 from 1977.

In this episode we uncover the audio capabilities of the system… and how you can make your games move lively and engaging by adding sound effects.

That’s all coming up on this episode of 8Blit.

If you remember sitting on the floor tethered to your TV by a slightly broken atari joystick in your hands that seems to make a rattling noise as you excitedly sway your upper body with every move. Captivated by the action and glow of the screen, and dreaming of one day making your own games for the Atari 2600?

Then you’ve found the right channel.

We explore the technology and history of arguably one of the most iconic game consoles ever made. It’s a flashback to when things were simple, when your fridge always had a tupperware pitcher full of kool aid, the house was full of rubber tree plants, and your friends would come by to play Atari.

Click on the subscribe button, including that little bell to stay up to date with new episodes and to gain access to tutorials with a ton of code examples. If you’d like to support future episodes capturing the intrepid spirit of Atari from the 70’s and right through the 80’s, then please consider joining us on Patreon.

More information on how you can become a patron today, in the video description.

In 1951, Christopher Strachey, a friend of Alan Turing, wrote a program to play chess on a Ferranti Mark 1 computer in Manchester, England. At the conclusion of each game, it would play “God Save The King”. I couldn’t find a recording of the Mark 1 playing the song, but what you’re hearing was recorded from Turning’s prototype Mark II computer. Thus, the very first video game original soundtrack was born.

According to a quick google search, no other video game could match this amazing feat until 1972… with the game Pong created by Allan Alcorn while working at Atari. If you know of an earlier system with sound, let us know in the comments.

Since the early days of pops and buzzers, sound circuits became ever more complex on each iteration of consoles, with today’s game audio being recorded on hollywood like sound stages by professional foley artists, and music scores performed by prestigious orchestras.

We’ve come a long way since our rudimentary bloops and beeps. So far, that my clothes dryer has better capabilities and fidelity than our beloved Atari 2600.

Somehow, though, despite the odds. The distinctive sound of the Atari 2600 is tightly ingrained into our wistful youth.

Let’s have a look at the specifications and hardware.

Internally, the sound is generated by the Television Interface Adaptor chip, or TIA for short. The TIA features two independent audio channels, which would be great for stereo sound, but unfortunately the traces on the circuit board where the two output pins on the TIA connect are joined resulting in a combined mono signal which is routed through the RF output to your television.

There are some hacks to restore stereo sound on the 2600, and even install two speakers in the case. Did you notice both the heavy and light sixers have grill holes for speakers? We’ll cover those in a future episode, so make sure you’re subscribed.

Each channel has three registers which specify the type, pitch and volume of the sound. The volume register is 4-bit giving you 16 steps of granularity, the pitch register is 5 bits giving 32 possible values, and finally the type of sound generated is set using the control register. Which is 4 bit and allows you to choose from several pure tones, or noises. Before we talk about the different types of tones and noises, it’s nice to see how those sounds are created. For many years now we’ve used wave forms of sounds or music in our games. Literally playing back recorded audio of the sound. Before that we had FM synthesis which used modulator and sine wave carrier oscillators to reproduce a wide range of sounds.

The ATARI 2600 uses another method. Linear-Feedback Shift Registers, or also commonly referred to as Polynomial Counters. If you’ve watched our previous episode on pseudo random numbers and Linear-Feedback shift registers then this will be very familiar to you. If you haven’t then I suggest you give it a watch after this episode. I’ll include a link in the description.

The shift register essentially generates the waveform pattern using individual bit’s, shifting one at a time. Pulsing either high or low, initiating the movement of the speaker’s cone which ultimately generates the sound we hear. The speed at which these bits are shifted are determined by which clock they use. Either based on the CPU Clock or the Pixel Clock, and the pitch value determines how often the bits will shift in relation to the clock, generating a wider or more narrow waveform.

Let’s have a look at the different sounds the TIA makes available to us. In theory the Atari 2600 has 16 sounds, but several of them are the same. In reality, we actually have only 9 distinct sounds.

Sounds 0 and 11 are a low noise that almost resembles a slight crackling or dust on a record player. Changing the pitch doesn’t seem to have any effect. Sound 1 is like a slightly gritty buzzer. Sounds 2 and 3 resemble a running motor with number 3 playing in a higher octave. Sounds 4 and 5 are a high pitched ringing tone, like a clarinet. Sounds 6 and 10 are a lower pitched buzzing tone, perhaps like a bass clarinet. Sounds 7 and 9 are a harsh bussing tone, resembling a game show buzzer. Sound 8 is a fast fluctuating noise. Maybe like a tractor beam. Sounds 12 and 13 are a high pitched tone, like a recorder. Sounds 14 and 15 are a lower pitched noise like a buzzer with 15 sounding more harsh and metallic.

Obviously the descriptions of the sounds are objective and you’re going to perceive them differently depending on how they’re used in a game. How would you describe them? Let me know in the comments.

Now that we know what the Atari 2600 is capable of, and the different sounds it can generate, let’s look at a pretty basic example.

For this we’re going to return to our bouncing ball code from the previous episode and add a sound whenever a collision occurs.

This one is a pretty basic example, but we have to start somewhere.

Let’s scroll to where we handle our collisions.

First we’ll load the accumulator with the value of four… and then store that into the channel zero audio Control, Frequency, and Volume registers.

We’ll then set a variable to store a value indicating if a sound should be playing or not.

It really is that easy to generate sound… but before we get too carried away, we’re going to want to be able to stop the sound or it’s going to get really annoying, really fast.

Let’s move up a bit to the start of our frame.

He’re we’re going to load our variable that will tell us if a sound should be playing. If the value is 0 then we already know there’s no sound, so we’ll jump ahead. However, if the value is one or greater then we’ll decrease that value by one.

Then we check if the result is greater than one and the sound should still be playing, if it is then we’ll jump ahead. If the result was zero then we’ll load A with zero and store it in channel 0’s volume register which turns off the sound. When we compile and run our code, it looks like this.

Makes our game a lot more interesting when we can actually hear the ball colliding with the walls. With this sound, you can perceive the ball being small and metallic or glass, adding a whole new dimension to your game using simple sound cues..

Let’s clean up the code a bit and extend this to other areas, with more sounds, and use the second channel. First we’re going to start out by defining some sounds. For this we’ll use a data table. You can call them byte tables, byte arrays, whatever you want. I probably call it something different every time. If you have a preferred nomenclature then please let me know if in the comments below and maybe I’ll start sticking to a ubiquitous language. We’re defining 4 different sounds with one table for each register, and another to define how many frames we want the sound to play. The bytes in each table represent which sound we’re going to play. One for bounces, reset, previous arena, and next arena.

Next we’ll define a subroutine to set up a sound to play.

This subroutine takes in two parameters, y selects which of the 4 sounds we want to set up, and x determines which channel we want to play the sound.

We’re going to load the accumulator with a value from Sound Bank Type by using y as the offset. What this does is starts at the address defined by Sound Bank Type, and then moves up by y bytes.

For example, If Sound Bank Type is at address F200, and Y is 2, then we would load the value of the byte located at F202 into the accumulator.

We do the same for storing our byte in the accumulator into the Audio Control register, but this time we’ll use X as the offset. If X happens to be 0, then it would store the value in the Channel 0 register. If X is 1, then it would store the value in to address which is one byte after the Channel 0 address, which would be the Channel 1 address. We continue to use this pattern for Volume, Frequency, and Sound Length, before returning execution back to the caller.

Now let’s have a look at how we call the subroutine…

Our code is a little easier this time. All we need to do is set the channel in X, and which sound we want in Y. Since we’re supporting two channels in our game, we had to review our code to stop the sound when it’s time runs out. For this we created another subroutine.

The logic behind this is the same as the previous example. We’re going to determine if a sound is playing, or if it should be turned off. If it should be stopped then we set the volume to zero.

The difference is that we’re going to do this for both channels by using X as our channel offset. After we’ve handled channel 1, then we decrease X and handle channel 0. We then decrease X one more which brings it to zero where our branch instruction will let us out of the loop and return execution to the caller. Just like our previous example, we’ll check if we need to turn off the sound at the beginning of each frame. This time just calling our subroutine.

Bringing that all together, it looks and sounds like this.

This episode demonstrates online the fundamental audio capabilities of the Atari 2600. In future episodes we’ll do a deeper dive on how to create complex sounds, and even compose music for your game.

If you found the video interesting I’d appreciate it if you’d hit that like button and share this episode with your friends or online communities, like facebook, reddit, or discord. Anywhere retro gaming and programming enthusiasts hang out. If you haven’t already done so, subscribe to the channel and hit the bell to make sure you’re notified when a new video comes out… and finally… help keep history alive by supporting future episodes and becoming a Patron. I’m excited to start a larger project which will spread out over a series of future episodes. It’s going to be a lot of work and there’s lot’s of technical challenges to overcome. Details of the project and more will be made available to our supporters on Patreon as the project progresses. Your contribution is greatly appreciated.

Information on becoming a patron is in the video description.

That’s all for now, thanks for watching, and I’ll catch you later!

Back to top of page