Revs on the BBC Micro

# Track geometry: GetSegmentAngles (Part 3 of 3)

```       Name: GetSegmentAngles (Part 3 of 3)                          [Show more]
Type: Subroutine
Category: Track geometry
Summary: Process a visible segment
Deep dive: Data structures for the track calculations
The track verges
Context: See this subroutine in context in the source code
References: No direct references to this subroutine in this source file

.gseg10

\ If we get here then the segment's pitch angle is
\ positive and the segment is visible on-screen

JSR GetVergeAndMarkers \ Get the details for this segment's corner markers and
\ verge marks

CMP edgeSegmentNumber  \ to keep checking segments, as we haven't yet gone past
BEQ gseg13             \ the closest segment to the player
BCC gseg13

\ If we get here then we have gone past the closest
\ segment to the player, so we need to check whether the
\ segment is within the 20-degree field of view, and
\ stop when the segments become hidden from view

LDY segmentListPointer \ Set Y to the segment list pointer

LDA xVergeRightHi,Y    \ Set A to the high byte of the yaw angle of the
\ segment's right verge

BPL gseg11             \ If the angle is negative, negate it, so we now have
EOR #&FF               \ A = |yaw angle|

.gseg11

CMP #20                \ If A < 20, then the segment is within the 20-degree
BCC gseg13             \ field of view, so jump to gseg13 to keep checking
\ segments

LDA xVergeRightHi-1,Y  \ Set A to the high byte of the yaw angle of the
\ previous segment's right verge

BPL gseg12             \ If the angle is negative, negate it, so we now have
EOR #&FF               \ A = |yaw angle|

.gseg12

CMP #20                \ If A >= 20, then the previous segment was also outside
BCS gseg16             \ the 20-degree field of view, so jump to gseg16 to
\ return from the subroutine

JMP gseg4              \ If we get here then the current segment is outside the
\ 20-degree field of view, but the previous one wasn't,
\ so we jump to gseg4 to try processing a segment that's
\ one-quarter of the size, in case that fits

.gseg13

\ If we get here then we have successfully processed a
\ visible segment

STX prevSegmentOffset  \ Store the offset from xSegmentCoordILo of this
\ segment's 3D coordinates in prevSegmentOffset, to use
\ in the next iteration if the next segment is not
\ visible

INC segmentListPointer \ Increment the segment list pointer to point to the
\ next entry in the list

INC segmentCounter     \ Increment the segment counter to indicate that we have
\ populated a visible segment (so this will become 1 if
\ this is the first visible segment we have processed,
\ 2 for the second visible segment, and so on)

LDY segmentCounter     \ Set Y to the number of visible segments we have
\ populated so far

CPY #18                \ If Y >= 18, i.e. Y > 17, then Y was > 16 before we
BCS gseg16             \ incremented it, which means we have filled the track
\ gseg16 to return from the subroutine to stop
\ processing segments

LDA segmentStep,Y      \ Set T to the segment step for segment number Y, so to
STA T                  \ get the next segment, we step back T steps in the
\ track segment buffer
\
\ This makes us step a long way backwards for the first
\ few segments, and then make shorter steps as we get
\ closer to the player

TXA                    \ Set A to the segment offset that's in X

SEC                    \ Set A = A - segmentOffset
SBC segmentOffset      \
\ so A contains the number of the segment * 3 (as X
\ contains the offset from xSegmentCoordILo, which will
\ be 120 + X for the X-th outer segment coordinate, so
\ subtracting segmentOffset brings the offset down to
\ the number * 3, whether this is an inner or outer
\ coordinate)

CMP T                  \ If A >= T, jump to gseg14 to jump back T segments
BCS gseg14             \ towards the player, for the next iteration

\ If we get here then A < T, so we can't jump back T
\ segments or we will jump past the beginning of the
\ track segment buffer, so we need to add 120 to wrap
\ around to the end of the buffer before we can jump
\ back T segments

TXA                    \ Set A to the segment offset that's in X

CLC                    \ Set A = A + 120 to wrap around to the end of the track

.gseg14

TXA                    \ Set A to the segment offset that's in X

.gseg15

SEC                    \ Set X = A - T
SBC T                  \
TAX                    \ So the next segment to be tested is T steps backwards
\ in the track segment buffer, towards the player (so
\ if T = 3, we step back one segment, or if T = 13 * 3,
\ we step back 13 segments)

JMP gseg1              \ Loop back to gseg1 to move on to the next segment

.gseg16

RTS                    \ Return from the subroutine
```