The NES: Cartridge Constraints
Constraints can be annoying. Being limited in what you are able to do is frustrating. But the great thing about constraints is that they force you to think of new, creative solutions to work around them, ones you wouldn’t ordinarily try out.
A common thing I’ll do in creative projects is use random generators to determine names, species, clothing, scenarios, whatever I need to make the project work. Once I’m given these immutable choices, it’s up to me to craft a story, design, or piece around them. It can be freeing to know what the limits are, so you can focus on the parts you can change.
The venerable Nintendo Entertainment System had such constraints. It had essentially the same processor, a 6502, as a Commodore 64/128, so it could only address 64K of RAM. The NES used 32K of that RAM for storing program variables and for things like controller input data, and the remaining 32K was used to load in code from the cartridge.
The NES also had a video card, a Picture Processing Unit (PPU), that could address 64K of RAM, but only had 16K for cost reasons. 8K of that was for graphics data – “patterns” that could be use to make UIs, maps, sprites, whatever – and 4K for “pattern tables”, used to store the map data. When you hear maps, think the backgrounds and (most) environment objects that Mario is jumping onto or in front of. Sprites are Mario himself and all the enemies, powerups, and so on. They’re special because they need to move anywhere on the screen, and quickly.
When the NES (or rather, the Family Computer or Famicom) was first designed, the cartridges it used were divided into two pieces. One part, PRG-ROM, stored the program code, and one part, CHR-ROM, stored the graphics data. PRG-ROM came in 16K increments, and CHR-ROM in 8K increments. Typically, the first and last 16K PRG-ROM chunks are made available to the CPU when you start up the NES, and first 8K CHR-ROM chunk, containing patterns for maps and sprites, is made available to the PPU.
Very simple games, like Excitebike, came with only 16K of code and 8K of graphics. This code and graphics data fit perfectly into the NES’s limited code-and-graphics RAM.
But what about the first NES game I ever rented, Mega Man 3? Well, that came with 256KB of code and 128KB of graphics data. Dr. Wily’s creations were Big Bosses, after all. How did that work when the NES could only manage 40K?
Once game manufacturers realized that 40K was not going to cut it, they did what Commodore did when you have processors that can only address a set amount of RAM and you need to expand:
They hired memory magicians!
These magicians, known as Memory Management Controllers or mappers in the Nintendo and emulation world, use magic to trick CPUs into thinking there’s only a certain amount of ROM – the 32K of code and 8K of graphics – when in reality they’re hiding the rest of it. It’s how the Commodore 128 was able to double the RAM of its predecessor (64K -> 128K), despite the CPU only being able to see 64K of data at a time.
Excitebike had no magician. The NES hardware had full access to the contents of the cartridge with nothing standing in its way.
Mega Man 3 had a powerful magician known as MMC3 that could swap in lots ands lots of CHR-ROM and PRG-ROM.
Many games hired magicians that all operated in very different ways, depending on the game involved. There were dozens of different ones, each solving particular problems and offering certain capabilities. There were 4 big ones, along with “no mapper”, or NROM:
Excitebike
The first time I played this was on a PlayChoice-10 cabinet at a roller skating rink.
- NROM (no mapper)
- 16K PRG-ROM
- 8K CHR-ROM
Arkista's Ring
I got this super cheap at a flea market.
- CNROM (CHR-ROM mapping only)
- 32K PRG-ROM
- 32K CHR-ROM
Contra
I recently rewatched Predator.
- UNROM (PRG-ROM mapping only)
- 128K PRG-ROM
- No CHR-ROM! All the graphics are stored in code and dumped into a CHR-RAM chip as needed. The NES treats the contents of this RAM chip exactly as it would treat a ROM chip.
Dragon Warrior
The first RPG I ever played to completion.
- MMC1
- 64K PRG-ROM
- 16K CHR-ROM
- Battery backup, the "hold down RESET and power off" variety
Mega Man 3
The first game I ever rented, and the first Mega Man game I ever played.
- MMC3
- 256K PRG-ROM
- 128K CHR-ROM
This use of memory management controllers, a clever approach to work around some very limiting constraints, allowed the NES to grow and expand far beyond its capabilities, and allowed for making some truly amazing games for a console with such humble specifications.
Links
- Details on NES hardware and MMCs/mappers
- https://www.howitworksdaily.com/how-the-nes-worked/
- http://nesdev.com/NESDoc.pdf
- https://wiki.nesdev.com/w/index.php/Cartridge_and_mappers%27_history
- https://www.reddit.com/r/gamedev/comments/dfxs86/super_mario_bros_game_was_just_31_kilobytes_hows/
- https://wiki.nesdev.com/w/index.php/Programming_NROM
- Nintendo Power’s 1991 description of all this. I found this issue of Nintento Power while cleaning. It’s the only one I have left from back then, and I rediscovered it while writing this very blog post!
- The games I chose for this were games I played on an actual NES when I was
younger.
- Excitebike: https://nescartdb.com/profile/view/18
- Arkista’s Ring: https://nescartdb.com/profile/view/433
- Contra: https://nescartdb.com/profile/view/52
- Dragon Warrior: https://nescartdb.com/profile/view/54
- Mega Man 3: https://nescartdb.com/profile/view/46
Changelog
- 2021-03-09: Initial post