Ah, NES. Good old NES. Who can forget the brilliant classics (not including Action 52) that thrived in that unassuming grey box? The revolutionary platforming of Super Mario Bros, the mind-boggling difficulty of Ghosts n’ Goblins and the rage-inducing level design brilliance of Castlevania all lived out their memorable lives in the labyrinth of transistors that grey box stored. The NES was, quite simply, a part of millions of childhoods.
But do not be fooled. While the NES was simple, the games were most definitely not. In fact, the greatest challenge for developers may have been this simplicity. The NES was simple. Too simple.
Nowadays, adding a few more megabytes worth of textures or sound effects is trivial. Hard drives are expendable. Memory is cheap.
Nowadays, adding a recording of speech or a complex sound is simple. Speakers are powerful. Sound channels are intricate. Data transfer is fast.
Nowadays, displaying another sprite on the screen is straightforward. Graphics cards are effective. People can buy better components. 3D is possible.
In that unassuming grey box, the labyrinth of transistors is another story indeed.
Storage is Expensive
In the NES, memory is a scarce resource that developers had to take into consideration.
The cartridge is probably the most obvious example of this. The game cartridge had to somehow hold all the data of your game, from start to finish. That included all art, levels, sounds, music, NPC AI and more. Unfortunately, the average game in NES days usually had to fit anywhere between 64 and 512 kilobits – no mean feat, to be sure. Nowadays, a game can span several gigabytes and still be completely playable.
To put this into perspective, take a look at this adorable fluffy photo:
This photo is about 256 kilobytes worth of data. In comparison, take a look at this Legend of Zelda (NES) ROM; it’s only 64 kilobytes. That means you can fit around 4 Legend of Zelda’s in the space of this photo alone. Alternatively, consider the fact that it would take 4 NES Legend of Zelda cartridges to contain this lovely kitten’s face.
Yeah. Memory was tight. So developers had to be smart about it.
Many strategies were used:
Hardware level programming.
Because of all these constraints, the unnecessarily large programs produced by compilers were completely insufficient, as memory was much tighter and compilers were less effective for such specific platforms than today. Thus, many programmers found themselves writing assembly code directly, having to be aware of the NES’s hardware and bottlenecks to a tee. Of course, this led to simple tasks today like getting a sprite to move across the screen being far more intricate (more on that later).
The mentality of programming in such an environment is completely alien to any game programmer today; rather than writing more code to be more readable and structured, lines of code had to be reused as much as possible. Constants and arrays were dangerous; finding a subroutine to generate the array is much better. It was not a matter of simply optimising performance and memory consumption; it was a tight balance between CPU power and the size of the program itself. (It should be understood that this mentality was natural for game programmers of the day, as many came to game development through hardware work or related hardware programming / electronics disciplines.)
Oftentimes, developers would find themselves rewriting libraries from the ground up that they needed. Why does abs() cover so many different types of input? I don’t need that – if I rewrite it, I get 20 whole bytes back! Linked lists, draconian stack management, and sacrificing your soul to the pointer gods were expected. 8 bit data paths wasted less memory than, say, 16 or 32 bit, as if you only need 3 bits you waste 5 in an 8-bit path architecture rather than 27 in a 32 bit path.
Data compression seems obvious, but is so fundamental to the NES programming mindset that I feel it needs to be emphasised. Data is beyond important, and using it sparingly is likely as important – if not more so – than even good game design (or for some developers, any game design!).Let’s take another look at Legend of Zelda for the NES, as it is a brilliant example of well-used memory space. Here are some levels in the game:
Scratch that. Here are all the levels in the game.
These levels are crammed into the smallest grid size, which is the first most notable optimisation. The overworld and half of each underworld is 16×8 screens; 128 such screens in an overworld, and 256 for an underworld. (Remember that Legend of Zelda had a set number of screens that were transitioned between, like Megaman.) This means that 4 bits x 4 bits is enough to store which screen Link is on, one bit of the Y coordinate not used in the overworld. Also, take a look at the indigo upper-left part of the second underworld, which was supposed to be an ‘L’ shape in ‘Zelda’. It does not fit in such a constrained space; the bottom of the ‘L’ was instead nestled into the side of the ‘Z’ and a portal to those rooms was placed at the bottom of the remainder of the ‘L’ room. Several other such transformations had to be made to the map as well, in order to maintain this grid constraint.
Inside each screen, a room will have 16×11 tiles, much like the grid of the overworld overall. Each screen can have up to 3 tile types besides bare ground out of < 16 possible types, so 4 bits can be used to store a type of tile. Each screen has a preliminary 2 bytes holding 3 such ‘nibbles’ of data, meaning each tile only needs 2 bits to identify which of the 4 tiles it holds (bare ground / 3 possible extra). That means each room only needs 2*8 + 16*11*2 = 386 bits = 46 bytes. 46 bytes. That means the overworld only requires 128*46 = 5888 bytes, which is just five and a half kilobytes. Overall, with even more ingenious techniques used in the underworld (derived from the fact that no two obstacles are in the same screen and that each screen only has two main colors), the entire collection of levels spans only 8 kilobits.
The perceptive embedded systems programmer would note many a similarity between writing embedded software and writing NES games. Nowadays, the similarity is almost gone, but the skills were relevant back then.
It is interesting to note how game design was heavily influenced by memory constraints. As levels had to be small and games short, game developers had to artificially make these smaller games hold more playtime in various ways. The easiest of these was introducing a high difficulty curve; enemies were faster, levels were complex and player abilities were limited. The best examples of this are Contra, Castlevania 1 on the NES and most notoriously Ghouls n’ Goblins. The last game, in fact, did this with such fervor that the second half of the game was just the game repeated with tougher enemies! This, of course, was not a favourite moment of the NES players of old.
Sound is Primitive
Sound is probably one of the most, if not the most, underrated aspects of video game development. Many a brilliant composer or sound designer have been ignored in the face of beautiful art, writing or game design. Normally, the challenges faced by sound engineers may include making sounds descriptive of a particular effect or event, realistic if a real-world sound effect and aesthetically pleasing.
For sound engineers in the NES days, the challenges were even greater. Sounds had to fulfill the constraints of the limited NES system, including the aforementioned lack of storage space and the somewhat primitive NES APU (Audio Processing Unit). The APU has a measly 5 channels: two pulse wave generators, a triangle wave, noise, and a delta modulation channel for DPCM channels. This introduces a number of subtle problems:
Sometimes, sounds would cut each other out. As music and sound effects had to play on the same channels, one sound being newly played could take a channel from currently playing music to be heard. This meant that the quality of the music could wildly vary as numerous sounds were played. Thus, sound had to be used efficiently, and countless sound effects were not cheap to play at once. Note how many NES games will drop bass, drums or harmony of the melody in favour of cramming in more sound effects.
By having so few channels, the quality of sound was very low. This, of course, was not so much a negative constraint as it was an introduction of a new kind of music, and brought 8-bit music and sound to the fore. Many well-loved pieces of music, such as the classic Dr. Wiley’s Theme from Megaman 2, would not exist, and the music style of ‘chiptune’ was founded.
The second point raises an important fact: the NES was almost defined by its hardware constraints, and in many ways, gained its unique retro feel from these constraints. In a way, many consoles were defined by the power of hardware they had, such as the ’16-bit’ era, the pre-rendered 3D images of Donkey Kong Country, and many more.
Sprites are a Bottleneck
Art, on the other hand, is one of the easiest aspects of a game to appreciate; the mastery of an artist is quickly noticed, and their command over the brush (or the pixel) can decide the aesthetic beauty and atmosphere of a game. Art will also decide how convincingly menacing the enemies are, how obvious the player’s walk cycle is, and how alluringly valuable the treasure at the end of a dungeon is to the green-capped adventurer who dares to go alone.
On a screen, as is now to be expected, the hardware is our enemy. As with sound, though, note that the uniqueness of NES games is partly from the low-quality ‘pixel art’ graphics capabilities provided, and opened up the possibility for this new art style.
The constraints on graphics were as follows:
Even the simple concept of color was a concern. The NES supported only 64 different colors. On top of that, only 25 can be displayed on the screen at a time.
This is, obviously, a severe issue. Games had to make the most of a few colors on the screen, which in and of itself led to a variety of interesting design decisions. For instance, the original Castlevania chose particular groups of color that strongly contrasted with each other, namely orange and blue.
Orange and blue complement each other, and thus the platforms and player are distinct against the background; despite a ledge apparently being beneath the player in the picture above, anyone playing would recognise that they would fall through, as the image is not an orange platform. This was an effective way to make use of a small subset of the colour palette for a particular ‘platforming’ section.
I’ve said it before and I’ll say it again – memory was the game developer’s water in the Sahara Desert. Scarce and necessary. That goes for graphics memory, too. Take a look at this snapshot of NES video memory from Megaman:
On the left is the background data. On the right is movable 8×8 tiles. Note how much memory space Megaman’s sprites take up; they all need to be in video memory so they can be accessed quickly, as Megaman hops between his different animations. Thus, any massive boss can’t hope to be stored in such a small remaining memory space. The workaround is an interesting one: make the boss into the background, and have a black background. Then move the background around, so that the boss moves. It worked, and worked with splendour; the black background certainly put a special focus on bosses in their epic bouts with the hero.
Again, it is interesting to note that these constraints defined many memorable design choices in NES games of the day.
All in all, the NES was one nasty piece of work – or lack thereof – for any hardware-phobic developer. This, of course, is due to the constraints for the product’s pricing and level of technical knowledge available to hardware developers at the time.
In any case, the game developers we revel to this day prevailed in the face of technical obstacles, and deserve even more praise than they already have.
Simplicity is a strange thing. Sometimes it is a boon. Sometimes it is a punishment. Sometimes, though, it is the breeding ground for fond childhood memories.