23 December to 29 December 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:
- 23 December 2025 Run first spell check, identify polygonGoesRight and polygonGoesLeft, document part 2 of DrawPolygonLines
- 24 December 2025 - Rename GetPolygonLines, xPolygonRight and xPolygonLeft
- 26 December 2025 - Analyse considerObjects, document yAccuracyLo, identify xPolygonPoint(Hi Lo), categorise all headers
- 27 December 2025 - Document parts 3 and 4 of GetPolygonLines
- 28 December 2025 - Identify yEdgeStart(Hi Lo), yEdgeEnd(Hi Lo), xEdgeStart(Hi Lo) and xEdgeEnd(Hi Lo), clarify "polygon lines" and "polygon edges" terminology, identify yEdgeDelta(Hi Lo), xPolygonAddrHi and TracePolygonEdge, document part 5 of GetPolygonLines
- 29 December 2025 - Identify ModifyStoringCode, document part 6 of GetPolygonLines, reach 95% progress, start analysing TracePolygonEdge, identify xEdgeDelta
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.
23 December 2025
================
See all the GitHub commits and diffs for 23 December 2025.
Ran a spell check on the commentary, using my extraction script, so lots of small fixes.
Let's do part 2 of DrawPolygonLines.
It's lots of edge cases (literally!) to do with detecting whether the polygon extends past the left or right edges of the screen buffer.
The results are stored in L002C and L002D, so:
This is fairly straightforward, though there are some doublings in here that are weird. The whole yaw angle buffer configuration thing is not matching my analysis, so I guess the next stage is to move on to AnalysePolygon... which is all that's left anyway.
Back to looking at AnalysePolygon.
24 December 2025
================
See all the GitHub commits and diffs for 24 December 2025.
Only got five minutes - it's Christmas Eve! - so just some tidying up:
yVectorLo, zVectorLo are reused in AnalysePolygon, so put them back to L0030, L0031.
Split first bit of AnalysePolygon into a separate part 1.
Rename as follows, so GetPolygonLines and DrawPolygonLines feel more connected:
So... are all the buffer yaw/pitch angle constraints actually pixel constraints?
Full landscape view is 160 pixels wide, 192 pixels tall.
- Yaw angle * 8 = pixels
- Pitch angle * 8 = pixels
Custom screen mode 5 is 40 character columns wide, 25 character rows high.
Top row is energy icon and scanner row, so landscape view is 24 character rows.
Summary:
Screen is 20 yaw angles wide = 40 character columns, so yaw * 2 = columns
= 160 pixels, so yaw * 8 = pixels
Screen is 36 pitch angles tall = 24 character rows, so pitch * 2/3 = rows
= 192 pixels, so pitch * 8 = pixels
So rename back to the names we originally picked, as that's clearer:
and:
- L298B -> buffersL011YawHi for now so all buffer configs start with "buffers"
Probably going to have to rename buffersYaw to xBuffers or something, we'll see.
26 December 2025
================
See all the GitHub commits and diffs for 26 December 2025.
A quick bit of downtime after the main Christmas festivities to polish off some of the question marks in the source code.
First up, bit 6 of considerObjects.
Turns out that when bit 7 of considerObjects are set, then GetTileAltitude can also set bit 6 when the gaze vector is close to, but not hitting, a platform object (boulder, tower).
This doesn't apply to trees, only platforms.
FollowGazeVector part 1 checks for bit 6 and if it's set, then it will report that a tile can't be seen, so this means that platform objects effectively block partially visible tiles that peek out from behind them, but trees don't do this.
I did wonder about the LSR considerObjects in FollowGazeVector part 2, and does this implement some kind of "previous bit 7" thing.
Turns out it doesn't. The only time we care about bit 6 is in this sequence, where there are no labels where we can join in early:
LDA #%10000000 \ Clears bit 6 STA considerObjects ... JSR GetTileAltitude \ Might set bit 6 BCS gaze5 \ Jumps to code containing LSR considerObjects ... BIT considerObjects \ Checks bit 6 BVS gaze4
So the LSR is indeed a shorthand for setting considerObjects to zero, as we only get here if bit 7 is set, and once we duck out to gaze5, then if we come back we override considerObjects with the STA anyway.
Now for L000C.
First, a renaming of the platform byte:
GetTileAltitude can set L000C, which is then used in FollowGazeVector.
L000C is set to 128 normally, but GetTileAltitude might set to 16 for tower.
So L000C is platform fraction 0.5 normally in FollowGazeVector, 0.0625 for tower only.
Also, a realisation that L000C is reused in the polygon routine, which leads us to this renaming:
- L000C -> yAccuracyLo
It's how close to the correct height we need to be to see a platform or tile, so change comparison to:
LDA yPlatformLo \ If yPlatformLo >= yAccuracyLo, then the vertical
CMP yAccuracyLo \ distance between the gaze and the platform is greater
BCS gaze4 \ than the accuracy specified in yAccuracyLo, so jump to
\ gaze4 to return from the subroutine with the C flag
\ set to indicate that the viewer is not looking at a
\ tile or object
Also, in GetTileAltitude, naming of labels is odd, so:
The original was from when this was called GetTileData, which was ages ago.
While we're renaming, it's clear that the polygon lines routine uses L0B40(Hi Lo) to stash polygon x-coordinates, so let's rename them like this:
Also, might as well add a category of "Drawing polygons" to the three remaining subs, as they are pretty clearly related to this: sub_C2EAE, sub_C3087, sub_C316E.
So that's everything categorised in their headers - nice!
Still got 12 Summary header lines with "???"s, but we're getting there...
27 December 2025
================
See all the GitHub commits and diffs for 27 December 2025.
Back onto GetPolygonLines.
These two seem to be part of the main routine flow rather than subroutines, so:
Also, rename labels to match routine name better:
Also, vectorYawAngleHi and vectorPitchAngleLo don't seem to contain vector angles, so they must be reused, so:
Documented parts 3 and 4, which convert the yaw angle into an x-coordinate by multiplying by 8.
Started on part 5, which is all about pitch angles, so presumably this part is more about the y-coordinates, but we'll see...
28 December 2025
================
See all the GitHub commits and diffs for 28 December 2025.
Following the threads, turns out that GetPolygonLines part 7 is actually sub_C2EAE part 2, so rename it accordingly.
Also, vectorPitchAngleHi is reused, so:
Let's try to name these variables:
LDA drawViewPitchHi,Y STA L003E LDA drawViewPitchLo,Y STA L001A LDA drawViewPitchHi,X STA L003F LDA drawViewPitchLo,X STA L0016 LDA xPolygonPointLo,Y STA L0018 LDA xPolygonPointLo,X STA L0039
X and Y are end points for the polygon edge we are drawing, but which is the start and which the end?
The only clue I can find is that L003E gets decremented with DEC L003E, while none of the others, so is this an indication that as we traverse the edge, we move from Y to X?
Eh, we can always change them around later, but for now:
- L003E -> yEdgeStartHi
- L001A -> yEdgeStartLo
- L003F -> yEdgeEndHi
- L0016 -> yEdgeEndLo
- L0018 -> xEdgeStartLo
- L0039 -> xEdgeEndLo
And here's a clue for the high x bytes:
LDA xPolygonPointHi,Y STA L0042
So:
- L0042 -> xEdgeEndHi
And we also have:
LDA xEdgeStartLo SEC SBC xEdgeEndLo STA L000D LDA L0041 SBC xEdgeEndHi
So:
Some terminology clarifications.
I'm going to refer to the polygon's sides as "polygon edges", to match the colour scheme terminology, while "polygon lines" are the horizontal scan lines that we are calculating in GetPolygonLines.
So we will be tracing polygon edges to work out the coordinates of the polygon lines.
Search and replace to the rescue!
OK, back to GetPolygonLines part 5 to continue the commentary.
(A L000C) and (V L000C) are used to store the difference in y-coordinate along an edge, so rename L000C to yEdgeDeltaLo for now.
V is used as the high byte, so add a label of yEdgeDeltaHi to V in this part of the code only.
L0002 is set to &5A or &5B, and is poked into the high byte of this instruction:
.C2F29 STX xTileMaxAltitude+63 \ Gets modified
xPolygonLeft is at &5A00 and xPolygonRight is at &5B00, so L0002 is being set to the high byte of the destination table for the polygon line x-coordinates (i.e. right or left).
So:
Working through part 5, it looks like L001E is a counter that is incremented when we have edges with a y-axis delta of 0.
So there's a whole section devoted to horizontal edges and polygons that are only made up of horizontal edges.
Looks like part 5 loops through the edges, processes horizontal edges itself, and then sends edges with two-byte coordinates to part 6 for splitting up.
In both cases, sub_C2EAE is called to process the edge, so:
Finished documenting part 5 of GetPolygonLines, but with a fair few question marks.
As an aside, let's try to make the buffer-related variables have a consistent naming convention.
Old name -> new name in the following:
minYawAngleHi bufferMinYawHi minYawAngleLo bufferMinYawLo maxYawAngleHi bufferMaxYawHi minBufferPitch bufferMinPitch maxBufferPitch bufferMaxPitch bufferYawWidth OK as is L0011YawHi bufferYawHi L0011YawLo bufferYawLo bufferYawLeft OK as is bufferYawRight OK as is buffersL011YawHi buffersYawHi
This might help work out what these actually mean! Maybe...
29 December 2025
================
See all the GitHub commits and diffs for 29 December 2025.
Let's start by looking at the last remaining sub_Cxxxx routine, sub_C316E.
It modifies the code in ProcessPolygonEdge, changing opcodes between BIT, STA and STY, where:
&2C = BIT &8C = STY &8E = STX
It changes the instructions at pedg41 and pedg50, which poke into locations at xPolygonAddrHi, i.e. xPolygonLeft or xPolygonRight.
So sub_C316E changes the code that stores the polygon line data, switching it between storing X, Y and nothing (the BIT is effectively a NOP).
So rename:
This renaming means that we finally have a completed hierarchy sheet - see the completed version of the hierarchy sheet in Google Sheets.
Also, these are equivalent and more relevant, as these instructions are modified to write into the xPolygonRight or xPolygonLeft tables, and the actual values are just placeholders:
STX xTileMaxAltitude+62 -> xPolygonRight+&9E STX xTileMaxAltitude+63 -> xPolygonRight+&9F
Back to part 6 of GetPolygonLines.
The L007F variable controls whether there is are any polygon pixels to draw, so rename it to drawPolygon.
Also L000A is only used for storing the high byte of the x-delta for polygon points, so name it xPointDeltaHi.
This part calls the edge-tracing process, splitting the edge up into smaller parts if they are too big for the deltas to fit into one byte.
As the polygon edge is processed by tracing along the edge and calculating the coordinates, this might be a better name:
>>> I have now broken through the 95% barrier <<<
And of that, 1.5% is zero page, and that only has one unlabelled variable (L000D), so this means there is effectively only 3.5% to go and 96.5% coverage.
I might even post something to social media to get people excited!
So, on to TracePolygonEdge, the last undocumented routine.
Working through, it starts by updating yPolygonTop and yPolygonBottom.
That said, I think I might have my start and end points the wrong way around in terms of height, as this logic seems to be the wrong way around. Or, rather, I've got the start and end point heights the wrong way around. Will need to look into this.
Turns out L000D is a single-byte x-axis delta, so rename L000D to xEdgeDelta - not to be confused with the two-byte version in xEdgeDelta(Hi Lo).
And that's the whole of zero page identified, though there are still some "???"s in there, particularly around the buffer variables. Still, that's a big jump, as I can mark zero page with "Explain", and we're now at 96.5% done. Getting close!
That's it for the day. I can almost feel the home straight under my feet...