How ‘River Raid Squadron’ Came to Be... Eventually

River Raid old-vs-new comparison

It began at a game jam. No, wait. It began when I was 12 and asked a friend, Joey, to play River Raid with me. I was sure it had a play-together mode. It didn’t.

Now... fast forward to the game jam decades later. It began again at a game jam. Not because of the jam directly, though. Maybe more in spite of it. January 24th, 2018, according to my earliest file dates... which sounds like GGJ (Jan 26-28) and it sounds like I got started a few days early. Sounds right. I don’t really participate much at GGJ. I don’t like their rules much. It’s okay, but not much. Jams also typically conflict with my weekly schedule so it’s hard to be a meaningful member of a team. But, I do like hanging out with my friends at jams and helping out when and where I can.

Anyhow, it looks like I came into the jam ready (not a jammy thing to do)... ready to finally hack River Raid into a co-op game. I didn’t imagine I could finish it in a few days, but I wanted to see how far I could get. I had thought that Thomas Jentzsch’s decompiled and commented 2600 code (written by Carol Shaw, not Thomas) would get me pretty far pretty quickly. First, to be clear, Thomas did a great job deciphering the code (and I’m sure it took a ton of work) but I expect he would be the first to tell you that it is far from complete. Yeah... that.

So, I didn’t get very far during GGJ. Actually, practically nowhere other than collecting some reference art and beginning some sprite art. I actually spent much of the time in a deep conversation with a friend. That seemed more important at the time... and still does.

Also, to be clear on another point, my goal here has been to do a legit port of the code, and not to produce just another game that merely looks like the original. Plenty of those around. This was not to be one of those.

2 years and 7 months later, and I finally release the prototype beta. Clearly, this is not my main project. For most of that period, that main project was GRITS Racing. Lately, I’ve been back at doing IT contract work. Oh well. Not young enough to work at a startup (I’ve applied to many). Not educated enough for enterprise. Not cool enough to work at a game studio. So, I take what I can get. Thus, I worked on River Raid Squadron only on the occasional Sunday afternoon – which is pretty much the only time I have for hobbies – of which I have many.

Factoid: I might rather have called the game River Raid Wingman, but that’s really hard to fit your mouth around. It wants to come out more like “Wiver Waid Wingman” so I went with Squadron instead (and River Raid Flight sounds odd even though it would be more correct). Besides, you never know when I might up this game to 4 or 8 or 28.6 players.

I’m guessing I have about 250 hours in this game (not counting last week – I’ll get to that in a bit). According to my notes, about 140 of that is just in reading and writing comments into the 2600 ASM source code trying to understand it. (I’ll make that code available for download as soon as I get to it.)

Factoid: I haven’t played this game with anyone yet... stupid pandemic forcing me to live alone and keep my wife distant and safe.


Aside from wanting to mod River Raid into a 2-player couch co-op game, I wanted to remaster the graphics (and sound, if possible) without changing the original gameplay. I believe in this kind of work. That is, I believe in remastering games while keeping the original gameplay.

River Raid is a masterpiece at showing off the capabilities of the Atari 2600. It plays to the 2600’s strengths while avoiding its weaknesses. The top-down player sprite and side-view enemy sprites may appear like a silly style clash but, considering how sprites are colored on the 2600, this was a good move (ignoring the absurd house sprite). It gave us a full screen of nice color. The vertical stacking of all sprites also helps this. But, really, it was probably the level generator for an endless shooter that won the day.

As such, the later ports that came to more-powerful systems and the changes that came to the game because of that, never spoke to me (not that we could afford anything but a 2600). They were valid attempts but, well, maybe you should just leave a masterpiece alone. Otherwise, you just might end up with a fish out of water.

So, here I am, messing with a masterpiece. Oops. Oh well. We’ll see if I do it right or not.

This brings me to the question: What to remaster the graphics to? Full color at low res doesn’t feel right. The perfect-and-bright, 256-color palette of later systems, and 320x240, felt like the max I could go to. But, realizing that I could probably publish my work on the 7800 (and be some sort of Atari hero for it – everybody wants to be some sort of hero), I decided to limit this project to the 7800 specs: funky 200-ish-color palette, 160x224, 3-color sprites, 13-color splash screen, etc.

annotated 7800 palette

Curiously, of the limits that I’m guessing I’m pushing on the 7800 (I don’t have any 7800 dev experience yet), it is what I have done with the ground/bank textures that I believe will give me the most trouble – if doable at all. I tried a couple solutions to this future problem in the game engine I’m prototyping in (GameMaker: Studio) and, well, it’s a challenge. Currently, I’m drawing this with a few hundred sprites 2 pixels tall. The 7800 can’t handle that. I tried really large sprites at first but the bank-sloping algorithm is too dynamic to work for that. Thus, the solution lies somewhere in between with some creative code and sprite data-space balancing. Or, possibly, with some tricky color switching on top of the old 2600’s playfield bits. (This applies to only the dark/jagged levels – the light/straight levels are more easily solved [assuming adequate data space].)

Regarding gameplay, there’s been a lot of back-and-forth thought here. How to make a single-player game interesting for two players without changing it much? Yes, many would find it great if I simply added another player and nothing more. But, at the very least, you need to work out scoring and extra lives. With two players potentially “stealing” points from each other, balance can go out of whack quickly. Thus, I end up in thought experiments of cascading effects with various changes and trying to find a new balance.

Ultimately, I decided to not change much and to share scores and extra lives. I then changed the bridge hit from a single hit to a double hit, but at half points each hit (reasoning is complex/fuzzy behind this and I don’t really want to try to explain it here). To up the interaction/conflict/conversation/cooperation between players, I added a fuel-balancing feature that balances the fuel between the player’s jets when they touch. Plus, some other changes to allow players to fly at different speeds (more or less) and other minutia I might insert here later.

All that was great... but I was still torn about accommodating various player types when analyzing them in my thought experiments. Some players are happy to share, assist, or simply go along for the ride. Others, however, are more aggressive while still being good co-op friends to play with. Consider Metal Slug and how it is co-op but still, basically, every man for himself. Thus, I added a second play mode (something I try really hard to avoid) that uses the player’s individual score (not shown) to award extra lives. The differences may not stop here, however.

I hope Carol Shaw and Activision are cool with fan mods to old games.

Sound design and unsound design

The Atari 7800 has a problem I didn’t know about until I started this project. It has only 2 channels of sound. Worse, those two channels are from a 2600 chip, the TIA.

Apparently, the original 7800 goals called for a new custom sound chip, the GUMBY. That was later canceled. Regardless, those were plans for a pack-in chip in the cartridge and not in the system itself. Why oh why? This left the system with just the 2600’s sound that was primarily there for backwards compatibility.

A couple games did include a POKEY chip from Atari’s computer line as a pack-in chip in their cartridges. The POKEY was (reportedly) not as great as what was originally being designed for the 7800 (and more expensive?), but it at least had 4 channels of 8-bit sound (with each channel better than a TIA channel), or 2 channels of 16-bit sound (or 2+1 channels).

So, this leaves me with questions and a new understanding about how maybe Atari got what they deserved (which I can admit in spite of my fandom). Why didn’t Atari make a slightly bigger motherboard to accommodate the POKEY or the GUMBY?

Maybe the public didn’t care about audio specs back then (and we probably didn’t much) but, as a developer, this is a hard sell. After hearing what River Raid Squadron sounds like with unlimited channels (I use 4 to 6 channels, peaking at around 10 in rare cases), it’s hard to imagine limiting a 2-player game to 2 channels. I really do not want to do that in my 7800 port! (I will likely target a POKEY or homebrew chip so I don’t have to... assuming I ever get that far.) I see a 6-channel minimum for 2 players (2 player + 2 enemy + 2 environment) but 4 channels would be tolerable.

Consequently, I wonder how many studios, when asked to port a 2-player game to the system, ran the numbers on the extra cost of the POKEY in their carts and were like “Yeah... we’ll get back to you.” ... I’m guessing that number is not zero.

‘GameMaker: Studio’ vs Linux vs Matt

Packaging a game for its first release is never easy. Lots of scripts to write and test (so that packaging later releases is easy). Both GM:S and Linux, however, made releasing this simple game much more difficult than any other (except for, maybe, jumping through the hoops at Steam with GRITS Racing).

First, came the challenge of Linux. This will soon be the subject of a blog post (below) to help future travelers on the same path... but I will hit some relevant points/rants here. GM:S makes a fair attempt at packaging for Linux, but not a great one. Certainly, not one that had any hope of lasting beyond their target Linux flavor and version. They should have seen that. Even back then (I use GM:S 1.4 which, annoyingly, was outdated as soon as I bought it !!?).

So, in a sheer push of frustration, I ignored my contract work for a week and burnt maybe 80 hours working out how to build a proper Linux release. I’ve seen the posts on other games built in GM:S1 asking for help running the Linux build of the game. I hear you! Help is coming. I wanted to solve this, and did. Many thanks to’s docs and Ethan Lee for showing the way. The gory details on that are in my blog post here:

From GameMaker To Ubuntu 14, 16, 18, and Beyond

More info on the Linux build in this devlog.

I also wasted a bunch of time on Linux trying to get my gamepads to work. They worked fine on Windows. But, actually, that was mostly my fault for not trying my older gamepads sooner... only to discover the older ones worked fine. My newer ones worked on Windows only because of XInput.

More info on that in this devlog.

Finally, I burnt another day with a bug in GM:S itself. Last-minute changes weren’t making it into the final build. I first found this on Linux but eventually discovered it on Windows too. Dev builds run fine but the final (YYC) builds do not. I found no help on this so, dunno, maybe I broke something unique in GM:S (maybe when I renamed my project because they name builds by folder name and not the name in project settings!), or few do YYC builds to ZIP. Eventually, however, I found the YYC build cache and saw that YYC builds never update it after first write. Thus, I have to manually clear it out before final build. Ugh. (I also found during this that GM:S set its temp folder to AppData\Local instead of AppData\Local\Temp, which is stupid, but that was much less of a problem to clean and fix.)

tl;dr (hidden at the bottom 😁)

This has been an enigma in many different ways. Not all bad though.

(Even GM:S is not all bad even though I trash on it a lot. I’m still upset about their bait-and-switch business tactics. I only used it for this project because I was too lazy to implement my own pixel-perfect collision detection. Most game engines don’t have that as most games don’t need it. The Atari 2600, however, has it, so I needed it. I actually started in GM:S, switched to Godot, then back to GM:S as soon as I realized there was no quick pixel-perfect-collision solution in Godot and other engines.)

Files 4 MB
Version 0.9.0 Sep 01, 2020 8 MB
Version 0.9.0 Sep 01, 2020

Get River Raid Squadron

Leave a comment

Log in with to leave a comment.