Skip to navigation

Elite on the BBC Micro and NES

BBC Micro cassette Elite memory map

Memory usage in the classic version of Elite, where space is really tight

The cassette version of BBC Micro Elite uses almost every nook and cranny of the BBC Micro Model B, which isn't surprising when you consider just how much the authors managed to squeeze into this 32K micro. Sure, the BBC Micro disc version of the game has more features, but that's because the main game code is split into two different programs, one that's loaded when you're docked and another that's loaded for spaceflight. The cassette version that's documented here doesn't have the luxury of fast loading - quite the opposite, in fact - so it has to cram the whole game into memory, all at once. It's an absolute marvel of efficiency.

When the cassette version of Elite is loaded, this is how the memory map of the BBC Micro Model B looks.

  +-----------------------------------+   &FFFF
  |                                   |
  | Machine Operating System (MOS)    |
  |                                   |
  +-----------------------------------+   &C000
  |                                   |
  | Paged ROMs                        |
  |                                   |
  +-----------------------------------+   &8000
  |                                   |
  | Python blueprint (PYTHON.bin)     |
  |                                   |
  +-----------------------------------+   &7F00 = SHIP_PYTHON
  |                                   |
  | Memory for the split-screen mode  |
  |                                   |
  +-----------------------------------+   &6000
  |                                   |
  | Ship blueprints (SHIPS.bin)       |
  |                                   |
  +-----------------------------------+   &563A = XX21
  |                                   |
  | Main game code (ELTcode.bin)      |
  |                                   |
  +-----------------------------------+   &0F40 = S%
  |                                   |
  | &0F34-&0F3F unused                |
  |                                   |
  +-----------------------------------+   &0F34
  |                                   |
  | WP workspace                      |
  |                                   |
  +-----------------------------------+   &0D40 = WP
  |                                   |
  | Ship line heap descends from WP   |
  |                                   |
  +-----------------------------------+   SLSP
  |                                   |
  .                                   .
  .                                   .
  .                                   .
  .                                   .
  .                                   .
  |                                   |
  +-----------------------------------+
  |                                   |
  | Ship data blocks ascend from K%   |
  |                                   |
  +-----------------------------------+   &0900 = K%
  |                                   |
  | MOS sound/printer workspace       |
  |                                   |
  +-----------------------------------+   &0800
  |                                   |
  | Recursive tokens (WORDS9.bin)     |
  |                                   |
  +-----------------------------------+   &0400 = QQ18
  |                                   |
  | MOS tape filing system workspace  |
  |                                   |
  +-----------------------------------+   &0372
  |                                   |
  | T% workspace                      |
  |                                   |
  +-----------------------------------+   &0300 = T%
  |                                   |
  | MOS general workspace             |
  |                                   |
  +-----------------------------------+   &0200
  |                                   |
  | 6502 stack descends from &01FF    |
  |                                   |
  +-----------------------------------+
  |                                   |
  .                                   .
  .                                   .
  .                                   .
  .                                   .
  .                                   .
  |                                   |
  +-----------------------------------+
  |                                   |
  | Heap space ascends from XX3       |
  |                                   |
  +-----------------------------------+   &0100 = XX3
  |                                   |
  | Zero page workspace               |
  |                                   |
  +-----------------------------------+   &0000 = ZP

This memory map shows the full 64K of addressable memory that's supported by the BBC's 6502 processor, but only the bottom 32K is writable RAM, and hence usable by Elite. The top 16K is mapped to the MOS (Machine Operating System) ROM, and the next 16K is mapped to the currently selected paged ROM, which might be anything from BBC BASIC to the VIEW word processor.

This 32K of RAM includes both screen memory and the various operating system workspaces, which can leave a pretty small amount for programs (especially in high resolution screen modes). Let's take a look at how the authors managed to shoehorn their game into such a small amount of memory.

Memory usage
------------

Here's a full breakdown of memory usage in bytes, once the cassette version of Elite is loaded and running:

                                                               Used     Unused

  Machine operating system (MOS) ROM                         16,384          -
  Paged ROMs                                                 16,384          -
  MOS general workspace in page 2                               256          -
  MOS sound and printer workspace in page 8                     256          -
  MOS tape filing system workspace in page 3                    142          -
  MOS zero page locations, &B0-&D0 and &E2-&FF inclusive         63          -
                                                             ------     ------
                              Total MOS and ROM memory       33,485          -


  Memory for the split-screen mode (31 rows of 256 bytes)     7,936          -
  6502 stack and XX3 heap space (at opposite ends of page 1)    256          -
                                                             ------     ------
                              Total shared memory             8,192          -


  Main game code                                             18,136         34
  Ship blueprints (11 different designs, all except Python)   2,502          -
  Game text (recursive token table)                           1,023          1
  Python ship blueprint and SVN, VEC variables                  245         11
                                                             ------     ------
                              Total game code memory         21,906         46


  K% workspace (ship data blocks and line heaps)              1,088          -
  WP workspace (ship slots, variables)                          499         13
  Zero page workspace (INWK workspace, variables)               192          1
  T% workspace (current commander data, stardust data)          108          6
                                                             ------     ------
                              Total workspace memory          1,887         20


                              Total memory                   65,536

As you can see - and contrary to popular legend - Elite does not use every single last byte of the BBC Micro's usable memory. There are actually quite a few unused bytes in the cassette version, as noted in the "Unused" column above; 66 of them, to be precise. Here are the details, in the order in which they appear above:

  • In the main game code:
    • There are six unused bytes in the last saved commander data at NA%. Two of them are between LASER and CRGO, just after the four laser powers; they were originally used for up and down lasers, but those views were dropped and the space never reclaimed. There are four more unused bytes between the escape pod at ESCP and the cargo bay capacity at CRGO, which might have been for additional equipment that didn't get implemented... who knows?
    • There's an unused and unlabelled duplicate of the multiplication routine MULTU sandwiched between FMLTU and MLTU2 that takes up 24 bytes
    • The MUT3 routine is never called and would be identical to MUT2 even if it were, so that's another four bytes that aren't used
  • In the recursive token table at QQ18:
    • There is one unused byte at &07FF, right at the end of the table
  • In the WP workspace:
    • The one-byte variable XX24 is never used
    • There are 12 bytes at the end of the WP workspace, from &0F34 to &0F40, which aren't used
  • In the Python workspace:
    • There are 11 unused bytes between the end of the Python ship blueprint and the SVN and VEC variables, right at the top of user memory
  • In the zero page workspace:
    • The one-byte variable XX14 is never used
  • In the T% workspace:
    • There are six unused bytes in the current commander data block at T%, which correspond with the unused bytes in the last saved commander data block at NA% (see above)

On top of this, there are quite a few instructions in the main game code that have no effect and could have been culled without impact; I've identified 22 of them, but there are no doubt more of them to find (search the comments for "no effect" to find the ones I've spotted).

But this is splitting hairs, as Elite swells the BBC Micro to near bursting point while being both incredibly clever and incredibly efficient, and for that, very serious respect is due to the authors.

Shared locations
----------------

Some locations have two names in the source code. This is partly because some of the code was developed on an Acorn Atom, which restricts the names you can use for labels to two letters followed by one or more numbers. Presumably when this code was merged with the code that was developed on a BBC Micro, where label naming is more flexible, it was easier just to share label names than refactor the Atom code.

The following label names point to the same locations in memory, and are therefore interchangeable:

  LOIN        = LL30
  INWK        = XX1
  INWK(34 33) = XX19(1 0)
  X1          = XX15
  Y1          = XX15+1
  X2          = XX15+2
  Y2          = XX15+3
  K5          = XX18         = QQ17
  K3          = XX2
  LSO         = LSX
  CABTMP      = MANY

The last one is slightly different, in that the first byte of the MANY table is unused, so CABTMP simply makes the most of the otherwise unused location.

Elite code as an image
----------------------

To see just how small the cassette version of Elite is, we can convert the main game binary into an image, with one byte per pixel, and a greyscale showing each byte's value, with 0 being shown as black, 255 being shown as white, and interim values as greyscale pixels. The result is a 162-pixel square, like this:

The game binary for BBC Micro cassette Elite as animage

This image contains the entire main game. That's some nice, bloat-free code!