Updating an 8-Bit Game, 35 Years Later

In 1990, a computer magazine published a game I wrote. It was a big deal for teenage me.

There is now a thriving “retrocomputing” scene, with people making new software and hardware for computers like the Commodore 64 and Apple II. I decided to update my old game, and experience what developing for these classic machines is like now.

The Game

In August 1987, Compute!’s Gazette published Bounty Hunter, an educational game in which you chase a bad guy around the U.S. It was played on a map that flipped between east and west halves. I thought it would be fun to do a similar game with countries, played on a scrolling world map. Compute!’s Gazette published that game, International Bounty Hunter, in March 1990.

The Challenge

My goals for the 2025 edition:

  • An updated map, of course. The original had 2 Germanies and a Soviet Union!
  • A bigger map.
  • Make it run on the Commodore 64. The original was written for the C128, using BASIC 7’s new graphics commands. But I want this to run on the real hardware of the best-selling personal computer ever.

Can I do it with my rusty 8-bit programming skills?

Just for context: when I developed this in 1989, there was no World Wide Web (the first web page went online in late 1990). There were bulletin-board systems (BBSes) but participating in one would have meant a modem call to Winnipeg. Computer class in school was just typing, so learning programming was a solo exercise, using magazines and books.

A boy and his C128

The Data

How I made the map in 1989: I photocopied a map onto graph paper and colored the squares with markers. Which got the aspect ratio wrong, incidentally, because the characters on the C64 aren’t square. 🙄

How I made the map in 2025:

  1. I downloaded a shapefile from Natural Earth.
  2. The original map looks like a Robinson projection, so I projected the new map the same way: ogr2ogr -f "ESRI Shapefile" -lco ENCODING=UTF-8 -t_srs "ESRI:54030" projected_map.shp.zip /vsizip/ne_110m_admin_0_map_units.zip
  3. I used Python libraries Fiona and Pillow to draw the shapes into a GIF.

I mostly re-used the country colors from the original game. For the countries in the Balkan Peninsula and the post-Soviet states, I used a greedy graph coloring algorithm to assign new colors.

How I got the routes between countries in 1989: I looked at a map and listed the connections by hand.

How I got the routes in 2025: I used the The World Factbook’s list of land boundaries. There’s some commentary mixed in with the data, but with a small amount of cleanup the list can be parsed with Beautiful Soup.

I asked ChatGPT what the main hub for international travel is on each continent. It told me: Atlanta, São Paulo, London, Dubai, Johannesburg, Sydney, and Tokyo. I allowed shortcuts between those hubs wherever you could draw a line over just ocean.

In the original game, your starting point—the country you’re “working for”—was random. I’m a tad uncomfortable even “pretend-working” for some unpleasant regimes out there, so in this update, you work only for countries rated “Free” in the Freedom in the World report.

The Code

This time around, I am developing on a Mac with the VICE emulator.

What language to use? I considered compiled BASIC, but opted for the cc65 C compiler. My C skills are rusty, but not as rusty as my BASIC!

I mentioned that I want a bigger map. Will I run into memory limits? The original map was 192×101, but for the correct aspect ratio it should have been 266×101. That already multiplies to 26,000, and we only have 38K for the program and data combined. Storing 2 color values per byte (Commodore computers have only 16 colors) is a quick way to cut the map’s bulk in half.

I began with the map drawing code, which would be the hardest part because it needs to be fast. Specifically, it must run in less than 1/60 of a second.

Why? The C64 used a cathode-ray tube monitor, where an electron beam races from the top to the bottom of the screen, lighting up pixels as it goes. If you’re modifying the whole screen—for example, to redraw a map—then you really don’t want to be drawing where the electron beam currently is, because that produces nasty flickering effects. Ideally, you want to follow along behind the beam, making your screen updates, ready for when the beam returns to the top of the screen.

The screen is redrawn 60 times per second. On a 1 MHz computer, that means I get about 16,666 clock cycles to retrieve the color data, unpack the 2 colors from each byte, write them to the screen, and handle loop counters.

As a baseline, drawing the map using C with nested loops (rows & columns) and *dst++=*src++ style copying takes around 210,500 cycles.

My final version, written in assembly language, comes in around 14,900 cycles. The speed was achieved with 3 techniques:

  • Loop unrolling: I do just 2 loops, one for the top half of the map and one for the bottom half.
  • Self-modifying code: Typically, to retrieve data from dynamically-allocated memory, you would use indirect-indexed addressing: LDA ($addr),Y. Indexed absolute addressing is faster, but to use it you have to know the memory addresses ahead of time and hardcode them. Or, calculate the addresses and insert them into your code on the fly. Self-modifying code sounds dangerous, but cc65 has macros to help make the code readable and the operations safer.
  • Counting down: I loop right-to-left across the screen. If you make your loop variable X go from 0 to 40, then after each INX (increment X) you have to compare to 40 to know if you’ve hit the end of your loop. But if you go from 40 to 0, then after each DEX (decrement X) you don’t have to compare to 0: DEX has a built-in check of whether it has hit zero. That saves one compare operation for every step of the loop.

You can measure speed using the stopwatch and breakpoints in the VICE monitor, but there’s a more fun way to do it. There’s a trick where you change the screen border color as your code runs, and the width of the color stripes shows you how long your code takes:

Scrolling the map is potentially a faster operation than drawing it from scratch. Scrolling is mostly just shifting data that’s already on the screen, and you only have to retrieve & unpack new data for the edges. Maybe that can be an exercise for 2026 🙂.

The other speed concern is the C64’s legendarily slow disk drive. I want to minimize the map size and the number of disk operations to read it. As in the original game, I compressed the map data, using run-length encoding for its simplicity. I tried a few variations of RLE. The one that worked best on this data: any byte with the high bit set to 0 is a color, any byte with the high bit set to 1 is a count between 3–130. I use only 2 disk reads: read 4 bytes to get the map dimensions, then read the remainder of the file in one go, using the same memory allocated for the map as the read buffer.

With map scrolling and disk I/O done, the rest of the program logic is simple:

And here’s the game: ibh2025.d64. Not much explanation is needed for playing it. You can generally jump along island chains and from islands to the nearest large landmass. Some tiny countries are missing. Some countries are abbreviated to save your poor typing fingers (like USA and DRC). You can type HELP or HINT or simply press Return to get a suggestion on where you can go next.

So how was the experience of coding for the C64 now? It was fantastic being able to write in C, build with Makefiles, debug with the VICE monitor, and browse advice on Lemon64. I was shocked how many details about the C64 sprang readily from my memory like 1989 was just yesterday.

The C64 is a classic for a reason: a powerful but affordable and friendly computer that savvy programmers pushed to do amazing things. I feel privileged to have grown up in the era of those machines and I am delighted that a community of enthusiasts is keeping them alive.

I’ll close by saying I’m still kinda proud of how teenage me captured those cartoon characters as sprites!

Map Technology Then & Now, Part 1: Chasing Bad Guys on a Commodore 128

When Google Maps first appeared, I remember reading a popular-press-type article that disparaged geeks for getting so excited about a program that draws maps.  That sentiment made me chuckle, but it also made me realize that I have been intrigued by the combination of maps and computers for a long time.

Compute!’s Gazette March 1990 coverThis is the cover of the March 1990 issue of Compute!’s Gazette, a magazine dedicated to the Commodore 64 and 128 personal computers.  On page 26 is a game called “International Bounty Hunter” in which you, the bounty hunter, pursue a bad guy around a world map, moving from country to country by typing in the name (easy setting) or capital city (hard setting) of an adjacent country.

The world map was too large for the screen, so the map had to scroll as you moved around. The map-scrolling code marked my first foray into assembly language; BASIC was too slow for the task. The map itself was run-length encoded to make it easier for the magazine subscriber to type in.  (Yep, type in: that’s how we rolled back in 1990.)

International Bounty Hunter screenshot

I can still play it in VICE!

It was a fun little game, and playing it so much while debugging had an unexpected side benefit: I dominated capital city trivia questions on my school’s Reach for the Top team.  🙂

That game was the beginning and end of my illustrious career as a game designer.  It was also the last time I looked at computerized maps for a while… until 2003, when I decided to create a Virtual Races website for my running group, and I would get to see how far that map tools available to the hobbyist had come.

The world map that I digitized by hand for the game. Look, it’s the Soviet Union! And two Germanies!