Skip to content
Techniques & Technology

Memory Management

Making the most of limited RAM

Memory management techniques enabled complex games on hardware with kilobytes of RAM, from bank switching to compression to careful data structure design.

C64zx-spectrumNESAmiga programmingoptimisationretro

Overview

Early computers and consoles offered kilobytes, not gigabytes, of memory. Developers created sophisticated techniques to fit games into impossibly small spaces. Bank switching accessed more ROM than addressable. Compression squeezed data smaller. Clever data structures represented complex game states in bytes. These constraints bred creativity that modern developers study for optimisation insight.

Fast facts

  • C64 RAM: 64 KB (around 38 KB usable for BASIC programs).
  • ZX Spectrum: 48 KB.
  • NES: 2 KB RAM, variable ROM.
  • Modern context: Gigabytes available but efficiency still matters.

Memory maps

Understanding available space:

SystemTotal RAMAvailableNotes
C6464 KB~38 KBBASIC, Kernal reduce
ZX Spectrum 48K48 KB~41 KBSystem overhead
NES2 KBVariableMapper ROM expansion
Amiga 500512 KB~400 KBOS requirements

Bank switching

Accessing more than addressable:

  • CPU can only address limited memory.
  • Switch โ€œbanksโ€ of ROM/RAM into view.
  • NES mappers enable large games.
  • C64 could switch out BASIC/Kernal ROMs.

Example:

  • NES addresses 32 KB ROM directly.
  • MMC3 mapper allows 512 KB ROM.
  • Switch banks as needed during play.

Data compression

Shrinking content:

TechniqueApplication
Run-length encodingRepeated patterns
Huffman codingVariable-length symbols
LZ variantsRepeated sequences
Delta encodingSimilar sequential data
Custom formatsGame-specific optimisation

Tile-based graphics

Memory-efficient visuals:

  • Define tiles once (8x8 or 16x16 pixels).
  • Reference tiles by index.
  • Screen map uses one byte per tile.
  • 256 tiles cover most needs.

Example: 20x12 tile screen = 240 bytes (map) + 4 KB (tile definitions).

Sprite management

Limiting active objects:

  • Hardware sprites limited (8 per line on NES).
  • Multiplexing shares sprites across objects.
  • Object pooling reuses memory.
  • Priority systems manage overflow.

Zero page on 6502

Fast memory access:

  • First 256 bytes of memory.
  • Faster addressing modes.
  • Store frequently used variables.
  • Precious resource, allocate carefully.

Self-modifying code

Code as data:

  • Change instructions during runtime.
  • Avoid repeated calculations.
  • Table lookups via modified addresses.
  • Saves memory at complexity cost.

Example: unrolled loops with modified addresses.

Streaming and paging

Loading content dynamically:

  • Disk-based games load sections.
  • Earlier areas unloaded for new content.
  • Cassette games more constrained.
  • Level streaming in 3D games today.

Stack management

Limited stack space:

  • Call depth limited.
  • Local variables consume stack.
  • Recursion dangerous.
  • Global variables often necessary.

Memory allocation strategies

StrategyTrade-off
Static allocationPredictable but inflexible
Pool allocationEfficient reuse, fixed types
Dynamic allocationFlexible but fragmentation

Retro games typically used static allocation.

Amiga chip vs fast RAM

Amiga-specific considerations:

  • Chip RAM: Accessible by custom chips (graphics, audio).
  • Fast RAM: CPU only, faster access.
  • Careful placement of data.
  • DMA requires chip RAM.

Modern relevance

Why this matters today:

  • Mobile game optimisation.
  • Console memory budgets.
  • Cache efficiency.
  • Embedded systems.
  • Understanding fundamentals.

Learning from constraints

Lessons from limited memory:

  • Every byte matters.
  • Data structure design is crucial.
  • Trade computation for storage.
  • Know your hardware.
  • Constraints breed creativity.

See also