This page contains a map of all the routines and variables in the original version of The Sentinel, in the order in which they appear in the original source. The source files are structured like this:
- The main game source, which consists of Workspaces, The Sentinel A, The Sentinel B, The Sentinel C, The Sentinel D, The Sentinel E, The Sentinel F, The Sentinel G, The Sentinel H, The Sentinel I and The Sentinel J
You can click on the links above to jump to the relevant part of the map.
Workspaces
----------
| Category | Details |
|---|---|
Workspaces | Mainly temporary variables that are used a lot |
Workspaces | Variables that share page 1 with the stack |
The Sentinel A
--------------
| Category | Details |
|---|---|
Landscape | Altitude and shape data for landscape tiles |
3D objects | The x-coordinates in 3D space for the 3D objects |
3D objects | The y-coordinates in 3D space for the 3D objects (high byte) |
3D objects | The z-coordinates in 3D space for the 3D objects |
3D objects | The yaw angle for each object (i.e. the horizontal direction in which they are facing) |
3D objects | The y-coordinates in 3D space for the 3D objects (low byte) |
3D objects | The object types table for up to 64 objects |
Drawing the landscape | Storage for the pitch angles of tiles and object points for drawing the current landscape view (low bytes) |
Drawing the landscape | Storage for the pitch angles of tiles and object points for drawing the current landscape view (high bytes) |
Drawing polygons | Pixel x-coordinates for all the points in the polygon that we are currently drawing (high bytes) |
Drawing the landscape | Storage for the yaw angles of tiles and object points for drawing the current landscape view (low bytes) |
Workspaces | Workspace: Main variable workspace The main block of game variables |
Setup | The NMI handler at the start of the NMI workspace |
Main game loop | Stores the previous value of IRQ1V before we install our custom IRQ handler |
Maths (Arithmetic) | Calculate (A T) = T * U |
Maths (Geometry) | Subroutine: GetAngleFromCoords (Part 1 of 3) Given the coordinates along two axes, calculate the pitch or yaw angle to those coordinates |
Maths (Geometry) | Subroutine: GetAngleFromCoords (Part 2 of 3) Overflow and accuracy calculations |
Maths (Geometry) | Subroutine: GetAngleFromCoords (Part 3 of 3) Calculate the arctangent to get the angle |
Maths (Geometry) | Subroutine: GetRotationMatrix (Part 1 of 5) Calculate the rotation matrix for rotating the pitch or yaw angle for the sights into the global 3D coordinate system |
Maths (Geometry) | Subroutine: GetRotationMatrix (Part 2 of 5) Calculate sin(H G) for smaller angles |
Maths (Geometry) | Subroutine: GetRotationMatrix (Part 3 of 5) Calculate sin(H G) for bigger angles |
Maths (Geometry) | Subroutine: GetRotationMatrix (Part 4 of 5) Loop back to calculate cos instead of sin |
Maths (Geometry) | Subroutine: GetRotationMatrix (Part 5 of 5) Apply the correct signs to the result |
Maths (Geometry) | Temporary storage for X so it can be preserved through calls to GetRotationMatrix |
Cracker protection | Obfuscated storage for the high byte of the landscape number as part of the anti-cracker code |
Maths (Geometry) | Convert a 16-bit angle into radians, restricted to a quarter circle |
Maths (Arithmetic) | Multiply an 8-bit and a 16-bit number |
Keyboard | Scan the keyboard for a specific key press |
Maths (Geometry) | Calculate the sine and the cosine of an angle |
Maths (Arithmetic) | Multiply a sign-magnitude 16-bit number and a signed 16-bit number |
Maths (Arithmetic) | Calculate the absolute value (modulus) of a 16-bit number |
Maths (Arithmetic) | Negate a 16-bit number |
Main title loop | The main title loop: display the title screen, fetch the landscape number/code, preview the landscape and jump to the main game loop |
Main title loop | Display the "WRONG SECRET CODE" error, wait for a key press and rejoin the main title loop |
Landscape | The secret entry code for landscape 0000 (06045387) |
Graphics | Clear the screen to a specified background |
The Sentinel B
--------------
| Category | Details |
|---|---|
Drawing the landscape | Pan the landscape and update the landscape view |
Sights | The pitch angle of the highest point that the player can look at with the sights |
Sights | The pitch angle of the lowest point that the player can look at with the sights |
Main title Loop | Reset all the game's main variables |
Main title Loop | Reset the tile visibility table and deallocate all object numbers |
Keyboard | Subroutine: CheckForKeyPresses Check for various game key presses and update the key logger and relevant variables (during the interrupt handler) |
Keyboard | Tell the game to start focusing effort on the action that has been initiated, such as a pan of the landscape, absorb, transfer etc. |
Keyboard | Subroutine: CheckForSamePanKey Check to see whether the same pan key is being held down compared to the last time we checked |
Keyboard | A variable to flag whether the SPACE key has been pressed, so we can implement debounce |
3D objects | Attempt to place an object on a tile that is below the maximum altitude specified in A |
Maths (Arithmetic) | Set A to the next number from the landscape's sequence of seed numbers, converted to the range 0 to 30 |
Gameplay | A gameplay loop that processes all game key presses, returning to the main game loop when the player moves, quits, loses or pans |
Gameplay | Update the timers that control the enemy tactics |
Graphics | Subroutine: ResetScreenAddress Reset the address of the start of screen memory |
Sights | Initialise the variables used to manage the sights, so the sights appear in the middle of the screen |
Keyboard | Scan for game key presses and update the key logger |
Keyboard | Negative inkey values for the game keys |
Keyboard | The configuration table for storing keys the key logger |
Title screen | Draw the main title screen, the secret code screen or the landscape preview |
Title screen | The y-coordinate of the viewer for the large 3D text on the title screen |
Title screen | The pitch angle of the viewer for the large 3D text on the title screen |
Title screen | The x-coordinate of the viewer for the large 3D text on the title screen |
Title screen | An offset to apply to the large 3D text for the title screen |
Title screen | The z-coordinate of the viewer for the large 3D text on the title screen |
Title screen | The yaw angle of the viewer for the large 3D text on the title screen |
Title screen | Storage for the type of title view we are drawing in DrawTitleView (title screen or landscape preview) |
Landscape | Calculate the number of enemies for this landscape, add them to the landscape and set the palette accordingly |
Landscape | Add the player object to the landscape, ideally placing it below all the enemies and in the bottom half of the landscape |
Landscape | Add trees to the landscape, ideally placing them below all the enemies in the landscape |
Landscape | Subroutine: CheckSecretCode (Part 1 of 2) Generate the secret code for this landscape and optionally check it against the entered code in the keyboard input buffer |
Landscape | Physical colours for colour 3 in the game palette for the different numbers of enemies |
Landscape | Subroutine: CheckSecretCode (Part 2 of 2) Check the results of the secret code matching process, and if the secret codes match, jump to PlayGame to play the game |
Landscape | Physical colours for colour 2 in the game palette for the different numbers of enemies |
Landscape | Add the required number of enemies to the landscape, starting from the highest altitude and working down, with one enemy per contour |
Landscape | Subroutine: GetTilesAtAltitude Return a list of tile blocks at a specified altitude |
Landscape | A table for converting the number of leading clear bits in a number into a bit mask with the same number of leading zeroes |
Landscape | Calculate both the highest tiles in each 4x4 block of tiles in the landscape and the altitude of the highest tile in the landscape |
Scanner/energy row | Update the scanner, if required |
Scanner/energy row | Update the scanner to a new state |
Scanner/energy row | Storage for a random number that's used to generate static in the scanner |
Scanner/energy row | A counter for the eight character blocks that make up the scanner |
Scanner/energy row | The current state of the scanner (black, static or green) |
Scanner/energy row | Pixel bytes for the three states of the scanner (black, static and green) |
Gameplay | Apply tactics to an enemy object, setting things up so the next call applies tactics to the next enemy object |
Gameplay | Update enemyObject so the next time we consider applying enemy tactics, we apply them to the next enemy, looping from 7 to 0 |
Gameplay | Subroutine: ApplyTactics (Part 1 of 8) Apply tactics to the Sentinel or a sentry |
Gameplay | Subroutine: ApplyTactics (Part 2 of 8) Process the tactics for a meanie |
Gameplay | Subroutine: ApplyTactics (Part 3 of 8) If the enemy has any residual energy, try expending it onto the landscape in the form of a tree (and end tactics if successful) |
Gameplay | Subroutine: ApplyTactics (Part 4 of 8) If configured, search the landscape for a suitable target for the enemy to drain of energy |
Gameplay | Subroutine: ApplyTactics (Part 5 of 8) Look for a suitable robot to drain of energy, or look for a drainable tree or boulder if there are no suitable robots |
Gameplay | Subroutine: ApplyTactics (Part 6 of 8) Rotate the enemy and make a rotation sound |
Gameplay | Subroutine: ApplyTactics (Part 7 of 8) Drain energy from the enemy's target object, or try scanning for a tree to turn into a meanie if the target's tile is obscured |
Gameplay | Subroutine: ApplyTactics (Part 8 of 8) Redraw the object on the screen, optionally with a dithered effect |
The Sentinel C
--------------
| Category | Details |
|---|---|
Gameplay | Subroutine: CheckEnemyGaze (Part 1 of 2) Check to see whether the current enemy can see a specific target object of a specific type |
Cracker protection | Create an altered version of the anti-cracker seed-related data, as part of the anti-cracker code |
Gameplay | Subroutine: CheckEnemyGaze (Part 2 of 2) Calculate whether the current enemy can see the specified object |
Gameplay | Temporary storage for X so it can be preserved through calls to CheckEnemyGaze |
Gameplay | Calculate whether the player is being scanned by an enemy and whether the enemy can see the player's tile |
Gameplay | Reset the data stored for any meanie scans that the enemy has tried in the past, so we can start looking with a clean slate |
Gameplay | Scan through the objects in the landscape to see if any of them are trees that are suitable for turning into a meanie |
Gameplay | Drain energy from an object into an enemy, transforming it into an object with an energy level of one unit less (if applicable) |
Gameplay | Drain one unit of energy from an enemy and expend it onto the landscape by spawning a tree, if possible |
Main game loop | Add the player's energy to the landscape number to get the number of the next landscape and display that landscape's secret code |
Gameplay | Find a suitable target object for an enemy to drain |
Gameplay | Abort applying the tactics for this gameplay loop if updating the object on-screen will corrupt a screen pan |
Gameplay | Subroutine: FinishEnemyTactics Stop applying tactics to the current enemy and return to the ProcessGameplay routine to continue with the gameplay loop |
Drawing objects | Subroutine: CheckObjVisibility Check whether an object is visible on-screen and should therefore not be changed if a pan operation is about to happen |
Keyboard | Subroutine: ProcessActionKeys (Part 1 of 2) Process an action key press from key logger entry 1 (absorb, transfer, create, hyperspace, U-turn) |
Cracker protection | Subroutine: SetPlayerIsOnTower Set up the playerIsOnTower value for checking the game is won, as part of the anti-cracker code |
Keyboard | Subroutine: ProcessActionKeys (Part 2 of 2) Process an action key press from key logger entry 1 (absorb, transfer, create, hyperspace, U-turn) |
Maths (Geometry) | Calculate the angles of the vector from the player's eyes to the sights |
Maths (Geometry) | Subroutine: GetVectorForAngles Convert a vector from pitch and yaw angles into a 3D cartesian vector |
Maths (Arithmetic) | Multiply a 16-bit signed number and a 16-bit sign-magnitude value |
Maths (Arithmetic) | Divide a 16-bit sign-magnitude number by 16 |
Maths (Geometry) | Add a vector to a coordinate |
Maths (Geometry) | Subroutine: FollowGazeVector (Part 1 of 5) Follow a gaze vector from a viewing object to determine whether the viewer can see a flat tile or platform (i.e. boulder or tower) |
Maths (Geometry) | Subroutine: FollowGazeVector (Part 2 of 5) Calculate the altitudes of the four corners in a non-flat tile |
Maths (Geometry) | Subroutine: FollowGazeVector (Part 3 of 5) Calculate whether the viewing object's gaze is obstructed by a tile of shape 4 or 12 (i.e. a tile with one horizontal edge) |
Maths (Geometry) | Subroutine: FollowGazeVector (Part 4 of 5) For non-flat tiles with two horizontal edges, work out which tile edge to use when checking for obstruction of the gaze vector |
Maths (Geometry) | Subroutine: FollowGazeVector (Part 5 of 5) For non-flat tiles with two horizontal edges, work out whether the tile edge obstructs the gaze vector |
Landscape | A table to map tile shapes and gaze vector direction to tile edges |
Landscape | Calculate the altitude of a tile, optionally including platform objects and trees in the calculation |
The Sentinel D
--------------
| Category | Details |
|---|---|
Maths (Geometry) | Subroutine: CheckForTileCentre Calculate max(|xCoordLo - 128|, |zCoordLo - 128|) |
3D objects | Get an object's coordinates |
3D objects | Delete an object, removing it from the landscape and vacating its object number |
3D objects | Place an object on a tile, putting it on top of any existing boulders or towers |
3D objects | The tile number to which we are adding an object in the PlaceObjectOnTile routine |
Drawing objects | Draw an updated object on-screen, optionally with a dithered effect, and with or without the surrounding landscape |
Screen buffer | Storage for the address for the current drawing operation in the screen buffer |
Screen buffer | The screen address of the object we are updating |
Screen buffer | A counter for the inner loop when dithering objects to the screen in the DitherScreenBuffer routine |
Screen buffer | The yaw offset of the left edge of the object being updated, relative to the left edge of the screen, in yaw angles |
Gameplay | Calculate whether any part of an object is visible on-screen, and if so, which character columns it spans on the screen |
Gameplay | Each object's width in terms of tile widths, for half the object |
3D objects | Add a new object of the specified type to the objectTypes table |
Gameplay | Subroutine: UpdatePlayerEnergy Update the player's energy levels by adding or subtracting the amount of energy in a specific object |
3D objects | The amount of energy required to create each object or the amount energy acquired when absorbing each object |
Gameplay | Hyperspace the player to a brand new tile, ideally at the same altitude as the current tile |
Drawing objects | Draw an entire stack of objects |
Graphics | Fill a rectangular in screen memory or the screen buffer with the specified background |
Graphics | Pixel bytes for even pixel rows in the screen background |
Graphics | Pixel bytes for odd pixel rows in the screen background |
Graphics | A table for converting a pixel number in the range 0 to 3 into a screen mode 5 bit mask with that pixel's bits set and others clear |
Graphics | A table that maps logical colours 0 to 3 to a four-pixel byte in that colour |
Graphics | Pixel byte with all the pixels to the left of position X set |
Graphics | Pixel byte with all the pixels to the right of position X set |
Graphics | Pixel byte with all the pixels to the right of position X + 1 set, to give the complementary pixel byte to pixelsToRight |
Screen buffer | An offset to add to the address of the right column screen buffer (low byte) |
Screen buffer | An offset to add to the address of the right column screen buffer (low byte) |
Drawing polygons | Subroutine: DrawPolygonLines (Part 1 of 4) Draw an analysed polygon into the screen buffer |
Drawing polygons | Subroutine: DrawPolygonLines (Part 2 of 4) Process the line overflowing the sides of the buffer, or fitting into one pixel byte, and loop on to the next polygon pixel line |
Drawing polygons | Subroutine: DrawPolygonLines (Part 3 of 4) Draw the left and right edges of the polygon line and fall into part 4 to draw the line in between |
Drawing polygons | Subroutine: DrawPolygonLines (Part 4 of 4) Draw a horizontal pixel line of a specific length in character columns |
Drawing the landscape | For each tile in the landscape, calculate whether the player can see that tile, to speed up the process of drawing the landscape |
Drawing the landscape | A table for converting a number in the range 0 to 7 into a bit mask with only that bit set, when counting from the left |
Drawing the landscape | Subroutine: GetRowVisibility (Part 1 of 2) Set up the calculations to determine whether each tile corner in a tile row is obscured from the player by any intervening landscape |
Cracker protection | Check whether the secret code stash is correctly set up, as part of the anti-cracker code |
Drawing the landscape | Subroutine: GetRowVisibility (Part 2 of 2) Calculate whether each tile corner in a tile row is obscured from the player by any intervening landscape |
The Sentinel E
--------------
| Category | Details |
|---|---|
Drawing the landscape | Calculate tile corner altitudes and maximum tile corner altitudes for each tile in the landscape |
Drawing the landscape | Subroutine: DrawLandscapeView (Part 1 of 3) Set up a number of variables for drawing the landscape view |
Drawing the landscape | Subroutine: DrawLandscapeView (Part 2 of 3) Work through the landscape, drawing one row of tiles/objects at a time, from the back row to the front row |
Drawing the landscape | Subroutine: DrawLandscapeView (Part 3 of 3) Draw a tile row in two parts, one on either side of the viewer |
Drawing the landscape | Offsets into the tile view data tables for the four different viewing directions |
Drawing the landscape | For a given tile row, work out the edges of the visible portion of the row in the current player view, as left to right tile numbers |
Drawing the landscape | Move one tile to the left along the tile row that we are analysing for view edges and tile angles |
Drawing the landscape | Subroutine: GetTileEdgeToRight Move one tile to the right along the tile row that we are analysing for view edges and tile angles |
Drawing the landscape | Subroutine: GetTileViewAngles (Part 1 of 4) Calculate the pitch and yaw angles for a tile corner, relative to a viewer object (e.g. the player), and whether it is on-screen |
Drawing the landscape | Subroutine: GetTileViewAngles (Part 2 of 4) Fetch the tile data for the tile corner we are analysing |
Drawing the landscape | Subroutine: GetTileViewAngles (Part 3 of 4) Calculate the pitch angle for the tile corner |
Drawing the landscape | Subroutine: GetTileViewAngles (Part 4 of 4) Calculate how much of the tile is on-screen |
Drawing the landscape | Draw a row of tiles between the left visible edge and the right visible, in two parts towards each side of the viewer |
Screen buffer | Flip the buffer type between buffer type 0 (left row buffer) and buffer type 1 (right row buffer) |
Screen buffer | Set up the variables required to configure the screen buffer to a specific buffer type |
Screen buffer | The offset to add to yaw angles for each screen buffer to convert from the origin in the buffer centre to the origin on the left |
Screen buffer | The left edge of each screen buffer in pixels |
Screen buffer | The width of each screen buffer in pixels |
Screen buffer | Minimum allowed yaw angles for points in the screen buffer |
Screen buffer | Subroutine: ConfigureObjBuffer Set up the variables required to configure the screen buffer for updating an object |
Drawing the landscape | Subroutine: DrawTileAndObjects Draw a tile and any objects stacked on it |
Drawing the landscape | Draw a flat tile in the correct colour for the chess board effect that we use to draw the landscape |
Cracker protection | Alter the secret code stash, as part of the anti-cracker code |
Drawing the landscape | Draw a tile with one quadrilateral (four-sided) face |
Drawing the landscape | Draw a sloping tile that is not shape 4 or 12 |
Drawing the landscape | Draw a tile with two triangular (three-sided) faces |
Drawing polygons | Draw a polygon |
Landscape | Generate tile data for the landscape |
Landscape | Process the tile data for all tiles in the landscape |
Landscape | Smooth the entire landscape |
Landscape | Get the tile data and tile data address for a specific tile |
The Sentinel F
--------------
| Category | Details |
|---|---|
Landscape | Subroutine: SmoothTileCorners (Part 1 of 4) Smooth a row or column of tile corners (a "strip of tiles") |
Landscape | Subroutine: SmoothTileCorners (Part 2 of 4) Smooth a strip by moving each outlier tile corner to the altitude of its closest immediate neighbour (in terms of altitude) |
Landscape | Subroutine: SmoothTileCorners (Part 3 of 4) Smooth a strip by setting the tile corner altitudes to the average of the current tile corner altitude and three following corners |
Cracker protection | Set up anti-cracker tile-related data that can be checked in the CheckCrackerSeed routine |
Landscape | Subroutine: SmoothTileCorners (Part 4 of 4) Copy the smoothed strip data back into the tileData table |
Landscape | Calculate the shape of the tile anchored at (xTile, zTile) |
Drawing polygons | The value to add to the second point number to get the third point number when drawing a tile face as two triangles |
Drawing the landscape | Tile colours by shape and the orientation of the viewer |
Drawing polygons | The number of the first point in each two-face shape that is drawn as a pair of triangles |
Drawing polygons | Subroutine: GetPolygonLines (Part 1 of 6) Calculate the points in a two-face tile polygon when it consists of a pair of triangles |
Drawing polygons | Subroutine: GetPolygonLines (Part 2 of 6) The main entry point for the routine to calculate the horizontal lines in filled polygon and prepare them for drawing on-screen |
Drawing polygons | Subroutine: GetPolygonLines (Part 3 of 6) Convert all the polygon point yaw angles into pixel x-coordinates (for larger yaw angles that convert into a 16-bit x-coordinate) |
Drawing polygons | Subroutine: GetPolygonLines (Part 4 of 6) Convert all the polygon point yaw angles into pixel x-coordinates (for smaller yaw angles that convert into an 8-bit x-coordinate) |
Drawing polygons | Subroutine: GetPolygonLines (Part 5 of 6) Loop through all the edges in the polygon and call the correct routines to process one-byte, two-byte or horizontal edges |
Drawing polygons | Subroutine: TracePolygonEdge (Part 1 of 8) Trace a polygon edge, populating xPolygonRight or xPolygonLeft with the x-coordinate of the edge for each y-coordinate |
Drawing polygons | Subroutine: TracePolygonEdge (Part 2 of 8) Trace a polygon edge with a steep gradient by stepping along the y-axis |
Drawing polygons | Subroutine: TracePolygonEdge (Part 3 of 8) Trace a polygon edge with a shallow gradient by stepping along the x-axis |
Drawing polygons | Subroutine: TracePolygonEdge (Part 4 of 8) Trace a steep edge that starts off-screen, without storing the coordinates, until we reach the screen and return to part 2 |
Drawing polygons | Subroutine: TracePolygonEdge (Part 5 of 8) Trace a shallow edge that starts off-screen, without storing the coordinates, until we reach the screen and return to part 3 |
Drawing polygons | Subroutine: GetPolygonLines (Part 6 of 6) Split polygon edges whose coordinates are stored in two-byte numbers into smaller sections for processing |
Drawing polygons | Subroutine: TracePolygonEdge (Part 6 of 8) Trace a polygon edge where the start or end point x-coordinates are two-byte numbers |
Drawing polygons | Subroutine: TracePolygonEdge (Part 7 of 8) Trace a polygon edge with a steep gradient by stepping along the y-axis (for two-byte x-coordinates) |
Drawing polygons | Subroutine: TracePolygonEdge (Part 8 of 8) Trace a polygon edge with a shallow gradient by stepping along the x-axis (for two-byte x-coordinates) |
Cracker protection | Corrupt the generation process for the landscape's secret code by fetching one more seed number than necessary |
Drawing polygons | Modify the code in TracePolygonEdge that stores the coordinates of the polygon edge that is being traced |
Maths (Arithmetic) | Set A to a seed number |
Maths (Arithmetic) | Temporary storage for Y so it can be preserved through calls to GetNextSeedNumber |
Text | Print a number as a single digit, printing zero as a capital "O" |
Text | Print a numerical digit, printing zero as a capital "O" |
Title screen | Subroutine: SpawnCharacter3D (Part 1 of 2) Spawn a character on the landscape in large 3D blocks for drawing on the main title screen or secret code screen |
Cracker protection | Check whether the anti-cracker seed-related data is correctly set up, as part of the anti-cracker code |
Title screen | Subroutine: SpawnCharacter3D (Part 2 of 2) Spawn large 3D blocks for the extracted character definition |
Title screen | A lookup table to convert bit pairs into object numbers for spawning 3D text blocks on the landscape |
Title screen | Draw the title screen or the screen showing the secret code |
Title screen | A variable that determines whether we are drawing the title screen or the secret code screen in the DrawTitleScreen routine |
Title screen | The text to draw on the title screen |
Keyboard | Read a number from the keyboard into the input buffer |
Text | Print the contents of the keyboard input buffer |
The Sentinel G
--------------
| Category | Details |
|---|---|
Text | Convert a string of ASCII digits in the input buffer in-place into a multi-byte BCD number |
Text | Convert a digit from the input buffer into a number |
Text | Print a binary coded decimal (BCD) number using two digits |
Maths (Arithmetic) | Set A to the next number from the landscape's sequence of seed numbers, converted to a binary coded decimal (BCD) number |
Maths (Arithmetic) | Storage for the low nibble when constructing a BCD seed number in the GetNextSeedAsBCD routine |
Title screen | Draw the landscape's secret code by spawning a set of large 3D text block objects |
Text | Print the four-digit landscape number (0000 to 9999) |
Landscape | Initialise the seed number generator so it generates the sequence of seed numbers for a specific landscape number |
Text | Process and print a character from a text token, which can encode another text token or be a one-byte character or VDU command |
Landscape | Calculate the number of enemies for the current landscape |
Maths (Arithmetic) | Set A to the next number from the landscape's sequence of seed numbers, converted to the range 0 to 22 |
Maths (Arithmetic) | Subroutine: GetPlayerEnergyBCD Fetch the player's energy in binary coded decimal (BCD) |
Sound | Make a sound |
Sound | Define a sound envelope |
Sound | Either make a sound or set up an envelope |
Sound | Temporary storage for use in the DefineEnvelope routine |
Sound | A table to map a sound number (0 to 6) to the sound data block(s) that are used to make the sound |
Sound | Adjust the volume of the sound envelopes when the volume keys are pressed |
Sound | The volume level, which can be changed by pressing "7" and "8" |
Sound | A table of offsets into the envelope data for bytes that control the volume of each envelope, so we can change their volume levels |
Keyboard | Pause or unpause the game when COPY or DELETE are pressed |
Sound | Play the configured music in the background |
Sound | Flush all four sound channel buffers |
Sound | Flush the sound channel 0 buffer |
Keyboard | Flush the specified buffer |
Sound | Process any sound effects that have been configured so they play in the background (this is called regularly throughout gameplay) |
Main game loop | Start playing the generated landscape |
Main game loop | The main game loop for playing a landscape |
Scanner/energy row | Clear the energy icon and scanner row at the top of the screen |
Text | Print a recursive text token |
Graphics | A table for converting a pixel number in the range 0 to 3 into a screen mode 5 bit mask with that pixel's bits clear and others set |
Scanner/energy row | Subroutine: UpdateIconsScanner Update the icons in the top-left corner of the screen to show the player's current energy level and redraw the scanner box |
Scanner/energy row | Draw a single icon in the top-left corner of the screen (via the icon screen buffer at iconBuffer) and move along to the right |
Main game loop | The main interrupt handler, which gets run 50 times a second to update the game state and check for game key presses |
Graphics | Scroll the screen and copy data from the screen buffer into screen memory to implement the player's scrolling landscape view |
Screen buffer | Update the player's scrolling landscape view by copying the relevant parts of the screen buffer into screen memory |
Screen buffer | Update the player's scrolling landscape view by copying a 2-pixel wide column from the screen buffer into screen memory |
Screen buffer | Update the player's scrolling landscape view by copying an 8-pixel high character row from the screen buffer into screen memory |
Screen buffer | Update the player's scrolling landscape view by copying an 8-byte character block from the screen buffer into screen memory |
Screen buffer | The offset within screen memory for the player's landscape view of the area to update following a scroll (low byte) |
Screen buffer | The offset within screen memory for the player's landscape view of the area to update following a scroll (high byte) |
Screen buffer | The amount to change the start of screen memory in order to scroll the player's landscape view through each direction (low byte) |
Screen buffer | The amount to change the start of screen memory in order to scroll the player's landscape view through each direction (high byte) |
Screen buffer | The value to add to scrollScreenHi for each direction to get the high byte of the screen buffer address of the content to scroll in |
Screen buffer | The value to add to scrollScreenLo for each direction to get the low byte of the screen buffer address of the content to scroll in |
Drawing the landscape | Pitch and yaw angles for panning the landscape view, so the output of DrawLandscapeView will be the bit we add when updating the view |
Screen buffer | Subroutine: StartScrollingView Start a scroll process in the background by setting the number of scroll steps and the address to start copying new content from |
Screen buffer | Set screenBufferAddr(1 0) to the address from which the interrupt handler should fetch new content to scroll onto the screen |
Screen buffer | Configure the row buffer for use |
Screen buffer | Maximum allowed pitch angles for points in the screen buffer |
Screen buffer | Minimum allowed pitch angles for points in the screen buffer |
Screen buffer | Configure the column buffer for use |
Screen buffer | Subroutine: SetColumnBufferMax Set the maximum and minimum pitch angles for the column buffer |
The Sentinel H
--------------
| Category | Details |
|---|---|
Sights | Check for up/down/left/right key presses and move the sights accordingly, panning the screen if they go past the screen edges |
Sights | Subroutine: MoveSightsSideways Check for the left/right keys and move the sights accordingly, panning to the left or right if they go past the screen edges |
Sights | Check for the up/down keys and move the sights accordingly, panning up or down if they go past the screen edges |
Sights | Update the address variables for the sights when they move into a new character block or row |
Sights | Draw the sights on the screen, saving the existing screen contents in the sights pixel byte stash |
Graphics | A table for converting a pixel number in the range 0 to 3 into a screen mode 5 pixel byte with that pixel set to colour 2 (%10) |
Sights | Steps to take along the x-axis when drawing the sights |
Sights | Steps to take along the y-axis when drawing the sights |
Sights | Remove the sights from the screen |
Sights | The change to apply to the screen address of the sights when they move into a new character block or row (low byte) |
Sights | The change to apply to the screen address of the sights when they move into a new character block or row (high byte) |
Scanner/energy row | Calculate the address in screen memory of the icon and scanner row at the top of the screen |
Screen buffer | Display the redrawn icon and scanner row by copying the contents of the icon screen buffer into screen memory |
Maths (Geometry) | Table for arctan values when calculating yaw angles (low byte) |
Maths (Geometry) | Table for arctan values when calculating yaw angles (high byte) |
Maths (Geometry) | Table for hypotenuse lengths given the tangent of an angle |
Screen buffer | Address lookup table for character rows in screen memory (low byte) |
Screen buffer | Address lookup table for character rows in the screen buffer (low byte) |
Graphics | Address lookup table for character rows in screen memory (high byte) |
Screen buffer | Address lookup table for character rows in the screen buffer (high byte) |
Sights | The sights pixel byte stash, which contains the screen pixel bytes behind the sights, so they can be restored to remove the sights |
Sights | The screen addresses of the bytes in the sights pixel byte stash, to which they can be restored to remove the sights (high byte) |
Drawing polygons | Table to convert a polygon colours byte and a pixel offset (0-3) into a pixel byte for the left edge of the polygon pixel line |
Drawing polygons | Table to convert a polygon colours byte and a pixel offset (0-3) into a pixel byte for the right edge of the polygon pixel line |
Drawing the landscape | A table for storing the visibility of each tile from the player's point of view, with one bit per tile (1 = visible, 0 = hidden) |
Landscape | A stash for calculated values for each iteration in the CheckSecretCode routine |
Screen buffer | The screen buffer for character row 0 |
Screen buffer | The screen buffer for character row 16 (as part of a column buffer) |
Screen buffer | The screen buffer for character row 1 |
Screen buffer | The screen buffer for character row 17 (as part of a column buffer) |
Screen buffer | The screen buffer for character row 2 |
Screen buffer | The screen buffer for character row 18 (as part of a column buffer) |
Screen buffer | The screen buffer for character row 3 |
Screen buffer | The screen buffer for character row 19 (as part of a column buffer) |
Screen buffer | The screen buffer for character row 4 |
Screen buffer | The screen buffer for character row 20 (as part of a column buffer) |
Screen buffer | The screen buffer for character row 5 |
Screen buffer | The screen buffer for character row 21 (as part of a column buffer) |
Screen buffer | The screen buffer for character row 6 |
Screen buffer | The screen buffer for character row 22 (as part of a column buffer) |
Screen buffer | The screen buffer for character row 7 |
Screen buffer | The screen buffer for character row 23 (as part of a column buffer) |
Screen buffer | The screen buffer for character row 8 |
Drawing objects | The first and last point numbers for each object |
Drawing objects | The first and last polygon numbers for each object |
Drawing objects | The phase configuration for each object |
Sights | The screen addresses of the bytes in the sights pixel byte stash, to which they can be restored to remove the sights (low byte) |
Drawing objects | The list of polygons and points for the meanie object (polygons 77 to 101, using points 76 to 93) |
3D objects | The yaw angle through which each enemy rotates on each scheduled rotation |
Screen buffer | The screen buffer for character row 9 |
Drawing objects | Polar yaw angles for each of the points in each of the objects |
Screen buffer | The screen buffer for character row 10 |
Drawing objects | The height of each of the points in each of the objects, relative to the object's origin |
Screen buffer | The screen buffer for character row 11 |
Drawing objects | Polar distances for each of the points in each of the objects |
Screen buffer | The screen buffer for character row 12 |
Drawing objects | Various data for object polygons (colour, drawing phase) |
The Sentinel I
--------------
| Category | Details |
|---|---|
Screen buffer | The screen buffer for character row 13 |
Drawing objects | Addresses for the list of polygons and points for each object (low byte) |
Screen buffer | The screen buffer for character row 14 |
Drawing objects | Addresses for the list of polygons and points for each object (high byte) |
Screen buffer | The screen buffer for character row 15 |
Drawing objects | The list of polygons and points for the Sentinel object (polygons 102 to 136, using points 94 to 123) |
Drawing objects | The list of polygons and points for the tree object (polygons 52 to 66, using points 51 to 67) |
Drawing objects | The list of polygons and points for the boulder object (polygons 67 to 76, using points 68 to 75) |
Drawing objects | The list of polygons and points for the Sentinel's tower object (polygons 137 to 147, using points 124 to 135) |
Drawing objects | The list of polygons and points for the 3D text block object (polygons 148 to 151, using points 136 to 143) |
Drawing objects | The list of polygons and points for the robot object (polygons 0 to 26, using points 0 to 28) |
Drawing objects | The list of polygons and points for the sentry object (polygons 27 to 51, using points 29 to 50) |
Drawing polygons | Pixel x-coordinates for all the points in the polygon that we are currently drawing (low bytes) |
Drawing the landscape | Storage for the yaw angles of tiles and object points for drawing the current landscape view (high bytes) |
Maths (Geometry) | Subroutine: GetHypotenuseAngle Calculate the angle of the hypotenuse in a right-angle triangle given the two non-hypotenuse sides (i.e. two orthogonal axes) |
Maths (Geometry) | Subroutine: GetPitchAngleDelta Calculate the pitch angle of a vector relative to an object's pitch angle |
Maths (Geometry) | Calculate the hypotenuse from an angle and two triangle sides with one lookup and one multiplication (so without a square root) |
Maths (Geometry) | Temporary storage for Y so it can be preserved through calls to GetHypotenuse |
Maths (Arithmetic) | Set A to a random number |
Maths (Arithmetic) | A 24-bit random number generator that works independently from the landscape seeds and with a much simpler generation algorithm |
Maths (Arithmetic) | Storage for randomGenerator(2 1 0) while we shift it left by two places |
Graphics | Draw 80 randomly positioned stars on the screen in colour 2 (white, yellow, cyan or red) |
Graphics | Draw 80 randomly positioned dots on the screen in colour 1 (black) |
Graphics | Draw 80 randomly positioned dots on the screen |
Graphics | A counter for the number of dots drawn in the DrawRandomDots routine |
Graphics | A flag that determines the colour of the dots drawn by the DrawRandomDots routine |
Sights | A table for converting a pixel number in the range 0 to 3 into a screen mode 5 pixel byte with that pixel set to colour 1 (%01) |
Main game loop | Subroutine: SetScannerAndPause Set the scanner update status and delay for 40 empty loops of 256 iterations each (i.e. 10,240 loops) |
Text | Print a single-byte VDU command or character from a text token, optionally printing a drop shadow if the character is alphanumeric |
Text | Print a one-byte character from a text token or a multi-byte VDU 25 command |
Text | The number of bytes in a VDU 25, n, x; y; command |
Text | Address offsets for the text tokens (each offset in the table is the offset of the token from tokenBase) |
Text | VDU commands for printing the front character of a drop shadow |
Text | VDU commands for printing the rear character of a drop shadow |
Text | Background colour blue, print "PRESS ANY KEY" at (64, 100), set text background to black |
Text | Print 13 spaces at (64, 100), print "LANDSCAPE NUMBER?" at (64, 768), switch to text cursor, move text cursor to (5, 27) |
Text | Background colour blue, print "SECRET ENTRY CODE?" at (64, 768), switch to text cursor, move text cursor to (2, 27) |
Text | Background colour blue, print "WRONG SECRET CODE" at (64, 768), print "PRESS ANY KEY" at (64, 100), set text background to black |
Text | Background colour black, print "PRESS ANY KEY" at (192, 64), print "LANDSCAPE" two chars right of (64, 768), move cursor right |
Text | Text token 5: Print "SECRET ENTRY CODE" at (64, 768), "LANDSCAPE" at (192, 704), move cursor right |
Text | Text token 6: Print "PRESS ANY KEY" at (64, 100) |
Text | Text token 7: Move the graphics cursor to (64, 768) |
Text | Text token 8: Move the graphics cursor to (192, 704) |
Text | Text token 9: Move the graphics cursor to (192, 64) |
Text | Text token 10: Configure text to be printed at the graphics cursor and set the background colour to colour 0 (blue) |
Text | Text token 11: Configure text to be printed at the graphics cursor and set the background colour to colour 1 (black) |
Text | Text token 12: Move graphics cursor to (64, 100) |
Text | Text token 13: Print "LANDSCAPE" |
Text | Text token 14: Print "SECRET ENTRY CODE" |
Text | Text token 15: Print five spaces |
Text | Text token 16: Print three spaces |
Text | Text token 17: Print "PRESS ANY KEY" |
Sound | Data for the game's music |
Graphics | Screen mode 5 bitmap data for the ten icons that make up the energy icon and scanner row at the top of the screen |
Sound | OSWORD blocks for making the various game sounds |
Sound | Data for the six sound envelopes |
Maths (Geometry) | Table for sine values |
Graphics | The icon screen buffer, which is used to buffer the energy icon and scanner row before writing to screen memory |
Drawing polygons | The pixel x-coordinate of the left edge of each pixel line in the polygon being drawn |
Drawing polygons | The pixel x-coordinate of the right edge of each pixel line in the polygon being drawn |
Landscape | Storage for tile data when smoothing strips of tiles during the landscape generation process |
Landscape | Storage for tile blocks at specific altitudes for placing enemies on the landscape |
Landscape | The maximum tile altitude for each 4x4 block of tiles |
Landscape | The tile x-coordinate of the highest tile within each 4x4 block of tiles |
Landscape | The tile z-coordinate of the highest tile within each 4x4 block of tiles |
The Sentinel J
--------------
| Category | Details |
|---|---|
3D objects | Calculate the angles and distances of the vector from the viewer to a specific object |
Drawing objects | Calculate the view-relative pitch and yaw angles of all the points in an object |
Drawing objects | Draw a 3D object |
Maths (Geometry) | Subroutine: GetHorizontalDelta Calculate the difference in the x-axis and z-axis between two objects, as both signed and absolute deltas |
Maths (Geometry) | Calculate the difference in the y-axis between two objects as a signed delta |
Keyboard | Enable the keyboard and read a character from it |
Keyboard | Read a character from the currently selected input stream |
Keyboard | Select the keyboard as the input stream and flush the keyboard buffer |
Graphics | Set the logical colours for each of the four physical colours in screen mode 5 |
Graphics | The logical colours for two mode 5 palettes |
Screen buffer | Subroutine: DitherScreenBuffer Dither the contents of the screen buffer onto the screen |
Title screen | Subroutine: ShowGameOverScreen Display the game over screen |
Graphics | Subroutine: DecayScreenToBlack Smother the screen with randomly placed black dots to decay the screen to black |
Cracker protection | An intentionally confusing jump point for controlling the main title loop flow when returning from the GenerateLandscape routine |
Title screen | Spawn the title object (robot or the Sentinel) as object #1 |
Title screen | The z-coordinate of an object on the title screen, as a delta from the z-coordinate of the viewing object |
Landscape | Draw an aerial preview of the landscape |
Title screen | The pitch angle of the viewer for objects on the title screen |
Title screen | The y-coordinate of an object on the title screen, as a delta from the y-coordinate of the viewing object |
Title screen | The yaw angle of an object on the title screen |
Title screen | The yaw angle of the viewer for objects on the title screen |
Title screen | Draw an object on top of a tower on the title screen |
Title screen | Draw an object on the title screen |
Sound | Play a piece of music |
Setup | Configure the custom screen mode, set the break handler to clear memory, move code, reset timers and set the interrupt handler |
Setup | Clear game memory, so that the BREAK key can remove all trace of the game code in early versions of the operating system |
Setup | The main entry point for the game |