When I was a kid I played a lot of NES games. As I started learning how to program games myself, I always wondered what kind of magic it must take to make these games that I loved so much. Even once I had learned enough to be able to think about how I would approach programming any of these games, I still imagined that the REAL games must be so much more advanced than any lame design that I could come up with. I seemed doomed to forever wonder about something I had no means of ever finding out.
A number of years later I had gotten really interested in console game emulation and had been working on an emulator to play NES games on my Playstation 1. Part of the process of developing that emulator was to become gruelingly familiar with the machine code of NES games so that I could diagnose problems that the emulator had with various games and fix it. At some point it hit me that the thing that made my favorite NES games tick was not some kind of abstract magic, but the very concrete sequence of numbers that I had been staring at every day for months. I was so excited – how long could it possibly take to study these hundreds of thousands of numbers and finally find out how these NES games were programmed? Turns out the answer was quite a long time, but luckily one thing that I had in spades when I was younger was free time.
So began my hobby of reverse engineering old games which I’ve worked at with varying levels of commitment over the years. Today I’m starting a series of blog posts in which I want to document what I’ve learned about the games, from a game programmer’s point of view. I’m going to try to focus on how the game systems work at the game/engine level and not at the hardware level (so more like how does this game decide which things it wants to draw on this frame as opposed to how do sprites work on the NES.) I’ll also try to throw in any tidbits about the games that I think are interesting like things that weren’t obvious to me just from playing the game casually or instances of bugs in the game’s logic.
The first game that I’m going to write about is Contra on the NES. The remainder of this post will be a short overview of the objects and data that exist in a game of Contra and then subsequent posts will go into more detail about each system the game uses to manipulate its model of the world. The basic model that the game maintains is made up of:
- Player characters
- Player bullets
- Enemies and other objects
- Level data
The player characters are the main heavyweight objects of the game and have lots and lots of code that explicitly deals with them as you might expect. The bullets from player characters are treated differently from every other kind of object in the game for reasons that are probably performance related. We’ll see later on how the player bullets being separated out from the other game objects makes various things the game has to do more efficient. The final class of objects are the enemies which are managed by a simple entity system. This includes the enemies themselves along with enemy bullets and explosions, but also a couple of friendly things like flying power-up balloons and power-ups sitting on the ground. I’ll use the term enemies to refer to all of these things just to have a more descriptive term for them than “objects.” The key feature is that there is code in the game that deals with them abstractly as opposed to the player characters and player bullets which are always manipulated by specialized code.
The tile based level data is the final major part of the game simulation. Contra features standard horizontal levels along with a vertical level and pseudo-3D levels. Levels only support moving forward through them, never backwards. The game maintains a double buffer of tiles that hold collision and visual data for the current screen in the first buffer, while it builds the next screen in the second buffer. We’ll see later on how the level data is organized, how it is updated as you make your way through the levels and how enemies are spawned from it.
I have a rough outline of where I’d like to go from here with this series but it’s still very much a work in progress. Topics I have ear marked to talk about include data representations, enemy behavior, scrolling, collision detection, random number generation, player control and other assorted things. I’d love to get feedback about what people might be interested in going forward. You can leave a comment below or reach me on twitter @allan_blomquist