# Track geometry: GetVergeAndMarkers (Part 2 of 4)

```       Name: GetVergeAndMarkers (Part 2 of 4)                        [Show more]
Type: Subroutine
Category: Track geometry
Summary: Calculate the segment's verge width and outside verge coordinates
Context: See this subroutine in context in the source code
References: No direct references to this subroutine in this source file

.gmar3

\ We calculate the verge width as follows:
\
\   (U A) = scaleUp * 2 ^ (scaleDown - vergeScale)
\
\ to determine the width of the verge marks on the side
\ of the track
\
\ The higher the value of (U A), the wider the verge for
\ this segment
\
\ The vergeScale factor is between 3 and 5, and scales
\ the verge width differently for different track
\ configurations, with larger values of vergeScale
\ giving smaller verges
\
\ This gives the following:
\
\   * If both verges are black-and-white, then the
\     verges are thin (vergeScale = 5), on both curved
\     and straight sections
\
\   * If this is a curve and at least one of the verges
\     is red-and-white, or we're on a straight and both
\     verges are red-and-white, then the verges are
\     medium thickness (vergeScale = 4)
\
\   * If this is a straight and only one of the verges
\     is red-and-white, then the verges are thick
\     (vergeScale = 3)

LDA scaleDown          \ Set Y = scaleDown - vergeScale
SEC
SBC vergeScale,Y
TAY

LDA #0                 \ Set U = 0, to use as the high byte in (U A)
STA U

LDA scaleUp            \ Set A = scaleUp
\
\ So (U A) = scaleUp

DEY                    \ Set Y = Y - 1
\       = scaleDown - vergeScale - 1

\ We now scale (U A) by 2 ^ Y, so if Y is 0 we don't
\ do any scaling, if it's negative we scale down, and
\ if it's positive we scale up
\
\ Note that the -1 in the scale factor calculation is
\ reversed by the right-shift that we apply below when
\ setting bit 7 of the shifted result, so the result is
\ as above, despite the extra -1

BEQ gmar6              \ If Y = 0, then there is no scaling to be done, so jump
\ to gmar6

BPL gmar5              \ If Y > 0, then we need to scale up, so jump to gmar5

\ If we get here then Y < 0, so we need to scale down,
\ specifically by right-shifting (U A) by |Y| places

.gmar4

LSR U                  \ Set (U A) = (U A) >> 1
ROR A

INY                    \ Increment the shift counter in Y

BNE gmar4              \ Loop back to gmar4 to keep shifting right until we
\ have shifted by |Y| places

BEQ gmar6              \ Jump to gmar6 (this BEQ is effectively a JMP, as we
\ just passed through a BNE)

.gmar5

\ If we get here then Y > 0, so we need to scale up,
\ specifically by left-shifting (U A) by Y places

ASL A                  \ Set (U A) = (U A) << 1
ROL U

DEY                    \ Decrement the shift counter in Y

BNE gmar5              \ Loop back to gmar5 to keep shifting left until we
\ have shifted by Y places

.gmar6

STA T                  \ Set (U T) = (U A)
\
\ So (U T) contains our scaled value

LDA segmentDirection   \ Set the C flag to bit 0 of segmentDirection, which
LSR A                  \ will be 0 when our car is facing in the same direction
\ as the segment we are checking, or 1 if it's the
\ opposite direction

ROR A                  \ Set A = A >> 1 and set bit 7 to the C flag

EOR directionFacing    \ If the C flag matches directionFacing, jump to gmar7
BPL gmar7

\ If we get here then this is the left verge, so we need
\ to negate (U T) so the outside of the verge is to the
\ left of the track, i.e. in a negative direction along
\ the x-axis

LDA #0                 \ Negate (U T), starting with the low bytes
SEC
SBC T
STA T

LDA #0                 \ And then the high bytes
SBC U
STA U

\ So we now have our verge width result:
\
\   (U T) = scaleUp * 2 ^ (scaleDown - vergeScale)
\
\ where the sign of (U T) is positive for the right
\ verge and negative for the left verge

.gmar7

LDY segmentListPointer \ Set Y to the index of the current entry in the track
\ segment list

\ We now calculate the coordinates for the outside edge
\ of the track verge by adding the verge width in (U T)
\ to the track segment's verge coordinates, storing the
\ result in the track segment list, 16 bytes after the
\ corresponding track segment entry (so indexes 6 to 21
\ contain the track segment list, while indexes 22 to 37
\ contain the corresponding entries for the outside of
\ the verge)

LDA xVergeRightLo,Y    \ Set (xVergeRightHi+16 xVergeRightLo+16)
CLC                    \      = (xVergeRightHi xVergeRightLo) + (U T)