Skip to navigation

The Sentinel memory map

Interleaving code and data to make the most of the BBC Micro's 32K of RAM

Geoff Crammond did a pretty good job of squeezing the complexity of The Sentinel into the relatively modest 32K of RAM on the unexpanded BBC Micro. There's not a lot of headroom; indeed, The Sentinel leaves even less free space than Revs, his previous game, and that's saying something.

Revs leaves only 388 spare bytes in the 32,768 bytes of RAM in the BBC Micro, which is impressive, but The Sentinel trumps that by leaving just 291 bytes unused. Elite still wins as the most memory-hungry game that I have analysed, with only 144 spare bytes in the cassette version, but The Sentinel's memory usage is still amazingly high, taking up a good 99.1% of the Beeb's memory.

Here's the memory map once the game has loaded:

  +-----------------------------------+   &FFFF
  |                                   |
  | Machine Operating System (MOS)    |
  |                                   |
  +-----------------------------------+   &C000
  |                                   |
  | Paged ROMs                        |
  |                                   |
  +-----------------------------------+-- &8000
  |                                   |
  | Screen memory (custom mode 5)     |
  |                                   |
  +-----------------------------------+-- &6000
  |                                   |
  | Main game code                    |
  |                                   |
  +-----------------------------------+   &5260 = objSentinel
  |                                   |
  | Main game code & screen buffers   |
  |                                   |
  +-----------------------------------+-- &3F00 = screenBufferRow0
  |                                   |
  | Main game code                    |
  |                                   |
  +-----------------------------------+   &0D00 = NMIHandler
  |                                   |
  | Main variable workspace           |
  |                                   |
  +-----------------------------------+   &0C00 = sinAngleLo
  |                                   |
  | Object variables & drawing tables |
  |                                   |
  +-----------------------------------+   &0900 = xObject
  |                                   |
  | MOS sound envelope buffer         |
  |                                   |
  +-----------------------------------+   &08C0
  |                                   |
  | MOS printer buffer                |
  |                                   |
  +-----------------------------------+   &0880
  |                                   |
  | MOS sound workspace and buffer    |
  |                                   |
  +-----------------------------------+   &0800
  |                                   |
  | Tile data                         |
  |                                   |
  +-----------------------------------+   &0400 = tileData
  |                                   |
  | MOS VDU workspace                 |
  |                                   |
  +-----------------------------------+   &0300
  |                                   |
  | MOS general workspace             |
  |                                   |
  +-----------------------------------+   &0200
  |                                   |
  | 6502 stack descends from &01FF    |
  |                                   |
  +-----------------------------------+
  |                                   |
  .                                   .
  .                                   .
  .                                   .
  .                                   .
  .                                   .
  |                                   |
  +-----------------------------------+   &01C0
  |                                   |
  | Stack variables workspace         |
  |                                   |
  +-----------------------------------+   &0100 = objectFlags
  |                                   |
  | Zero page workspace               |
  |                                   |
  +-----------------------------------+   &0000 = enemyObject

Note that the 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 The Sentinel. 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.

The 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 exactly how much unused memory there is in The Sentinel.

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

Here's a full breakdown of memory usage in bytes, once The Sentinel is loaded and running. The figures show the number of available bytes in each section and how many of those are unused:

Memory contents (ROMs)Address rangeBytesUnused
Paged ROMs&8000 to &BFFF16,384-
Machine operating system (MOS) ROM&C000 to &FFFF16,384-
Total ROM memory 32,768-
Memory contents (MOS workspace)Address rangeBytesUnused
MOS zero page filing system workspace&00B0 to &00CF3232
MOS zero page VDU workspace&00D0 to &00E118-
MOS zero page tape filing system workspace&00E2 to &00E322
MOS zero page general workspace&00E4 to &00FF28-
MOS general workspace&0200 to &02FF256-
MOS VDU workspace&0300 to &037F128-
MOS tape filing system workspace&0380 to &03DF9696
MOS keyboard buffer&03E0 to &03FF32-
MOS sound workspace and buffer&0800 to &087F128-
MOS printer buffer&0880 to &08BF6464
MOS envelope buffer&08C0 to &08FF64-
Total MOS workspace memory 848194
Memory contents (shared memory)Address rangeBytesUnused
6502 stack&01C0 to &01FF64-
Memory for the custom screen mode&6000 to &7FFF8,192-
Total shared memory 8,256-
Memory contents (game code)Address rangeBytesUnused
Zero page workspace&0000 to &00AF17641
Stack variables&0100 to &01BF192-
Tile data&0400 to &07FF1,024-
Object variables & drawing tables&0900 to &0BFF768-
Main variable workspace&0C00 to &0CFF25635
Main game code, excluding screen buffers&0D00 to &5FFF17,40821
24 screen buffers (160 bytes each)&3F00 to &525F3,840-
Total game code memory 23,66497
Summary BytesUnused
Total ROM memory 32,768-
Total MOS workspace memory 848194
Total shared memory 8,256-
Total game code memory 23,66497
Totals 65,536291

In total, once the game is loaded and running, there are just 291 unused bytes; given that the BBC Micro has 32,768 bytes of RAM, that's pretty packed.

Because the game doesn't need to use the filing system once it's been loaded, and it also doesn't use a printer, there are 194 unused bytes in MOS workspace memory that could potentially be used by the game. And within the game itself there are 97 unused bytes, with 41 unused bytes in zero page, 35 unused bytes in the main variable workspace and 21 unused bytes dotted throughout the main game code (a number of which are the result of aligning lookup tables in memory).

It doesn't leave a lot of space.

The Sentinel code as an image
-----------------------------

To see just how small the game code for The Sentinel 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 147-pixel square, like this (shown here at double size, so you can see the pixels more clearly):

The game binary for The Sentinel on the BBC Micro as an image

The game binary includes 2,304 bytes of workspace data at the start that could easily have been omitted from the binary, as the workspaces are initialised when the game loads. This includes the tile data workspace, the MOS sound/printer workspace, the object variables, the drawing tables and the main variable workspace, all of which can be seen in the black strip at the top of the image. Meanwhile, the white stripes towards the bottom of the image are the screen buffers, which mainly contain workspace noise consisting of &00 and &FF values that show up as black and white in the image.