Home bank treemaps in three NES games

By on 2023-08-08 in Retrotainment

These are treemaps of the fixed bank and semi-fixed ACTORLIB bank in three NES games developed by Retrotainment Games. A treemap shows sizes of parts of a whole by dividing a rectangle into smaller rectangles. The fixed banks contain routines used most widely in the program.

Haunted: Halloween '86

Haunted: Halloween '86 home bank treemap
Treemap of home banks in Haunted: Halloween '86 - The Curse of Possum Hollow (2016). Text version

Full Quiet

Full Quiet home bank treemap
Treemap of home banks in Full Quiet (2022). Text version

Garbage Pail Kids

Garbage Pail Kids home bank treemap
Treemap of home banks in Garbage Pail Kids: Mad Mike and the Quest for Stale Gum (2022). Text version

What are treemaps?

A treemap is a graph that shows the relative sizes of the parts that make up a whole by dividing a rectangle into smaller rectangles. For example, one might make a treemap of the files on a disk by what folder they're in, or the products that a country exports by what sector of the economy they're in. The rule is that if something makes up 10 percent of the whole, the area of its rectangle will be 10 percent of the whole rectangle. The rectangle for a part that contains smaller parts is divided into smaller rectangles that represent the sizes of the parts inside it. Hence the name "treemap" because the containment relationship forms a rooted tree.

A computer program is made of several modules, also called translation units. Each module results from assembling one source code file and the header files it includes to one object code file. For example, routines for moving Walkee, a monkey-like enemy in the Crags, Forest, and Cliffs of Full Quiet, are in the walkee module. Routines related to loading new areas of the background as the camera moves are in the mapdecoding and camera modules. Routines to draw the radio, MID, and ARK are in radio, routines to draw inventory supply refills are in campcache, and routines to draw the PDA (pause screen) are split across a few modules whose name begins with pda.

Most 8-bit games have more data than the CPU can read at once. The circuit board of a game cartridge for NES or Game Boy carries a support circuit called a mapper. One important job of a mapper is bank switching, or making different parts of the program available to the CPU at different points in time. Some parts are available all the time; these are called the "fixed bank" or "home bank." Other banks are available most of the time alongside another bank; these are called a "semi-fixed bank." For example, a library of utility subroutines called by actors' movement routines goes in a semi-fixed bank that we call ACTORLIB, and banks with routines to move individual enemies are switched in alongside ACTORLIB.

Some routines are automatically called by the system, particularly the two interrupts that the NES provides. One is an NMI at the start of vertical blanking, the brief period between one frame and the next, that signals when to update video memory. The other interrupt is an interval timer that the mapper asserts when it is time to change the background's scroll position for a strip of parallax scrolling. Each interrupt handler belongs in a fixed bank because it needs to be available no matter what bank is switched in at the moment.

Some routines call routines in multiple banks, read large amounts of data from multiple banks, or are called by routines in multiple banks. These usually need to go in a fixed bank. Examples include mapdecoding, which reads 8×8-pixel characters and background maps from multiple banks, and spritevram, which decompresses actors' sprite sheets from multiple banks into video memory.

Some routines call smaller routines in other banks. For example, actors' movement routines call utility routines in ACTORLIB to implement gravity, inertia, and collision detection against one another and against the terrain. The terrain reader in turn needs to switch to the bank with a map's terrain and then back to the bank with the movement routine. The sound driver goes in another semi-fixed bank alongside one of the two banks of music sequence data.

Pino, our lead developer, wrote a Python program that reads the debug symbols to find which routines are in each bank, which module they're in, and how big each routine is. Then he used a Python module by Uri Laserson called Squarify to convert this to a rectangle layout. The rectangle for each module lists the largest routines inside of it.

As the fixed banks fill over the course of a game's development, a treemap like this comes in handy to find things to move out if possible. On the NES, drum samples and bass samples have to go in either the fixed bank or the semi-fixed bank, which competes for space with routines.