17 September to 24 September 2025
Here's my disassembly diary for this part of my project to document The Sentinel on the BBC Micro. You can click on the following links to jump to a specific day in the diary:
- 17 September 2025 - Document ProcessTileData, identify SmoothTileCorners and SmoothTileData
- 18 September 2025 - Start documenting SmoothTileCorners and SmoothTileData, more thinking around stripData
- 19 September 2025 - Finish documenting SmoothTileCorners, work out obfuscated jump code for JumpToPreview
- 22 September 2025 - Finish documenting GenerateLandscape, clarify "tile corner" vs "tile" in commentary
- 23 September 2025 - Start analysing SpawnEnemies, GetEnemyCount and AddEnemiesToTiles, work out landscape colour variables
- 24 September 2025 - Continue analysing AddEnemiesToTiles, document GetHighestTiles, identify maxAltitude, xTileMaxAltitude and zTileMaxAltitude, reach 20% progress, document GetObjectNumber, identify objectType, objectTypes and objectFlags, work out that there are 64 objects, start looking at GetTilesAtAltitude
Please note that this diary is a dump of my thoughts as I disassembled and documented The Sentinel, and as such it contains lots of mistakes and dead ends and misinterpretations. This diary is all about the journey, rather than the destination; for the latter, see the finished product.
17 September 2025
=================
See all the GitHub commits and diffs for 17 September 2025.
Next up is sub_C2AF2, which takes an argument in A that performs various actions on the tile data (such as zeroing it, setting it to random values, swapping nibbles(?) and doing some kind of scaling and capping).
Documented sub_C2AF2 -> ProcessTileData.
It contains some very weird multiplication and capping stuff, probably need to look at this again later as it seems to be converting random tile data into the stepped landscape in the game (i.e. tile data values from 1 to 11).
PlayGame is probably better renamed as GenerateLandscape.
More speculative naming:
- sub_C2B53 - Works through rows of tiles, starting with rows in and out of the screen ("columns"?) and then left-to-right rows, calling sub_C2B90 for each strip of tiles.
- sub_C2B90 - Seems to look at the neighbouring values of tiles (+1, +2, +3, +4) and adds them and divides by 4 - is it averaging out the heights? Smoothing the landscape?
So rename like this:
- sub_C2B53 -> SmoothTileData - Smooth the whole landscape, strip by strip?
- sub_C2B90 -> SmoothTileStrip - Smooth a row or column of tiles, i.e. a strip of tiles?
18 September 2025
=================
See all the GitHub commits and diffs for 18 September 2025.
Started documenting the SmoothTileData and SmoothTileStrip routines.
Not sure that landscapeHeight actually seeds the heights, as its content seems to be largely ignored after being filled (the random heights that the landscape starts with are populated directly into tileData by ProcessTileData with A = &80).
Renamed landscapeHeight to landscapeRandom to stop me being distracted by it, will probably change this again at some point!
19 September 2025
=================
See all the GitHub commits and diffs for 19 September 2025.
Finishing documenting the SmoothTileStrip routine.
Follow through the strange stack return address modifications in SmoothTileStrip to work out how we return from the GenerateLandscape routine.
We either return to the last part of the main loop, so rename this to SecretCodeError, or we modify the stack so we return to PreviewLandscape. This goes via some tricky code at JumpToPreview that is easy to misinterpret (which I did at first).
Rename "landscape code" to "secret code" throughout as that's what the game calls it.
22 September 2025
=================
See all the GitHub commits and diffs for 22 September 2025.
Document sub_C2C4E -> SetTileSlope.
This compares tiles with neighbours to work out a slope - begs the question, are we storing tiles or tile corners here? Might need to look into that.
Finish documenting GenerateLandscape.
Ah... so looking at a screenshot of the preview screen, the landscape is 31 tiles across and not 32, so it looks like tileData actually contains tile corner data, and the slope is the slope from that corner to the next three corners.
So go through all commentary and update it to be clear when we are talking about tile corners, tiles, tile anchors (e.g. "the tile anchored at (x, z)") and so on.
It is worth getting this stuff 100% correct, as that is how you ensure that everything is clear and understandable. By me as well as the audience!
23 September 2025
=================
See all the GitHub commits and diffs for 23 September 2025.
Analysing from PreviewLandscape down, starting with sub_C1410.
Rename sub_C33F0 -> GetEnemyCount, uses a weird bit-counting scheme to get a random number.
landscapeColour2 and landscapeColour3 are for setting the game palette depending on number of enemies.
24 September 2025
=================
See all the GitHub commits and diffs for 24 September 2025.
Some speculative naming for the subroutines off the PreviewLandscape routine, given some quick analysis:
Continue analysing by looking at CreateEnemies.
Analyse sub_C15BC, rename it to GetHighestTiles, as goes through the landscape and analyses it in 4x4 blocks, storing the details of the highest tile in each block.
Data is stored in various data blocks from &5B10, so name them: maxTileHeight, xMaxTileHeight, zMaxTileHeight.
>>> I have now broken through the 20% barrier <<<
Back to CreateEnemies itself.
If enemy count = 1 then we must be putting the Sentinel on the landscape, so when X = 0 we are spawning the Sentinel.
sub_C210E takes an argument that depends on whether we are spawning the Sentinel vs Sentry and sticks it in a table - rename to SpawnObject for the time being, argument is objectType?
It seems that objects have slots, like Elite, with flags stored in L0100 (name this objectFlags), where bit 7 set means slot is empty.
There are 64 objects, as SpawnObject loops through all 64 slots looking for an empty slot.
There's a table at L0A40 that stores the argument, objectType, so call this objectTypes.
Also we can organise the blocks and labels around &0A00 better, as they clearly split up into blocks of 64 bytes (so they probably contain object-related data.
Start looking at CreateEnemies > sub_C158D.