skip navigation

Programming for Different World Regions on the Atari 2600


In this episode we learn about the formation and technical challenges of the 3 world broadcast standards and how you can program your own ATARI 2600 games to target one or more.

October 7, 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’re going in depth into the birth of television, the establishment of regional broadcast standards, and how ATARI 2600 games were made to handle this mess. That’s all coming up on this episode of 8Blit.

If you were the type of person that stared so intensely at the television screen while doing battle in Combat… that you could see the phosphor afterglow as the electron beam swept across the tube… and wondered how you could take control over the screen yourself… and make 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, your toilet and sink were teal, everyone you knew also had the tupperware pitcher with the push button sealing top in their fridge, and your friends would all come by to play Atari.

We’re well into the third season and our subscriber count keeps climbing every day. I’ve noticed over 80% of people watching each episode are not subscribed. I’d like to reach 2000 by Christmas, so if you like these episodes and want to keep seeing original content then please click on the Subscribe button. It really helps us out.

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 also joining us on Patreon. We have a couple of membership tiers… Pong Legend, and Pitfall Champion. Each is for only a few dollars a month, both really help to cover the costs of producing quality content for the channel.

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

Television has been around in some form since the seeds were planted in 1873 with a discovery which would lead to the invention of telephotography, a way to send images through a phone line. It went through several revisions, and major technological side steps until 1906 with a demonstration of a Braun Tube used as a receiver of the images. We would normally refer to this as a CRT or Cathode-ray tube.

The technology drastically changed from mechanical solutions that involved motors and spinning discs, to an all electric version which was first publicly demonstrated in Philadelphia in 1934.

Over the years, the technology and the groups researching it, used various names, like Iconoscope, Televisor, Televista, and eventually settled on Television. Most variations use the prefix tele, which means ‘far off’ or ‘distant’. As in “Telephone” meaning ‘distant sound’, and Television ‘Distant Sight’

With so many different competing implementations of the technology, the United States Federal Communications Commission established the National Television System Committee to create a standardized nationwide analog television system which resulted in the 1941 NTSC standard.

Up until this time, the broadcasted images were based on luminance, which we would refer to as black and white.. Which is not exactly accurate as there were different degrees of luminance, providing many shades of gray.

12 years after the introduction of the NTSC standard, the committee approved the NTSC “color” television standard, which retained full backward compatibility with the already existing black and white television sets. It managed this by retaining the existing method to display luminance and adding the color (or chroma) information as two subcarrier frequencies added to the luminance to form a composite signal.

1953 not only brought the NTSC color “standard”, but also color “television” sets into the home as well. However, the price of these sets were very high, and the available color programming options were very low. It was not until 1972 before all the US programming would be broadcast in color. By the late 80’s non-color television sets were generally abandoned.

Meanwhile in Western Europe, built upon its already existing International Telecommunication Union (or ITU) standard for black and white broadcasts, they established the PAL (or Phase Alternating Line) color broadcast standard in 1967. At the time they didn’t adopt the NTSC standard due to several reasons including poor existing electrical infrastructure. This resulted in the NTSC color subcarrier becoming susceptible to degraded amplitude resulting in color bleeding and distortion. PAL also uses a composite signal like NTSC, but it overcomes NTSC’s limitations by switching the phase of the color subcarriers on alternating scan lines.

A third standard began in France even before PAL was introduced. The SECAM standard started development in 1956, and stands for Sequential Color and Memory. Like PAL, SECAM was also built upon the existing ITU standard. Unlike PAL, SECAM treated the luminance signal as Green, and alternated sending a Red or Blue subcarrier on each scanline. In order to build a full color image we would need all three colors for each scanline. SECAM provided for this by including a circuit in the television that would copy and delay the previous scanlines Red or Blue color signal just enough to be added when the next scanline started. This allowed the circuit the ability to add the Red, Green, and Blue signal on each scanline to build a full color picture.

NTSC, PAL, and SECAM were the broadcast standards that covered most of the world. Atari would eventually release a version of the 2600 with a regional Television Interface Adaptor (or TIA) chip for each region. However, due to the differences in each of the standards, games would need to be programmed slightly differently for each region, and depending on the potential customer base in these regions, the effort put into modifying and releasing games… would vary greatly.

Let’s have a look at which standard dominated each region, along with the associated Atari 2600 technical specs. Later, we’ll dive into some code examples on how you can implement region specific programming.

The major countries that used NTSC were the United States, Canada, Mexico, and Japan. It runs at 60 Hertz, which provides a stable screen at 60 frames per second when using all of the 262 available scanlines. Of all the available regions, an NTSC TIA chip can display more colors than anywhere else, with 126 colors. The chart at the bottom shows the luminosity on the x axis, and the available colors (or chroma) on the Y axis.

PAL was dominated in most European and African Countries, Brazil, Australia and most of Asia and the Pacific. It runs at 50 hertz, providing a stable screen at 50 frames per second. PAL boasts a greater number of scan lines with 312… however, the available colors are lower at 104. I believe this is due to the way the color subcarrier alternates phase with each scanline, and probably some cost cutting when producing the PAL TIA chip.

Speaking of cost cutting, the SECAM TIA chip operates in mostly the same way as the PAL TIA. Running at 50hz, with 50 frames per second, and 312 scanlines. However, due to the complexity with SECAM’s subcarrier signal alternating the RED and BLUE values on each successive scanline, along with the need to store and calculate those values based on the previous scanline. The SECAM TIA can only produce 8 colors. As you can tell from the color chart below, the SECAM TIA is hardwired to generate these eight colors based on the luminance values which is normally the x axis.

It must have proven too costly to produce a SECAM TIA that is comparable to the PAL or NTSC versions, and the available market was limited to France, The Soviet Union, Madagascar, and a handful of some west African Countries.

The Atari 2600 doesn’t have region locks. Meaning that, except for the TIA chip, the internal hardware of the console is pretty much the same across all regions. A cart from any region, will fit into and play on a console from any other region. It’s left up to the software running on the cart to run correctly for the target region.

In fact, the Atari 2600 console doesn’t know what region it is, and there’s no way for your game to determine that. This means the programmers and publishers need to alter the code, assemble the ROM, and package separate versions for each region… and this is exactly what they did for many games.

So why would you want to make different versions of your game, for different regions. After all… these regions don’t exist anymore. Most of the world has already switched to digital, and CRT’s are getting harder to find with each passing day.

The answer to this question is probably the exact same as asking an Atari 2600 programmer why they write games in assembly language, for an over 40 year old game console… because it’s there, because it’s a challenge, and because it’s fun.

If you haven’t tried programming for the 2600 yet, or think it’s too hard, then I encourage you to check out the first episode in the series and get a development environment setup. All our episodes come with fully commented examples demonstrating the code and concepts, so you can mess around with it on your own.

I know many of our viewers will be surprised just how easy it is to get started.

There are several technical factors that affect your game in different regions… (1) The number of scanlines. If you plug in a NTSC cart into a PAL or SECAM console, you won’t be generating enough scanlines. This will result in an unstable, rolling or flickering screen. Likewise for PAL or SECAM carts in NTSC consoles. (2) The colors you choose for your game. If you plug a PAL cart into a SECAM console, all the colors will be wrong, and in some cases, everything might end up being the same color. A trick you can use for this is to choose the color for your PAL carts so all the game objects have different luminosity, this will ensure they will be represented as different colors if it’s plugged into a SECAM console. And vice versa. (3) Game play will be slower… or faster. NTSC runs at 60 hertz while PAL and SECAM run at a slower 50 hertz. This can drastically affect gameplay, making an exciting game on NTSC feel boring on PAL and SECAM. Likewise, a PAL or SECAM game could be impossible to play on NTSC. There’s ways to account for this difference in your programming, so your game will run at the same speed in any region. We’ll be covering this in a future episode when we talk about ‘Time Slicing’. Make sure you’re subscribed to get notified when that episode comes out. (4) Sound is slower… or faster. For the same reason as the previous point, the sound and music on PAL and SECAM games will be a slightly lower pitched. Again, you may be able to account for this in your programming by adjusting the pitch you’re using, but you won’t be able to get it exactly the same as NTSC. So it’s up to the programmer to determine if it really is a problem.

Let’s have a look at our next example code, but targeting NTSC in a way that we’ve shown in some of our past episodes. In our Vertical Blank, we can see here that we’re loading X with an immediate value of 43 and storing that to our 64 clock interval timer. This would give us 37 scanlines. Down much further is our Overscan, where we do the same thing, except we set our 64 clock interval timer to 35 intervals, giving us 30 scanlines. Our kernel in this example is a 2 line kernel. Meaning that each loop in our kernel will produce 2 scanlines. We set up our kernel loop with an immediate value of 96 into the address of pf_count. Our Vertical Sync uses up 3 scanlines, so if we add that to our 37 scanlines of Vertical Blank and 30 Scanlines of Overscan, that leaves us with 192 available scanlines for our NTSC frame which should consist of 262 scanlines. Since we’re using a 2 line kernel, we divide 192 by 2, giving us 96. Our kernel will simply countdown on each loop until it reaches 0… Let’s run our code and see what it looks like.

Hardcoding the timing values works when you’re only targeting a single region, but let’s have a look at what we can do to make it a little easier to modify for assembling into individual ROM for each region.

This code is exactly the same as the previous example, with two major exceptions.

Instead of using immediate values buried in our code, we’re going to switch to using symbols to hold our region specific values. Symbols don’t get assembled into opcodes as instructions in your ROM. They’re used by the assembler as placeholders for values. Anywhere in your code where you use the symbol, the assembler will replace it with the value you assigned. In essence, this example and the previous example will be assembled into the exact same binary rom. All we’re doing here is making it easier for us to change.

Here we can see the same timing values we used in the previous example, but this time assigned to symbols. One additional thing we should explain is the PF SEG HEIGHT symbol. This is used to determine how many scanlines tall each line of the playfield lines is going to be for NTSC. We have it set that each playfield segment will be 4 scanlines tall. On each scanline we’ll just shift right until it’s zero and then start again. We added this as a symbol because if we’re going to target PAL or SECAM, we want to extend the height of the playfield to fill the additional number of scanlines on the screen, and this just seems like an easy way to do that.

We also defined some additional symbols to represent the different colors used for our game objects. This will make it much easier to customize colors for each region.

Scrolling down to our vertical blank.

Here you can see how we use the symbol. In this case we’re still assigning an immediate value to x and assigning it to an interval timer, just like we did in the previous example.

This time, however, it’s easier to read, and easier to change. Since this would assemble to the exact same ROM as our previous example which was NTSC… Let’s change this one to target PAL.

We’re going to need to calculate our timing values again to match the PAL standard, but this time we’re going to play with the numbers a little to better fit the playfield.

Let’s update VBLANK to 43 intervals, and increase our total Kernel height to 120 loops which would be 240 scanlines. Overscan is going to be 35 intervals, and we want to make each block of our playfield to be 10 scanlines tall. This will give us a stable PAL screen. Now we deal with the color values. Let’s look at a side-by-side comparison of our current colors we’re using for NTSC… but running on a PAL console. They’re completely different, and worst of all… one of the balls is missing! We’ll need to select color values that are closer to how it looks on NTSC. This looks pretty close, and at least we can see both balls now.

Using symbols for managing our region settings works great… but we can make it more… better’er. The assembler’s pre-parser that replaces our symbols within the code, also has the ability to use conditional statements. Like IF and ELSE… and these can be used to selectively include or exclude certain portions of code based on whatever condition you want.

Let’s see what we can do with this.

First we’re going to add a new file to our project. We’ve named it ‘build.h’. In here we’re going to add all the region specific logic so we have it encapsulated into a single file that’s easy to modify. To link the new file to our code, we just add it in as an ‘include’ file within our main code. To start off our build file, we define symbols for all the different regions we want to support. We’ll use these as ENUMS so we don’t need to use quotes in our conditional statements. As you can see here, we’re defining a region called PAL underscore SECAM. We could use this to handle a case where you don’t want to create two different ROMS for these regions, but you want to define colors that look good on both. Normally we wouldn’t think you’d create a ROM for all of these regions. Either you make a separate ROM for each, or you adjust your PAL colors so they also work for SECAM. We have this in-between region here for demonstration purposes to show the different options available to you.

Now we define a symbol to represent which region we’re targeting… We’ll start again with NTSC. With this in place, we can use it with IF conditional statements… In the first IF statement, we’re going to handle the screen timings. Since PAL and SECAM use the same timings, all we need to do is check if it’s NTSC, if not then it uses the PAL and SECAM timings.

We did something a little different than we did in the previous examples. Here we’re not defining the values by the interval timer counts. We’ll define them by the number of scan lines we want, which is easier to visualize. Down below we’ll use the assemblers preprocessor to define additional symbols which will automatically calculate the interval counts for us. It’s these symbols that we’ll use in our code.

Next, we’ll define the color values for each of our regions… and write something to the console to communicate back to us what region is being assembled. We can use the ECHO statement which will be invoked during the assembly process and appear on the command line, or within your IDE’s output window. Lastly, we want a bit more feedback from the build, so we’ll output the timing information as well.

In order to assemble the ROM, we need to go back to our main assembly file. The assembly output looks like this, with all the information we wanted to display, and our game looks, and runs correctly for NTSC.

Now, if we go back to the ‘build’ file. All we need to do is change the REGION symbol and re-assemble the code. Let’s have a look at PAL Now let’s try SECAM… since SECAM and PAL have the same number of scan lines per-frame, the emulator doesn’t know which region this is for so it defaults to PAL. Since SECAM’s 8 colors are assigned to PAL’s 8 luminosity values, it displays in black and white on a PAL console. We need to tell the emulator to switch to SECAM. For Stella on windows, we do this by pressing CONTROL ‘F’.

Not much of a color scheme, but we make due with what we have, and it’s perfectly playable.

As we saw, the SECAM cart playing on PAL was in black and white. This is not technically because it’s a SECAM cart. It’s because the values we chose for SECAM was the first chroma color. Which on NTSC and PAL would be black and white. We did this to reinforce the concept that SECAM’s ‘chroma’ is based on the luminance value… and if you want to target SECAM, you’re going to need to put some thought into the colors you choose, or more specifically the luminance.

As an example, let’s compare how the PAL ROM looks when running on a SECAM console… Here’s a PAL console… and here’s a SECAM console. Just like we saw in a previous example when we couldn’t see one of the balls at all, this time we can barely see the white ball!

This is why we created the additional REGION option of PAL UNDERSCORE SECAM. If we switch over to that ROM we can see that the PAL colors are… pretty close to our PAL only ROM…. but if we plug our cart into a SECAM console, we can still see all the game objects nice and clear.

Ultimately, it’s up to us to decide if you want to take on this additional challenge. These regions don’t exist anymore, but the hardware still does. It would be nice to preserve this interesting period of history in the way that future generations can experience.

Before we end this segment, let’s make one more change to our ‘Build’ file. Creating all these ROM’s over and over again for testing, and capturing video for this episode was tedious, so we extended the code a bit to make it a little easier. This will help you build ROMs for all your supported regions all at once. Let’s have a look.

We’re going to add a reference to a new symbol called REGION PARAM but we’re not going to assign a value to it, so it looks like an undefined symbol to the assembler. Normally, the assembler would throw an exception if it encountered an undefined symbol, so we’re going to wrap it in a conditional statement to check if a symbol is not defined. If it’s not, then we set the REGION to our default, which here is NTSC. However, if the symbol is defined, then we’ll set the REGION to that value.

Now all we need to do is define REGION PARAM, but we’re not going to do that anywhere in our code. We’re going to define the symbol on the command line when we assemble the code.

Let’s have a look at this batch file we created… we’re executing the ‘dasm’ assembler four times. Once for every region we want to build. We’re passing the file we want to assemble, the format we want it assembled in (which in this case is RAW format). ‘V’ is verbosity level, which is how wordy you want the details of the assembly to be. We’re only interested in error messages so it’s set to zero. Next is what we want to name the assembled ROM. We have a different name for each region so they don’t get mixed up. Lastly, we use the ‘M’ parameter which allows us to define a symbol. This is where we define REGION PARAM along with the enum value to use.

When we execute the batch file it assembles the 4 ROMs, 1 for each region. Along with showing use the timing information in the output.

The ATARI 2600 was manufactured for 3 of the world’s leading broadcast standards. NTSC, PAL, and SECAM. While the technologies are different, the hardware was almost exactly the same. This left a lot of the responsibility on the programmer… but it also gave the programmer a lot of power in how to distribute their game to these different regions.

All the code for this episode is available from our Github. We’ll provide a link in the episode description. If you found the episode interesting I’d appreciate it if you’d hit that like button and share this with your friends and online communities, like facebook, reddit, discord… or anywhere retro gaming and programming enthusiasts hang out.

If you haven’t already done so, please subscribe to the channel and hit the bell to make sure you’re notified when a new episode comes out… and finally… help keep history alive by supporting future episodes and becoming an 8blit Patron. These episodes are a ton of work and your contribution is greatly appreciated. Information on becoming a patron is in the episode description.

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

Back to top of page