Aviator on the BBC Micro

```       Name: GetRadarVector                                          [Show more]
Type: Subroutine
Category: Dashboard
Summary: Calculate the radar line vector for a line (the runway) or a dot
(an alien)
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:

Arguments:

A                    For the runway line only, this is either the current
compass direction from yRotationHi (if we are drawing
the radar line), or a previous compass direction (if we
are erasing the existing radar line)

X                    The type of radar line to calculate:

* 0 = runway line

* Non-zero = alien (shown as a dot)

Returns:

T                    Magnitude of x-coordinate of line's vector |x-delta|

U                    Magnitude of y-coordinate of line's vector |y-delta|

V                    The direction of the line (runway), or an arbitrary
direction for the dot, because it doesn't matter (alien)

* Bit 7 is the direction of the x-delta

* Bit 6 is the direction of the y-delta

Direction is like a clock, so positive (clear) is up and
right

CPX #0                 \ If X = 0, jump to rvec1 to calculate the line vector
BEQ rvec1              \ for the runway

\ Otherwise we return the deltas for a dot, T = U = 1,
\ and don't worry about setting the direction in V as
\ it gets ignored when drawing dots

LDY #1                 \ Set Y = 1 to return as the y-delta in U

BNE rvec2              \ Jump down to rvec2 to set X = 1 and return from the
\ subroutine (this BNE is effectively a JMP as Y is
\ never zero)

.rvec1

\ We now want to calculate the vector for the runway
\
\ The runway runs north-south, so our compass direction
\ in A lets us work out the direction of the runway line
\ on the radar. The value of our compass in A is:
\
\   *   0 = north
\   *  64 = east
\   * 128 = south
\   * 192 = west

STA previousCompass    \ Store A in previousCompass, so we can pass it to this
\ routine again when we want to erase the line we are

CLC                    \ Set A = A + 16
\ This rotates the compass needle clockwise by 16, or
\ 22.5 degrees, so if the needle is just anticlockwise
\ of a cardinal compass point (e.g. NNW, ENE) it will be
\ bumped along to the quadrant and will inherit the
\ correct direction bit in bit 7. At the cardinal
\ points, A now contains the following:
\
\   *  16 = north   -> bit 7 clear
\   *  80 = east    -> bit 7 clear
\   * 144 = south   -> bit 7 set
\   * 208 = west    -> bit 7 set
\
\ So bit 7 contains the direction of the needle along
\ the x-axis, with 0 to the right and 1 to the left

ASL A                  \ Shift bit 7 of the result into the C flag, which we
\ will use below as the direction of the line's x-delta

STA P                  \ Store the result in P, so:
\
\   P = (A + 16) << 1
\
\ which looks like this:
\
\   * %00100000 = north
\   * %10100000 = east
\   * %00100000 = south
\   * %10100000 = west
\
\ We use this below to work out the line's vector

PHP                    \ Store the flags on the stack, in particular the C
\ flag from the above operation, which gives us the
\ direction of the line's x-delta

ROR A                  \ Shift the C flag back into bit 7 of A, so bit 7 once
\ again contains the direction of the x-delta

SEC                    \ Set A = A - 64
SBC #64                \
\ This rotates the compass needle anticlockwise by 64,
\ or 90 degrees, which will change bit 7 from being the
\ direction of the x-delta to the being the direction of
\ the y-delta

PLP                    \ Retrieve the C flag from above, which contains the
\ direction of the x-delta

ROR A                  \ Shift the direction of the x-delta into bit 7 of A,
\ and at the same time shift the y-delta from bit 7 to
\ bit 6

EOR #%11000000         \ Reverse both deltas by flipping bits 6 and 7 of A
\ (I am not sure why this is done)

STA V                  \ Store the result in V to set the direction of the line
\ vector

\ Above, we stored a value in P like this:
\
\   * %00100000 = north
\   * %10100000 = east
\   * %00100000 = south
\   * %10100000 = west
\
\ We can use this below to work out the vector of the
\ line to show, as follows:
\
\   * A set bit 6 means the line is between the cardinal
\     points, e.g. northeast, southwest and so on, so
\     the line is diagonal
\
\   * A set bit 7 means the line is generally east-west,
\     which is horizontal
\
\   * A clear bit 7 means the line is generally north-
\     south, which is vertical
\
\ We use this to set the vector in T and U to the
\ following:
\
\   * Diagonal: x-delta = 2, y-delta = 4
\
\   * Horizontal: x-delta = 2, y-delta = 1
\
\   * Vertical: x-delta = 1, y-delta = 4
\
\ The y-delta is twice the x-delta because the pixels
\ in mode 5 are twice as wide as they are tall

LDX #2                 \ Set X = 2 to return as the x-delta in T for a diagonal

LDY #4                 \ Set Y = 4 to return as the y-delta in U for a diagonal

BIT P                  \ If bit 6 of P is set, jump to rvec3 to return these
BVS rvec3              \ values as the deltas (i.e. 2 and 4), as the runway
\ line is diagonal

BPL rvec2              \ If bit 7 of P is clear, jump to rvec2 to return an
\ x-delta of 1 and a y-delta of 4, as the runway line is
\ vertical

LDY #1                 \ Otherwise set Y = 1 and jump to rvec3 to return an
BNE rvec3              \ x-delta of 2 and a y-delta of 1, as the runway line is
\ horizontal

.rvec2

LDX #1                 \ Set X = 1 to return as the x-delta in T

.rvec3

STX T                  \ Return X as the x-delta in T

STY U                  \ Return Y as the y-delta in U

RTS                    \ Return from the subroutine
```