ORG CODE% \ Set the assembly address to &0400THE SENTINEL MAIN GAME CODE Produces the binary file Sentinel.bin that contains the main game code..tileData EQUB &00, &00, &00, &00, &00, &00, &00, &27 \ These values are workspace EQUB &29, &20, &27, &29, &29, &27, &20, &00 \ noise and have no meaning EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &20, &20, &20 EQUB &20, &20, &20, &29, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &29, &29, &29 EQUB &29, &29, &29, &29, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &29, &29, &29 EQUB &29, &29, &29, &29, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &20, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &29, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &29, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &29, &29, &29 EQUB &29, &29, &29, &29, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &27, &29, &28, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &20, &20, &20 EQUB &29, &20, &20, &20, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &29, &20, &20 EQUB &29, &20, &20, &29, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &27, &29, &28, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &29, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &28 EQUB &29, &29, &28, &20, &29, &28, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &28, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &20, &20, &20 EQUB &20, &20, &20, &29, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &29, &29, &29 EQUB &29, &29, &29, &29, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &29, &20, &20 EQUB &28, &20, &20, &29, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &20, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &29, &29, &29, &29, &29, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &28, &20, &20, &29, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &29 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &20, &20, &20 EQUB &20, &20, &20, &20, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &20, &20, &20 EQUB &20, &20, &20, &20, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &20, &20, &20 EQUB &20, &20, &20, &20, &20, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &20 EQUB &20, &20, &20, &20, &20, &20, &20, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &FF, &00, &00, &00, &00, &00, &00, &00 EQUB &C0, &C0, &C0, &C0, &04, &04, &04, &04 EQUB &00, &00, &00, &64, &00, &00, &00, &FF EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &05, &00, &00, &00, &FF EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &FF, &00, &00, &00, &00, &F0, &00, &0E EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &64, &06, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &90 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00Name: tileData [Show more] Type: Variable Category: Landscape Summary: Altitude and shape data for landscape tilesContext: See this variable on its own page References: This variable is used as follows: * GetTileData uses tileData * GetTileViewAngles (Part 2 of 4) uses tileData
The landscape in The Sentinel consists of a tiled area of 31x31 tiles, like an undulating chess board that's sitting on a table in front of us, going into the screen. The shape of the landscape is defined by the altitude of the corners of each tile, so that's a 32x32 grid of altitudes, one for each tile corner. The x-axis is along the front edge, from left to right, while the z-axis goes into the screen from front to back, away from us. This table contains one byte of data for each tile corner in the landscape. If there is no object placed on the tile, then the data contained in each byte is as follows: * The low nibble of each byte contains the tile shape, which describes the layout and structure of the landscape on that tile (0 to 15). * The high nibble of each byte contains the altitude of the tile corner in the front-left corner of the tile (i.e. the corner closest to the origin of the landscape). We call this tile corner the "anchor". The altitude is in the range 1 to 11, so the top nibble never has both bit 6 and 7 set. If there is an object placed on the tile, then the data contained in each byte is as follows: * Bits 0 to 5 contain the number of the object on the tile (0 to 63). If there are multiple objects stacked on the tile, this is the number of the object on the top of the stack. * Bits 6 and 7 of the byte are set. We can therefore test for the presence of an object on a tile by checking whether both bit 6 and 7 are set (as empty tiles have the tile altitude in the top nibble, and this is in the range 1 to 11). As each tile is defined by a tile corner and a shape, we tend to use the terms "tile" and "tile corner" interchangeably, depending on the context. That said, for tile corners along the furthest back and rightmost edges of the landscape, the shape data is ignored, as there is no landscape beyond the edges. See the GetTileShape routine for information on the different types of tile shape..xObject EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ These values are workspace EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ noise and have no meaning EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &18Name: xObject [Show more] Type: Variable Category: 3D objects Summary: The x-coordinates in 3D space for the 3D objectsContext: See this variable on its own page References: This variable is used as follows: * DeleteObject uses xObject * DrawLandscapeView (Part 1 of 3) uses xObject * DrawTileAndObjects uses xObject * DrawTitleView uses xObject * FindObjectToDrain uses xObject * FollowGazeVector (Part 1 of 5) uses xObject * GetHorizontalDelta uses xObject * GetObjectCoords uses xObject * PerformHyperspace uses xObject * PlaceObjectOnTile uses xObject * ResetVariables uses xObject * ScanForMeanieTree uses xObject * SpawnTitleObject uses xObject.yObjectHi EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ These values are workspace EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ noise and have no meaning EQUB &4B, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &02Name: yObjectHi [Show more] Type: Variable Category: 3D objects Summary: The y-coordinates in 3D space for the 3D objects (high byte)Context: See this variable on its own page References: This variable is used as follows: * DeleteObject uses yObjectHi * DrawObjectStack uses yObjectHi * DrawTitleScreen uses yObjectHi * DrawTitleView uses yObjectHi * GetObjectCoords uses yObjectHi * GetTileAltitude uses yObjectHi * GetTileViewAngles (Part 3 of 4) uses yObjectHi * GetTileVisibility uses yObjectHi * GetVerticalDelta uses yObjectHi * PerformHyperspace uses yObjectHi * PlaceObjectOnTile uses yObjectHi * SpawnTitleObject uses yObjectHi
The y-coordinate (i.e. the altitude) of each object is stored as a 16-bit number of the form yObject(Hi Lo). The low byte is effectively a fractional part, as a y-coordinate of (1 0) is the same magnitude as an x-coordinate or z-coordinate of 1. A full coordinate in the 3D space is therefore in the form: (xObject, yObject(Hi Lo), zObject).zObject EQUB &00, &07, &00, &00, &00, &00, &00, &00 \ These values are workspace EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ noise and have no meaning EQUB &BF, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &07Name: zObject [Show more] Type: Variable Category: 3D objects Summary: The z-coordinates in 3D space for the 3D objectsContext: See this variable on its own page References: This variable is used as follows: * DeleteObject uses zObject * DrawLandscapeView (Part 1 of 3) uses zObject * DrawTileAndObjects uses zObject * DrawTitleView uses zObject * FindObjectToDrain uses zObject * FollowGazeVector (Part 1 of 5) uses zObject * GetHorizontalDelta uses zObject * GetObjectCoords uses zObject * PerformHyperspace uses zObject * PlaceObjectOnTile uses zObject * ScanForMeanieTree uses zObject * SpawnTitleObject uses zObject.objectYawAngle EQUB &00, &CE, &F8, &00, &00, &00, &00, &00 \ These values are workspace EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ noise and have no meaning EQUB &12, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &80Name: objectYawAngle [Show more] Type: Variable Category: 3D objects Summary: The yaw angle for each object (i.e. the horizontal direction in which they are facing)Context: See this variable on its own page References: This variable is used as follows: * AddEnemiesToTiles uses objectYawAngle * ApplyTactics (Part 2 of 8) uses objectYawAngle * ApplyTactics (Part 6 of 8) uses objectYawAngle * DrawLandscapeView (Part 1 of 3) uses objectYawAngle * DrawTitleScreen uses objectYawAngle * DrawTitleView uses objectYawAngle * DrawUpdatedObject uses objectYawAngle * GetObjectAngles uses objectYawAngle * GetSightsVector uses objectYawAngle * PanLandscapeView uses objectYawAngle * PlaceObjectOnTile uses objectYawAngle * ProcessActionKeys (Part 1 of 2) uses objectYawAngle * ProcessActionKeys (Part 2 of 2) uses objectYawAngle * SpawnTitleObject uses objectYawAngle.yObjectLo EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ These values are workspace EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ noise and have no meaning EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &E0Name: yObjectLo [Show more] Type: Variable Category: 3D objects Summary: The y-coordinates in 3D space for the 3D objects (low byte)Context: See this variable on its own page References: This variable is used as follows: * DrawObjectStack uses yObjectLo * DrawTitleScreen uses yObjectLo * GetObjectCoords uses yObjectLo * GetTileAltitude uses yObjectLo * GetTileViewAngles (Part 3 of 4) uses yObjectLo * GetVerticalDelta uses yObjectLo * PlaceObjectOnTile uses yObjectLo * ResetVariables uses yObjectLo * SpawnTitleObject uses yObjectLo
The y-coordinate (i.e. the altitude) of each object is stored as a 16-bit number of the form yObject(Hi Lo). The low byte is effectively a fractional part, as a y-coordinate of (1 0) is the same magnitude as an x-coordinate or z-coordinate of 1. A full coordinate in the 3D space is therefore in the form: (xObject, yObject(Hi Lo), zObject).objectTypes EQUB &00, &06, &00, &00, &00, &00, &00, &00 \ These values are workspace EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ noise and have no meaning EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &09Name: objectTypes [Show more] Type: Variable Category: 3D objects Summary: The object types table for up to 64 objectsContext: See this variable on its own page References: This variable is used as follows: * AddEnemiesToTiles uses objectTypes * ApplyEnemyTactics uses objectTypes * ApplyTactics (Part 2 of 8) uses objectTypes * CheckEnemyGaze (Part 1 of 2) uses objectTypes * DrainObjectEnergy uses objectTypes * DrawObjectStack uses objectTypes * DrawTileAndObjects uses objectTypes * FindObjectToDrain uses objectTypes * GetObjectAngles uses objectTypes * GetObjVisibility uses objectTypes * GetPlayerDrain uses objectTypes * GetTileAltitude uses objectTypes * PlaceObjectOnTile uses objectTypes * ProcessActionKeys (Part 1 of 2) uses objectTypes * ProcessActionKeys (Part 2 of 2) uses objectTypes * ScanForMeanieTree uses objectTypes * SetPlayerIsOnTower uses objectTypes * SpawnObject uses objectTypes * SpawnTitleObject uses objectTypes * UpdatePlayerEnergy uses objectTypes
The different object types are as follows: * 0 = Robot (one of which is the player) * 1 = Sentry * 2 = Tree * 3 = Boulder * 4 = Meanie * 5 = The Sentinel * 6 = The Sentinel's tower.drawViewPitchLo EQUB &6F, &70, &71, &73, &74, &75, &76, &78 \ These values are workspace EQUB &79, &7B, &7C, &7E, &7F, &81, &82, &84 \ noise and have no meaning EQUB &86, &87, &89, &8B, &8D, &8E, &90, &92 EQUB &95, &96, &98, &9A, &9C, &9E, &A0, &A2 EQUB &73, &75, &76, &77, &78, &79, &7A, &7C EQUB &7D, &7E, &80, &82, &83, &84, &86, &88 EQUB &89, &8B, &8D, &8F, &90, &92, &94, &96 EQUB &98, &99, &9B, &9D, &9F, &A1, &A3, &A5 EQUB &96, &96, &9A, &9C, &A0, &9E, &A1, &A4 EQUB &58, &59, &5A, &5A, &A1, &A3, &B1, &B0 EQUB &AC, &AD, &B3, &B3, &A9, &AA, &B9, &B9 EQUB &BC, &BC, &C6, &C6, &C4, &C4, &00, &00Name: drawViewPitchLo [Show more] Type: Variable Category: Drawing the landscape Summary: Storage for the pitch angles of tiles and object points for drawing the current landscape view (low bytes)Context: See this variable on its own page References: This variable is used as follows: * DrawLandscapeView (Part 3 of 3) uses drawViewPitchLo * GetObjPointAngles uses drawViewPitchLo * GetPolygonLines (Part 5 of 6) uses drawViewPitchLo * GetPolygonLines (Part 6 of 6) uses drawViewPitchLo * GetTileViewAngles (Part 3 of 4) uses drawViewPitchLo
Tile angles are stored in the first 64 bytes (in two sets of 32 bytes), and object point angles are stored in the last 32 bytes, from offset 64 onwards..drawViewPitchHi EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ These values are workspace EQUB &00, &00, &00, &00, &00, &00, &00, &00 \ noise and have no meaning EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &00, &00 EQUB &00, &00, &00, &00, &00, &00, &10, &10Name: drawViewPitchHi [Show more] Type: Variable Category: Drawing the landscape Summary: Storage for the pitch angles of tiles and object points for drawing the current landscape view (high bytes)Context: See this variable on its own page References: This variable is used as follows: * DrawLandscapeView (Part 3 of 3) uses drawViewPitchHi * GetObjPointAngles uses drawViewPitchHi * GetPolygonLines (Part 5 of 6) uses drawViewPitchHi * GetPolygonLines (Part 6 of 6) uses drawViewPitchHi * GetTileViewAngles (Part 3 of 4) uses drawViewPitchHi
Tile angles are stored in the first 64 bytes (in two sets of 32 bytes), and object point angles are stored in the last 32 bytes, from offset 64 onwards..xPolygonPointHi EQUB &10, &10, &10, &10, &10, &10, &10, &10 \ These values are workspace EQUB &10, &10, &10, &10, &10, &10, &10, &10 \ noise and have no meaning EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10 EQUB &10, &10, &10, &10, &10, &10, &10, &10Name: xPolygonPointHi [Show more] Type: Variable Category: Drawing polygons Summary: Pixel x-coordinates for all the points in the polygon that we are currently drawing (high bytes)Context: See this variable on its own page References: This variable is used as follows: * GetPolygonLines (Part 3 of 6) uses xPolygonPointHi * GetPolygonLines (Part 5 of 6) uses xPolygonPointHi * GetPolygonLines (Part 6 of 6) uses xPolygonPointHi.drawViewYawLo EQUB &3B, &C1, &48, &D6, &5A, &DD, &69, &EB \ These values are workspace EQUB &6B, &F3, &71, &EE, &73, &ED, &67, &E7 \ noise and have no meaning EQUB &5E, &D3, &50, &C3, &35, &AE, &1D, &8A EQUB &FF, &6A, &D5, &44, &AC, &12, &77, &E2 EQUB &1D, &A4, &2B, &B0, &35, &B8, &3B, &BC EQUB &46, &C6, &44, &C2, &3E, &B9, &32, &AB EQUB &2B, &A1, &16, &8A, &FC, &6E, &DE, &4C EQUB &C1, &2D, &98, &02, &6A, &D1, &37, &9B EQUB &71, &02, &30, &95, &D2, &6D, &30, &95 EQUB &4E, &2D, &58, &84, &E0, &1D, &65, &49 EQUB &9B, &B7, &EC, &2A, &F8, &8D, &CD, &49 EQUB &47, &53, &33, &A5, &E2, &65, &10, &10Name: drawViewYawLo [Show more] Type: Variable Category: Drawing the landscape Summary: Storage for the yaw angles of tiles and object points for drawing the current landscape view (low bytes)Context: See this variable on its own page References: This variable is used as follows: * GetObjPointAngles uses drawViewYawLo * GetPolygonLines (Part 3 of 6) uses drawViewYawLo * GetPolygonLines (Part 4 of 6) uses drawViewYawLo * GetTileViewAngles (Part 1 of 4) uses drawViewYawLo * GetTileViewAngles (Part 4 of 4) uses drawViewYawLo
Tile angles are stored in the first 64 bytes (in two sets of 32 bytes), and object point angles are stored in the last 32 bytes, from offset 64 onwards..sinAngleLo EQUB 0 \ The low byte of the sine of a pitch or yaw angle, \ as calculated by the GetRotationMatrix routine \ \ [Show more]Name: Main variable workspace [Show more] Type: Workspace Address: &0C00 to &0CFF Category: Workspaces Summary: The main block of game variablesContext: See this workspace on its own page References: No direct references to this workspace in this source file\ \ This variable is used by the following: \ \ * DivideBy16 \ * GetRotationMatrix (Part 2 of 5) \ * GetRotationMatrix (Part 3 of 5) \ * GetRotationMatrix (Part 5 of 5) \ * MultiplyCoords \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.cosAngleLo EQUB 0 \ The low byte of the cosine of a pitch or yaw angle, \ as calculated by the GetRotationMatrix routine \ \ [Show more]\ \ This variable is used by the following: \ \ * GetRotationMatrix (Part 5 of 5) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.sinAngleHi EQUB 0 \ The high byte of the sine of a pitch or yaw angle, \ as calculated by the GetRotationMatrix routine \ \ [Show more]\ \ This variable is used by the following: \ \ * DivideBy16 \ * GetRotationMatrix (Part 2 of 5) \ * GetRotationMatrix (Part 3 of 5) \ * MultiplyCoords \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.cosAngleHi EQUB 0 \ The high byte of the cosine of a pitch or yaw angle, \ as calculated by the GetRotationMatrix routine .scannerUpdate EQUB 0 \ A flag to control whether the scanner gets updated: \ \ * Non-zero = update scanner \ \ * Zero = do not update scanner \ \ [Show more]\ \ This variable is used by the following: \ \ * GetPlayerDrain \ * SetScannerAndPause \ * UpdateScanner \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.xIconCounter EQUB &28 \ A counter for drawing the icons in the top-left of the \ screen that show the player's energy level, as we work \ from left to right along the x-axis \ \ [Show more]\ \ This variable is used by the following: \ \ * ClearIconsScanner \ * DrawIcon \ * UpdateIconsScanner \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.minEnemyAltitude EQUB 0 \ The altitude of the lowest enemy on the landscape \ \ [Show more]\ \ This variable is used by the following: \ \ * AddEnemiesToTiles \ * ExpendEnemyEnergy \ * SpawnPlayer \ * SpawnTrees \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.maxNumberOfEnemies EQUB 0 \ The maximum number of enemies that can appear on the \ current landscape, which is calculated as follows: \ \ min(8, 1 + (landscapeNumber div 10)) \ \ So landscapes 0000 to 0009 have a maximum enemy count \ of 1, landscapes 0010 to 0019 have a maximum enemy \ count of 2, and so on up to landscapes 0070 and up, \ which have a maximum enemy count of 8 \ \ [Show more]\ \ This variable is used by the following: \ \ * InitialiseSeeds \ * SpawnEnemies \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.tileDataMultiplier EQUB 0 \ A multiplier that we apply to the altitudes of the \ tile corners to alter the steepness of the landscape \ during landscape generation \ \ [Show more]\ \ This variable is used by the following: \ \ * GenerateLandscape \ * ProcessTileData \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.lastScannerState EQUB 0 \ The state of the scanner the last time that it was \ updated: \ \ * 0 = fill scanner with black \ \ * 4 = fill the scanner with static in colour 3 \ \ * 8 = fill scanner with green \ \ [Show more]\ \ This variable is used by the following: \ \ * UpdateScanner \ * UpdateScannerNow \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.playerEnergy EQUB 0 \ The player's energy level (in the range 0 to 63) \ \ [Show more]\ \ This variable is used by the following: \ \ * DrainObjectEnergy \ * GetPlayerEnergyBCD \ * SpawnPlayer \ * UpdateIconsScanner \ * UpdatePlayerEnergy \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0 \ This byte appears to be unused .J EQUB 0 \ Temporary storage, used in the maths routines from \ Revs \ \ [Show more]\ \ This variable is used by the following: \ \ * GetRotationMatrix (Part 1 of 5) \ * GetRotationMatrix (Part 5 of 5) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.gameplayStack EQUB 0 \ The value of the stack pointer at the start of the \ ApplyEnemyTactics routine, so we can return back to \ the ProcessGameplay routine from deep within the \ tactics routines if required \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyEnemyTactics \ * FinishEnemyTactics \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.meanieYawStep EQUB 0 \ The yaw angle through which we rotate a meanie as it \ searches for the player in the ApplyTactics routine \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 2 of 8) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.textDropShadow EQUB 0 \ Controls whether text in text tokens is printed with a \ drop shadow \ \ * Bit 7 clear = drop shadow \ \ * Bit 7 set = no drop shadow \ \ [Show more]\ \ This variable is used by the following: \ \ * PrintCharacter \ * PrintInputBuffer \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.characterDef EQUB 0, 0, 0, 0 \ An OSWORD block for reading a character definition EQUB 0, 0, 0, 0 \ from the operating system, for use when drawing text EQUB 0 \ in large 3D blocks \ \ [Show more]\ \ This variable is used by the following: \ \ * SpawnCharacter3D (Part 1 of 2) \ * SpawnCharacter3D (Part 2 of 2) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.xTileSentinel EQUB 0 \ The tile x-coordinate of the Sentinel \ \ [Show more]\ \ This variable is used by the following: \ \ * AddEnemiesToTiles \ * PerformHyperspace \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.zTileSentinel EQUB 0 \ The tile z-coordinate of the Sentinel \ \ [Show more]\ \ This variable is used by the following: \ \ * AddEnemiesToTiles \ * PerformHyperspace \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.keepCheckingPanKey EQUB 0 \ Controls whether the DrawLandscapeView routine aborts \ drawing if the pan key is released before it has \ finished \ \ * Bit 7 clear = keep drawing the landscape view \ irrespective of whether the pan key \ is still being pressed \ \ * Bit 7 set = check whether the same pan key is \ being held down and abort the drawing \ if it is no longer being pressed \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawLandscapeView (Part 2 of 3) \ * MainGameLoop \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.titleObjectToDraw EQUB 5 \ The object we are drawing in the DrawTitleView routine \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyEnemyTactics \ * ApplyTactics (Part 2 of 8) \ * DrawTitleView \ * ProcessActionKeys (Part 1 of 2) \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.latestPanKeyPress EQUB 0 \ The key logger value of the latest pan key press, \ which will either be a current key press or the value \ from the last pan key press to be made \ \ * 0 = pan right \ \ * 1 = pan left \ \ * 2 = pan up \ \ * 3 = pan down \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckForKeyPresses \ * CheckForSamePanKey \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.doNotDitherObject EQUB 0 \ Controls whether the DitherScreenBuffer routine can \ update an object on the screen using a dithered effect \ \ * Bit 7 clear = dithering objects is enabled \ \ * Bit 7 set = dithering objects is disabled \ \ [Show more]\ \ This variable is used by the following: \ \ * DitherScreenBuffer \ * DrawUpdatedObject \ * FocusOnKeyAction \ * MainGameLoop \ * ProcessGameplay \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.samePanKeyPress EQUB 0 \ Records whether the same pan key is being held down \ after we have just finished panning the landscape view \ \ * Bit 7 clear = same pan key is not being held down \ \ * Bit 7 set = same pan key is being held down \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckObjVisibility \ * ProcessGameplay \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyDrainTimer EQUB 0, 0, 0, 0 \ A timer for each enemy that counts down every 0.06 EQUB 0, 0, 0, 0 \ seconds and controls the rate at which an enemy will \ drain energy from its target object \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 2 of 8) \ * ApplyTactics (Part 5 of 8) \ * ApplyTactics (Part 7 of 8) \ * DrainObjectEnergy \ * GetPlayerDrain \ * UpdateEnemyTimers \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyRotateTimer EQUB 0, 0, 0, 0 \ A timer for each enemy that counts down every 0.06 EQUB 0, 0, 0, 0 \ seconds and controls the rate at which the enemy \ rotates with the rotation step given in enemyYawStep \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 5 of 8) \ * ApplyTactics (Part 6 of 8) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyTacticTimer EQUB 0, 0, 0, 0 \ A timer for each enemy that counts down every 0.06 EQUB 0, 0, 0, 0 \ seconds and controls the rate at which we apply \ tactics to that enemy \ \ [Show more]\ \ This variable is used by the following: \ \ * AddEnemiesToTiles \ * ApplyTactics (Part 1 of 8) \ * ApplyTactics (Part 2 of 8) \ * ApplyTactics (Part 5 of 8) \ * ApplyTactics (Part 7 of 8) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0, 0, 0, 0 \ These bytes appear to be unused EQUB 0, 0, 0, 0 .polygonPoint EQUB 0, 0, 0, 0, 0 \ Up to five coordinates for the points of the polygon \ being drawn \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawLandscapeView (Part 1 of 3) \ * DrawObject \ * GetPolygonLines (Part 1 of 6) \ * GetPolygonLines (Part 2 of 6) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0, 0 \ These bytes appear to be unused .drawingPhase EQUB 0 \ The number of the current drawing phase when drawing \ two-phase objects: \ \ * Bit 7 = 0: first phase \ \ * Bit 7 = 1: second phase \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawObject \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.xTileLeftPrevious EQUB 2 \ The previous value of xTileViewLeft \ \ This makes the search for edges more efficient in the \ DrawLandscapeView routine as the edges in neighbouring \ rows will be close together \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawLandscapeView (Part 2 of 3) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.xTileCharacter EQUB 32 \ The tile x-coordinate of the character being spawned \ in large 3D blocks on the landscape for the title \ screen \ \ [Show more]\ \ This variable is used by the following: \ \ * SpawnCharacter3D (Part 1 of 2) \ * SpawnCharacter3D (Part 2 of 2) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.zTileCharacter EQUB 7 \ The tile z-coordinate of the character being spawned \ in large 3D blocks on the landscape for the title \ screen \ \ [Show more]\ \ This variable is used by the following: \ \ * SpawnCharacter3D (Part 1 of 2) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.drawingTitleScreen EQUB %10000000 \ A flag to indicate whether we are currently drawing a \ title screen in the DrawTitleScreen routine \ \ * Bit 7 clear = we are not drawing a title screen \ \ * Bit 7 set = we are drawing a title screen \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawTileAndObjects \ * DrawTitleScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.screenBackground EQUB 1 \ The type of screen background when clearing the screen \ \ * 0 = fill with alternating colour 0/1 (blue/black) \ pixel rows, for the sky during gameplay \ \ * 1 = fill with solid colour 0 (blue) \ \ * 2 = fill with dithered pixels in colour 0 (blue) \ and colour 3 (e.g. green in landscape 0000) \ by alternating colour 3/0/3/0 and 0/3/0/3 \ pixel bytes \ \ * 3 = fill with solid colour 1 (black) and draw 240 \ randomly positioned stars on the background \ \ [Show more]\ \ This variable is used by the following: \ \ * ClearScreen \ * DrawTitleView \ * FillScreen \ * PerformHyperspace \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.drawLandscape EQUB 0 \ Configures whether to draw the landscape behind the \ object in the DrawUpdatedObject routine \ \ * Bit 7 clear = draw the landscape behind the object \ as well as the object \ \ * Bit 7 set = just draw the object \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawUpdatedObject \ * IRQHandler \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.sentinelHasWon EQUB 0 \ A flag to record when the player runs out of energy \ (i.e. the energy level goes negative), at which point \ the Sentinel wins \ \ * Bit 7 clear = player still has positive energy \ \ * Bit 7 set = player has run out of energy and the \ Sentinel has won \ \ [Show more]\ \ This variable is used by the following: \ \ * DrainObjectEnergy \ * DrawUpdatedObject \ * IRQHandler \ * MainGameLoop \ * ProcessGameplay \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.playerTileIsHidden EQUB 0 \ A flag that records when the player is being scanned \ but the player's tile is hidden from the Sentinel or \ sentry doing the scan \ \ * 64 = player's tile is hidden from the scan \ \ * Not 64 = player's tile is visible \ \ [Show more]\ \ This variable is used by the following: \ \ * GetPlayerDrain \ * UpdateScannerNow \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.updateTimer EQUB 0 \ A counter that ensures the enemy timers are updated on \ one of every three calls to the interrupt handler \ \ [Show more]\ \ This variable is used by the following: \ \ * UpdateEnemyTimers \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.uTurnStatus EQUB 0 \ A flag to record whether we are performing or have \ just performed a U-turn \ \ * Bit 6 clear = do not perform a U-turn if "U" is \ pressed \ \ * Bit 6 set = do a U-turn if "U" is pressed \ \ Bit 6 is set in CheckForKeyPresses (which is called by \ the interrupt handler) if "U" is not being pressed, so \ this flag ensures that pressing and holding the "U" \ key does not continuously perform U-turns, and instead \ only performs a single U-turn \ \ When a "U" key press is detected in ProcessActionKeys, \ uTurnStatus is shifted left, so for the first \ iteration of the main game loop after "U" is pressed, \ bit 7 is set to indicate that we just performed a \ U-turn \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckForKeyPresses \ * MainGameLoop \ * ProcessActionKeys (Part 1 of 2) \ * ProcessGameplay \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.landscapeZero EQUB 0 \ A flag that is set depending on whether we are playing \ landscape 0000 \ \ * Zero = this is landscape 0000 \ \ * Non-zero = this is not landscape 0000 \ \ [Show more]\ \ This variable is used by the following: \ \ * GenerateLandscape \ * InitialiseSeeds \ * MainTitleLoop \ * SpawnEnemies \ * SpawnPlayer \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.G2 EQUB 0 \ Temporary storage, used in the maths routines from \ Revs, where the original variable name was G (this \ variable has been renamed to G2 to prevent a clash \ with the G variable that is used by The Sentinel) \ \ [Show more]\ \ This variable is used by the following: \ \ * GetRotationMatrix (Part 1 of 5) \ * GetRotationMatrix (Part 2 of 5) \ * GetRotationMatrix (Part 3 of 5) \ * GetRotationMatrix (Part 4 of 5) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.H2 EQUB 0 \ Temporary storage, used in the maths routines from \ Revs, where the original variable name was H (this \ variable has been renamed to H2 to prevent a clash \ with the H variable that is used by The Sentinel) \ \ [Show more]\ \ This variable is used by the following: \ \ * GetRotationMatrix (Part 1 of 5) \ * GetRotationMatrix (Part 2 of 5) \ * GetRotationMatrix (Part 3 of 5) \ * GetRotationMatrix (Part 4 of 5) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.stashOffset EQUB 0 \ The offset into the secretCodeStash where we store a \ set of generated values for later checking in the \ GetRowVisibility routine \ \ The value of stashOffset is set in the SetSecretStash \ routine during the landscape drawing process, where it \ is set to a value that is unique and consistent for \ each individual landscape \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckSecretCode (Part 1 of 2) \ * CheckSecretStash \ * SetSecretStash \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.targetOnTile EQUB 0 \ A flag to record whether the tile being analysed in \ the GetTileAltitude routine contains the target object \ whose number is in targetObject \ \ * Bit 7 clear = tile does not contain the target \ object \ \ * Bit 7 set = tile contains the target object \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckEnemyGaze (Part 2 of 2) \ * FollowGazeVector (Part 1 of 5) \ * GetTileAltitude \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objectViewYawHi EQUB 13 \ The yaw angle of the object being analysed, relative \ to the current viewer (high byte) \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 2 of 8) \ * CheckEnemyGaze (Part 2 of 2) \ * GetObjectAngles \ * GetObjPointAngles \ * GetObjVisibility \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.targetObject EQUB 0 \ The number of the object that is being targeted in the \ DrainObjectEnergy routine \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckEnemyGaze (Part 1 of 2) \ * CheckEnemyGaze (Part 2 of 2) \ * DrainObjectEnergy \ * FindObjectToDrain \ * GetTileAltitude \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objectViewYawLo EQUB &16 \ The yaw angle of the object being analysed, relative \ to the current viewer (low byte) \ \ [Show more]\ \ This variable is used by the following: \ \ * GetObjectAngles \ * GetObjPointAngles \ * GetObjVisibility \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0 \ This byte appears to be unused .objectOppositeLo EQUB &E0 \ The height of an object relative to the viewer, \ expressed as the length of the opposite side in a \ triangle with the vector from the viewer to the object \ as the hypotenuse (low byte) \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawObject \ * GetObjectAngles \ * GetObjPointAngles \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objectOppositeHi EQUB &B7 \ The height of an object relative to the viewer, \ expressed as the length of the opposite side in a \ triangle with the vector from the viewer to the object \ as the hypotenuse (high byte) \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawObject \ * GetObjectAngles \ * GetObjPointAngles \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objectAdjacentLo EQUB &E4 \ The distance of an object from the viewer, expressed \ as the length of the adjacent side in a triangle with \ the vector from the viewer to the object as the \ hypotenuse (low byte) \ \ [Show more]\ \ This variable is used by the following: \ \ * GetObjectAngles \ * GetObjPointAngles \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objectAdjacentHi EQUB &52 \ The distance of an object from the viewer, expressed \ as the length of the adjacent side in a triangle with \ the vector from the viewer to the object as the \ hypotenuse (high byte) \ \ [Show more]\ \ This variable is used by the following: \ \ * GetObjectAngles \ * GetObjPointAngles \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.sightsAreVisible EQUB 0 \ Controls whether the sights are being shown \ \ * Bit 7 clear = sights are not being shown \ \ * Bit 7 set = sights are being shown \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckForKeyPresses \ * DrawUpdatedObject \ * MainGameLoop \ * ProcessGameplay \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.printTextIn3D EQUB 0 \ Controls whether we are printing text normally or in \ 3D (as in the game's title on the title screen) \ \ * Bit 7 clear = normal text \ \ * Bit 7 set = 3D text \ \ [Show more]\ \ This variable is used by the following: \ \ * PrintDigit \ * SpawnSecretCode3D \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objectType SKIP 0 \ The type of object that we are spawning \ \ This variable shares the same memory location as \ keyPress \ \ [Show more]\ \ This variable is used by the following: \ \ * SpawnObject \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.keyPress EQUB 0 \ The key logger value for a key press \ \ This variable shares the same memory location as \ objectType \ \ This means that if the player presses one of the \ "create" keys, then the value in the key logger (as \ defined in the keyLoggerConfig table) can be used as \ the object type to create, as "Create robot" puts a 0 \ in the key logger (the object type for a robot), \ "Create tree" puts a 2 in the logger (the object type \ for a tree) and "Create boulder" puts a 3 in the \ logger (the object type for a boulder) \ \ [Show more]\ \ This variable is used by the following: \ \ * ProcessActionKeys (Part 1 of 2) \ * ProcessGameplay \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objYawOffset EQUB 0 \ The yaw offset of the left edge of the object being \ analysed in GetObjVisibility, relative to the left \ edge of the screen, in on-screen character columns \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawUpdatedObject \ * GetObjVisibility \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.playerHasMovedTile EQUB 0 \ A flag to record whether the player has moved to a new \ tile by transferring or hyperspacing, so we can decide \ whether to regenerate the player's landscape view \ \ * Bit 7 clear = player has not moved to a new tile \ \ * Bit 7 set = player has moved to a new tile \ \ [Show more]\ \ This variable is used by the following: \ \ * PerformHyperspace \ * ProcessActionKeys (Part 2 of 2) \ * ProcessGameplay \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.quitGame EQUB 0 \ A flag to record whether the player has pressed \ function key f1 to quit the game \ \ * Bit 7 clear = do not quit the game \ \ * Bit 7 set = quit the game \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckForKeyPresses \ * MainGameLoop \ * ProcessGameplay \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.secretCodeChecks EQUB 0 \ Bits 1 to 4 store the results of checking each of the \ four two-digit numbers in a landscape's secret entry \ code \ \ A set bit indicates a match while a clear bit \ indicates a failure \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckSecretCode (Part 1 of 2) \ * CheckSecretCode (Part 2 of 2) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0 \ This byte appears to be unused .boulderOnTile EQUB 0 \ A flag to record whether the tile being analysed in \ the GetTileAltitude routine contains a boulder \ \ * Bit 7 clear = tile does not contain a boulder \ \ * Bit 7 set = tile contains a boulder \ \ [Show more]\ \ This variable is used by the following: \ \ * FollowGazeVector (Part 1 of 5) \ * GetTileAltitude \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyViewingArc EQUB 0 \ The viewing arc of the enemy that is being processed \ in the ApplyTactics routine \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 1 of 8) \ * CheckEnemyGaze (Part 2 of 2) \ * ScanForMeanieTree \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.bufferColumns EQUB 0 \ The number of character columns in the current screen \ buffer \ \ [Show more]\ \ This variable is used by the following: \ \ * DitherScreenBuffer \ * DrawUpdatedObject \ * GetObjVisibility \ * PanLandscapeView \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objYawWidth EQUB 0 \ The width of the visible portion of the object being \ analysed in GetObjVisibility, in on-screen character \ columns \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawUpdatedObject \ * GetObjVisibility \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.objectStackCounter EQUB 0 \ A counter for the objects in an object stack, for use \ when drawing the stack \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawObjectStack \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.topObjectOnStack EQUB 0 \ The number of the object on the top of an object stack \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawObjectStack \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.ditherObjectSights EQUB 0 \ Configures how an updated object is drawn onto the \ screen in the DrawUpdatedObject routine \ \ * Bit 6 set = dither the updated object onto the \ screen \ \ * Bit 7 set = remove the sights from the screen \ before drawing the object \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 8 of 8) \ * DrawUpdatedObject \ * ProcessGameplay \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyCheckingRobot EQUB 0 \ A flag to pass to the FollowGazeVector routine, with \ bit 7 set if the routine is being called when an enemy \ is checking to see if it can see a robot object \ \ This allows the routine to return a positive result \ even if the viewer is below the robot and can't see \ the robot's tile (so we can show a partial scan of the \ player on the scanner) \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckEnemyGaze (Part 2 of 2) \ * FollowGazeVector (Part 1 of 5) \ * ProcessActionKeys (Part 1 of 2) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.numberOfEnemies EQUB 0 \ The number of enemies in the current landscape, \ including the Sentinel (in the range 1 to 8) \ \ [Show more]\ \ This variable is used by the following: \ \ * AddEnemiesToTiles \ * SpawnEnemies \ * SpawnTrees \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.noteCounter EQUB 0 \ The sound counter for an individual note while playing \ chords in the music player \ \ [Show more]\ \ This variable is used by the following: \ \ * ProcessMusic \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.doNotPlayLandscape EQUB 0 \ A flag that controls whether we preview and play the \ landscape after generating it \ \ * Bit 7 clear = preview and play the landscape \ \ * Bit 7 set = do not preview or play the landscape \ \ This allows us to generate a landscape and its secret \ code without actually playing it, which we need to do \ in two cases: \ \ * When the player enters an incorrect secret code \ \ * When displaying a landscape's secret code after \ the level is completed \ \ In both cases we need to generate the landscape before \ we can check or display the secret code, but we don't \ want to go on to preview or play the landscape \ \ This variable is reset to zero by the ResetVariables \ routine, so when a new game starts the default \ behaviour is to preview and play the landscape after \ generating it in the GenerateLandscape routine \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckSecretCode (Part 1 of 2) \ * PerformHyperspace \ * SmoothTileCorners (Part 2 of 4) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.gamePaused EQUB 0 \ A flag to record whether the game is paused \ \ * Bit 7 clear = the game is not paused \ \ * Bit 7 set = the game is paused \ \ [Show more]\ \ This variable is used by the following: \ \ * IRQHandler \ * ProcessPauseKeys \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.soundEffect EQUB 0 \ Determines how the current sound is processed by the \ ProcessSound routine \ \ * 0 = no processing required \ \ * 3 = music \ \ * 4 = scanner sound \ \ * 6 = game over sound \ \ [Show more]\ \ This variable is used by the following: \ \ * GetPlayerDrain \ * MainGameLoop \ * PlayMusic \ * ProcessSound \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.gameOverSoundPitch EQUB 0 \ A timer for the game over sound \ \ Sound is made in ProcessSound when the timer is 80 or \ higher, and it starts at 250 in ShowGameOverScreen and \ decrements in ProcessSound until it dips below 80, at \ which point the sound stops \ \ [Show more]\ \ This variable is used by the following: \ \ * ProcessSound \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.alteredSeed EQUB 0 \ An altered version of the anti-cracker seed-related \ data that gets created in AlterCrackerSeed and checked \ in CheckCreckerSeed as part of the anti-cracker code \ \ [Show more]\ \ This variable is used by the following: \ \ * AlterCrackerSeed \ * CheckCrackerSeed \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.treeVisibility EQUB 0 \ Reports whether a gaze is interrupted by a tree in the \ CheckEnemyGaze routine \ \ * If the target object is a robot, then bit 6 will \ be set if there is a tree blocking the view of the \ robot object \ \ * Bit 7 will be set if there is a tree blocking the \ view of the target object's tile \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 5 of 8) \ * CheckEnemyGaze (Part 2 of 2) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0 \ This byte appears to be unused .xTitleOffset EQUB 239 \ An x-coordinate offset for drawing the title screen \ this is zero during gameplay) \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawTitleView \ * GetHorizontalDelta \ * GetTileViewAngles (Part 1 of 4) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0 \ This byte appears to be unused .blendPolygonEdges EQUB &AA \ A flag to determine whether polygon edges are drawn \ in the same colour as the polygon fill, thus blending \ the edges into the polygon body \ \ * Bit 7 set = draw edges in the fill colour so they \ blend with the polygon body \ \ * Bit 7 clear = draw edges in the edge colour \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawObject \ * DrawPolygonLines (Part 1 of 4) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.seedNumberLFSR EQUB 0 \ A five-byte linear feedback shift register for EQUB 0 \ generating a sequence of seed numbers for each EQUB 1 \ landscape EQUB 0 EQUB 0 .enemyMeanieScan EQUB 0, 0, 0, 0 \ Enemy meanie scan object counter (one byte per enemy) EQUB 0, 0, 0, 0 \ \ A counter that works through all the object numbers as \ we scan the objects from last to first for a tree to \ turn into a meanie \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 4 of 8) \ * ResetMeanieScan \ * ScanForMeanieTree \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyEnergy EQUB 0, 0, 0, 0 \ Enemy energy levels (one byte per enemy) EQUB 0, 0, 0, 0 \ \ If an enemy has a non-zero energy level, it will try \ to expend that energy on the landscape by creating a \ tree \ \ [Show more]\ \ This variable is used by the following: \ \ * DrainObjectEnergy \ * ExpendEnemyEnergy \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyFailTarget EQUB 0, 0, 0, 0 \ Enemy failed to find meanie: target object (one byte EQUB 0, 0, 0, 0 \ per enemy) \ \ If an enemy searches for a tree to turn into a meanie \ to attack a target enemy on its behalf, but it can't \ find a suitable tree, then the target object number is \ stored here so the enemy doesn't try looking again \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 5 of 8) \ * ResetMeanieScan \ * ScanForMeanieTree \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyFailCounter EQUB 0, 0, 0, 0 \ Enemy failed to find meanie: counter (one byte per EQUB 0, 0, 0, 0 \ enemy) \ \ If an enemy searches for a tree to turn into a meanie \ to attack a target enemy on its behalf, but it can't \ find a suitable tree, then this counter is incremented \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 7 of 8) \ * ResetMeanieScan \ * ScanForMeanieTree \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyMeanieTree EQUB 0, 0, 0, 0 \ Enemy has turned a tree into a meanie (one byte per EQUB 0, 0, 0, 0 \ enemy) \ \ * Bit 7 clear = the enemy has turned a tree into a \ meanie and the object number of the \ tree/meanie is in bits 0 to 6 \ \ * Bit 7 set = the enemy has not turned a tree into a \ meanie \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 1 of 8) \ * ApplyTactics (Part 2 of 8) \ * ApplyTactics (Part 7 of 8) \ * ProcessActionKeys (Part 2 of 2) \ * ResetMeanieScan \ * ScanForMeanieTree \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyTarget EQUB 0, 0, 0, 0 \ The object number of the enemy's target (one byte per EQUB 0, 0, 0, 0 \ enemy) \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 2 of 8) \ * ApplyTactics (Part 5 of 8) \ * ApplyTactics (Part 7 of 8) \ * GetPlayerDrain \ * ScanForMeanieTree \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyVisibility EQUB 0, 0, 0, 0 \ Visibility of the enemy's target (one byte per enemy) EQUB 0, 0, 0, 0 \ \ * Bit 7 set = the enemy can see the target's tile \ \ * Bit 6 set = the enemy can see the target object \ but it can't see the target's tile \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 7 of 8) \ * GetPlayerDrain \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.enemyDrainScan EQUB 0, 0, 0, 0 \ Enemy will perform a scan for a drainable object (one EQUB 0, 0, 0, 0 \ byte per enemy) \ \ * Bit 7 set = the next time we apply tactics to the \ enemy, it will scan the landscape for \ a suitable object for draining of \ energy (i.e. an exposed boulder or a \ tree on top of another object, where \ the enemy can see the object's tile) \ \ * Bit 7 clear = the enemy will not scan for a \ drainable object \ \ [Show more]\ \ This variable is used by the following: \ \ * ApplyTactics (Part 4 of 8) \ * ApplyTactics (Part 7 of 8) \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0 \ This byte appears to be unused .scrollCounter EQUB 0 \ A counter for the number of columns or rows we still \ need to scroll in the player's scrolling landscape \ view when the player pans \ \ Scrolling is implemented in the interrupt handler one \ column or row at a time, scrolling one character block \ width or height at each step via the ScrollPlayerView \ routine \ \ This counter keeps track of each step, decrementing \ after each column or row is scrolled, so we only \ scroll when scrollCounter is non-zero \ \ [Show more]\ \ This variable is used by the following: \ \ * IRQHandler \ * MainGameLoop \ * ScrollPlayerView \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.viewScreenAddr EQUW &60C0 \ The screen address of the player's scrolling landscape \ view, which is just below the icon and scanner row at \ the top of the screen \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawRandomDots \ * DrawUpdatedObject \ * GetIconRowAddress \ * InitialiseSights \ * ResetScreenAddress \ * ScrollPlayerView \ * UpdateScannerNow \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.sightsScreenAddr EQUW 0 \ The screen address of the sights \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawSights \ * InitialiseSights \ * SetSightsAddress \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.xSights EQUB 0 \ The pixel x-coordinate of the sights on-screen \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawSights \ * GetSightsVector \ * InitialiseSights \ * MoveSightsSideways \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.ySights EQUB 0 \ The pixel y-coordinate of the sights on-screen \ \ [Show more]\ \ This variable is used by the following: \ \ * GetSightsVector \ * InitialiseSights \ * MoveSightsUpDown \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.sightsInitialMoves EQUB 0 \ Controls the initial movement of the sights over the \ first eight calls to the CheckForKeyPresses routine \ \ Movement in the first eight calls is determined by \ the settings of bit 7 to bit 0, where a set bit \ indicates a pause and a clear bit indicates a move \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckForKeyPresses \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.sightsByteCount EQUB 0 \ The number of screen bytes in the sights pixel byte \ stash that contain the contents of the screen behind \ the sights (so they can be restored to remove the \ sights) \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawSights \ * MainGameLoop \ * RemoveSights \ * ShowGameOverScreen \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.iconRowAddr EQUW &7F80 \ The screen address of the icon and scanner row along \ the top of the screen \ \ [Show more]\ \ This variable is used by the following: \ \ * GetIconRowAddress \ * ScrollPlayerView \ * ShowIconBuffer \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.xSightsBrush EQUB 0 \ The x-coordinate of the "brush" that we use to draw \ the sights, relative to the top-left corner of the \ character block containing the top of the sights \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawSights \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.pixelByteToDither EQUB 0 \ A random pixel byte in a character row in the screen \ buffer to use when dithering an object to the screen \ \ [Show more]\ \ This variable is used by the following: \ \ * DitherScreenBuffer \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.doNotCheckSecret EQUB 0 \ A flag to control whether we perform the secret code \ check that's buried in the GetRowVisibility routine \ \ * Bit 7 clear = perform check \ \ * Bit 7 set = do not perform check \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckSecretStash \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.bitMaskDither EQUB 0 \ A bit mask for use in the DitherScreenBuffer routine \ that has a matching number of leading zeroes as the \ size of the screen buffer in bytes \ \ [Show more]\ \ This variable is used by the following: \ \ * DitherScreenBuffer \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.ditherRandom EQUB 0 \ Storage for a random value in the DitherScreenBuffer \ routine \ \ [Show more]\ \ This variable is used by the following: \ \ * DitherScreenBuffer \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.numberOfScrolls EQUB 0 \ The total number of scrolls that we need to perform \ for the current panning operation \ \ This is used to initialise the value of the scroll \ counter in scrollCounter before we start scrolling \ \ [Show more]\ \ This variable is used by the following: \ \ * MainGameLoop \ * StartScrollingView \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.ditherInnerLoop EQUB 0 \ A counter for the inner loop when dithering objects to \ the screen in the DitherScreenBuffer routine \ \ [Show more]\ \ This variable is used by the following: \ \ * DitherScreenBuffer \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.bufferWidthBytes EQUB 0 \ The width of the screen buffer in pixel bytes for \ implementing the dithered effect in DitherScreenBuffer \ \ [Show more]\ \ This variable is used by the following: \ \ * DitherScreenBuffer \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.minObjWidth EQUB 0 \ The on-screen width to use when updating objects \ \ When set to a non-zero width, this width is taken into \ consideration when calculating how much of an object \ visible on-screen, particularly when an object is \ being updated \ \ [Show more]\ \ This variable is used by the following: \ \ * DrainObjectEnergy \ * GetObjVisibility \ * ScanForMeanieTree \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0, 0 \ These bytes appear to be unused .doNotDrawSights EQUB 0 \ A flag that controls whether we draw the sights in the \ DrawSights routine \ \ * Bit 7 clear = draw the sights \ \ * Bit 7 set = do not draw the sights \ \ [Show more]\ \ This variable is used by the following: \ \ * DrawSights \ * DrawUpdatedObject \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0, 0, 0, 0 \ These bytes appear to be unused .previousFocus EQUB 0 \ The previous setting of focusOnKeyAction, so we can \ detect (in the ProcessGameplay routine) whether the \ player is still holding down a pan key after we finish \ scrolling the screen for the previous pan \ \ [Show more]\ \ This variable is used by the following: \ \ * FocusOnKeyAction \ * ProcessGameplay \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.gazeCanSeeTree EQUB 0 \ A flag to record whether the gaze vector can see a \ tree: \ \ * Bit 7 clear = gaze vector cannot see a tree \ \ * Bit 7 set = gaze vector can see a tree \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckEnemyGaze (Part 2 of 2) \ * FollowGazeVector (Part 1 of 5) \ * GetTileAltitude \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.hyperspaceEndsGame EQUB 0 \ Records whether the player performing a hyperspace has \ just ended the game \ \ * Bit 7 set = the player has hyperspaced and has \ ended the game (see bit 6 for the \ details) \ \ Bit 7 clear = the game has not been ended by a \ hyperspace action \ \ * Bit 6 set = the player has won by hyperspacing \ from the Sentinel's tower \ \ Bit 6 clear = the player has run out of energy by \ trying to hyperspace without being \ able to create a robot into which \ they can hyperspace \ \ [Show more]\ \ This variable is used by the following: \ \ * GetTileVisibility \ * MainGameLoop \ * PerformHyperspace \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.soundCounter EQUB 0 \ A counter for the sound currently being made, which \ counts down in the IRQHandler routine at a rate of 50 \ times a second \ \ When the counter reaches zero, it indicates that the \ sound has finished \ \ [Show more]\ \ This variable is used by the following: \ \ * IRQHandler \ * MainGameLoop \ * ProcessMusic \ * ProcessSound \ * ProcessVolumeKeys \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0, 0, 0, 0 \ These bytes appear to be unused .focusOnKeyAction EQUB %10000000 \ A flag that determines whether the game should focus \ effort on implementing a key action, such as a pan of \ the landscape view \ \ * Bit 7 clear = run everything normally \ \ * Bit 7 set = focus effort on the key action \ \ Specifically, setting bit 7 disables the following \ keyboard scans: \ \ * Volume keys in ProcessVolumeKeys \ \ * Game key presses in IRQHandler \ \ * Game key presses in ProcessGameplay \ \ This speeds things up so the action can be implemented \ more quickly and without having to run unnecessary \ keyboard scans \ \ [Show more]\ \ This variable is used by the following: \ \ * FocusOnKeyAction \ * IRQHandler \ * ProcessGameplay \ * ProcessVolumeKeys \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.activateSentinel EQUB %10000000 \ A flag to record when the Sentinel is activated at the \ start of the game (by the player pressing a key that \ expends or absorbs energy \ \ * Bit 7 clear = the Sentinel is activated \ \ * Bit 7 set = the Sentinel is not yet activated \ \ This gives the player time to get their bearings when \ they first start a landscape \ \ [Show more]\ \ This variable is used by the following: \ \ * IRQHandler \ * ProcessGameplay \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.playerIsOnTower EQUB 128 \ A flag to record whether the player is on top of the \ the Sentinel's tower \ \ * 6 = the player is on top of the Sentinel's tower \ \ * Any other value = the player is not on top of the \ Sentinel's tower \ \ This value is used when generating the secret code on \ completion of a level, where an incorrect value will \ corrupt the code (so this forms part of the cracker \ protection code) \ \ [Show more]\ \ This variable is used by the following: \ \ * SetPlayerIsOnTower \ * SpawnSecretCode3D \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.musicCounter EQUB %10000000 \ A counter for the music currently being made, which \ counts up in the ProcessMusic routine while the music \ is being played \ \ If bit 7 is set then there is no music being played \ \ [Show more]\ \ This variable is used by the following: \ \ * MainGameLoop \ * PlayMusic \ * ProcessMusic \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.keyLogger EQUB &80, &80 \ The four-byte key logger for logging game key presses EQUB &80, &80 EQUB &80, &80 \ These bytes appear to be unused EQUB &80, &80 .inputBuffer EQUB 0, 0, 0, 0 \ The eight-byte keyboard input buffer EQUB 0, 0, 0, 0 \ \ Key presses are stored in the input buffer using an \ ascending stack, with new input being pushed into \ inputBuffer, and any existing content in the buffer \ moving up in memory \ \ [Show more]\ \ This variable is used by the following: \ \ * CheckSecretCode (Part 1 of 2) \ * DigitToNumber \ * MainTitleLoop \ * PrintInputBuffer \ * ReadNumber \ * StringToNumber \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0, 0, 0, 0 \ These bytes appear to be unused .gameInProgress EQUB %11000000 \ Flags whether or not a game is in progress (i.e. the \ player is playing a landscape rather than interacting \ with the title and preview screens) \ \ * Bit 7 clear = game is in progress \ \ * Bit 7 set = game is not in progress \ \ This controls whether or not the interrupt handler \ updates the game \ \ [Show more]\ \ This variable is used by the following: \ \ * ConfigureMachine \ * IRQHandler \ * PlayGame \ * ResetVariables \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.landscapeNumberLo EQUB 0 \ The low byte of the four-digit binary coded decimal \ landscape number (0000 to 9999) \ \ [Show more]\ \ This variable is used by the following: \ \ * FinishLandscape \ * InitialiseSeeds \ * MainGameLoop \ * PrintLandscapeNum \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned above.landscapeNumberHi EQUB 0 \ The high byte of the four-digit binary coded decimal \ landscape number (0000 to 9999) \ \ [Show more]\ \ This variable is used by the following: \ \ * FinishLandscape \ * GetEnemyCount \ * InitialiseSeeds \ * MainGameLoop \ * PrintLandscapeNum \ \ This list only includes code that refers to the \ variable by name; there may be other references to \ this memory location that don't use this label, and \ these will not be mentioned aboveEQUB 0 \ This byte appears to be unused.NMIHandler RTI \ This is the address of the current NMI handler, at \ the start of the NMI workspace at address &0D00 \ \ We put an RTI instruction here to make sure we return \ successfully from any NMIs that call this workspaceName: NMIHandler [Show more] Type: Subroutine Category: Setup Summary: The NMI handler at the start of the NMI workspaceContext: See this subroutine on its own page References: No direct references to this subroutine in this source file.irq1Address EQUW &DC93 \ This value is workspace noise and has no meaningName: irq1Address [Show more] Type: Variable Category: Main game loop Summary: Stores the previous value of IRQ1V before we install our custom IRQ handlerContext: See this variable on its own page References: This variable is used as follows: * ConfigureMachine uses irq1Address * IRQHandler uses irq1Address.Multiply8x8 STA T \ Set T = A \ We now calculate (A T) = T * U \ = A * U LDA #0 \ Set A = 0 so we can start building the answer in A LSR T \ Set T = T >> 1 \ and C flag = bit 0 of T \ We are now going to work our way through the bits of \ T, and do a shift-add for any bits that are set, \ keeping the running total in A, and instead of using a \ loop, we unroll the calculation, starting with bit 0 BCC P%+5 \ If C (i.e. the next bit from T) is set, do the CLC \ addition for this bit of T: ADC U \ \ A = A + U ROR A \ Shift A right to catch the next digit of our result, \ which the next ROR sticks into the left end of T while \ also extracting the next bit of T ROR T \ Add the overspill from shifting A to the right onto \ the start of T, and shift T right to fetch the next \ bit for the calculation into the C flag BCC P%+5 \ Repeat the shift-and-add loop for bit 1 CLC ADC U ROR A ROR T BCC P%+5 \ Repeat the shift-and-add loop for bit 2 CLC ADC U ROR A ROR T BCC P%+5 \ Repeat the shift-and-add loop for bit 3 CLC ADC U ROR A ROR T BCC P%+5 \ Repeat the shift-and-add loop for bit 4 CLC ADC U ROR A ROR T BCC P%+5 \ Repeat the shift-and-add loop for bit 5 CLC ADC U ROR A ROR T BCC P%+5 \ Repeat the shift-and-add loop for bit 6 CLC ADC U ROR A ROR T BCC P%+5 \ Repeat the shift-and-add loop for bit 7 CLC ADC U ROR A ROR T RTS \ Return from the subroutineName: Multiply8x8 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate (A T) = T * UContext: See this subroutine on its own page References: This subroutine is called as follows: * FollowGazeVector (Part 5 of 5) calls Multiply8x8 * GetObjPointAngles calls Multiply8x8 * GetRotationMatrix (Part 2 of 5) calls Multiply8x8 * Multiply16x16 calls Multiply8x8 * Multiply8x16 calls Multiply8x8 * ProcessTileData calls Multiply8x8 * Multiply8x16 calls via Multiply8x8+2
Do the following multiplication of two unsigned 8-bit numbers: (A T) = A * U This routine is from Revs, Geoff Crammond's previous game.
Returns: X X is unchanged
Other entry points: Multiply8x8+2 Calculate (A T) = T * U.GetAngleFromCoords \ We start by calculating the following using a similar \ shift-and-subtract algorithm as Revs: \ \ T = 256 * (A T) / (V W) \ \ In Revs, W is always zero, so there is some extra code \ below to cater for a full 16-bit value in (V W) ASL T \ Shift T left, which clears bit 0 of T, ready for us to \ start building the result in T at the same time as we \ shift the low byte of (A T) out to the left \ We now repeat the following seven-instruction block \ eight times, one for each bit in T ROL A \ Shift the high byte of (A T) to the left to extract \ the next bit from the number being divided BCS gang1 \ If we just shifted a 1 out of A, skip the next few \ instructions and jump straight to the subtraction CMP V \ If A < V then jump to gang2 with the C flag clear, so BCC gang2 \ we shift a 0 into the result in T \ This part of the routine has been added to the Revs \ algorithm to cater for both arguments being full \ 16-bit values (in Revs the second value always has a \ low byte of zero) BNE gang1 \ If A > V then jump to gang1 to calculate a full 16-bit \ subtraction \ If we get here then A = V LDY T \ If T < W then jump to gang2 with the C flag clear, so CPY W \ we shift a 0 into the result in T BCC gang2 .gang1 \ If we get here then T >= W and A >= V, so we know that \ (A T) >= (V W) \ \ We now calculate (A T) - (V W) as the subtraction part \ of the shift-and-subtract algorithm STA U \ Store A in U so we can retrieve it after the following \ calculation LDA T \ Subtract the low bytes as T = T - W SBC W \ STA T \ This calculation works as we know the C flag is set, \ as we passed through a BCC above LDA U \ Restore the value of A from before the subtraction SBC V \ Subtract the high bytes as A = A - V SEC \ Set the C flag so we shift a 1 into the result in T .gang2 ROL T \ Shift the result in T to the left, pulling the C flag \ into bit 0 ROL A \ Repeat the 16-bit shift-and-subtract loop for the BCS gang3 \ second shift CMP V BCC gang4 BNE gang3 LDY T CPY W BCC gang4 .gang3 STA U \ Repeat the 16-bit subtraction for the second shift LDA T SBC W STA T LDA U SBC V SEC .gang4 ROL T \ Shift the result for the second shift into T ROL A \ Repeat the 16-bit shift-and-subtract loop for the BCS gang5 \ third shift CMP V BCC gang6 BNE gang5 LDY T CPY W BCC gang6 .gang5 STA U \ Repeat the 16-bit subtraction for the third shift LDA T SBC W STA T LDA U SBC V SEC .gang6 PHP \ Store the C flag on the stack, so the stack contains \ the result bit from shifting and subtracting the third \ shift CMP V \ If A = V then jump to gang10 with the C flag set, as BEQ gang10 \ we can skip the rest of the shifts and still get a \ good result ASL T \ Shift a zero for the third shift into T, so bit 5 of \ the result is always clear \ \ We do this so we can set this bit later, depending on \ the value that we stored on the stack above ROL A \ Repeat the shift-and-subtract loop for the fourth BCS P%+6 \ shift CMP V BCC P%+5 SBC V SEC ROL T ROL A \ Repeat the shift-and-subtract loop for the fifth shift BCS P%+6 CMP V BCC P%+5 SBC V SEC ROL T ROL A \ Repeat the shift-and-subtract loop for the sixth shift BCS P%+6 CMP V BCC P%+5 SBC V SEC ROL T ROL A \ Repeat the shift-and-subtract loop for the seventh BCS P%+6 \ shift CMP V BCC P%+5 SBC V SEC ROL T ROL A \ Repeat the shift-and-subtract loop for the eighth BCS P%+6 \ shift CMP V BCC P%+5 SBC V SEC ROL T \ We now have the division result that we want: \ \ T = 256 * (A T) / (V W) \ \ but with bit 5 clear rather than the actual result \ \ This result can be used to look up the resulting angle \ from the arctangent table, but first we continue the \ division to enable us to improve accuracyName: GetAngleFromCoords (Part 1 of 3) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Given the coordinates along two axes, calculate the pitch or yaw angle to those coordinatesContext: See this subroutine on its own page References: This subroutine is called as follows: * GetHypotenuseAngle calls GetAngleFromCoords
The first part of this routine is based on the Divide16x16 routine in Revs, Geoff Crammond's previous game, except it supports a divisor (V W) instead of (V 0), though only the top three bits of W are included in the calculation. The calculation is as follows: angle(Hi Lo) = arctan( (A T) / (V W) ) where (A T) < (V W).
Arguments: (A T) First coordinate as an unsigned integer (V W) Second coordinate as an unsigned integer
Returns: angle(Hi Lo) The pitch or yaw angle from the origin to the coordinate angleTangent Contains 256 * (A T) / (V W), which is the tangent of the pitch or yaw angle\ We now do two more shift-and-subtracts to see if we \ can should make the result more accurate in part 3 \ with interpolation and rounding ROL A \ Repeat the shift-and-subtract loop for the ninth BCS P%+6 \ shift, but without updating the result in T CMP V BCC P%+5 SBC V SEC ROR G \ Shift the carry into bit 7 of G, so it contains the \ result from shifting and subtracting bit 8 ROL A \ Repeat the shift-and-subtract loop for the tenth BCS gang7 \ shift, but without subtracting or updating the result CMP V \ in T .gang7 ROR G \ Shift the carry into bit 7 of G, so it contains the \ result from shifting and subtracting the tenth shift, \ and the result from the ninth shift is now in bit 6 \ of G \ \ So G now contains two results bits as follows: \ \ * Bit 6 is the first extra bit from the result, \ and if it is set then we apply interpolation to \ the result in part 3 \ \ * Bit 7 is the second extra bit from the result, \ and if it is set then we apply rounding to the \ result in part 3 \ \ We use these below to work out whether to interpolate \ results from the arctan lookup table, to improve the \ accuracy of the result LDA T \ Set A to the result of the division we did above, so \ we now have the following: \ \ A = 256 * (A T) / (V W) \ \ but with bit 5 clear rather than the actual result \ and the next two result bits in bits 6 and 7 of Q .gang8 \ We now use the result of the third shift of the \ shift-and-subtract calculation to set bit 5 in the \ result, which we cleared in the calculation above PLP \ Retrieve the result bit from the third shift, which \ we stored on the stack in part 1 \ \ This bit represents the third bit pushed into the \ result, so that's what should be bit 5 of the result \ \ It is now in the C flag (because it was in the C flag \ when we performed the PHP to push it onto the stack) BCC gang9 \ If the C flag is clear then bit 5 of the result should \ remain clear, so skip the following \ Otherwise bit 5 of the result should be set, which we \ can do with the following addition (in which we know \ that the C flag is set, as we just passed through a \ BCC instruction) ADC #%00100000 - 1 \ Set A = A + %00100000 - 1 + C \ = A + %00100000 \ \ If we get here having done all ten shifts, then we \ know that bit 5 of the result in A is clear, as we \ cleared it with the ASL T instruction just after gang6 \ above, so this just sets bit 5 of the result in A \ without any risk of the addition overflowing \ \ If, however, we get here by aborting the sequence of \ shifts after the second shift and jumping to gang10, \ then we have already set bit 5 of the result with an \ ORA instruction in gang10 before jumping back to \ gang8, so there is a possibility for this addition to \ overflow .gang9 BCC gang11 \ If the above addition was skipped, or it was applied \ and didn't overflow, then jump to gang11 to continue \ with the calculation \ If we get here then the above addition overflowed, so \ we return the highest angle possible from the table, \ which is 45 degrees LDA #255 \ Set angleTangent = 255, which is the closest we can STA angleTangent \ get to the tangent of 45 degrees, which should really \ be represented by (1 0) in our scale LDA #&00 \ Set angle(Hi Lo) = (&20 0) STA angleLo \ LDA #&20 \ This represents an angle of 45 degrees, as a full STA angleHi \ circle of 360 degrees is represented by (1 0 0), and: \ \ 360 degrees / 8 = 45 \ \ 256 / 8 = &20 RTS \ Return from the subroutine .gang10 \ If we get here then we have stopped shifting and \ subtracting after just three shifts \ \ We stored the first two shifts in T, but didn't store \ the third shift in T LDA #0 \ Clear bits 6 and 7 of G to indicate that we should not STA G \ apply interpolation or rounding in part 3 ROR T \ Set A to the bottom two bits of T, which is the same ROR A \ result as if we had shifted T left through the rest of ROR T \ the shift-and-subtract process that we've skipped ROR A ORA #%00100000 \ Set bit 5 of the result in A \ \ So we now have the result of the division in A JMP gang8 \ Jump to gang8 to continue the processing from the end \ of the division processName: GetAngleFromCoords (Part 2 of 3) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Overflow and accuracy calculationsContext: See this subroutine on its own page References: No direct references to this subroutine in this source file.gang11 \ By this point we have calculated the following: \ \ A = 256 * (A T) / (V W) \ \ so now we calculate arctan(A) TAY \ Set Y to the value of A so we can use it as an index \ into the arctan tables STA angleTangent \ Set angleTangent = 256 * (A T) / (V W) \ \ So we return the tangent from the routine in \ angleTangent LDA arctanLo,Y \ Set angle(Hi Lo) = arctan(Y) STA angleLo LDA arctanHi,Y STA angleHi \ We now improve the accuracy of this result by applying \ interpolation and rounding, but only if one of bit 6 \ or bit 7 is set in G BIT G \ If bit 7 of G is set, jump to gang12 to calculate BMI gang12 \ a value in (U T) that we can then use for rounding up \ the result of the interpolation BVS gang14 \ If bit 7 of G is clear and bit 6 of G is set, jump to \ gang14 to interpolate the result with the next entry \ in the arctan table, without using rounding JMP gang16 \ Otherwise both bit 7 and bit 6 of G must be clear, so \ jump to gang16 to return from the subroutine, as the \ result in angle(Hi Lo) is already accurate and doesn't \ need interpolating .gang12 \ If we get here then we need to apply rounding to the \ result as well as interpolating the result between \ arctan(Y) and arctan(Y + 1) LDA angleLo \ Set (A T) = angle(Hi Lo) - arctan(Y + 1) SEC \ = arctan(Y) - arctan(Y + 1) SBC arctanLo+1,Y \ STA T \ So (A T) contains the amount of rounding we need to LDA angleHi \ add to the result (the result is divided by two below) SBC arctanHi+1,Y BIT G \ If bit 6 of G is set, negate (A T) to give the correct BVC gang13 \ sign to the amount of rounding JSR Negate16Bit .gang13 STA U \ Set (U T) = (A T) \ = arctan(Y) - arctan(Y + 1) ROL A \ Set the C flag to bit 7 of A, which is the top bit of \ (U T), so the next instruction rotates the correct \ bit into bit 7 of U to retain the sign of the result ROR U \ Set (U T) = (U T) / 2 ROR T \ = arctan(Y) - arctan(Y + 1) \ \ So (U T) contains half the difference between \ arctan(Y) and arctan(Y + 1) \ \ This is effectively half the difference between the \ two values, so this is the equivalent of the 0.5 in \ INT(x + 0.5) when rounding x to the nearest integer, \ just with the arctan results in our calculation .gang14 \ If we get here then we need to interpolate the result \ between arctan(Y) and arctan(Y + 1) LDA angleLo \ Set angle(Hi Lo) = angle(Hi Lo) + arctan(Y + 1) CLC \ = arctan(Y) + arctan(Y + 1) ADC arctanLo+1,Y \ STA angleLo \ We will divide this value by two to get the average LDA angleHi \ of arctan(Y) and arctan(Y + 1), but first we need to ADC arctanHi+1,Y \ add the rounding in (U T), if applicable STA angleHi BIT G \ If bit 7 of G is clear, jump to gang15 to skip the BPL gang15 \ following, as the rounding in (U T) is only applied \ when bit 7 of G is set \ If we get here then bit 7 of G is set and we need to \ add on the rounding in (U T) LDA angleLo \ Set angle(Hi Lo) = angle(Hi Lo) + (U T) CLC ADC T STA angleLo LDA angleHi ADC U STA angleHi .gang15 LSR angleHi \ Set angle(Hi Lo) = angle(Hi Lo) / 2 ROR angleLo \ \ So we now have the average value of arctan(Y) and \ arctan(Y + 1), including rounding if applicable, so \ the result has now been interpolated for more accuracy .gang16 RTS \ Return from the subroutineName: GetAngleFromCoords (Part 3 of 3) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Calculate the arctangent to get the angleContext: See this subroutine on its own page References: No direct references to this subroutine in this source file.GetRotationMatrix STA J \ Set (J T) = (A T) \ = vectorYawAngle or vectorPitchAngle \ \ Note that because this routine is copied almost \ verbatim from Revs, the commentary only refers to yaw \ angles, but this routine can work just as well with \ pitch angles as arguments STX xStoreMatrix \ Store X in xStoreMatrix so it can be preserved across \ calls to the routine JSR GetAngleInRadians \ Set (U A) to the vectorYawAngle, reduced to a quarter \ circle, converted to radians, and halved \ \ Let's call this yawRadians / 2, where yawRadians is \ the reduced player yaw angle in radians STA G2 \ Set (U G) = (U A) = yawRadians / 2 LDA U \ Set (A G) = (U G) = yawRadians / 2 STA H2 \ Set (H G) = (A G) = yawRadians / 2 \ So we now have: \ \ (H G) = (A G) = (U G) = yawRadians / 2 \ \ This is the angle vector that we now project onto the \ x- and z-axes of the world 3D coordinate system LDX #1 \ Set X = 0 and secondAxis = 1, so we project sin(H G) STX secondAxis \ into sinAngle and cos(H G) into cosAngle LDX #0 BIT J \ If bit 6 of J is clear, then vectorYawAngle is in one BVC rotm1 \ of these ranges: \ \ * 0 to 63 (%00000000 to %00111111) \ \ * -128 to -65 (%10000000 to %10111111) \ \ The degree system in the Sentinel looks like this: \ \ 0 \ -32 | +32 Overhead view of player \ \ | / \ \ | / 0 = looking straight ahead \ \|/ +64 = looking sharp right \ -64 -----+----- +64 -64 = looking sharp left \ /|\ \ / | \ \ / | \ \ -96 | +96 \ 128 \ \ So vectorYawAngle is in the top-right or bottom-left \ quarter in the above diagram \ \ In both cases we jump to rotm1 to set sinAngle and \ cosAngle \ If we get here then bit 6 of J is set, so \ vectorYawAngle is in one of these ranges: \ \ * 64 to 127 (%01000000 to %01111111) \ \ * -64 to -1 (%11000000 to %11111111) \ \ So vectorYawAngle is in the bottom-right or top-left \ quarter in the above diagram \ \ In both cases we set the variables the other way \ round, as the triangle we draw to calculate the angle \ is the opposite way round (i.e. it's reflected in the \ x-axis or y-axis) INX \ Set X = 1 and secondAxis = 0, so we project sin(H G) DEC secondAxis \ into cosAngle and cos(H G) into sinAngle \ We now enter a loop that sets sinAngle + X to \ sin(H G) on the first iteration, and sets \ sinAngle + secondAxis to cos(H G) on the second \ iteration \ \ The commentary is for the sin(H G) iteration, see the \ end of the loop for details of how the second \ iteration calculates cos(H G) instead .rotm1 \ If we get here, then we are set up to calculate the \ following: \ \ * If vectorYawAngle is top-right or bottom-left: \ \ sinAngle = sin(vectorYawAngle) \ cosAngle = cos(vectorYawAngle) \ \ * If vectorYawAngle is bottom-right or top-left: \ \ sinAngle = cos(vectorYawAngle) \ cosAngle = sin(vectorYawAngle) \ \ In each case, the calculation gives us the correct \ coordinate, as the second set of results uses angles \ that are "reflected" in the x-axis or y-axis by the \ capping process in the GetAngleInRadians routine CMP #122 \ If A < 122, i.e. U < 122 and H < 122, jump to rotm2 BCC rotm2 \ to calculate sin(H G) for smaller angles BCS rotm3 \ Jump to rotm3 to calculate sin(H G) for larger angles \ (this BCS is effectively a JMP as we just passed \ through a BCS) LDA G2 \ It doesn't look like this code is ever reached, so CMP #240 \ presumably it's left over from development BCS rotm3Name: GetRotationMatrix (Part 1 of 5) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Calculate the rotation matrix for rotating the pitch or yaw angle for the sights into the global 3D coordinate systemContext: See this subroutine on its own page References: This subroutine is called as follows: * GetVectorForAngles calls GetRotationMatrix
This routine is used to calculate the following: sinAngle = sin(vectorPitchAngle) cosAngle = cos(vectorPitchAngle) or: sinAngle = sin(vectorYawAngle) cosAngle = cos(vectorYawAngle) We can use these to convert the pitch and yaw angles of the vector from the player's eyes to the sights into a cartesian vector within the 3D world. This routine is from Revs, Geoff Crammond's previous game. There are only minor differences: the argument is (A T) instead of (A X), and the value of X is preserved. Note that to avoid clashing names, the variables G and H have been renamed to G2 and H2, but the routine is otherwise the same. For the calculations in The Sentinel we don't need a full rotation matrix, but the Revs routine calculates the values that we do need, as mentioned above. I could have renamed this routine for The Sentinel to something like GetSinAndCos16, as all it does is calculate the sine and cosine to 16-bit accuracy, but I've left the Revs code alone as much as possible to show the influence of Geoff Crammond's previous game. Also, because this routine comes from Revs, where it is only used to rotate through the driver's yaw angle, I have renamed the result variables from sinYawAngle and cosYawAngle to sinAngle and cosAngle, as The Sentinel uses the routine to rotate through both yaw angles and pitch angles. To keep things simple the commentary still refers to yaw angles, but the calculations apply equally to pitch angles.
Arguments: (A T) The pitch or yaw angle to encapsulate in the rotation matrix
Returns: X X is preserved.rotm2 \ If we get here then (U G) = yawRadians / 2 and U < 122 LDA #171 \ Set A = 171 JSR Multiply8x8 \ Set (A T) = (A * U) * U JSR Multiply8x8 \ = A * U^2 \ = 171 * (yawRadians / 2)^2 STA V \ Set (V T) = (A T) \ = 171 * (yawRadians / 2)^2 JSR Multiply8x16 \ Set (U T) = U * (V T) / 256 \ = (171 / 256) * (yawRadians / 2)^3 \ = 2/3 * (yawRadians / 2)^3 LDA G2 \ Set (A T) = (H G) - (U T) SEC \ = yawRadians / 2 - 2/3 * (yawRadians / 2)^3 SBC T \ STA T \ starting with the low bytes LDA H2 \ And then the high bytes SBC U ASL T \ Set (A T) = (A T) * 2 ROL A \ So we now have the following in (A T): \ \ (yawRadians / 2 - 2/3 * (yawRadians / 2)^3) * 2 \ \ = yawRadians - 4/3 * (yawRadians / 2)^3 \ \ = yawRadians - 4/3 * yawRadians^3 / 2^3 \ \ = yawRadians - 8/6 * yawRadians^3 * 1/8 \ \ = yawRadians - 1/6 * yawRadians^3 \ \ = yawRadians - yawRadians^3 / 3! \ \ The Taylor series expansion of sin(x) starts like \ this: \ \ sin(x) = x - (x^3 / 3!) + (x^5 / 5!) - ... \ \ If we take the first two parts of the series and \ apply them to yawRadians, we get: \ \ sin(yawRadians) = yawRadians - (yawRadians^3 / 3!) \ \ which is the same as our value in (A T) \ \ So the value in (A T) is equal to the first two parts \ of the Taylor series, and we have effectively just \ calculated an approximation of this: \ \ (A T) = sin(yawRadians) STA sinAngleHi,X \ Set sinAngle(Hi Lo) = (A T) LDA T \ AND #%11111110 \ with the sign bit cleared in bit 0 of sinAngleLo to STA sinAngleLo,X \ denote a positive result JMP rotm5 \ Jump to rotm5 to move on to the next axisName: GetRotationMatrix (Part 2 of 5) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Calculate sin(H G) for smaller anglesContext: See this subroutine on its own page References: No direct references to this subroutine in this source file.rotm3 \ If we get here then (H G) = yawRadians / 2 and \ H >= 122 \ PI is represented by 804, as 804 / 256 = 3.14, so 201 \ represents PI/4, which we use in the following \ subtraction LDA #0 \ Set (U T) = (201 0) - (H G) SEC \ = PI/4 - yawRadians / 2 SBC G2 \ STA T \ starting with the low bytes LDA #201 \ And then the high bytes SBC H2 STA U STA V \ Set (V T) = (U T) \ = PI/4 - yawRadians / 2 JSR Multiply8x16 \ Set (U T) = U * (V T) / 256 \ = U * (PI/4 - yawRadians / 2) \ \ U is the high byte of (U T), which also contains \ PI/4 - yawRadians / 2, so this approximation holds \ true: \ \ (U T) = U * (PI/4 - yawRadians / 2) \ =~ (PI/4 - yawRadians / 2) ^ 2 ASL T \ Set (U T) = (U T) * 2 ROL U \ = (PI/4 - yawRadians / 2) ^ 2 * 2 \ By this point we have the following: \ \ (U T) = (PI/4 - yawRadians / 2) ^ 2 * 2 \ = ((PI/2 - yawRadians) / 2) ^ 2 * 2 \ \ If we define x = PI/2 - yawRadians, then we have: \ \ (U T) = (x / 2) ^ 2 * 2 \ = ((x ^ 2) / (2 ^ 2)) * 2 \ = (x ^ 2) / 2 \ \ The small angle approximation states that for small \ values of x, the following approximation holds true: \ \ cos(x) =~ 1 - (x ^ 2) / 2! \ \ As yawRadians is large, this means x is small, so we \ can use this approximation \ \ We are storing the cosine, which is in the range 0 to \ 1, in the 16-bit variable (U T), so in terms of 16-bit \ arithmetic, the 1 in the above equation is (1 0 0) \ \ So this is the same as: \ \ cos(x) =~ (1 0 0) - (x ^ 2) / 2! \ = (1 0 0) - (U T) \ \ It's a trigonometric identity that: \ \ cos(PI/2 - x) = sin(x) \ \ so we have: \ \ cos(x) = cos(PI/2 - yawRadians) \ = sin(yawRadians) \ \ and we already calculated that: \ \ cos(x) =~ (1 0 0) - (U T) \ \ so that means that: \ \ sin(yawRadians) = cos(x) \ =~ (1 0 0) - (U T) \ \ So we just need to calculate (1 0 0) - (U T) to get \ our result LDA #0 \ Set A = (1 0 0) - (U T) SEC \ SBC T \ starting with the low bytes AND #%11111110 \ Which we store in sinAngleLo, with bit 0 cleared to STA sinAngleLo,X \ denote a positive result (as it's a sign-magnitude \ number we want to store) LDA #0 \ And then the high bytes SBC U BCC rotm4 \ We now need to subtract the top bytes, i.e. the 1 in \ (1 0 0) and the 0 in (0 U T), while including the \ carry from the high byte subtraction \ \ So the top byte should be: \ \ A = 1 - 0 - (1 - C) \ = 1 - (1 - C) \ = C \ \ If the C flag is clear, then that means the top byte \ is zero, so we already have a valid result from the \ high and low bytes, so we jump to rotm4 to store the \ high byte of the result in sinAngleHi \ \ If the C flag is set, then the result is (1 A T), but \ the highest possible value for sin or cos is 1, so \ that's what we return \ \ Because sinAngle is a sign-magnitude number with \ the sign bit in bit 0, we return the following value \ to represent the closest value to 1 that we can fit \ into 16 bits: \ \ (11111111 11111110) LDA #%11111110 \ Set sinAngleLo to the highest possible positive STA sinAngleLo,X \ value (i.e. all ones except for the sign in bit 0) LDA #%11111111 \ Set A to the highest possible value of sinAngleHi, \ so we can store it in the next instruction .rotm4 STA sinAngleHi,X \ Store A in the high byte in sinAngleHiName: GetRotationMatrix (Part 3 of 5) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Calculate sin(H G) for bigger anglesContext: See this subroutine on its own page References: No direct references to this subroutine in this source file.rotm5 CPX secondAxis \ If we just processed the second axis, then we have BEQ rotm6 \ now set both sinAngle and cosAngle, so jump to \ rotm6 to set their signs LDX secondAxis \ Otherwise set X = secondAxis so the next time we reach \ the end of the loop, we take the BEQ branch we just \ passed through LDA #0 \ Set (H G) = (201 0) - (H G) SEC \ SBC G2 \ starting with the low bytes STA G2 LDA #201 \ And then the high bytes SBC H2 STA H2 STA U \ Set (U G) = (H G) \ \ (U G) and (H G) were set to yawRadians / 2 for the \ first pass through the loop above, so we now have the \ following: \ \ 201 - yawRadians / 2 \ \ PI is represented by 804, as 804 / 256 = 3.14, so 201 \ represents PI/4, so this the same as: \ \ PI/4 - yawRadians / 2 \ \ Given that we expect (U G) to contain half the angle \ we are projecting, this means we are going to find the \ sine of this angle when we jump back to rotm1: \ \ PI/2 - yawRadians \ \ It's a trigonometric identity that: \ \ sin(PI/2 - x) = cos(x) \ \ so jumping back will, in fact, find the cosine of the \ angle JMP rotm1 \ Loop back to set the other variable of sinAngle and \ cosAngle to the cosine of the angleName: GetRotationMatrix (Part 4 of 5) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Loop back to calculate cos instead of sinContext: See this subroutine on its own page References: No direct references to this subroutine in this source file.rotm6 \ By this point, we have the yaw angle vector's \ x-coordinate in sinAngle and the y-coordinate in \ cosAngle \ \ The above calculations were done on an angle that was \ reduced to a quarter-circle, so now we need to add the \ correct signs according to which quarter-circle the \ original vectorYawAngle in (J T) was in LDA J \ If J is positive then vectorYawAngle is positive (as BPL rotm7 \ J contains vectorYawAngleHi), so jump to rotm7 to skip \ the following \ If we get here then vectorYawAngle is negative \ \ The degree system in the Sentinel looks like this: \ \ 0 \ -32 | +32 Overhead view of player \ \ | / \ \ | / 0 = looking straight ahead \ \|/ +64 = looking sharp right \ -64 -----+----- +64 -64 = looking sharp left \ /|\ \ / | \ \ / | \ \ -96 | +96 \ 128 \ \ So vectorYawAngle is in the left half of the above \ diagram, where the x-coordinates are negative, so we \ need to negate the x-coordinate LDA #1 \ Negate sinAngle by setting bit 0 of the low byte, ORA sinAngleLo \ as sinAngle is a sign-magnitude number STA sinAngleLo .rotm7 LDA J \ If bits 6 and 7 of J are the same (i.e. their EOR is ASL A \ zero), jump to rotm8 to return from the subroutine as EOR J \ the sign of cosAngle is correct BPL rotm8 \ Bits 6 and 7 of J, i.e. of vectorYawAngleHi, are \ different, so the angle is in one of these ranges: \ \ * 64 to 127 (%01000000 to %01111111) \ \ * -128 to -65 (%10000000 to %10111111) \ \ The degree system in the Sentinel looks like this: \ \ 0 \ -32 | +32 Overhead view of player \ \ | / \ \ | / 0 = looking straight ahead \ \|/ +64 = looking sharp right \ -64 -----+----- +64 -64 = looking sharp left \ /|\ \ / | \ \ / | \ \ -96 | +96 \ 128 \ \ So vectorYawAngle is in the bottom half of the above \ diagram, where the y-coordinates are negative, so we \ need to negate the y-coordinate LDA #1 \ Negate cosAngle by setting bit 0 of the low byte, ORA cosAngleLo \ as cosAngle is a sign-magnitude number STA cosAngleLo .rotm8 LDX xStoreMatrix \ Restore the value of X that we stored in xStoreMatrix \ at the start of the routine, so that it's preserved RTS \ Return from the subroutineName: GetRotationMatrix (Part 5 of 5) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Apply the correct signs to the resultContext: See this subroutine on its own page References: No direct references to this subroutine in this source file.xStoreMatrix EQUB 0Name: xStoreMatrix [Show more] Type: Variable Category: Maths (Geometry) Summary: Temporary storage for X so it can be preserved through calls to GetRotationMatrixContext: See this variable on its own page References: This variable is used as follows: * GetRotationMatrix (Part 1 of 5) uses xStoreMatrix * GetRotationMatrix (Part 5 of 5) uses xStoreMatrix.CrackerSeed LDA #0 \ This instruction is never run but the operand is used \ to hide data as part of the anti-cracker codeName: CrackerSeed [Show more] Type: Subroutine Category: Cracker protection Summary: Obfuscated storage for the high byte of the landscape number as part of the anti-cracker codeContext: See this subroutine on its own page References: This subroutine is called as follows: * AlterCrackerSeed calls CrackerSeed * CheckCrackerSeed calls CrackerSeed * SetCrackerSeed calls CrackerSeed.GetAngleInRadians ASL T \ Set (V T) = (A T) << 2 ROL A \ ASL T \ This shift multiplies (A T) by four, removing bits 6 ROL A \ and 7 in the process STA V \ \ The degree system in the Sentinel looks like this: \ \ 0 \ -32 | +32 Overhead view of player \ \ | / \ \ | / 0 = looking straight ahead \ \|/ +64 = looking sharp right \ -64 -----+----- +64 -64 = looking sharp left \ /|\ \ / | \ \ / | \ \ -96 | +96 \ 128 \ \ The top byte of (A T) is in this range, so shifting to \ the left by two places drops bits 6 and 7 and scales \ the angle into the range 0 to 252, as follows: \ \ * 0 to 63 (%00000000 to %00111111) \ -> 0 to 252 (%00000000 to %11111100) \ \ * 64 to 127 (%01000000 to %01111111) \ -> 0 to 252 (%00000000 to %11111100) \ \ * -1 to -64 (%11111111 to %11000000) \ -> 252 to 0 (%11111100 to %00000000) \ \ * -65 to -128 (%10111111 to %10000000) \ -> 252 to 0 (%11111100 to %00000000) \ We now convert this number from a Revs angle into \ radians \ \ The value of (V T) represents a quarter-circle, which \ is PI/2 radians, but we actually multiply by PI/4 to \ return the angle in radians divided by 2, to prevent \ overflow in the GetRotationMatrix routine LDA #201 \ Set U = 201 STA U \ Fall through into Multiply8x16 to calculate: \ \ (U A) = U * (V T) / 256 \ = 201 * (V T) / 256 \ = (201 / 256) * (V T) \ = (3.14 / 4) * (V T) \ \ So we return (U A) = PI/4 * (V T) \ \ which is the original angle, reduced to a quarter \ circle, converted to radians, and halvedName: GetAngleInRadians [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Convert a 16-bit angle into radians, restricted to a quarter circleContext: See this subroutine on its own page References: This subroutine is called as follows: * GetRotationMatrix (Part 1 of 5) calls GetAngleInRadians
This routine is from Revs, Geoff Crammond's previous game.
Arguments: (A T) A yaw angle (-128 to +127)
Returns: (U A) The angle, reduced to a quarter circle, converted to radians, and halved.Multiply8x16 JSR Multiply8x8+2 \ Set (A T) = T * U STA W \ Set (W T) = (A T) \ = T * U \ \ So W = T * U / 256 LDA V \ Set A = V JSR Multiply8x8 \ Set (A T) = A * U \ = V * U STA U \ Set (U T) = (A T) \ = V * U LDA W \ Set (U T) = (U T) + W CLC \ ADC T \ starting with the low bytes STA T BCC mult1 \ And then the high bytes, so we get the following: INC U \ \ (U T) = (U T) + W \ = V * U + (T * U / 256) \ = U * (V + T / 256) \ = U * (256 * V + T) / 256 \ = U * (V T) / 256 \ \ which is what we want .mult1 RTS \ Return from the subroutineName: Multiply8x16 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Multiply an 8-bit and a 16-bit numberContext: See this subroutine on its own page References: This subroutine is called as follows: * GetHypotenuse calls Multiply8x16 * GetRotationMatrix (Part 2 of 5) calls Multiply8x16 * GetRotationMatrix (Part 3 of 5) calls Multiply8x16
Do the following multiplication of two unsigned numbers: (U T) = U * (V T) / 256 The result is also available in (U A). This routine is from Revs, Geoff Crammond's previous game..ScanKeyboard TYA \ Store Y on the stack so we can preserve it PHA LDA #129 \ Call OSBYTE with A = 129, Y = &FF and the inkey value LDY #&FF \ in X, to scan the keyboard for key X JSR OSBYTE PLA \ Retrieve Y from the stack so it is unchanged TAY CPX #&FF \ If the key in X is being pressed, the above call sets \ both X and Y to &FF, so this sets the Z flag depending \ on whether the key is being pressed (so a BEQ after \ the call will branch if the key in X is being pressed) RTS \ Return from the subroutineName: ScanKeyboard [Show more] Type: Subroutine Category: Keyboard Summary: Scan the keyboard for a specific key pressContext: See this subroutine on its own page References: This subroutine is called as follows: * CheckForKeyPresses calls ScanKeyboard * ScanForGameKeys calls ScanKeyboard
This routine is from Revs, Geoff Crammond's previous game. There is only one minor difference: the value of Y is preserved.
Arguments: X The negative inkey value of the key to scan for (in the range &80 to &FF)
Returns: Z flag The result: * Set if the key in X is being pressed, in which case BEQ will branch * Clear if the key in X is not being pressed, in which case BNE will branch Y Y is preserved.GetSineAndCosine BPL scos1 \ If A is in the range 128 to 255, flip bit 6 EOR #%01000000 \ \ The degree system in the Sentinel looks like this: \ \ 0 \ -32 | +32 Overhead view of player \ \ | / \ \ | / 0 = looking straight ahead \ \|/ +64 = looking sharp right \ -64 -----+----- +64 -64 = looking sharp left \ /|\ \ / | \ \ / | \ \ -96 | +96 \ 128 \ \ Bit 7 is set in the left half, so this operation only \ affects angles in that half \ \ In the left half, bit 6 is as follows: \ \ * -1 to -64 (%11111111 to %11000000) \ \ * -65 to -128 (%10111111 to %10000000) \ \ so flipping bit 6 effectively swaps the two quarters \ from this: \ \ 0 \ -32 | \ \ | \ \ | \ \| \ -64 -----+ \ /| \ / | \ / | \ -96 | \ 128 \ \ into this: \ \ -64 \ -96 | \ \ | \ \ | \ \| \ 128 -----+ \ \ and this: \ \ 0 -----+ \ /| \ / | \ / | \ -32 | \ -64 \ \ by doing these conversions: \ \ * -1 to -64 (%11111111 to %11000000) \ -> -65 to -128 (%10111111 to %10000000) \ \ * -65 to -128 (%10111111 to %10000000) \ * -1 to -64 (%11111111 to %11000000) \ \ This is the same as rotating the angle through 90 \ degrees, which is the same as adding PI/2 to the angle \ \ It's a trigonometric identity that: \ \ cos(x) = sin(x + PI/2) \ \ so this shifts the angle so that when we fetch from \ sine lookup table, we are actually getting the cosine \ \ We use this fact below to determine which result to \ return in sinA and cosA after we have done the lookups \ from the sine table .scos1 STA H \ Store the updated angle argument in H so we can fetch \ bits 6 and 7 from the angle below ASL T \ Set (A T) = (A T) << 1 ROL A \ \ The original argument represents a full circle in the \ range A = 0 to 255, so this reduces that range to a \ half circle with A = 0 to 255, as bit 7 is shifted out \ of the top \ \ This effectively drops the left half of the angle \ circle, to leave us with an angle in this range: \ \ 0 \ | +64 \ | / \ | / \ |/ \ +----- +128 \ |\ \ | \ \ | \ \ | +192 \ 256 AND #%01111111 \ Clear bit 6 of the result, so A represents a quarter \ circle in the range 0 to 127 \ \ This effectively drops the bottom-right quarter of the \ angle circle, to leave us with an angle in this range: \ \ 0 \ | +64 \ | / \ | / \ |/ \ +----- +127 \ \ So by this point we have discarded bits 6 and 7 of the \ original angle and scaled the angle to be in the range \ 0 to 127, so we can use the result as an index into \ the sine table (which contains 128 values) \ \ The sine table only covers angles in the first quarter \ of the circle, which means the result of looking up a \ value from the sine table will always be positive, so \ this will return the absolute value, i.e. |sin(x)| TAX \ Copy A into X so we can use it as an index to fetch \ the sine of our angle EOR #%01111111 \ Negate A using two's complement, leaving bit 7 clear CLC \ ADC #1 \ Because A was in the range 0 to 127 before being \ negated, this is effectively the same as subtracting \ A from 127, like this: \ \ A = 127 - X BPL scos2 \ If A > 127 then set A = 127, so A is capped to the LDA #127 \ range 0 to 127 and is suitable for looking up the \ result from the sine table .scos2 TAY \ Copy A into Y so we can use it as an index into the \ sine table, so we have the following: \ \ Y = 127 - X \ Because our angle is in the first quadrant where 127 \ represents a quarter circle of 90 degrees or PI/2 \ radians, we can now look up the sine and cosine as \ follows: LDA sin,X \ Set A = sin(X) LDX sin,Y \ Set X = sin(Y) \ = sin(127 - X) \ = sin(PI/2 - X) \ \ And because X is in the range 0 to PI/2, we have: \ \ X = sin(PI/2 - X) \ = cos(X) \ Because the sine table only contains positive values \ from the first quadrant, this means we have the \ following: \ \ A = |sin(X)| \ \ X = |cos(X)| \ \ We now need to analyse the original angle argument A \ (via bits 6 and 7 of the angle in H) to make sure we \ return the correct result \ \ Here's the angle system again: \ \ 0 \ -32 | +32 Overhead view of player \ \ | / \ \ | / 0 = looking straight ahead \ \|/ +64 = looking sharp right \ -64 -----+----- +64 -64 = looking sharp left \ /|\ \ / | \ \ / | \ \ -96 | +96 \ 128 \ \ If our original angle argument A is the top-right \ quadrant then the result above will be correct \ \ If our original angle argument A is the bottom-right \ quadrant then we can apply the following trigonometric \ identities: \ \ sin(A) = sin(X + PI/2) \ = cos(X) \ \ cos(A) = cos(X + PI/2) \ = -sin(X) \ \ So for the original argument A, we have: \ \ |sin(A)| = |cos(X)| \ \ |cos(A)| = |-sin(X)| \ = |sin(X)| \ \ So it follows that for this angle range, we need to \ return the current value of X for the sine result and \ the current value of A for the cosine result \ \ If our original angle argument A is the bottom-left \ quadrant then we can apply the following trigonometric \ identities: \ \ sin(A) = sin(X + PI) \ = -sin(X) \ \ cos(A) = cos(X + PI) \ = -cos(X) \ \ And given that we are returning the absolute value, \ this means for this quadrant, the return values are \ correct \ \ If our original angle argument A is the top-left \ quadrant then we can apply the following trigonometric \ identities: \ \ sin(A) = sin(X - PI/2) \ = -cos(X) \ \ cos(A) = cos(X - PI/2) \ = sin(X) \ \ So again we need to return the current value of X for \ the sine result and the current value of A for the \ cosine result \ \ In terms of the original angle A, then, we have the \ following: \ \ * Top-right quadrant = results are correct \ \ * Bottom-right quadrant = swap sin and cos \ \ * Bottom-left quadrant = results are correct \ \ * Top-left quadrant = swap sin and cos \ \ In terms of bits 6 and 7 of H, we swapped the left two \ quadrants, so this means: \ \ * Top-right quadrant = both clear \ \ * Bottom-right quadrant = bit 7 clear, bit 6 set \ \ * Bottom-left quadrant = both set \ \ * Top-left quadrant = bit 7 set, bit 6 clear \ \ So the return values are correct when bits 6 and 7 are \ either both clear or both set, and we need to swap the \ sine and cosine results if one is set and the other is \ clear \ \ Also, this means that the signs of the results are \ captured in H as follows, as the quadrant defines the \ sign of sin(A) and cos(A): \ \ * Top-right quadrant = both clear \ sin(A) is positive \ cos(A) is positive \ \ * Bottom-right quadrant = bit 7 clear, bit 6 set \ sin(A) is positive \ cos(A) is negative \ \ * Bottom-left quadrant = both set \ sin(A) is negative \ cos(A) is negative \ \ * Top-left quadrant = bit 7 set, bit 6 clear \ sin(A) is negative \ cos(A) is positive \ \ We now return the sign in H along with the absolute \ values in sinA and cosA, making sure that they are the \ correct way around BIT H \ If bit 7 of H is set, jump to scos4 BMI scos4 \ If we get here then bit 7 of H is clear BVS scos5 \ If bit 6 of H is set, jump to scos5 .scos3 \ If we get here then one of these is true: \ \ * Bit 7 of H is clear and bit 6 of H is clear \ \ * Bit 7 of H is set and bit 6 of H is set \ \ So the results we calculated above are correct: \ \ A = |sin(X)| \ \ X = |cos(X)| \ \ and they will be the same for |sin(A)| and |cos(A)| \ for the original argument A: STA sinA \ Store A in sinA to return |sin(A)| STX cosA \ Store X in cosA to return |cos(A)| RTS \ Return from the subroutine .scos4 \ If we get here then bit 7 of H is set BVS scos3 \ If bit 6 of H is set, jump to scos3 .scos5 \ If we get here then one of these is true: \ \ * Bit 7 of H is clear and bit 6 of H is set \ \ * Bit 7 of H is set and bit 6 of H is clear \ \ So the results we calculated above: \ \ A = |sin(X)| \ \ X = |cos(X)| \ \ need to be swapped around to be correct for |sin(A)| \ and |cos(A)| for the original argument A: \ \ A = |cos(A)| \ \ X = |sin(A)| STA cosA \ Store A in cosA to return |cos(A)| STX sinA \ Store X in sinA to return |sin(A)| RTS \ Return from the subroutineName: GetSineAndCosine [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Calculate the sine and the cosine of an angleContext: See this subroutine on its own page References: This subroutine is called as follows: * GetObjPointAngles calls GetSineAndCosine
Arguments: (A T) The angle, representing a full circle with the range A = 0 to 255, and T representing the fractional part (though only bit 7 of T is used)
Returns: sinA The value of |sin(A)| cosA The value of |cos(A)| H The sign of each of the results: * Bit 7 is the sign of sin(A), with 0 = positive and 1 = negative * Bit 6 is the sign of cos(A), with 0 = positive and 1 = negative.Multiply16x16 LDA QQ \ If (QQ PP) is positive, jump to muls1 to skip the BPL muls1 \ following LDA #0 \ (QQ PP) is negative, so we now negate (QQ PP) so it's SEC \ positive, starting with the low bytes SBC PP STA PP LDA #0 \ And then the high bytes SBC QQ \ STA QQ \ So we now have (QQ PP) = |QQ PP| LDA H \ Flip bit 7 of H, so when we set the result to the sign EOR #%10000000 \ of H below, this ensures the result is the correct STA H \ sign .muls1 LDA RR \ If bit 0 of RR is clear, then (SS RR) is positive, so AND #1 \ jump to muls2 BEQ muls2 LDA H \ Flip bit 7 of H, so when we set the result to the sign EOR #%10000000 \ of H below, this ensures the result is the correct STA H \ sign .muls2 LDA QQ \ Set U = QQ STA U LDA RR \ Set A = RR JSR Multiply8x8 \ Set (A T) = A * U \ = RR * QQ STA W \ Set (W T) = (A T) \ = RR * QQ LDA T \ Set (W V) = (A T) + 128 CLC \ = RR * QQ + 128 ADC #128 \ STA V \ starting with the low bytes BCC muls3 \ And then the high byte INC W \ So we now have (W V) = RR * QQ + 128 .muls3 LDA SS \ Set A = SS JSR Multiply8x8 \ Set (A T) = A * U \ = SS * QQ STA G \ Set (G T) = (A T) \ = SS * QQ LDA T \ Set (G W V) = (G T 0) + (W V) CLC \ ADC W \ starting with the middle bytes (as the low bytes are STA W \ simply V = 0 + V with no carry) BCC muls4 \ And then the high byte INC G \ So now we have: \ \ (G W V) = (G T 0) + (W V) \ = (SS * QQ << 8) + RR * QQ + 128 .muls4 LDA PP \ Set U = PP STA U LDA SS \ Set A = SS JSR Multiply8x8 \ Set (A T) = A * U \ = SS * PP STA U \ Set (U T) = (A T) \ = SS * PP LDA T \ Set (G T ?) = (G W V) + (U T) CLC \ ADC V \ starting with the low bytes (which we throw away) LDA U \ And then the high bytes ADC W STA T BCC muls5 \ And then the high byte INC G \ So now we have: \ \ (G T ?) = (G W V) + (U T) \ = (SS * QQ << 8) + RR * QQ + 128 + SS * PP \ = (QQ * SS) << 8 + (QQ * RR) + (PP * SS) \ + 128 \ = (QQ PP) * (SS RR) / 256 \ \ So: \ \ (G T) = (G T ?) / 256 \ = (QQ PP) * (SS RR) / 256^2 \ \ which is the result that we want .muls5 LDA G \ Set (A T) = (G T) BIT H \ We are about to fall through into Absolute16Bit, so \ this ensures we set the sign of (A T) to the sign in \ H, so we get: \ \ (A T) = (A T) * abs(H)Name: Multiply16x16 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Multiply a sign-magnitude 16-bit number and a signed 16-bit numberContext: See this subroutine on its own page References: This subroutine is called as follows: * MultiplyCoords calls Multiply16x16
This routine calculates: (A T) = (QQ PP) * (SS RR) / 256^2 It uses the following algorithm: (QQ PP) * (SS RR) = (QQ << 8 + PP) * (SS << 8 + RR) = (QQ << 8 * SS << 8) + (QQ << 8 * RR) + (PP * SS << 8) + (PP * RR) = (QQ * SS) << 16 + (QQ * RR) << 8 + (PP * SS) << 8 + (PP * RR) Finally, it replaces the low byte multiplication in (PP * RR) with 128, as an estimate, as it's a pain to multiply the low bytes of a signed integer with a sign-magnitude number. So the final result that is returned in (A T) is as follows: (A T) = (QQ PP) * (SS RR) / 256^2 = ((QQ * SS) << 16 + (QQ * RR) << 8 + (PP * SS) << 8 + 128) / 256^2 which is the algorithm that is implemented in this routine. This routine is from Revs, Geoff Crammond's previous game.
Arguments: (QQ PP) 16-bit signed integer (SS RR) 16-bit sign-magnitude integer with the sign bit in bit 0 of RR H The sign to apply to the result (in bit 7)
Returns: (A T) (QQ PP) * (SS RR) * abs(H).Absolute16Bit BPL MainTitleLoop-1 \ If the high byte in A is already positive, return from \ the subroutine (as MainTitleLoop-1 contains an RTS) \ Otherwise fall through into Negate16Bit to negate the \ number in (A T), which will make it positive, so this \ sets (A T) = |A T|Name: Absolute16Bit [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate the absolute value (modulus) of a 16-bit numberContext: See this subroutine on its own page References: This subroutine is called as follows: * FollowGazeVector (Part 5 of 5) calls Absolute16Bit * GetPolygonLines (Part 6 of 6) calls Absolute16Bit * ProcessTileData calls Absolute16Bit
This routine sets (A T) = |A T|. It can also return (A T) * abs(n), where A is given the sign of n. This routine is from Revs, Geoff Crammond's previous game.
Arguments: (A T) The number to make positive N flag Controls the sign to be applied: * If we want to calculate |A T|, do an LDA or equivalent before calling the routine * If we want to calculate (A T) * abs(n), do a BIT n before calling the routine * If we want to set the sign of (A T), then call with: * N flag clear to calculate (A T) * 1 * N flag set to calculate (A T) * -1.Negate16Bit STA U \ Set (U T) = (A T) LDA #0 \ Set (A T) = 0 - (U T) SEC \ = -(A T) SBC T \ STA T \ starting with the low bytes LDA #0 \ And then the high bytes SBC U RTS \ Return from the subroutineName: Negate16Bit [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Negate a 16-bit numberContext: See this subroutine on its own page References: This subroutine is called as follows: * DivideBy16 calls Negate16Bit * GetAngleFromCoords (Part 3 of 3) calls Negate16Bit * GetObjPointAngles calls Negate16Bit
This routine negates the 16-bit number (A T). This routine is from Revs, Geoff Crammond's previous game.
Other entry points: Negate16Bit+2 Set (A T) = -(U T).MainTitleLoop LDX #&FF \ Set the stack pointer to &01FF, which is the standard TXS \ location for the 6502 stack, so this instruction \ effectively resets the stack \ \ This means that the JSR GenerateLandscape instruction \ below will put its return address onto the top of the \ stack, so we can manipulate the return address by \ modifying (&01FE &01FF) \ \ See the notes on the JSR GenerateLandscape instruction \ below for more details LDA #4 \ Set all four logical colours to physical colour 4 JSR SetColourPalette \ (blue), so this blanks the entire screen to blue JSR ResetVariables \ Reset all the game's main variables LDA #0 \ Call DrawTitleScreen with A = 0 to draw the title JSR DrawTitleScreen \ screen LDX #0 \ Print text token 0: Background colour blue, print JSR PrintTextToken \ "PRESS ANY KEY" at (64, 100), set text background to \ black LDA #&87 \ Set the palette to the second set of colours from the JSR SetColourPalette \ colourPalettes table, which contains the fixed palette \ for the title screens (blue, black, red, yellow) JSR ReadKeyboard \ Enable the keyboard, flush the keyboard buffer and \ read a character from it (so this waits for a key \ press) .main1 JSR ResetVariables \ Reset all the game's main variables LDX #1 \ Print text token 1: Print 13 spaces at (64, 100), JSR PrintTextToken \ print "LANDSCAPE NUMBER?" at (64, 768), switch to text \ cursor, move text cursor to (5, 27) LDA #4 \ Read a four-digit number from the keyboard into the JSR ReadNumber \ input buffer, showing the key presses on-screen and \ supporting the DELETE and RETURN keys JSR StringToNumber \ Convert the string of four ASCII digits in the input \ buffer into a BCD number in inputBuffer(1 0) LDY inputBuffer+1 \ Set (Y X) = inputBuffer(1 0) LDX inputBuffer \ \ So (Y X) is the entered landscape number in BCD JSR InitialiseSeeds \ Initialise the seed number generator to generate the \ sequence of seed numbers for the landscape number in \ (Y X) and set maxNumberOfEnemies and the landscapeZero \ flag accordingly LDA landscapeZero \ If the landscape number is not 0000, jump to main3 BNE main3 \ to ask for the landscape's secret entry code \ This is landscape 0000, so we don't ask for a secret \ entry code, but instead we copy the landscape's secret \ code from secretCode0000 into the input buffer, so \ it's as if the player has typed in the code themselves LDX #3 \ We are copying four bytes of secret code into the \ input buffer, so set a byte index in X .main2 LDA secretCode0000,X \ Copy the X-th byte of secretCode0000 to the X-th byte STA inputBuffer,X \ of the input buffer DEX \ Decrement the byte index BPL main2 \ Loop back until we have copied all four bytes BMI main4 \ Jump to main4 to skip asking the player to enter the \ code (this BMI is effectively a JMP as we just passed \ through a BPL) .main3 LDX #2 \ Print text token 2: Background colour blue, print JSR PrintTextToken \ "SECRET ENTRY CODE?" at (64, 768), switch to text \ cursor, move text cursor to (2, 27) LDA #8 \ Read an eight-digit number from the keyboard into the JSR ReadNumber \ input buffer, showing the key presses on-screen and \ supporting the DELETE and RETURN keys JSR StringToNumber \ Convert the string of eight ASCII digits in the input \ buffer into a BCD number in inputBuffer(3 2 1 0) .main4 \ The player has now chosen a landscape number and has \ entered the secret code (or, in the case of landscape \ 0000, we have entered the secret code for them) \ \ We also jump here if we are restarting a landscape \ after dying, so the player doesn't have to enter the \ landscape's secret code again LDA #4 \ Set all four logical colours to physical colour 4 JSR SetColourPalette \ (blue), so this blanks the entire screen to blue JSR GenerateLandscape \ Call GenerateLandscape to generate the landscape and \ play the game \ \ Calling this subroutine puts a return address of \ SecretCodeError on the stack (as that's the routine \ that follows directly after this JSR instruction), so \ running a normal RTS instruction at the end of the \ GenerateLandscape routine will return to the following \ code, which is what happens if the secret code entered \ doesn't match the landscape's secret code \ \ However, if the secret code does match the landscape, \ then the SmoothTileData routine that is called from \ GenerateLandscape alters the return address on the \ stack, so instead of returning here, the RTS at the \ end of the GenerateLandscape routine actually takes us \ to the PreviewLandscape routine \ \ Because we reset the position of the stack pointer \ with a TSX instruction at the start of this routine, \ we know that the JSR GenerateLandscape instruction \ will put its return address onto the top of the stack, \ so we can manipulate the return address in the \ SmoothTileData routine by modifying (&01FE &01FF) \ \ See the SmoothTileData routine for more detailsName: MainTitleLoop [Show more] Type: Subroutine Category: Main title loop Summary: The main title loop: display the title screen, fetch the landscape number/code, preview the landscape and jump to the main game loopContext: See this subroutine on its own page References: This subroutine is called as follows: * ConfigureMachine calls MainTitleLoop * MainGameLoop calls MainTitleLoop * Absolute16Bit calls via MainTitleLoop-1 * SecretCodeError calls via main1 * MainGameLoop calls via main4
Other entry points: MainTitleLoop-1 Contains an RTS main1 The entry point for rejoining the main title loop after the player enters an incorrect secret code main4 The entry point for restarting a landscape after dying, so the player doesn't have to enter the landscape's secret code again.SecretCodeError JSR ResetVariables \ Reset all the game's main variables LDA #0 \ Call DrawTitleScreen with A = 0 to draw the title JSR DrawTitleScreen \ screen LDA #&87 \ Set the palette to the second set of colours from the JSR SetColourPalette \ colourPalettes table, which contains the fixed palette \ for the title screens (blue, black, red, yellow) LDX #3 \ Print text token 3: Background colour blue, print JSR PrintTextToken \ "WRONG SECRET CODE" at (64, 768), print "PRESS ANY \ KEY" at (64, 100), set text background to black JSR ReadKeyboard \ Enable the keyboard, flush the keyboard buffer and \ read a character from it (so this waits for a key \ press) JMP main1 \ Loop back to main1 to restart the main title loopName: SecretCodeError [Show more] Type: Subroutine Category: Main title loop Summary: Display the "WRONG SECRET CODE" error, wait for a key press and rejoin the main title loopContext: See this subroutine on its own page References: This subroutine is called as follows: * PreviewLandscape calls SecretCodeError.secretCode0000 EQUD &06045387Name: secretCode0000 [Show more] Type: Variable Category: Landscape Summary: The secret entry code for landscape 0000 (06045387)Context: See this variable on its own page References: This variable is used as follows: * MainTitleLoop uses secretCode0000.ClearScreen JSR ResetScreenAddress \ Reset the address of the start of screen memory JSR ClearIconsScanner \ Clear the energy icon and scanner row at the top of \ the screen LDA #0 \ Call ConfigureBuffer with A = 0 to set up the screen JSR ConfigureBuffer \ buffer for use as a row buffer LDA #0 \ Set A = 0 to pass to FillScreen, so we clear the \ screen (as opposed to the screen buffer) LDY #24 \ Set Y = 24 to pass to FillScreen, so we clear all 24 \ character rows of the landscape view LDX #40 \ Set X = 16 to pass to FillScreen so we clear all 40 \ character columns of the landscape view JSR FillScreen \ Call FillScreen to fill the entire screen with the \ background specified in screenBackground LDA screenBackground \ If the screen background is not 3, jump to clrs2 to CMP #3 \ return from the subroutine BNE clrs2 \ If we get here then screenBackground = 3, so we now \ draw three lots of 80 stars on the screen LDA #3 \ Set a loop counter so we call the DrawStars routine STA loopCounter \ three times in the following loop, giving a total of \ 240 stars .clrs1 JSR DrawStars \ Draw 80 randomly positioned stars on the screen in \ colour 2 (white, yellow, cyan or red) DEC loopCounter \ Decrement the loop counter BNE clrs1 \ Loop back until we have called DrawStars three times .clrs2 RTS \ Return from the subroutineName: ClearScreen [Show more] Type: Subroutine Category: Graphics Summary: Clear the screen to a specified backgroundContext: See this subroutine on its own page References: This subroutine is called as follows: * DrawTitleView calls ClearScreen * MainGameLoop calls ClearScreen
Arguments: screenBackground The type of screen background: * 0 = fill with alternating colour 0/1 (blue/black) pixel rows, for the sky during gameplay * 1 = fill with solid colour 0 (blue) * 2 = fill with dithered pixels in colour 0 (blue) and colour 3 (e.g. green in landscape 0000) by alternating colour 3/0/3/0 and 0/3/0/3 pixel bytes * 3 = fill with solid colour 1 (black) and draw 240 randomly positioned stars on the background
[X]
Subroutine ClearIconsScanner (category: Scanner/energy row)
Clear the energy icon and scanner row at the top of the screen
[X]
Subroutine ConfigureBuffer (category: Screen buffer)
Set up the variables required to configure the screen buffer to a specific buffer type
[X]
Subroutine DrawStars (category: Graphics)
Draw 80 randomly positioned stars on the screen in colour 2 (white, yellow, cyan or red)
[X]
Subroutine DrawTitleScreen (category: Title screen)
Draw the title screen or the screen showing the secret code
[X]
Subroutine FillScreen (category: Graphics)
Fill a rectangular in screen memory or the screen buffer with the specified background
[X]
Variable G2 in workspace Main variable workspace
Temporary storage, used in the maths routines from Revs, where the original variable name was G (this variable has been renamed to G2 to prevent a clash with the G variable that is used by The Sentinel)
[X]
Subroutine GenerateLandscape (category: Landscape)
Generate tile data for the landscape
[X]
Subroutine GetAngleInRadians (category: Maths (Geometry))
Convert a 16-bit angle into radians, restricted to a quarter circle
[X]
Variable H2 in workspace Main variable workspace
Temporary storage, used in the maths routines from Revs, where the original variable name was H (this variable has been renamed to H2 to prevent a clash with the H variable that is used by The Sentinel)
[X]
Subroutine InitialiseSeeds (category: Landscape)
Initialise the seed number generator so it generates the sequence of seed numbers for a specific landscape number
[X]
Variable J in workspace Main variable workspace
Temporary storage, used in the maths routines from Revs
[X]
Entry point MainTitleLoop-1 in subroutine MainTitleLoop (category: Main title loop)
Contains an RTS
[X]
Subroutine Multiply8x16 (category: Maths (Arithmetic))
Multiply an 8-bit and a 16-bit number
[X]
Subroutine Multiply8x8 (category: Maths (Arithmetic))
Calculate (A T) = T * U
[X]
Entry point Multiply8x8+2 in subroutine Multiply8x8 (category: Maths (Arithmetic))
Calculate (A T) = T * U
[X]
Subroutine Negate16Bit (category: Maths (Arithmetic))
Negate a 16-bit number
[X]
Configuration variable OSBYTE
The address for the OSBYTE routine
[X]
Subroutine PrintTextToken (category: Text)
Print a recursive text token
[X]
Subroutine ReadKeyboard (category: Keyboard)
Enable the keyboard and read a character from it
[X]
Subroutine ReadNumber (category: Keyboard)
Read a number from the keyboard into the input buffer
[X]
Subroutine ResetScreenAddress (category: Graphics)
Reset the address of the start of screen memory
[X]
Subroutine ResetVariables (category: Main title Loop)
Reset all the game's main variables
[X]
Subroutine SetColourPalette (category: Graphics)
Set the logical colours for each of the four physical colours in screen mode 5
[X]
Subroutine StringToNumber (category: Text)
Convert a string of ASCII digits in the input buffer in-place into a multi-byte BCD number
[X]
Variable angleTangent in workspace Zero page
The tangent of an angle in a right-angled triangle
[X]
Variable arctanHi (category: Maths (Geometry))
Table for arctan values when calculating yaw angles (high byte)
[X]
Variable arctanLo (category: Maths (Geometry))
Table for arctan values when calculating yaw angles (low byte)
[X]
Label clrs1 in subroutine ClearScreen
[X]
Label clrs2 in subroutine ClearScreen
[X]
Variable cosAngleLo in workspace Main variable workspace
The low byte of the cosine of a pitch or yaw angle, as calculated by the GetRotationMatrix routine
[X]
Label gang1 in subroutine GetAngleFromCoords (Part 1 of 3)
[X]
Label gang10 in subroutine GetAngleFromCoords (Part 2 of 3)
[X]
Label gang11 in subroutine GetAngleFromCoords (Part 3 of 3)
[X]
Label gang12 in subroutine GetAngleFromCoords (Part 3 of 3)
[X]
Label gang13 in subroutine GetAngleFromCoords (Part 3 of 3)
[X]
Label gang14 in subroutine GetAngleFromCoords (Part 3 of 3)
[X]
Label gang15 in subroutine GetAngleFromCoords (Part 3 of 3)
[X]
Label gang16 in subroutine GetAngleFromCoords (Part 3 of 3)
[X]
Label gang2 in subroutine GetAngleFromCoords (Part 1 of 3)
[X]
Label gang3 in subroutine GetAngleFromCoords (Part 1 of 3)
[X]
Label gang4 in subroutine GetAngleFromCoords (Part 1 of 3)
[X]
Label gang5 in subroutine GetAngleFromCoords (Part 1 of 3)
[X]
Label gang6 in subroutine GetAngleFromCoords (Part 1 of 3)
[X]
Label gang7 in subroutine GetAngleFromCoords (Part 2 of 3)
[X]
Label gang8 in subroutine GetAngleFromCoords (Part 2 of 3)
[X]
Label gang9 in subroutine GetAngleFromCoords (Part 2 of 3)
[X]
Variable inputBuffer in workspace Main variable workspace
The eight-byte keyboard input buffer
[X]
Variable landscapeZero in workspace Main variable workspace
A flag that is set depending on whether we are playing landscape 0000
[X]
Variable loopCounter in workspace Zero page
A general-purpose loop counter
[X]
Entry point main1 in subroutine MainTitleLoop (category: Main title loop)
The entry point for rejoining the main title loop after the player enters an incorrect secret code
[X]
Label main2 in subroutine MainTitleLoop
[X]
Label main3 in subroutine MainTitleLoop
[X]
Entry point main4 in subroutine MainTitleLoop (category: Main title loop)
The entry point for restarting a landscape after dying, so the player doesn't have to enter the landscape's secret code again
[X]
Label muls1 in subroutine Multiply16x16
[X]
Label muls2 in subroutine Multiply16x16
[X]
Label muls3 in subroutine Multiply16x16
[X]
Label muls4 in subroutine Multiply16x16
[X]
Label muls5 in subroutine Multiply16x16
[X]
Label mult1 in subroutine Multiply8x16
[X]
Label rotm1 in subroutine GetRotationMatrix (Part 1 of 5)
[X]
Label rotm2 in subroutine GetRotationMatrix (Part 2 of 5)
[X]
Label rotm3 in subroutine GetRotationMatrix (Part 3 of 5)
[X]
Label rotm4 in subroutine GetRotationMatrix (Part 3 of 5)
[X]
Label rotm5 in subroutine GetRotationMatrix (Part 4 of 5)
[X]
Label rotm6 in subroutine GetRotationMatrix (Part 5 of 5)
[X]
Label rotm7 in subroutine GetRotationMatrix (Part 5 of 5)
[X]
Label rotm8 in subroutine GetRotationMatrix (Part 5 of 5)
[X]
Label scos1 in subroutine GetSineAndCosine
[X]
Label scos2 in subroutine GetSineAndCosine
[X]
Label scos3 in subroutine GetSineAndCosine
[X]
Label scos4 in subroutine GetSineAndCosine
[X]
Label scos5 in subroutine GetSineAndCosine
[X]
Variable screenBackground in workspace Main variable workspace
The type of screen background when clearing the screen
[X]
Variable secondAxis in workspace Zero page
The number of the second axis to calculate in the GetRotationMatrix routine
[X]
Variable secretCode0000 (category: Landscape)
The secret entry code for landscape 0000 (06045387)
[X]
Variable sin (category: Maths (Geometry))
Table for sine values
[X]
Variable sinAngleHi in workspace Main variable workspace
The high byte of the sine of a pitch or yaw angle, as calculated by the GetRotationMatrix routine
[X]
Variable sinAngleLo in workspace Main variable workspace
The low byte of the sine of a pitch or yaw angle, as calculated by the GetRotationMatrix routine
[X]
Variable xStoreMatrix (category: Maths (Geometry))
Temporary storage for X so it can be preserved through calls to GetRotationMatrix