Aviator on the BBC Micro

# Aviator D source

```       Name: AlienInAcornsville                                      [Show more]
Type: Subroutine
Category: The Theme
Summary: Move an alien towards Acornsville and check whether it has reached
it yet (and if so, end the game)
Deep dive: Aliens attack Acornsville!
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MainLoop (Part 4 of 15) calls AlienInAcornsville

.AlienInAcornsville

LDY alienToMove        \ Set Y to the number of the alien whose turn it is to
\ move towards Acornsville in this iteration of the main
\ loop, which we set in UpdateAliens

BMI acrn1              \ If Y is negative, then there is no alien to move, so

LDA alienState,Y       \ If the alien's state is 27, then it is heading for the
CMP #27                \ town, so jump to acrn7 if this is not the case
BNE acrn7

\ The alien is heading towards the town. This happens
\ in three stages: first, the alien takes off; then it
\ flies towards the town; and finally it descends. When
\ the alien's state is 27, it is working through the
\ first two stages, so that's what we do now

LDA yObjectHi+33       \ If the high byte of the alien's y-coordinate >= 12,
BCS acrn2              \ acrn2 to move it closer to Acornsville

LDA yObjectLo+33       \ Otherwise add 10 to the alien's yObject coordinate,
ADC #10                \ so that it rises into the air, starting with the low
STA yObjectLo+33       \ bytes

BCC acrn1              \ If the addition of the low bytes overflowed, increment
INC yObjectHi+33       \ the high byte

.acrn1

RTS                    \ Return from the subroutine

.acrn2

\ If we get here then the alien's yObjectHi coordinate
\ is 12 or more, so it's already flying high

LDX #0                 \ Set X = 0, to use in the following to check either the
\ x-coordinate (X = 0) or the z-coordinate (X = 80)

STX T                  \ Set T = 0, which we use to record whether we move the
\ alien along the x-axis or z-axis (or both)

.acrn3

\ We either do the following with X = 0 or X = 80, which
\ either checks the x-coordinate or the z-coordinate
\ (as zObjectHi - xObjectHi is 80)
\
\ The comments are for when X = 0, which checks the
\ x-coordinate

LDA xObjectHi+33,X     \ If the high byte of the alien's x-coordinate is zero,
BEQ acrn5              \ then we have already reached the right longitude for

LDA xObjectLo+33,X     \ Subtract alienSpeed from the alien's x-coordinate,
SEC                    \ starting with the low bytes, so the alien moves
SBC alienSpeed         \ towards Acornsville along the x-axis at the correct
STA xObjectLo+33,X     \ speed (which increases with later waves)

BCS acrn4              \ If the subtraction of the low bytes underflowed,
DEC xObjectHi+33,X     \ decrement the high byte

.acrn4

LDA #1                 \ Set T = 1, to record the fact that we moved the alien
STA T

.acrn5

CPX #80                \ If X = 80 then we have checked both axes, so jump to
BEQ acrn6              \ acrn6 to check the alien's altitude

LDX #80                \ Otherwise jump back to acrn3 with X = 80 to check the
BNE acrn3              \ alien's latitude in its z-coordinate (this BNE is
\ effectively a JMP as X is never zero)

.acrn6

LDA T                  \ If T <> 0 then we moved the alien along at least one
BNE acrn1              \ of the axes, so jump to acrn1 to return from the
\ subroutine as the alien is still in the process of
\ flying to Acornsville

LDA #28                \ Set the alien's state to 28, so the next time we call
STA alienState,Y       \ this routine, we jump straight to the following

.acrn7

CMP #28                \ If the alien's state is not 28, then it isn't
BNE acrn1              \ attacking the town, so jump to acrn1 to return from
\ the subroutine

\ The alien is heading towards the town. This happens
\ in three stages: first, the alien takes off; then it
\ flies towards the town; and finally it descends. When
\ the alien's state is 28, it is on the final stage, so
\ that's what we do now

LDA hitTimer           \ If hitTimer is non-zero, jump to acrn1 to return from
BNE acrn1              \ the subroutine, so the alien doesn't move if we
\ recently hit one of its comrades

LDA yObjectLo+33       \ Subtract 10 from the alien's yObject coordinate, so
SEC                    \ that it descends towards the town, starting with the
SBC #10                \ low bytes
STA yObjectLo+33

BCS acrn8              \ If the subtraction of the low bytes underflowed,
DEC yObjectHi+33       \ decrement the high byte

.acrn8

LDA yObjectHi+33       \ If the high byte of the alien's y-coordinate is zero,
BNE acrn1              \ then it is still too high to attack, so jump to acrn1
\ to return from the subroutine

LDA yObjectLo+33       \ If the low byte of the alien's y-coordinate is 10 or
CMP #10                \ more, then it is still too high to attack, so jump to
BCS acrn1              \ acrn1 to return from the subroutine

JSR PrintTooLate       \ Otherwise the alien is close enough to the town to
\ wreak havoc... which means it's game over, so print
\ the "TOO LATE!" message in the middle of the screen

LDA #90                \ Delay for 90^3 loop iterations
JSR Delay

JSR TerminateGame      \ Terminate the game

TSX                    \ Remove the two bytes from the top of the stack that
INX                    \ were put there by the JSR that called this routine, so
INX                    \ we can jump to NewGame without leaving any trace on
TXS                    \ the stack

Type: Subroutine
Category: Dashboard
Summary: Calculate the radar line vector for a line (the runway) or a dot
(an alien)
Context: See this subroutine on its own page
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

Type: Variable
Category: Drawing lines
Summary: Pixel bytes for drawing canopy lines left to right in colour 1
Context: See this variable on its own page
References: This variable is used as follows:
* DrawCanopyLine (Part 2 of 9) uses colour1L2R
* DrawCanopyLine (Part 4 of 9) uses colour1L2R
* DrawCanopyLine (Part 6 of 9) uses colour1L2R
* ModifyDrawRoutine uses colour1L2R

.colour1L2R

EQUB %00001000         \ Colour 1, drawing a line left to right
EQUB %00001100
EQUB %00001110
EQUB %00001111

EQUB %00000100
EQUB %00000110
EQUB %00000111

EQUB %00000010
EQUB %00000011
EQUB %00000001

Type: Variable
Category: Drawing lines
Summary: Pixel bytes for drawing canopy lines right to left in colour 1
Context: See this variable on its own page
References: This variable is used as follows:
* DrawCanopyLine (Part 2 of 9) uses colour1R2L
* DrawCanopyLine (Part 5 of 9) uses colour1R2L
* ModifyDrawRoutine uses colour1R2L

.colour1R2L

EQUB %00000001         \ Colour 1, drawing a line right to left
EQUB %00000011
EQUB %00000111
EQUB %00001111

EQUB %00000010
EQUB %00000110
EQUB %00001110

EQUB %00000100
EQUB %00001100
EQUB %00001000

Type: Variable
Category: Drawing lines
Summary: Pixel bytes for drawing canopy lines left to right in colour 2
Context: See this variable on its own page
References: This variable is used as follows:
* ModifyDrawRoutine uses colour2L2R

.colour2L2R

EQUB %10000000         \ Colour 2, drawing a line left to right
EQUB %11000000
EQUB %11100000
EQUB %11110000

EQUB %01000000
EQUB %01100000
EQUB %01110000

EQUB %00100000
EQUB %00110000
EQUB %00010000

Type: Variable
Category: Drawing lines
Summary: Pixel bytes for drawing canopy lines right to left in colour 2
Context: See this variable on its own page
References: This variable is used as follows:
* ModifyDrawRoutine uses colour2R2L

.colour2R2L

EQUB %00010000         \ Colour 2, drawing a line right to left
EQUB %00110000
EQUB %01110000
EQUB %11110000

EQUB %00100000
EQUB %01100000
EQUB %11100000

EQUB %01000000
EQUB %11000000
EQUB %10000000

Type: Variable
Category: Drawing lines
Summary: Pixel bytes for erasing canopy lines in colour 1
Context: See this variable on its own page
References: This variable is used as follows:
* ModifyDrawRoutine uses colour1Row

.colour1Row

EQUB %00001111         \ Solid colour 1
EQUB %00001111
EQUB %00001111
EQUB %00001111

EQUB %00001111
EQUB %00001111
EQUB %00001111

EQUB %00001111
EQUB %00001111
EQUB %00001111

Type: Variable
Category: Drawing lines
Summary: Pixel bytes for erasing canopy lines in colour 2
Context: See this variable on its own page
References: This variable is used as follows:
* ModifyDrawRoutine uses colour2Row

.colour2Row

EQUB %11110000         \ Solid colour 2
EQUB %11110000
EQUB %11110000
EQUB %11110000

EQUB %11110000
EQUB %11110000
EQUB %11110000

EQUB %11110000
EQUB %11110000
EQUB %11110000

Type: Variable
Category: Dashboard
Summary: Stores the value of the compass heading when we draw the runway
on the radar, so we can erase the line later
Context: See this variable on its own page
References: This variable is used as follows:

.previousCompass

EQUB &20

Type: Variable
Category: Main loop
Summary: Stores the current time (low byte only), so we can process lines
in a timely fashion during the main loop
Context: See this variable on its own page
References: This variable is used as follows:
* CheckTimePassed uses previousTime

.previousTime

EQUB &20

EQUB &20, &20          \ These bytes appear to be unused

Type: Subroutine
Category: Graphics
Summary: Clear the canopy to black, leaving the canopy edges alone
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* Crash calls ClearCanopy
* NewGame calls ClearCanopy

.ClearCanopy

LDX #0                 \ Set X = 0 so we clear the canopy to black

\ Fall through into FillCanopy to fill the canopy with
\ black, leaving the top and side edges alone

Type: Subroutine
Category: Graphics
Summary: Fill the canopy with a specified colour, leaving the canopy edges
alone
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* Crash calls FillCanopy

Arguments:

X                    The colour to fill the canopy with

.FillCanopy

TXA                    \ Copy the colour into X

LDX #19                \ Set R = 19, so we clear 19 character rows (the whole
STX R                  \ canopy view except for the top row containing the
\ canopy edge)

LDY #HI(row1_char1_0)  \ Set (Y X) to the screen address for row 1, character
LDX #LO(row1_char1_0)  \ block 1

\ Fall through into FillCanopyRows to fill the canopy
\ view, from the top row to the bottom, avoiding the top
\ and side edges

Type: Subroutine
Category: Graphics
Summary: Fill multiple screen rows with a particular colour, avoiding the
canopy edges
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* DrawGunSights calls FillCanopyRows
* RemoveScore calls FillCanopyRows

Arguments:

A                    The colour to fill the canopy with

(Y X)                The screen address to start filling from

R                    The number of character rows to fill

.FillCanopyRows

STY Q                  \ Set (Q P) = (Y X), so (Q P) is now the screen address
STX P                  \ we want to start filling from

STA S                  \ Store the value we want to store into S

.fill1

LDY #0                 \ Set a byte counter in Y

LDA S                  \ Fetch the value of A that we stored in S above

.fill2

STA (P),Y              \ Set the Y-th byte of (Q P) to A, which sets 4 pixels
\ to the pixel pattern in S

DEY                    \ Decrement the byte counter

BNE fill2              \ Loop back until we have set 256 bytes, starting at
\ (Q P), to the value in A

LDY #47                \ Set a byte counter in Y for 47 bytes

INC Q                  \ Set (Q P) = (Q P) + 256
\
\ so it points to the next byte to fill after the 256
\ bytes we just did

.fill3

STA (P),Y              \ Set the Y-th byte of (Q P) to A, which sets 4 pixels
\ to the pixel pattern in S

DEY                    \ Decrement the byte counter

BPL fill3              \ Loop back until we have set 47 bytes, starting at
\ (Q P), to the value in A

LDA P                  \ Set (Q P) = (Q P) + 64
CLC                    \
ADC #64                \ starting with the low bytes
STA P

BCC fill4              \ If the above addition didn't overflow, skip the next
\ instruction

INC Q                  \ The above addition overflowed, so increment the high
\ byte of (Q P) to point to the next page in memory

\ So now (Q P) is 320 greater than at the start, so it
\ points to the next character row in screen memory

.fill4

DEC R                  \ Decrement the row counter in R

BNE fill1              \ Loop back until we have updated R rows

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Utility routines
Summary: Delay for a specified number of loops
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* AlienInAcornsville calls Delay
* Crash calls Delay

This routine performs A^3 loop iterations, to create a delay.

Fragments of the original source for this routine appear in the game code, as
follows:

.dlp2 STA&76
.dl ...
... :BNE dlp2
DEC&74:BNE dlp1
rts

.Delay

STA T                  \ Set T as the counter for the outer loop

.dely1

STA U                  \ Set U as the counter for the middle loop

.dely2

STA V                  \ Set V as the counter for the inner loop

.dely3

DEC V                  \ Loop around for A iterations in the inner loop
BNE dely3

DEC U                  \ Loop around for A iterations in the middle loop
BNE dely2

DEC T                  \ Loop around for A iterations in the outer loop
BNE dely1

RTS                    \ Return from the subroutine

Type: Subroutine
Category: The Theme
Summary: Move the bullets through the air
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MainLoop (Part 3 of 15) calls UpdateBullets

This is called UBUL in the original source code.

.UpdateBullets

LDY #15                \ The bullets are made up of objects 12 to 15, so set a
STY objectId           \ counter in objectId to count through all four

LDA #98                \ Objects 12 to 15 are made up of points 95 to 98, so
STA GG                 \ set a counter in GG to count through all four

.ubul1

TYA                    \ Set X = Y + 216
CLC                    \
ADC #216               \ so X will be 228 to 231 for objects 12 to 15, which is
TAX                    \ the ID of each bullet object's velocity vector, as set
\ up in the FireGuns routine

JSR AddPointToObject   \ Add the vector in point X to the object coordinates
\ for object Y (in other words, add the velocity vector
\ to object Y's coordinates, which moves the bullet in
\ space by the correct amount)

LDA #0                 \ Set showLine = 0 as a starting point for the line's
STA showLine           \ visibility (so we start out by assuming the line is
\ visible, and change this in the following call to
\ SetObjectCoords if we find that it isn't)

JSR SetObjectCoords    \ Calculate the object's coordinates and visibilty,
\ updating the object's status byte with the results

BPL ubul2              \ If bit 7 of the object's updated status byte is clear,
\ then the bullets have hit the ground, so jump to ubul2
\ to remove the bullets

LDY GG                 \ Set Y to the point ID that we're checking

LDX #60                \ Set X to line ID 60 for the call to CheckLineDistance

JSR CheckLineDistance  \ Check whether point GG on line 60 is within the
\ visible distance for the line

BEQ ubul3              \ If the result is 0, then the point is visible, so

.ubul2

\ If we get here then this bullet point has either hit
\ the ground, or it is too far away to be seen any more,
\ so it's time to remove the bullets

LDA #0                 \ Set firingStatus = 0 to indicate that there are no
STA firingStatus       \ bullets are in the air

.ubul3

DEC GG                 \ Decrement the point counter to move on to the next
\ point from 98 down to 95

DEC objectId           \ Decrement the object counter to move on to the next
\ object from 15 down to 12

LDY objectId           \ Loop back until we have processed all four objects
CPY #12                \ and points
BCS ubul1

RTS                    \ Return from the subroutine

Type: Subroutine
Category: The Theme
Summary: If the Theme is enabled and the current wave does not yet have
eight aliens in it, spawn a new alien
Deep dive: Alien feeding and growth patterns
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MainLoop (Part 1 of 15) calls SpawnAlien

This routine tries to add a new alien to the current wave. It sets the alien's
state to 0, and chooses a random object ID from the range 16 to 29 for the
alien. If this object ID is already in use by an alien that we've already
spawned for this wave, then it aborts the spawning, otherwise it allocates the
object ID to the new alien's alienObjectId entry and our new alien is spawned.

This means that aliens only ever spawn in the fixed locations for objects 16
to 29, which can be seen in the xObjectLo table.

This is called SUTR in the original source code.

.SpawnAlien

LDX themeStatus        \ If bit 7 of themeStatus is set, then the Theme is not
BMI spaw3              \ enabled, so jump to spaw3 to return from the
\ subroutine

BEQ spaw3              \ If themeStatus is zero, then we have already spawned
\ all eight aliens in this wave, so return from the
\ subroutine

LDA onGround           \ If onGround is non-zero, then we are on the ground, so

\ If we get here, themeStatus is in the range 1 to 8 and
\ we are not on the ground, so the Theme has started but
\ we haven't yet spawned all eight aliens in the current
\ wave, so we need to spawn another alien (specifically
\ the alien whose ID is in themeStatus)

STA alienState-1,X     \ We know A is 0, as we just passed through a BNE above,
\ so this zeroes the state of the alien whose number is
\ in themeStatus, so it starts its feeding routine from
\ scratch

\ We now need to allocate an object ID to this alien,
\ from the range 16 to 29, making sure we don't reuse
\ any objects that are currently in use by other aliens
\ in the wave

LDA VIA+&64            \ Read the 6522 User VIA T1C-L timer 1 low-order
\ counter (SHEILA &64), which decrements one million
\ times a second and will therefore be pretty random

AND #15                \ Reduce the random number to the range 0 to 15

CMP #14                \ If the random number is >= 14 (12.5% chance), jump to
BCS spaw3              \ spaw3 to return from the subroutine

ORA #16                \ Increase the random number to the range 16 to 29, to
\ give us a potential object ID

DEC themeStatus        \ We are spawning a new alien, so decrement the counter
\ in themeStatus so it reflects the number of aliens
\ that still have to spawn to complete this wave

LDX #8                 \ We now need to confirm that this object ID isn't being
\ used by any other aliens that we've already spawned in
\ this wave, so set X to act as a loop counter, going
\ from 8 down to themeStatus (so this works through the
\ IDs of the aliens that we have already spawned in this
\ wave, as we start spawning at ID 8 and work our way
\ down to 1)

.spaw1

DEX                    \ Decrement the loop counter

CPX themeStatus        \ If X <> themeStatus, jump to spaw2 to check this
BNE spaw2              \ alien's object ID

STA alienObjectId,X    \ Otherwise we have run through all the other aliens in
\ this wave and none of them are using this object ID,
\ so set this as the object ID for this alien

RTS                    \ Return from the subroutine

.spaw2

CMP alienObjectId,X    \ If the object ID for the X-th alien does not match our
BNE spaw1              \ random number, then jump back to spaw1 to move on to
\ the next alien

INC themeStatus        \ Otherwise we've found an alien that is already using
\ the object ID we generated above, so we give up on
\ spawning this alien, incrementing the alien counter
\ in themeStatus so that it's back to the original value
\ (so we can have another go at spawning an alien on the
\ next call to SpawnAlien)

.spaw3

RTS                    \ Return from the subroutine

Type: Subroutine
Category: The Theme
Summary: Update the aliens so they progress through their feeding or attack
cycles
Deep dive: Scheduling tasks in the main loop
Alien feeding and growth patterns
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MainLoop (Part 6 of 15) calls UpdateAliens

We start by incrementing the state of any non-dormant aliens, so they slowly
move through their feeding or take-off cycles.

.UpdateAliens

LDA mainLoopCounter    \ If the mainLoopCounter is a multiple of 128, jump to
AND #127               \ upal3 to move on to part 2 (so we only do this part
BNE upal3              \ on 2 out of every 256 iterations round the main loop)

LDX #7                 \ We now progress the state of each alien, from alien 7
\ down to alien 0, so set a loop counter in X

.upal1

LDA alienState,X       \ If the state of alien X is zero, jump to upal2
BEQ upal2              \ to move on to the next alien

CMP #22                \ If the state of alien X is 22, jump to upal2
BEQ upal2              \ to move on to the next alien

CMP #27                \ If the state of alien X is 27 or higher, jump
BCS upal2              \ to upal2 to move on to the next alien

INC alienState,X       \ If we get here then the state of alien X is not 0, 22
\ or >= 27, i.e. it's 1-21 or 23-26, so increment the
\ state to progress through the feeding and take-off
\ stages

.upal2

DEX                    \ Decrement the alien number

BPL upal1              \ Loop back until we have progressed all eight aliens
\ to the next state

Type: Subroutine
Category: The Theme
Summary: Manage alien slots 31 and 32, and if there's a vacancy, wake up a
dormant alien, move it into the slot and start its feeding cycle
Deep dive: Alien feeding and growth patterns
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

Look at alien slots 31 and 32, and for each one:

* If the alien in the slot is in state 24, remove it from the slot

* Otherwise check to see if the alien in the slot has been destroyed, and if
so, empty the slot

* If the slot is not empty, search the aliens for one is dormant (i.e. in
state 0), isn't already in the other slot, and hasn't been destroyed, and
put that into the slot, bumping its state up to 1 and setting the size of
the alien to the correct size for the first feeding stage

.upal3

LDY #31                \ We run the following outer loop twice, once for alien
\ slot 31 and again for alien slot 32, so set a counter
\ in Y to iterate through 31 and 32

.upal4

LDX alienSlot-30,Y     \ If alien slot Y contains a negative number, then the

LDA alienState,X       \ If the state of the alien in slot Y is 24, then skip
CMP #24                \ the following two instructions
BEQ upal5

LDA alienObjectId,X    \ If the object ID of the alien in slot Y is positive,
BPL upal11             \ jump to upal11 to move on to the next alien

.upal5

\ If we get here then alien slot Y contains an alien
\ (with ID 0 to 7), and either the alien's state is 24,
\ or the alien's object ID is negative (which means it
\ has been destroyed)

LDA #254               \ Clear out slot Y by setting it to a negative number
STA alienSlot-30,Y

.upal6

\ We now run through aliens 7 to 0, until we find one
\ with a positive object ID and a state of 0, and which
\ is not already in the other slot. When we find it,
\ we insert it into the slot, bump its state up to 1
\ and stop looking

LDX #7                 \ Set a loop counter in X to contain the alien's number

.upal7

LDA alienObjectId,X    \ If the alien's object ID is negative, jump to upal10
BMI upal10             \ to move on to the next alien, as this alien has been
\ destroyed

LDA alienState,X       \ If the alien's state is non-zero, jump to upal10 to
BNE upal10             \ move on to the next alien

CPY #31                \ If we are processing alien slot 31 in the outer loop,
BEQ upal8              \ skip the following two instructions

CPX alienSlot+1        \ Compare the alien number with the contents of alien
JMP upal9              \ slot 31 and skip the following instruction

.upal8

CPX alienSlot+2        \ Compare the alien number with the contents of alien
\ slot 32

.upal9

BEQ upal10             \ If the current alien number matches the contents of
\ slot Y, jump to upal10 to move on to the next alien

TXA                    \ Insert this alien number into alien slot Y
STA alienSlot-30,Y

STX U                  \ Store the alien number in U

LDA #%10000000         \ Set bit 7 of A so the call to ResizeFeedingAlien sets
\ the size of the alien to the first feeding stage

JSR ResizeFeedingAlien \ Resize the alien to the first feeding stage

LDX U                  \ Retrieve the alien number from U

LDA #1                 \ Set the alien's state to 1
STA alienState,X

BNE upal11             \ Jump to upal11 to terminate the inner loop (this BNE
\ is effectively a JMP as A is never zero)

.upal10

DEX                    \ Decrement the inner loop alien counter

BPL upal7              \ Loop back until we have worked our way through aliens
\ 0 to 7

.upal11

INY                    \ Increment the alien counter

CPY #33                \ Loop back until we have processed both alien slots 31
BNE upal4              \ and 32

Type: Subroutine
Category: The Theme
Summary: If alien slot 33 is free and there's an alien waiting to take off,
promote it into slot 33
Deep dive: Alien feeding and growth patterns
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

Look at alien slot 33, and:

* If the alien in slot 33 has been destroyed, clear the slot

* If slot 33 is clear, then check slots 31 and 32 to see if either of then
contains an alien in state 22 (i.e. an alien that has finished feeding and
is ready to take off), and if so, move that alien into slot 33, promoting
it to state 23 in the process

\ At this point Y = 33, so we now process alien slot 33

LDX alienSlot-30,Y     \ If alien slot 33 contains a negative number, then the
\ skip the following

LDA alienObjectId,X    \ If the object ID of the alien in slot 33 is positive,
BPL upal15             \ then we already have an alien moving towards the town,

STA alienSlot-30,Y     \ Clear out slot 33 by setting it to a negative number
\ (we know A is negative because we just passed through
\ a BPL instruction)

.upal12

LDY #31                \ We now work our way through alien slots 31 and 32,
\ so set a counter in Y for the slot number

.upal13

LDX alienSlot-30,Y     \ If alien slot Y contains a negative number, then the
BMI upal14             \ slot is empty, so jump to upal14 to skip the following

LDA alienState,X       \ If the alien's state is not 22, jump to upal14 to skip
CMP #22                \ the following
BNE upal14

STX alienToMove        \ Set this alien as the one to move towards Acornsville
\ in this iteration of the main loop by setting
\ alienToMove to the alien number in X

LDA #23                \ Set the alien's state to 23
STA alienState,X

BNE upal15             \ Jump to upal15 to exit the loop (this BNE is
\ effectively a JMP as A is never zero)

.upal14

INY                    \ Increment the counter to point to the next alien slot

CPY #33                \ Loop back until we have done alien slots 31 and 32
BNE upal13

Type: Subroutine
Category: The Theme
Summary: When an alien reaches the next feeding stage, double its size
Deep dive: Scheduling tasks in the main loop
Alien feeding and growth patterns
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

.upal15

LDA mainLoopCounter    \ If the mainLoopCounter is a multiple of 128, jump to
AND #127               \ upal19 to skip the following (so we only do this part
BNE upal19             \ on 2 out of every 256 iterations round the main loop,
\ just like part 1)

LDY #31                \ We now work our way through alien slots 31 and 32,
\ so set a counter in Y for the slot number

.upal16

LDX alienSlot-30,Y     \ If alien slot Y contains a negative number, then the
BMI upal17             \ slot is empty, so jump to upal17 to move on to the
\ next slot

LDA alienState,X       \ If the alien's state is < 5, jump to upal17 to move on
CMP #5                 \ to the next slot, as the alien is still in feeding
BCC upal17             \ stage 1 and doesn't need resizing

CMP #20                \ If the alien's state is >= 20, jump to upal17 to move
BCS upal17             \ on to the next slot, as the alien has already reached
\ the last feeding stage and can't get any bigger

AND #%00000011         \ Check whether the feeding state is in the form
BNE upal17             \ %xxxxxx00, and if not, jump to upal17 to move on to
\ the next slot

\ If we get here, then the alien's state is between 6
\ and 19, and matches %xxxxxx00, so it's one of these:
\
\   * 8  = %00001000
\   * 12 = %00001100
\   * 16 = %00010000
\
\ These are the points in the feeding stage when the
\ size of the alien doubles

JSR ResizeFeedingAlien \ Double the size of the feeding alien to move it onto
\ the next feeding stage

.upal17

INY                    \ Increment the counter to point to the next alien slot

CPY #33                \ Loop back until we have done alien slots 31 and 32
BNE upal16

Type: Subroutine
Category: The Theme
Summary: Check whether the whole wave has been destroyed, and award points
accordingly
Deep dive: Alien feeding and growth patterns
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

LDX #7                 \ We now work through all the aliens, from alien 7 down
\ to alien 0, to check whether they have all been
\ destroyed (i.e. whether they all have a negative
\ object ID), so set a loop counter in X

.upal18

LDA alienObjectId,X    \ If the X-th alien object ID is positive, then that
BPL upal19             \ alien is still at large, so jump to upal19 to return
\ from the subroutine, as we haven't destroyed all eight
\ aliens in this wave

DEX                    \ Decrement the loop counter to point to the next alien

BPL upal18             \ Loop back until we have checked all eight aliens

\ If we get here then all eight aliens have negative
\ object IDs, so they have all been destroyed

LDA #8                 \ Set themeStatus = 8 to initiate a brand new wave of
STA themeStatus        \ aliens

LDX #&00               \ Add 500 points to the score and make a beep by calling
LDA #&50               \ ScorePoints with (X A) = &0050
JSR ScorePoints        \
\ This is the score for completing a wave in the Theme

LDA alienSpeed         \ Set A = alienSpeed + 4
CLC

CMP #19                \ If A >= 19, skip the following instruction, so
BCS upal19             \ alienSpeed has a maximum value of 22 (as alienSpeed
\ starts with a value of 10, and increases by 4 with
\ each wave until it is >= 19, which happens when it
\ reaches 22)

STA alienSpeed         \ Update alienSpeed with the faster speed so the next
\ wave has faster-moving aliens

.upal19

RTS                    \ Return from the subroutine

Type: Subroutine
Category: The Theme
Summary: Change the size of an alien so it grows bigger as it feeds
Deep dive: Alien feeding and growth patterns
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* UpdateAliens (Part 2 of 5) calls ResizeFeedingAlien
* UpdateAliens (Part 4 of 5) calls ResizeFeedingAlien

This routine grows the alien in slot 31 or 32 by scaling the z-coordinates for
the alien's four object points. Because object points are stored with the
scale factor in bits 4 to 7, we can double the size of the alien by adding
16 to each z-coordinate, thus doubling the scale factor.

If bit 7 of A is set, then this routine resets the size to the smallest
feeding stage, which has a scale factor of 32 (i.e. 2^2).

Arguments:

A                    Determines how the alien is resized:

* If bit 7 is clear, double the size of the alien

* If bit 7 is set, reset the alien to stage 1

Y                    The number of the alien slot to process (31 or 32),
which determines which object points have their
z-coordinates updated in the zObjectPoint table:

* Resize object points 183 to 186 for alien slot 31

* Resize object points 188 to 191 for alien slot 32

Returns:

zObjectPoint         Updated z-coordinates for the relevant object points,
scaled as required

Y                    Y is unchanged

.ResizeFeedingAlien

STA K                  \ Store the A argument in K so we can retrieve it below

STY T                  \ Store Y in T so we can ensure it is unchanged by the
\ routine

LDX #3                 \ We do the following loop four times, to update the
\ alien's four object ID z-coordinates, so set a loop
\ counter in X

LDA #186               \ Set A to the object point ID to update for slot 31, so
\ we update points 183 to 186 in the loop

CPY #31                \ If this is alien slot 31, skip the following
BEQ size1              \ instruction

LDA #191               \ Set A to the object point ID to update for slot 32, so
\ we update points 188 to 191 in the loop

.size1

TAY                    \ Copy the object point ID we just set in A into Y, so
\ we can use it as an index

.size2

LDA zObjectPoint,Y     \ Set A to the z-coordinate of the object point

CLC                    \ Add 16 to the z-coordinate, which doubles the scale
ADC #16                \ factor in bits 4 to 7

BIT K                  \ If bit 7 of K is clear, skip the following two
BPL size3              \ instructions, as we are done

AND #15                \ Otherwise bit 7 of S is set, so we need to reset the
ORA #32                \ scale to the first feeding stage, which we can do like
\ this:
\
\   z = 32 + (z + 16) MOD 16
\
\ This gives us a result with 32 in bits 4 to 7 (i.e. a
\ scale factor of 2^2) while retaining the value in bits
\ 0 to 3

.size3

STA zObjectPoint,Y     \ Store the updated z-coordinate

DEY                    \ Decrement the object point ID

DEX                    \ Decrement the loop counter

BPL size2              \ Loop back until we have updated three slots

LDY T                  \ Restore Y from T, so it doesn't get changed by the
\ routine

RTS                    \ Return from the subroutine

Type: Subroutine
Category: The Theme
Summary: Extract the alien's feeding stage, ready for the hit calculations
in part 2
Deep dive: Detecting alien hits
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MainLoop (Part 6 of 15) calls CheckIfAlienIsHit

Arguments:

Y                    The object ID of the alien to check (30 to 33)

objectId             The object ID of the alien to check (30 to 33)

.CheckIfAlienIsHit

LDA #%01111101         \ Set QQ = %01111101, to hold the y-axis dimension of
STA QQ                 \ the alien's weak spot (let's call this y-size), which
\ we will scale down to match the alien's current size

LDA #%01000000         \ Set Q = %01000000, to hold the low byte of the offset
STA Q                  \ of the alien's weak spot from the alien's anchor point
\ (the high byte is always 5), which we will scale down
\ to match the alien's current size

LDA #%10100000         \ Set RR = %10100000, to hold the x-axis dimension of
STA RR                 \ the alien's weak spot (let's call this x-size), which
\ we will scale down to match the alien's current size

STA PP                 \ Set PP = %10100000, to hold the z-axis dimension of
\ the alien's weak spot (let's call this z-size), which
\ we will scale down to match the alien's current size

BCS ahit1

\ If we get here then Y = 30, so this is a dormant alien

LDA #4                 \ Set A = 4, to set as the feeding stage in ahit5 (stage
\ 4 is the dormant phase)

LDX #3                 \ Set X = 3, so ahit4 shifts right by 3 places

BNE ahit4              \ Jump to ahit4 (this BNE is effectively a JMP as X is
\ never zero)

.ahit1

LDA #0                 \ Set A = 0, so if this is the flying alien (Y = 33), we
\ set the feeding stage to 0 in ahit5 (stage 0 is for
\ fully fed aliens, and only fully fed aliens can fly)

BCS ahit2

\ If we get here then Y = 31, so this is a feeding alien

LDX #183               \ Set X = 183, to use as the object point ID

BNE ahit3              \ Jump to ahit3 (this BNE is effectively a JMP as X is
\ never zero)

.ahit2

BNE ahit5              \ If Y <> 32, then Y = 33 and this is the flying alien,
\ so jump to ahit5 to store the feeding stage and move
\ on to the next part

\ If we get here then Y = 32, so this is a feeding alien

LDX #188               \ Set X = 188, to use as the object point ID

.ahit3

\ If we get here then Y = 31 or 32 and X is the ID of
\ the first object point for this alien, so now we
\ extract the alien's current feeding stage from the
\ scale of the object point' z-coordinate, which gets
\ updated in ResizeFeedingAlien as the alien grows
\
\ Note that the feeding stage goes from 4 (dormant) down
\ to 0 (fully fed) as the alien feeds and grows bigger,
\ so we need to invert the scale of the z-coordinate
\ to get the correct value for the feeding stage

LDA zObjectPoint,X     \ Set A to the object point's z-coordinate

EOR #%01110000         \ The z-coordinate contains scale information in bits 4
\ to 7, with the smallest feeding alien having a scale
\ factor of 2^2, and the largest having a scale factor
\ of 2^5 (there are four different sizes of feeding
\ alien)
\
\ This means that even at the largest scale, bit 7 of
\ the scale will still be zero, so to invert the scale
\ we only need to flip bits 4 to 6, as then:
\
\   * If scale is %0010 (2^2), result is %0101 (5)
\   * If scale is %0011 (2^3), result is %0100 (4)
\   * If scale is %0100 (2^4), result is %0011 (3)
\   * If scale is %0101 (2^5), result is %0010 (2)
\
\ so this EOR inverts the alien's scale factor to the
\ range 2 to 5, if we only consider the top nibble

LSR A                  \ We now shift the top nibble down, so A contains the
LSR A                  \ inverted scale factor (i.e. A is in the range 2 to 5)
LSR A
LSR A

TAX                    \ Finally, we subtract 2 from the inverted scale factor,
DEX                    \ so A is now in the range 0 to 3 and reflects the four
DEX                    \ feeding stages:
\
\   * 0 = large feeding alien (fully fed)
\   * 1 = medium feeding alien
\   * 2 = small feeding alien
\   * 3 = smallest feeding alien

TXA                    \ Copy the feeding stage into X

BEQ ahit5              \ If X = 0, the alien is at its largest size, so jump to
\ ahit5 to store the feeding stage and move on to the
\ next part

\ Otherwise we scale QQ, RR, PP and QQ right by the
\ number of places given in X

.ahit4

\ This loop shifts the following to the right by X
\ places, where X > 0

LSR QQ                 \ Shift QQ, RR, PP and QQ right by one place
LSR RR
LSR PP
LSR Q

DEX                    \ Decrement the shift counter in X

BNE ahit4              \ Loop back until we have shifted right by X places

\ By the time we get here, the variables are set as
\ follows:
\
\   * Fully fed (stage 0) or flying alien:
\
\       Q  = %01000000, so (5 Q) = &540 = 1360
\       RR = %10100000, so x-size = 160
\       QQ = %01111101, so y-size = 125
\       PP = %10100000, so z-size = 160
\
\   * Medium feeding alien (stage 1):
\
\       Q  = %00100000, so (5 Q) = &520 = 1312
\       RR = %01010000, so x-size = 80
\       QQ = %00111110, so y-size = 62
\       PP = %01010000, so z-size = 80
\
\   * Small feeding alien (stage 2):
\
\       Q  = %00010000, so (5 Q) = &510 = 1296
\       RR = %00101000, so x-size = 40
\       QQ = %00011111, so y-size = 31
\       PP = %00101000, so z-size = 40
\
\   * Smallest feeding alien (stage 3) or dormant alien:
\
\       Q  = %00001000, so (5 Q) = &508 = 1288
\       RR = %00010100, so x-size = 20
\       QQ = %00001111, so y-size = 15
\       PP = %00010100, so z-size = 20

.ahit5

STA feedingStage       \ Store the alien's feeding stage in feedingStage

Type: Subroutine
Category: The Theme
Summary: Check to see whether the alien has been hit, and if so, initiate
the explosion
Deep dive: Detecting alien hits
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

LDA #0                 \ Set hitTimer = 0 so the default result is a miss
STA hitTimer

LDY objectId           \ Set Y to the object ID of the alien

JSR GetAlienWeakSpot   \ Calculate the coordinate of the alien's weak spot as
\ follows:
\
\   (I+2 W+2) = xObject + (5 Q)
\
\   (I+1 W+1) = yObject
\
\   (I W)     = zObject + (5 Q)
\
\ So for the alien object, the weak spot is at a point
\ coordinate of ((5 Q), 0, (5 Q)) within the object

LDX #228               \ Set VV to iterate through the following in the outer
STX VV                 \ loop below (i.e. from ahit6 to the end):
\
\   * 228 = the trailing end of the left bullet trail
\
\   * 230 = the trailing end of the right bullet trail

.ahit6

LDX VV                 \ Set X to denote the trailing end of the bullet trail
\ that we are analysing (228 or 230)

LDA #31                \ Set WW to act as a loop counter for when we check
STA WW                 \ along the length of the bullet trail for a hit, moving
\ 1/32 of the way for each of the 32 iterations

LDY #0                 \ Set Y to loop through the three axes

.ahit7

STY Q                  \ Store the axis counter in Q so we can retrieve it
\ below

JSR GetTrailVectorStep \ Set (A V R) to 1/32 of the vector for the specified
\ bullet trail

LDY Q                  \ Restore the axis counter into Y

STA xTemp2Hi,Y         \ Set (xTemp2Hi xTemp2Lo xTemp1Lo) = (A V R)
LDA V
STA xTemp2Lo,Y
LDA R
STA xTemp1Lo,Y

INY                    \ Increment the loop counter to move on to the next axis

CPY #3                 \ Loop back until we have calculated the bullet trail
BNE ahit7              \ vector

LDX #LO(xTemp2Lo)      \ Set X so the call to CopyWorkToPoint copies the
\ coordinates from (xTemp2, yTemp2, zTemp2)

LDY #0                 \ Set Y so the call to CopyWorkToPoint copies the
\ coordinates to point 0

JSR CopyWorkToPoint    \ Copy the coordinates from (xTemp2, yTemp2, zTemp2)
\ to point 0

\ Point 0 now contains the vector of the bullet trail
\ for the bullet specified in VV, with the lowest byte
\ dropped, so each axis contains (A V) from the above

LDY VV                 \ Set Y to the bullet that we are analysing (228 or 230)

JSR CheckAlienWeakSpot \ Check whether this end of the bullet trail has hit the
\ alien's weak spot, and if it has, set up the explosion
\ and return from the subroutine

LDY VV                 \ Set Y to the bullet that we are analysing (228 or 230)

LDX #216               \ Set X to iterate through the coordinate offsets for
\ object 0

.ahit8

TYA                    \ Point Y to the next axis (xObject, yObject, zObject)
CLC                    \
ADC #nextAxis          \ The first iteration of this loop has Y = 228 or 230,
TAY                    \ so this bumps Y onto 268 or 260, which gets truncated
\ in the 8-bit register to 12 or 14, so this moves Y
\ through the xObject, yObject and zObject values for
\ object 12 (when the initial value of Y = 228) or
\ object 14 (when the initial value of Y = 230)

TXA                    \ Point X to the next axis (xObject, yObject, zObject)
CLC                    \
ADC #nextAxis          \ The first iteration of this loop has X = 216, so this
TAX                    \ bumps X onto 256, which gets truncated in the 8-bit
\ register to 0, so this moves X through the xObject,
\ yObject and zObject values for object 0

LDA xObjectLo,Y        \ Copy the coordinate from the bullet object to object 0
STA xObjectLo,X

CPX #200               \ Loop back until we have copied all six coordinates
BNE ahit8

\ By this point, object 0 is at the same coordinate as
\ the bullet we are checking, and we now work our way
\ along the trail vector, adding the 1/32 vector that
\ we calculated above for each of the 32 iterations of
\ the following loop

.ahit9

LDY #2                 \ Set a counter in Y to iterate through the three axes
\ (the comments below are for the x-axis calculation)

LDX #nextAxis*2        \ Set the index in X to point to the z-coordinate for
\ object 0, which we decrement by nextAxis over each
\ iteration to work through the three axes

.ahit10

\ Above we set (xTemp2Hi xTemp2Lo xTemp1Lo) to the 1/32
\ vector, but we only copied (xTemp2Hi xTemp2Lo) into
\ point 0, and ignored the fractional part, so we add
\ that part to the object 0 coordinate first

LDA xTemp1Lo,Y         \ Set xTemp2Hi = xTemp2Hi + xTemp1Lo
CLC                    \
ADC xTemp2Hi,Y         \ to work out when the fractional part cumulatively
STA xTemp2Hi,Y         \ adds up to an integer (in other words, we store the
\ cumulative sum of the fractional part from xTemp1Lo in
\ xTemp2Hi)

\ skip incrementing the object coordinate

\ Otherwise the cumulative sum of the fractional part
\ just reached an integer, so we need to add an extra
\ integer (1) to the object 0 coordinate

INC xObjectLo,X        \ Increment the object coordinate for object 0 in
BNE ahit11             \ (xObjectHi xObjectLo), starting with the low byte
INC xObjectHi,X        \ and incrementing the high byte if the low byte
\ overflows

.ahit11

TXA                    \ Point X to the next axis (zObject, yObject, xObject)
SEC
SBC #nextAxis
TAX

DEY                    \ Decrement the axis counter

BPL ahit10             \ Loop back until we have processed all three axes

\ We have now moved object 0 along the trail by adding
\ the fractional part of the 1/32 vector xTemp1Lo, so
\ now we can add the rest of the vector which we stored
\ in point 0 above, to move along the trail by exactly
\ 1/32 of the trail vector

LDX #0                 \ Move object 0 by the vector in point 0, which we set
LDY #0                 \ to the vector of the bullet trail above

\ We now check whether this point along the bullet trail
\ is in the alien's weak spot

LDY #216               \ Check whether object 0 has hit the alien's weak
JSR CheckAlienWeakSpot \ spot, and if it has, set up the explosion and return
\ from the subroutine

DEC WW                 \ Decrement the counter we set in WW so we repeat this
\ process 32 times

BPL ahit9              \ Loop back until we have stepped all the way along the
\ trail vector, from the back end of the trail all the
\ way to the bullet at the front, in steps of 1/32,
\ checking at each point whether it is in the weak spot

\ If we get here then we have now checked the entire
\ trail of the left bullet for a hit, so we repeat the
\ whole thing for the right bullet trail

LDA VV                 \ Set VV = VV + 2
CLC                    \
ADC #2                 \ so VV now points to the next bullet trail (i.e. 230)
STA VV

CMP #232               \ If VV = 232 then we have now processed both bullet
BEQ ahit12             \ trails, so jump to ahit12 to return from the
\ subroutine

JMP ahit6              \ Otherwise loop back to ahit6 to process the next
\ bullet trail

.ahit12

RTS                    \ Return from the subroutine

Type: Subroutine
Category: The Theme
Summary: Calculate the coordinates of an alien's weak spot
Deep dive: Detecting alien hits
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* CheckIfAlienIsHit (Part 2 of 2) calls GetAlienWeakSpot

The alien's weak spot is calculated as follows:

* x-coordinate = (xObjectHi xObjectLo) + (5 Q)

* y-coordinate = (yObjectHi yObjectLo)

* z-coordinate = (zObjectHi zObjectLo) + (5 Q)

where Q is

This is called STIP in the original source code.

Arguments:

Y                    The object ID of the alien (30 to 33)

Q                    The low byte of the amount to add

Returns:

(I+2 W+2)            The x-coordinate of the alien's weak spot

(I+1 W+1)            The y-coordinate of the alien's weak spot

(I W)                The z-coordinate of the alien's weak spot

.GetAlienWeakSpot

LDX #2                 \ Set a counter in X to iterate through 2, 1, 0, which
\ has the following effect:
\
\ When X = 2:
\
\   * (I+2 W+2) = (xObjectHi xObjectLo) + (5 Q)
\
\ When X = 1:
\
\   * (I+1 W+1) = (yObjectHi yObjectLo)
\
\ When X = 0:
\
\   * (I W) = (zObjectHi zObjectLo) + (5 Q)
\
\ note that

.weak1

LDA xObjectLo,Y        \ Set (I+X W+X) = (xObjectHi xObjectLo) + (5 Q)
CLC                    \
ADC Q                  \ starting with the low bytes
STA W,X

LDA xObjectHi,Y        \ And then the high bytes
STA I,X

.weak2

TYA                    \ Point Y to the next axis (xObject, yObject, zObject)
CLC
TAY

DEX                    \ Decrement the loop counter

BPL weak3              \ If we haven't yet done all three calculations, jump
\ to weak3

RTS                    \ Return from the subroutine

.weak3

BEQ weak1              \ If X = 0, jump up to weak1 to add (5 Q)

LDA xObjectLo,Y        \ If we get here then X = 1, so do the calculation
STA W,X                \ without adding (5 Q)
LDA xObjectHi,Y
STA I,X

JMP weak2              \ Jump back to weak2 to move on to X = 0

Type: Subroutine
Category: The Theme
Summary: Check whether an object is close enough to an alien's weak spot to
be hitting it
Deep dive: Detecting alien hits
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* CheckIfAlienIsHit (Part 2 of 2) calls CheckAlienWeakSpot

If the object is hitting the alien's weak spot, the routine returns to the
caller of the caller - in other words, it returns from the original call to
the CheckIfAlienIsHit routine, in part 6 of the main loop.

This is called HITS in the original source code.

Arguments:

Y                    The bullet trail to be calculated:

* 216 = object 0, which we set to points along the
bullet trail at 1/32 intervals

* 228 = the trailing end of the left bullet trail

* 230 = the trailing end of the right bullet trail

.CheckAlienWeakSpot

LDX #2                 \ Set a counter in X to iterate through the three axes

.spot1

TYA                    \ Point Y to the next axis (xObject, yObject, zObject)
CLC                    \
ADC #nextAxis          \ The routine is called is with Y = 216, 228 or 230, so
TAY                    \ this bumps X onto 256, 268 or 260, which gets
\ truncated in the 8-bit register to 0, 12 or 14, so
\ this moves X through the xObject, yObject and zObject
\ values for object 0 (when called with X = 216), object
\ 12 (when called with X = 228) or object 14 (when
\ called with X = 230)
\
\ Objects 12 and 14 are the trailing ends of the two
\ bullet trails, so the following checks whether the
\ trailing end is within the weak spot, rather than the
\ bullets themselves

LDA xObjectLo,Y        \ Set (A T) = (xObjectHi xObjectLo) - (I+X W+X)
SEC                    \
SBC W,X                \ starting with the low bytes
STA T

LDA xObjectHi,Y        \ And then the high bytes
SBC I,X

\ So we now have:
\
\   (A T) = xObject - (I W)
\
\ where xObject is the coordinate of the bullet, and
\ (I W) is the coordinate of the alien's weak spot
\
\ In other words, (A T) is the distance between the
\ bullet and the alien's weak spot

BNE spot2              \ If the high byte in A is non-zero, then the bullet is
\ too far from the weak spot to do any damage, so jump
\ to spot2 to return from the subroutine

LDA T                  \ If the low byte in T is >= the corresponding value in
CMP PP,X               \ PP, QQ or RR (for the z, y and x-axes respectively),
BCS spot2              \ then the bullet is too far away from the weak spot to
\ do any damage, so jump to spot2 to return from the
\ subroutine

DEX                    \ Otherwise the bullet is close enough to the weak spot
\ to cause damage in this axis, so decrement X to point
\ to the next axis

BPL spot1              \ Loop back until we have checked all three axes

\ If we get here then the bullet is close enough to the
\ weak spot in all three axes, so we have a hit

LDA objectId           \ Store the object ID of the hit alien in hitObjectId
STA hitObjectId

TSX                    \ Remove two bytes from the top of the stack, so the
INX                    \ RTS below returns us to the JSR CheckIfAlienIsHit in
INX                    \ part 6 of the main loop
TXS

LDA #27                \ Set the hitTimer to 27 to start the explosion counter
STA hitTimer

.spot2

RTS                    \ Return from the subroutine

Type: Subroutine
Category: The Theme
Summary: Calculate 1/32 of the vector for a bullet trail
Deep dive: Detecting alien hits
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* CheckIfAlienIsHit (Part 2 of 2) calls GetTrailVectorStep

Calculates one axis of the vector for the 1/32 of the specified bullet trail
and returns it in (A V R).

This is called ADIF in the original source code.

Arguments:

X                    The bullet trail to be calculated:

* 228 = left bullet trail

* 230 = right bullet trail

Returns:

X                    Updated to point to the next axis, so the first call
will return the x-axis of the vector, the second the
y-axis, and the third the z-axis

(A V R)               One axis of the vector for the specified bullet trail,
as a signed 24-bit number and divided by 32

.GetTrailVectorStep

LDA #0                 \ Set P = 0, to feed bits into the top bit of (A V R) in
STA P                  \ the final stage below

STA R                  \ Set R = 0, for use in constructing (A V R)

TXA                    \ Point X to the next axis (xObject, yObject, zObject)
CLC                    \
ADC #nextAxis          \ The first time that the routine is called is with
TAX                    \ X = 228 or 230, so this bumps X onto 268 or 260, which
\ gets truncated in the 8-bit register to 12 or 14, so
\ this moves X through the xObject, yObject and zObject
\ values for object 12 (when first called with X = 228)
\ or object 14 (when first called with X = 230)

\ We now subtract the following object coordinates:
\
\   * If first called with X = 228, we calculate object
\     13 - object 12 (i.e. the left bullet minus the
\     back end of the left bullet trail)
\
\   * If first called with X = 230, we calculate object
\     15 - object 13 (i.e. the right bullet minus the
\     back end of the right bullet trail)
\
\ In each case we end up with the vector of the relevant
\ bullet trail for axis Y in (A V)

LDA xObjectLo+1,X      \ Set (A V) = xObject+1 - xObject
SEC                    \
SBC xObjectLo,X        \ starting with the low bytes
STA V

LDA xObjectHi+1,X      \ And then the high bytes
SBC xObjectHi,X

BPL bulv1              \ If (A V) is negative, decrement P to &FF, so it is
DEC P                  \ full of bits of the correct polarity to shift into bit
\ 7 of A in (A V R)

.bulv1

\ We now have the number (A V 0) in (A V R), plus a byte
\ P made up of the correct sign bits, so the final stage
\ is to divide this by 32 by shifting right

LDY #4                 \ We want to shift the result right by five places to
\ divide the result by 32, so set a shift counter in Y

.bulv2

LSR P                  \ Shift (A V R) right by one place, shifting one of the
ROR A                  \ sign bits from P into bit 7 of A
ROR V
ROR R

DEY                    \ Decrement the shift counter

BPL bulv2              \ Loop back until we have done all five shifts, so we
\ now have:
\
\   (A V R) = (A V R) / 32

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Dashboard
Summary: Show or hide the upside down bar in the artificial horizon
indicator
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* ApplyFlightModel (Part 6 of 7) calls ShowUpsideDownBar

This routine shows the upside down bar in the artificial horizon if bit 6 and
bit 7 of zRotationHi are different.

This is how it works. The value of zRotationHi contains the following:

*   0 to  63 (bit 6 clear, bit 7 clear)
*  64 to 127 (bit 6 set,   bit 7 clear)
* 128 to 191 (bit 6 clear, bit 7 set)
* 192 to 255 (bit 6 set,   bit 7 set)

The zRotation angle determines how the plane is rotated around the z-axis. The
z-axis points into the screen, so rotating the plane around this axis is the
same as rolling the plane. A zRotation of 0 is a horizontal plane, and as the
angle increases, the plane rolls to the right. If we consider the plane doing
a full 360-degree roll, then for the first quarter the plane is still upright,
for the second and third quarters it is upside down, and then for the final
quarter it is upright again.

You will notice that bits 6 and 7 differ in the second and third quarters in
the list above, so if bits 6 and 7 of zRotationHi are different, then the
plane is upside down, and we should show a bar at the bottom of the artificial
horizon indicator.

.ShowUpsideDownBar

LDA zRotationHi        \ If bit 7 of zRotationHi is clear, skip the following
BPL upsi1              \ instruction

EOR #%11000000         \ Flip bits 6 and 7 of A, making bit 7 clear and bit 6
\ flipped

.upsi1

\ When we get here, we know bit 7 of A is clear

AND #%11000000         \ Extract bits 6 and 7 of A

BEQ upsi2              \ If bit 6 of A is clear (we already know bit 7 is
\ clear), then the plane is the correct way up, so skip
\ the following instruction

\ We get here if one of the following is true:
\
\   * Bit 7 of zRotationHi is clear and bit 6 is set
\   * Bit 7 of zRotationHi is set and bit 6 is clear
\
\ either of which means the plane is upside down

LDA #%00001110         \ Bit 6 is set, so set A to a three-pixel horizontal
\ line to show in the indicator

.upsi2

STA row25_char13_1     \ Set the line at the bottom of the artificial horizon
\ indicator to the pixel pattern in A (0 if the plane is
\ the right way up, %00001110 if it is upside down)

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Visibility
Summary: Calculate coordinates and visibility for a runway line
Deep dive: Visibility checks
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* ProcessLine (Part 2 of 7) calls ProcessRunwayLine

Arguments:

lineId               The line ID to process (1 to 11):

* 1 to 4 are the runway outline

* 5 to 11 are the dashes down the middle of the runway

Returns:

showLine             Whether this line is visible:

* 0 = line is visible

* Non-zero = line is not visible

.ProcessRunwayLine

LDA objectStatus+1     \ Fetch the status byte for object 1, the runway object

BEQ prun3              \ If object 1's status byte is zero, then we have not
\ yet calculated the runway object's coordinates and

BMI prun1              \ If bit 7 of object 1's status byte is set, then we
\ have already decided that the runway object is
\ accordingly

JMP prun9              \ If we get here then we have already decided that the
\ runway object is hidden, so jump to prun9 to set the
\ line's visibility as hidden

.prun1

LDA lineId             \ If lineId < 5, then the line ID is in the range 1 to
CMP #5                 \ 4, so it's part of the runway outline, so jump to
BCC prun2              \ prun2 to return from the subroutine as we always show
\ the outline when the runway is visible

LDA showRunwayDashes   \ The line we are checking is one of the dashes down the
STA showLine           \ middle of the runway, so set the line's visibility to
\ the value of showRunwayDashes, which contains the
\ visibility of the runway dashes

.prun2

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Visibility
Summary: Calculate coordinates and visibility for the runway outline
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

.prun3

LDA #0                 \ Set the matrix number so the call to SetPointCoords
STA matrixNumber       \ and SetObjPointCoords use matrix 1 in the calculation,
\ which will rotate the point by the plane's pitch, roll
\ and yaw angles,  transforming it from the outside
\ world's frame of reference to the plane's frame of
\ reference

LDA #1                 \ Set objectId = 1 to denote the runway object
STA objectId

JSR SetObjectCoords    \ Calculate the runway object's coordinates and
\ visibility, updating the object's status byte with the
\ results and setting point 217 to the object's anchor
\ point

BPL prun9              \ If bit 7 of the runway object's updated status byte is
\ clear, then the runway object is not visible, so jump
\ to prun9 to set the line's visibility accordingly

\ The runway object is visible, so now we work out the
\ coordinates of the runway outline, which is a
\ rectangle whose corners are points 1 to 4

LDA #0                 \ We start by zeroing the (xTemp1 yTemp1 zTemp1) vector,
\ which is stored in six bytes to give us three 16-bit
\ coordinate values (from xTemp1Lo to zTemp1Hi), so
\ first we set A = 0 to use as our zero

LDX #5                 \ Set a counter in X to count the six bytes

.prun4

STA xTemp1Lo,X         \ Zero the X-th byte of the six-byte coordinate block
\ between xTemp1Lo and zTemp1Hi

DEX                    \ Decrement the loop counter

BPL prun4              \ Loop back until we have zeroed all six bytes

\ We now calculate the coordinates for points 1 to 4,
\ starting with point 1

LDY #217               \ Set Y so the call to AddTempToPoint adds point 217 to
\ the xTemp1 vector

STY objectAnchorPoint  \ The anchor point of the runway is point 217, so set
\ objectAnchorPoint to this point for the call to
\ SetObjPointCoords

LDX #1                 \ Set X so the call to AddTempToPoint stores the result
\ in point ID 1

JSR AddTempToPoint     \ Add point 217 to the (xTemp1 yTemp1 zTemp1) point and
\ store the result in (xPoint, yPoint, zPoint) for
\ point 1
\
\ This simply sets point ID 1 to the object's anchor
\ point, as we just zeroed (xTemp1 yTemp1 zTemp1), so
\ point1 of the runway outline is now calculated

LDA #2                 \ Calculate the coordinates for object point 2 with
STA GG                 \ anchor point 217, so point 2 is now calculated
JSR SetObjPointCoords  \
\ This also sets (xTemp1 yTemp1 zTemp1) to the vector
\ from the anchor point to point 2, which we now copy
\ into xTemp2 by copying the following values:
\
\   xTemp1Lo, yTemp1Lo, zTemp1Lo
\   xTemp1Hi, yTemp1Hi, zTemp1Hi
\
\ into the following locations:
\
\   xTemp2Hi,  yTemp2Hi,  zTemp2Hi
\   xTemp2Top, yTemp2Top, zTemp2Top
\
\ so (xTemp2Top xTemp2Hi) etc. contain the vector from
\ the anchor point to the point 2

LDX #5                 \ Set a counter for six bytes

.prun5

LDA xTemp1Lo,X         \ Copy the X-th byte of xTemp1Lo to the X-th byte of
STA xTemp2Hi,X         \ xTemp2Hi

DEX                    \ Decrement the loop counter

BPL prun5              \ Loop back until we have copied all six bytes

\ By now we have coordinates for points 1 and 2, plus
\ the vector from the anchor point to point 2 (which
\ is the same as the vector from point 1 to point 2,
\ as point 1 is the runway's anchor point)

LDA #4                 \ Calculate the coordinates for object point 4 with
STA GG                 \ anchor point 217, so point 4 is now calculated
JSR SetObjPointCoords  \
\ This also sets (xTemp1 yTemp1 zTemp1) to the vector
\ from the anchor point (point 1) to point 4

\ By now we have coordinates for points 1, 2 and 4, and
\ we could just call SetObjPointCoords for point 3, but
\ we can save a bit of time as the runway outline is a
\ rectangle, so we already have all the data we need to
\ calculate the coordinates for point 3
\
\ The runway outline looks like this:
\
\      2         3
\       +-------+
\       |   :   |
\       |   :   |
\       |   :   |
\       |   :   |
\       |   :   |
\       +-------+
\      1         4
\
\ We know the vector from point 1 to point 4 - it's in
\ the (xTemp1 yTemp1 zTemp1) vector - and we know the
\ coordinates of point 2, so we can calculate the
\ coordinates of point 3 by simply adding the vector to
\ the coordinates of point 2, which is what we do next

LDY #2                 \ Set point 3's coordinates to point 2's coordinates +
LDX #3                 \ (xTemp1 yTemp1 zTemp1), so point 3 is now calculated

LDA showLine           \ If showLine is zero, then all four coordinates fit
BEQ prun6              \ within the boundaries of the world, so jump to prun6
\ to keep going

LDA #%01000000         \ At least one of the calculations above overflowed, so
STA objectStatus+1     \ at least one coordinate is outside the boundaries of
\ the world, so set bit 6 of the status byte for the
\ runway object to indicate that we have now calculated
\ the runway object's coordinates and visibility, and
\ clear bit 7 to indicate that the runway is not visible

RTS                    \ Return from the subroutine

.prun6

LDX #4                 \ Set the status byte for points 1 to 4 to indicate
JSR SetPointVisibility \ that their coordinates and visibility have been
\ calculated

Type: Subroutine
Category: Visibility
Summary: Calculate visibility for the runway dashes
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

LDY #1                 \ Set Y = 1 so we check point ID 1 in the call to
\ CheckLineDistance (point ID 1 is the anchor point of
\ the runway)

LDX #10                \ Set X = 10 so we check the distance against that for
\ line ID 10, which is one of the dashes in the middle
\ of the runway

.prun7

JSR CheckLineDistance  \ Check whether point Y on line X is within the visible
STA showLine           \ distance for the line and store the result in showLine

BNE prun8              \ If the point is too far away to be visible, then all
\ the dashes are too far away to be seen, so jump to
\ prun8 to return the relevant result

CPY #3                 \ If Y = 3, then we have checked both point 1 and 3 and
BEQ prun12             \ both are close enough to be visible, so jump to prun12
\ to finish off the processing

LDY #3                 \ Otherwise set Y = 3 and jump back prun7 to check point
BNE prun7              \ 3 as well (point 3 is the corner of the runway outline
\ opposite the anchor point)

.prun8

LDA #%10000000         \ Set showRunwayDashes to indicate that the dashes down
STA showRunwayDashes   \ the middle of the runway are not visible

LDA lineId             \ If lineId < 5, then the line ID is in the range 1 to
CMP #5                 \ 4, so it's part of the runway outline, so jump to
BCC prun10             \ prun10 to return the result that the line is visible,
\ as we always show the outline when the runway is
\ visible, even when the runway dashes are hidden

.prun9

LDA #%10000000         \ Set A to indicate the line is not visible, and jump to
BNE prun11             \ prun11 to return this as the value of showLine (this
\ BNE is effectively a JMP as A is never zero)

.prun10

LDA #0                 \ Set A to indicate the line is visible, so we can
\ return this as the value of showLine

.prun11

STA showLine           \ Set the line's visibility to the value in A, to return
\ as our result

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Visibility
Summary: Construct the dashes down the middle of the runway
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

.prun12

\ By the time we get here, (xTemp1 yTemp1 zTemp1)
\ contains the vector from the anchor point (point 1) to
\ point 4, which is the vector from one side of the
\ runway to the other
\
\ We now want to halve the (xTemp1 yTemp1 zTemp1)
\ vector, to give the vector from one side of the runway
\ to the line of dashes down the middle
\
\ As a reminder, the runway outline looks like this:
\
\      2         3
\       +-------+
\       |   :   |
\       |   :   |
\       |   :   |
\       |   :   |
\       |   :   |
\       +-------+
\      1         4
\
\ so we now calculate (xTemp1 yTemp1 zTemp1) to be the
\ vector from the left edge of the runway to the dashes
\ in the middle

LDX #2                 \ Set a counter in X to work through the three axes of
\ the (xTemp1 yTemp1 zTemp1) vector (the comments below
\ cover the iteration for the x-axis)

.prun13

CLC                    \ Clear the C flag, to use when (xTemp1Hi xTemp1Lo) is
\ positive

LDA xTemp1Hi,X         \ If xTemp1Hi is positive, skip the next instruction
BPL prun14

SEC                    \ Set the C flag, to use when (xTemp1Hi xTemp1Lo) is
\ negative

.prun14

ROR A                  \ Shift (xTemp1Hi xTemp1Lo) to the right by one place,
STA xTemp1Hi,X         \ inserting the C flag into the top bit of xTemp1Hi,
LDA xTemp1Lo,X         \ which ensures that we retain the same sign
ROR A
STA xTemp1Lo,X

DEX                    \ Decrement the loop counter to move to the next axis

BPL prun13             \ Loop back until we have halved xTemp1, yTemp1 and
\ zTemp1

\ (xTemp1 yTemp1 zTemp1) now contains the vector from
\ one side of the runway to the line of dashes down the
\ middle

LDY #2                 \ Set point 21's coordinates to point 2's coordinates +
LDX #21                \ (xTemp1 yTemp1 zTemp1)

LDY #1                 \ Set point 5's coordinates to point 1's coordinates +
LDX #5                 \ (xTemp1 yTemp1 zTemp1)

\ So we've now calculated points 5 and 21 as follows:
\
\      2    21   3
\       +-------+
\       |   :   |
\       |   :   |
\       |   :   |
\       |   :   |
\       |   :   |
\       +-------+
\      1    5    4
\
\ Next, we make a backup of the (xTemp1 yTemp1 zTemp1)
\ vector in (xDashesVector yDashesVector zDashesVector)

LDX #5                 \ Set a counter for six bytes

.prun15

LDA xTemp1Lo,X         \ Copy the X-th byte of xTemp1Lo to the X-th byte of
STA xDashesVectorLo,X  \ xDashesVectorLo

DEX                    \ Decrement the loop counter

BPL prun15             \ Loop back until we have copied all six bytes

\ So (xDashesVector yDashesVector zDashesVector) now
\ contains the vector from one side of the runway to the
\ line of dashes down the middle

\ We now zero variables T, U, V, W, G and H

LDX #5                 \ Set a counter for six bytes

LDA #0                 \ Set A = 0 so we can zero the variables

.prun16

STA T,X                \ Zero the X-th byte from T

DEX                    \ Decrement the loop counter

BPL prun16             \ Loop back until we have zeroed all six bytes

\ In part 2 above, we set (xTemp2Top xTemp2Hi) etc. to
\ the vector from the anchor point (i.e. point 1) to
\ point 2

LDX #2                 \ Set a counter in X to work through the three axes (the
\ comments below cover the iteration for the x-axis)

\ For each axis in turn, we

.prun17

LDA #0                 \ Set R = 0
STA R

LDA xTemp2Top,X        \ Set A = xTemp2Top

BPL prun18             \ If xTemp2Top is positive, skip the following
\ instruction

DEC R                  \ Decrement R to %11111111

\ So by this point, R contains the correct bits to
\ rotate into bit 7 of A to retain the sign of A

.prun18

\ Set (xTemp1Hi A T) = (xTemp2Top xTemp2Hi 0) / 2
\

ROR A
STA xTemp1Hi,X

LDA xTemp2Hi,X         \ Then the high byte
ROR A

ROR T,X                \ And then the low byte

LDY #2                 \ We now shift right by three places, so set a counter
\ in Y

.prun19

LSR R                  \ Set (xTemp1Hi A T) = (xTemp1Hi A T) / 2
ROR xTemp1Hi,X         \
ROR A                  \ keeping the sign intact by feeding in bits from R
ROR T,X

DEY                    \ Decrement the loop counter

BPL prun19             \ Loop back until we have shifted right by three places

\ In all, the above does the following:
\
\   (xTemp1Hi A T) = (xTemp2Top xTemp2Hi 0) / 16
\
\ while retaining the sign

STA xTemp1Lo,X         \ Set (xTemp1Hi xTemp1Lo T) = (xTemp1Hi A T)
\                          = (xTemp2Top xTemp2Hi 0) / 16

DEX                    \ Decrement the loop counter to move to the next axis

BPL prun17             \ Loop back until we have processed all three axes

\ So we have now calculated the vector from point 1 to
\ point 2, divided by 16, with the result stored in the
\ xTemp1 vector and the variables T, U and V used for
\ the lowest bytes, like this:
\
\   x-coordinate = (xTemp1Hi xTemp1Lo T)
\   y-coordinate = (yTemp1Hi yTemp1Lo U)
\   z-coordinate = (zTemp1Hi zTemp1Lo V)
\
\ In other words, the xTemp1/T/U/V vector contains 1/16
\ of the full vector between points 5 and 21

LDX #LO(xTemp2Lo)      \ Set X so the call to CopyPointToWork copies the
\ coordinates to (xTemp2, yTemp2, zTemp2)

LDY #5                 \ Set Y so the call to CopyPointToWork copies the
\ coordinates from point 5

JSR CopyPointToWork    \ Copy the coordinates from point 5 to
\ (xTemp2, yTemp2, zTemp2)

\ So (xTemp2, yTemp2, zTemp2) now contains the
\ coordinates of point 5

\ We now calculate the start and end points for the
\ dashes in the middle of the runway by starting at
\ point 5, and moving up the middle line in steps of
\ 1/16 of the distance between points 5 and 21

.prun20

LDX #2                 \ Set a counter in X to work through the three axes (the
\ comments below cover the iteration for the x-axis)

.prun21

CLC                    \ Set (xTemp2Hi xTemp2Lo W) += (xTemp1Hi xTemp1Lo T)
LDA W,X                \
ADC T,X                \ starting with the lowest bytes
STA W,X

LDA xTemp2Lo,X         \ Then the middle bytes
STA xTemp2Lo,X

LDA xTemp2Hi,X         \ And then the highest bytes
STA xTemp2Hi,X

DEX                    \ Decrement the loop counter to move to the next axis

BPL prun21             \ Loop back until we have added all three axes

\ On the first iteration through this code, the full
\ (xTemp2Hi xTemp2Lo W) vector contains a point 1/16
\ of the way from point 5 to point 21

LDX #LO(xTemp2Lo)      \ Set X so the call to CopyWorkToPoint copies the
\ coordinates from (xTemp2, yTemp2, zTemp2)

INY                    \ Increment Y so the call to CopyPointToWork copies the
\ coordinates from the next point along the dash line
\ (which will be point 6 on the first iteration through
\ this code, then point 7, and so on)

JSR CopyWorkToPoint    \ Copy the coordinates from (xTemp2, yTemp2, zTemp2)
\ to point Y, the next point along the dash line

CPY #19                \ Loop back to prun20 to move another 1/16 along the
BNE prun20             \ dash line, until we have done point 19, meaning we
\ have set the coordinates for points 6 through 19
\ (i.e. we have added 14 points, two for each of the
\ seven dashes in the middle of the runway)

LDX #19                \ Set the status byte for points 1 to 19 to indicate
JSR SetPointVisibility \ that their coordinates and visibility have been
\ calculated

Type: Subroutine
Category: Visibility
Summary: Clip any portion of the runway outline that's behind us
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

\ The final step is to check whether the runway appears
\ both in front of us and behind us (which will happen
\ when we are sitting on the runway, for example, or
\ during the final approach when trying to land)
\
\ If it is, then we want to clip the part of the runway
\ outline that's behind us, as close to the screen as
\ possible (though we still want the runway to go behind
\ us a bit, so clipping to the nearest coordinate behind
\ the screen is the best approach)
\
\ We start by restoring the vector that we stored in
\ (xDashesVector yDashesVector zDashesVector) back to
\ (xTemp1 yTemp1 zTemp1), which is the vector from one
\ side of the runway to the line of dashes down the
\ middle

LDX #5                 \ Set a counter for six bytes

.prun22

LDA xDashesVectorLo,X  \ Copy the X-th byte of xDashesVectorLo to the X-th byte
STA xTemp1Lo,X         \ of xTemp1Lo

DEX                    \ Decrement the loop counter

BPL prun22             \ Loop back until we have copied all six bytes

\ So (xTemp1 yTemp1 zTemp1) is once again the vector
\ from one side of the runway to the line of dashes down
\ the middle

\ We now work our way along the dash line, checking the
\ coordinates of the points we just added to see if the
\ sign of the z-coordinate changes between any of the
\ points (which will indicate that the runway is both in
\ front of us and behind us)

LDA zPointHi+6         \ Set P to the high byte of the z-coordinate for point 6
STA P                  \ (which contains the sign of the coordinate)

LDY #6                 \ We now loop through the points we just calculated for
\ the dashes, so we set a counter in Y to loop from 6 to
\ 19

.prun23

LDA zPointHi,Y         \ Set A = z-coordinate for point Y EOR P
EOR P

BMI prun24             \ If A has a set bit 7, then the z-coordinate for point
\ Y has a different sign to the z-coordinate for point
\ 6, so jump to prun24 as the runway is both behind us
\ and in front of us

INY                    \ Increment Y to point to the next point in the dash
\ line

CPY #20                \ Loop back until we have worked our way through all the
BCC prun23             \ points that we just calculated

BCS prun28             \ If we get here then all the points have the same sign
\ from the subroutine (this BCS is effectively a JMP as
\ we just passed through the BCC above)

.prun24

\ If we get here, then point Y has a different sign in
\ its z-coordinate to point 6, so the runway is both
\ behind us and in front of us
\
\ We now want to find out which part is in front of us
\ and which is behind
\
\ We do this by working out which part of the dash line
\ is in front of us and which is behind, using the
\ following:
\
\      2    21   3
\       +-------+
\       |   :   |   <- Dashes end at point 19
\       |   :   |
\       |   :   |
\       |   :   |
\       |   :   |   <- Dashes start at point 6
\       +-------+
\      1    5    4
\
\ If the start of the dash line is behind us (i.e. the
\ point 6 end), then that means we need to clip points 1
\ and 4 as close as possible to the screen, while if the
\ end of the dash line is behind us (i.e. the point 19
\ end), then we need to clip points 2 and 3 as close as
\ possible to the screen

LDA P                  \ If point 6 has a positive z-coordinate, jump to prun25
BPL prun25

\ If we get here then point 6 has a negative
\ z-coordinate, so point Y must have a positive
\ z-coordinate, and the point before Y must have a
\ negative z-coordinate
\
\ In other words, the dashes start behind us, and pass
\ in front of us at point Y, which is in front of us, so
\ the point before Y is the last point behind us
\
\ To clip the runway, we therefore need to move points 1
\ and 4

DEY                    \ Decrement Y to point to the last point in the sequence
\ we added that has a negative z-coordinate

LDA #1                 \ Set Q so the second call to AddTempToPoint moves point
STA Q                  \ 1

LDX #4                 \ Set X so the first call to AddTempToPoint moves point
\ 4

\ effectively a JMP as X is never zero)

.prun25

\ If we get here then point 6 has a positive
\ z-coordinate, so point Y must have a negative
\ z-coordinate, and the point before Y must have a
\ positive z-coordinate
\
\ In other words, the dashes start in front of us, and
\ go behind us at point Y, which is the first point
\ behind us
\
\ To clip the runway, we therefore need to move points 2
\ and 3

LDA #2                 \ Set Q so the second call to AddTempToPoint moves point
STA Q                  \ 2

LDX #3                 \ Set X so the first call to AddTempToPoint moves point
\ 3

.prun26

\ By the time we get here, Y is the point with the
\ negative z-coordinate that's nearest to the screen
\ (i.e. nearest to a z-coordinate of 0)
\
\ We now work out the new corner coordinates for the
\ end of the runway that's behind us, by taking point Y
\ and:
\
\   * Adding (xTemp1 yTemp1 zTemp1) to point Y to get
\     one corner (i.e. corner 3 or 4)
\
\   * Subtracting (xTemp1 yTemp1 zTemp1) from point Y to
\     get the other corner (i.e. corner 1 or 2)
\

JSR AddTempToPoint     \ Add point Y to the (xTemp1 yTemp1 zTemp1) vector and
\ store the result in (xPoint, yPoint, zPoint) for
\ point X

\ We now negate the (xTemp1 yTemp1 zTemp1) vector so we
\ can do the subtraction

LDX #2                 \ Set a counter in X to work through the three axes of
\ the (xTemp1 yTemp1 zTemp1) vector (the comments below
\ cover the iteration for the x-axis)

.prun27

LDA #0                 \ Negate (xTemp1Hi xTemp1Lo), starting with the low
SEC                    \ bytes
SBC xTemp1Lo,X
STA xTemp1Lo,X

LDA #0                 \ And then the high bytes
SBC xTemp1Hi,X
STA xTemp1Hi,X

DEX                    \ Decrement the loop counter to move to the next axis

BPL prun27             \ Loop back until we have negated xTemp1, yTemp1 and
\ zTemp1

\ The xTemp1 yTemp1 zTemp1) vector is now negated, so we
\ we want

LDX Q                  \ Set X so the call to AddTempToPoint stores the result
\ in point Q

JSR AddTempToPoint     \ Add point Y to the (xTemp1 yTemp1 zTemp1) vector and
\ store the result in (xPoint, yPoint, zPoint) for
\ point Q

.prun28

RTS                    \ Return from the subroutine

Type: Subroutine
Category: 3D geometry
Summary: Set the status byte for multiple points to indicate that their
coordinates and visibility have been calculated
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* ProcessRunwayLine (Part 2 of 5) calls SetPointVisibility
* ProcessRunwayLine (Part 4 of 5) calls SetPointVisibility

Arguments:

X                    The ID of the point to update

.SetPointVisibility

LDA #%10000000         \ Set bit 7 of point X's status byte, to indicate that
ORA pointStatus,X      \ the point's coordinates and visibility have been
STA pointStatus,X      \ calculated

DEX                    \ Decrement X to point to the previous point

BNE SetPointVisibility \ Loop back until we have set the status byte for points
\ X down to 1, i.e. points 1 to X

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Drawing lines
Summary: Draw half of the horizon line
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* DrawCanopyView calls DrawHalfHorizon

The horizon line is line ID 0, which is the line from point 31 to point 30.
This line is only half the actual horizon, so this routine calculates the
other half of the horizon into point 30, and draws the line from point 30 to
point 32.

Point 30 is therefore the mid-point of the two-segment horizon line, which
goes point 31 to point 30 to point 32.

The calculation looks like this:

+  (x_32, y_32)
.´ |
.´   |  h
.´     |
(x_30, y_30) .´_______|
.´|    w
.´  |
.´    | h
.´      |
(x_31, y_31)   ´--------+
w

We already know the coordinates of points 30 and 31, and we want to calculate
point 32. It's easy to calculate w and h in the bottom triangle:

w = x_30 - x_31
h = y_30 - y_31

so to extend the line to point 32, we simply add w and h to the coordinates
for point 30, like this:

x_32 = x_30 + w
= x_30 + x_30 - x_31
= (x_30 * 2) - x_31

y_32 = y_30 + h
= y_30 + y_30 - y_31
= (y_30 * 2) - y_31

This routine draws the horizon from point 30 to point 32, while the other half
from point 31 to 30 is drawn along with all the other lines in DrawCanopyView.

.DrawHalfHorizon

LDX #30                \ Set X = 30, to use as the point ID for point 30, which
\ is the start of the horizon line

LDY #32                \ Set Y = 32, to use as the point ID for point 32

LDA xPointHi,X         \ Set (T A) = x_30
STA T
LDA xPointLo,X

ASL A                  \ Set (T A) = (T A) * 2
ROL T                  \           = x_30 * 2

SEC                    \ Set x_32 = (T A) - x_31
SBC xPointLo+31        \          = (x_30 * 2) - x_31
STA xPointLo,Y
LDA T
SBC xPointHi+31
STA xPointHi,Y

LDA yPointHi,X         \ Set (T A) = y_30
STA T
LDA yPointLo,X

ASL A                  \ Set (T A) = (T A) * 2
ROL T                  \           = y_30 * 2

SEC                    \ Set y_32 = (T A) - y_31
SBC yPointLo+31        \          = (y_30 * 2) - y_31
STA yPointLo,Y
LDA T
SBC yPointHi+31
STA yPointHi,Y

\ So now we have:
\
\   x_32 = (x_30 * 2) - x_31
\   y_32 = (y_30 * 2) - y_31
\
\ which is what we want

STX L                  \ Set L to point 30, so we draw the line from this start
\ point

STY M                  \ Set L to point 32, so we draw the line to this end
\ point

JSR DrawClippedHorizon \ Draw the line from point 30 to 32, which is the first
\ half of the horizon line

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Flight model
Summary: Fill up the fuel tank by 1/65th of a full tank every four
iterations of the main loop
Deep dive: Scheduling tasks in the main loop
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MainLoop (Part 9 of 15) calls FillUpFuelTank

.FillUpFuelTank

LDA mainLoopCounter    \ If the mainLoopCounter is a multiple of 4, jump to
AND #3                 \ fuel1 to add some fuel to the tank (so we do this
BEQ fuel1              \ every four iterations of the main loop)

RTS                    \ Return from the subroutine

.fuel1

TAX                    \ We got here because A = 0, so this sets X = 0

LDA fuelLevel          \ If fuelLevel >= 65, then the tank is already full, so
CMP #65                \ jump to fuel2 to skip filling it up any more
BCS fuel2

INC fuelLevel          \ fuelLevel < 65, so increment the fuel level by 1, to
\ fill up the fuel tank by 1/65th of a full tank

JMP DrawFuelPixel      \ Draw an extra pixel at the top of the fuel level, so
\ the fuel gauge goes up by one pixel, returning from
\ the subroutine using a tail call

.fuel2

\ If we get here then the fuel tank is full

STX landingStatus      \ Set landingStatus = 0 to disable all the landing tasks
\ in the main loop, including filling up with fuel

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Dashboard
Summary: Update the fuel gauge every 16 iterations of the main loop
Deep dive: Scheduling tasks in the main loop
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MainLoop (Part 11 of 15) calls UpdateFuelGauge
* ResetVariables calls UpdateFuelGauge

.UpdateFuelGauge

LDA mainLoopCounter    \ If the mainLoopCounter is a multiple of 16, jump to
AND #15                \ upfu1 to update the fuel gauge
BEQ upfu1

RTS                    \ Return from the subroutine

.upfu1

LDX #128               \ Set X = 128, so we erase a pixel from the top of the
\ fuel gauge in DrawFuelPixel below, if there is one

LDA fuelLevel          \ Set A = fuelLevel

\ Fall through into DrawFuelPixel to erase a pixel from
\ the fuel gauge at the top of the gauge if there is
\ one, which will set the amount shown on the fuel gauge
\ to fuelLevel

Type: Subroutine
Category: Dashboard
Summary: Draw or erase a pixel on the fuel gauge on the dashboard
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* FillUpFuelTank calls DrawFuelPixel

Arguments:

A                    The fuel gauge pixel to draw or erase (0 to 65)

X                    Drawing mode:

* Bit 7 clear = draw (using OR logic)

* Bit 7 set = erase (using EOR logic)

.DrawFuelPixel

STX N                  \ Store the drawing mode in N

CLC                    \ Set J = A + 184
STA J                  \ so the line's start y-coordinate is between:
\
\   * 184, or -72, for A = 0  (empty tank)
\   * 249, or  -7, for A = 65 (full tank)
\
\ As y-coordinates that we send to DrawVectorLine are
\ relative to the top of the dashboard, this means we
\ draw a pixel on the vertical line from 72 pixels below
\ the top of the dashboard (i.e. the bottom of the fuel
\ gauge at screen y-coordinate 231), up to 7 pixels
\ below the top of the dashboard (i.e. the top of the
\ fuel gauge at screen y-coordinate 166)

LDA #2                 \ Set I = 2, the x-coordinate of the fuel gauge line
STA I

LDA #1                 \ Set T = 1, so line is 1 pixel wide
STA T

STA U                  \ Set U = 1, so the line is 1 pixel high

LDA #0                 \ Set V = 0 so the line is drawn in a positive direction
STA V                  \ for both axes

JSR DrawVectorLine     \ Draw/erase a pixel at (2, A + 184)

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Sound
Summary: Adjust the volume when the volume keys are pressed
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MainLoop (Part 9 of 15) calls ProcessVolumeKeys

.ProcessVolumeKeys

LDX #&DB               \ Scan the keyboard to see if "7" is being pressed
JSR ScanKeyboard

LDX #&EA               \ Scan the keyboard to see if "8" is being pressed
JSR ScanKeyboard

BNE volk4              \ If "8" is not being pressed, jump to volk4 to return
\ from the subroutine

LDA #255               \ "8" is being pressed, which is the increase volume
BNE volk2              \ key, so set A = 255 = -1 and jump to volk2

.volk1

LDA #1                 \ If we get here then "7" is being pressed, which is the
\ decrease volume key, so set A = 1

.volk2

\ By this point, A contains 1 if we want to decrease the
\ volume, or -1 if we want to increase it, which we can
\ now add to the SOUND command's amplitude parameter to
\ adjust the volume, as -15 is the loudest volume and 0
\ is the quietest

CLC                    \ Add A to byte #3 of sound #1 (low byte of amplitude)

BMI volk3              \ If the result is negative, then jump to volk3 to
\ update the volume

BNE volk4              \ If the result is non-zero, then we have just reduced
\ the volume beyond the quietest setting of 0, so jump
\ to volk4 to return from the subroutine without
\ changing the volume, as it is already at the quietest
\ setting

.volk3

CMP #241               \ If A < 241, i.e. A < -15, then we have just increased
BCC volk4              \ the volume past the loudest setting of -15, so jump
\ to volk4 to return from the subroutine without
\ changing the volume, as it is already at the loudest
\ setting

STA soundData+10       \ The new volume is valid, so update byte #3 of sound #1
\ (low byte of amplitude) with the new volume

INC soundData+60       \ Increment byte #5 of sound #7 (low byte of engine
\ pitch) to make the engine pitch jump up a bit, so we
\ can hear the engine noise changing while adjusting the
\ volume (the MakeEngineSound routine will bring it back
\ down to the correct pitch)

.volk4

RTS                    \ Return from the subroutine

Type: Subroutine
Category: Flight model
Summary: Retract the flaps if we are going faster than 150 mph
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* ApplyTurnAndThrust (Part 2 of 2) calls RetractFlapsIfFast

Arguments:

A                    The high byte of the current airspeed

.RetractFlapsIfFast

CMP #14                \ First we check the high byte of the current airspeed
BCC flap1              \ in A to see if it is less than 14, at which point the
\ airspeed is:
\
\   (14 0) * 100 / 2368 = 3584 * 100 / 2368 = 151
\
\ So if the airspeed is less than 151mph, we jump to
\ flap1 to return from the subroutine without changing
\ the flaps

BEQ flap1              \ return from the subroutine without changing anything

LDA #0                 \ The speed is at least 151 mph and the flaps are on,
STA flapsStatus        \ so we retract them by setting flapsStatus to 0

JSR IndicatorF         \ Update the flaps indicator

.flap1

RTS                    \ Return from the subroutine

Type: Variable
Category: 3D geometry
Summary: Scaled x-coordinates of the points that make up objects, relative
to the object's anchor point
Deep dive: 3D objects
Rotating and translating points in 3D space
Context: See this variable on its own page
References: This variable is used as follows:
* SetObjPointCoords (Part 1 of 2) uses xObjectPoint

For a point within an object, (xObjectPoint, yObjectPoint, zObjectPoint) are
the coordinates of this point relative to the object's anchor.

This is the same as saying (xObjectPoint, yObjectPoint, zObjectPoint) is the
vector from the object's anchor to the point.

This table effectively defines the shape of each object.

Each vector is stored as three coordinates, with each coordinate being in the
range 0 to 15, plus a scale factor, which is stored in bits 4 to 7 of the
z-coordinate in zObjectPoint. The scale is given as a power of 2, so a scale
factor of n means we scale the coordinates by 2^n (where n = 0 to 9).

All vectors are positive in all three axes, so the anchor point for an object
is therefore the closest point to the origin.

.xObjectPoint

EQUB 13                \ Point ID 0   is (13, 61, 13) with scale factor 2^0
EQUB 0                 \ Point ID 1   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 2   is ( 0,  0, 12) with scale factor 2^9
EQUB 0                 \ Point ID 3   is ( 0,  0,  0) with scale factor 2^0
EQUB 8                 \ Point ID 4   is ( 8,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 5   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 6   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 7   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 8   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 9   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 10  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 11  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 12  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 13  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 14  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 15  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 16  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 17  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 18  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 19  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 20  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 21  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 22  is ( 0,  0,  8) with scale factor 2^4
EQUB 0                 \ Point ID 23  is ( 0,  0,  8) with scale factor 2^4
EQUB 10                \ Point ID 24  is (10,  0,  0) with scale factor 2^6
EQUB 0                 \ Point ID 25  is ( 0,  1,  0) with scale factor 2^8
EQUB 0                 \ Point ID 26  is ( 0,  1,  0) with scale factor 2^8
EQUB 0                 \ Point ID 27  is ( 0,  1,  0) with scale factor 2^8
EQUB 0                 \ Point ID 28  is ( 0,  1,  0) with scale factor 2^8
EQUB 4                 \ Point ID 29  is ( 4,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 30  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 31  is ( 0,  0,  0) with scale factor 2^0
EQUB 4                 \ Point ID 32  is ( 4,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 33  is ( 0,  0, 10) with scale factor 2^5
EQUB 0                 \ Point ID 34  is ( 0,  0, 12) with scale factor 2^4
EQUB 0                 \ Point ID 35  is ( 0,  0,  0) with scale factor 2^0
EQUB 4                 \ Point ID 36  is ( 4,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 37  is ( 0,  0,  2) with scale factor 2^8
EQUB 12                \ Point ID 38  is (12,  0,  0) with scale factor 2^4
EQUB 5                 \ Point ID 39  is ( 5,  0, 10) with scale factor 2^5
EQUB 8                 \ Point ID 40  is ( 8,  0,  0) with scale factor 2^4
EQUB 0                 \ Point ID 41  is ( 0,  0,  8) with scale factor 2^3
EQUB 0                 \ Point ID 42  is ( 0, 10,  0) with scale factor 2^3
EQUB 0                 \ Point ID 43  is ( 0, 10,  0) with scale factor 2^3
EQUB 0                 \ Point ID 44  is ( 0,  0,  8) with scale factor 2^3
EQUB 0                 \ Point ID 45  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 46  is ( 0, 10,  0) with scale factor 2^3
EQUB 0                 \ Point ID 47  is ( 0, 10,  0) with scale factor 2^3
EQUB 12                \ Point ID 48  is (12,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 49  is ( 0,  0,  8) with scale factor 2^3
EQUB 0                 \ Point ID 50  is ( 0,  0,  8) with scale factor 2^3
EQUB 12                \ Point ID 51  is (12,  0,  0) with scale factor 2^5
EQUB 11                \ Point ID 52  is (11,  0,  0) with scale factor 2^6
EQUB 0                 \ Point ID 53  is ( 0, 10,  0) with scale factor 2^4
EQUB 0                 \ Point ID 54  is ( 0, 10,  0) with scale factor 2^4
EQUB 0                 \ Point ID 55  is ( 0, 10,  0) with scale factor 2^4
EQUB 0                 \ Point ID 56  is ( 0, 10,  0) with scale factor 2^4
EQUB 2                 \ Point ID 57  is ( 2,  0, 14) with scale factor 2^8
EQUB 1                 \ Point ID 58  is ( 1,  0, 11) with scale factor 2^8
EQUB 3                 \ Point ID 59  is ( 3,  0,  9) with scale factor 2^9
EQUB 6                 \ Point ID 60  is ( 6,  0, 12) with scale factor 2^8
EQUB 10                \ Point ID 61  is (10,  0,  1) with scale factor 2^8
EQUB 3                 \ Point ID 62  is ( 3,  0,  9) with scale factor 2^7
EQUB 9                 \ Point ID 63  is ( 9,  0, 15) with scale factor 2^6
EQUB 6                 \ Point ID 64  is ( 6,  0, 13) with scale factor 2^8
EQUB 13                \ Point ID 65  is (13,  0,  3) with scale factor 2^4
EQUB 0                 \ Point ID 66  is ( 0,  0, 14) with scale factor 2^9
EQUB 1                 \ Point ID 67  is ( 1,  0,  0) with scale factor 2^8
EQUB 5                 \ Point ID 68  is ( 5,  0, 12) with scale factor 2^9
EQUB 1                 \ Point ID 69  is ( 1,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 70  is ( 0,  0,  0) with scale factor 2^0
EQUB 9                 \ Point ID 71  is ( 9,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 72  is ( 0,  0,  9) with scale factor 2^5
EQUB 8                 \ Point ID 73  is ( 8,  0,  6) with scale factor 2^9
EQUB 0                 \ Point ID 74  is ( 0,  0,  1) with scale factor 2^8
EQUB 14                \ Point ID 75  is (14,  0,  7) with scale factor 2^9
EQUB 0                 \ Point ID 76  is ( 0,  0,  1) with scale factor 2^8
EQUB 13                \ Point ID 77  is (13,  0,  2) with scale factor 2^9
EQUB 5                 \ Point ID 78  is ( 5,  0, 13) with scale factor 2^4
EQUB 12                \ Point ID 79  is (12,  0,  0) with scale factor 2^8
EQUB 15                \ Point ID 80  is (15,  0, 15) with scale factor 2^1
EQUB 0                 \ Point ID 81  is ( 0, 12,  0) with scale factor 2^2
EQUB 7                 \ Point ID 82  is ( 7, 12,  7) with scale factor 2^1
EQUB 6                 \ Point ID 83  is ( 6,  7, 11) with scale factor 2^2
EQUB 12                \ Point ID 84  is (12,  8,  5) with scale factor 2^2
EQUB 0                 \ Point ID 85  is ( 0, 10,  0) with scale factor 2^0
EQUB 0                 \ Point ID 86  is ( 0,  0,  1) with scale factor 2^8
EQUB 8                 \ Point ID 87  is ( 8,  0,  0) with scale factor 2^4
EQUB 0                 \ Point ID 88  is ( 0,  2,  0) with scale factor 2^8
EQUB 15                \ Point ID 89  is (15,  0, 15) with scale factor 2^1
EQUB 0                 \ Point ID 90  is ( 0, 10,  0) with scale factor 2^2
EQUB 4                 \ Point ID 91  is ( 4, 12,  4) with scale factor 2^1
EQUB 3                 \ Point ID 92  is ( 3,  5, 12) with scale factor 2^2
EQUB 10                \ Point ID 93  is (10,  7,  8) with scale factor 2^2
EQUB 0                 \ Point ID 94  is ( 0, 10,  0) with scale factor 2^0
EQUB 0                 \ Point ID 95  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 96  is ( 0,  0,  1) with scale factor 2^8
EQUB 10                \ Point ID 97  is (10,  0,  0) with scale factor 2^1
EQUB 0                 \ Point ID 98  is ( 0,  0,  1) with scale factor 2^8
EQUB 0                 \ Point ID 99  is ( 0,  2,  0) with scale factor 2^8
EQUB 0                 \ Point ID 100 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 101 is ( 0,  0, 11) with scale factor 2^4
EQUB 0                 \ Point ID 102 is ( 0,  0, 10) with scale factor 2^4
EQUB 11                \ Point ID 103 is (11,  0,  7) with scale factor 2^8
EQUB 11                \ Point ID 104 is (11,  0,  4) with scale factor 2^9
EQUB 13                \ Point ID 105 is (13,  0, 13) with scale factor 2^3
EQUB 14                \ Point ID 106 is (14,  0,  0) with scale factor 2^9
EQUB 4                 \ Point ID 107 is ( 4,  0, 10) with scale factor 2^3
EQUB 4                 \ Point ID 108 is ( 4,  0,  0) with scale factor 2^8
EQUB 13                \ Point ID 109 is (13,  0,  3) with scale factor 2^8
EQUB 12                \ Point ID 110 is (12,  0,  0) with scale factor 2^8
EQUB 13                \ Point ID 111 is (13,  0, 10) with scale factor 2^9
EQUB 4                 \ Point ID 112 is ( 4,  0, 12) with scale factor 2^8
EQUB 14                \ Point ID 113 is (14,  0,  1) with scale factor 2^9
EQUB 0                 \ Point ID 114 is ( 0,  0, 12) with scale factor 2^8
EQUB 3                 \ Point ID 115 is ( 3,  0,  5) with scale factor 2^8
EQUB 15                \ Point ID 116 is (15,  0,  0) with scale factor 2^8
EQUB 10                \ Point ID 117 is (10,  0,  5) with scale factor 2^8
EQUB 11                \ Point ID 118 is (11,  0,  4) with scale factor 2^8
EQUB 2                 \ Point ID 119 is ( 2,  0, 14) with scale factor 2^8
EQUB 14                \ Point ID 120 is (14,  0,  0) with scale factor 2^4
EQUB 0                 \ Point ID 121 is ( 0,  0,  9) with scale factor 2^8
EQUB 11                \ Point ID 122 is (11,  0,  7) with scale factor 2^9
EQUB 10                \ Point ID 123 is (10,  0,  3) with scale factor 2^9
EQUB 10                \ Point ID 124 is (10,  0,  3) with scale factor 2^9
EQUB 5                 \ Point ID 125 is ( 5,  0,  9) with scale factor 2^9
EQUB 14                \ Point ID 126 is (14,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 127 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 128 is ( 0,  0,  7) with scale factor 2^8
EQUB 11                \ Point ID 129 is (11,  0, 14) with scale factor 2^8
EQUB 14                \ Point ID 130 is (14,  0, 10) with scale factor 2^8
EQUB 5                 \ Point ID 131 is ( 5,  0,  0) with scale factor 2^8
EQUB 4                 \ Point ID 132 is ( 4,  0, 14) with scale factor 2^8
EQUB 9                 \ Point ID 133 is ( 9,  0,  4) with scale factor 2^9
EQUB 10                \ Point ID 134 is (10,  0,  2) with scale factor 2^9
EQUB 0                 \ Point ID 135 is ( 0,  0,  0) with scale factor 2^0
EQUB 1                 \ Point ID 136 is ( 1,  0, 15) with scale factor 2^8
EQUB 5                 \ Point ID 137 is ( 5,  0, 10) with scale factor 2^9
EQUB 13                \ Point ID 138 is (13,  0,  4) with scale factor 2^8
EQUB 0                 \ Point ID 139 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 140 is ( 0,  0, 11) with scale factor 2^8
EQUB 13                \ Point ID 141 is (13,  0,  9) with scale factor 2^8
EQUB 15                \ Point ID 142 is (15,  0,  0) with scale factor 2^7
EQUB 2                 \ Point ID 143 is ( 2,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 144 is ( 0,  0, 13) with scale factor 2^8
EQUB 9                 \ Point ID 145 is ( 9,  0,  9) with scale factor 2^9
EQUB 13                \ Point ID 146 is (13,  0, 11) with scale factor 2^8
EQUB 15                \ Point ID 147 is (15,  0,  5) with scale factor 2^8
EQUB 11                \ Point ID 148 is (11,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 149 is ( 0,  0, 11) with scale factor 2^8
EQUB 11                \ Point ID 150 is (11,  0, 13) with scale factor 2^8
EQUB 13                \ Point ID 151 is (13,  0,  2) with scale factor 2^8
EQUB 2                 \ Point ID 152 is ( 2,  0,  0) with scale factor 2^8
EQUB 3                 \ Point ID 153 is ( 3,  0,  8) with scale factor 2^8
EQUB 10                \ Point ID 154 is (10,  0,  7) with scale factor 2^8
EQUB 8                 \ Point ID 155 is ( 8,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 156 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 157 is ( 0,  0,  6) with scale factor 2^8
EQUB 4                 \ Point ID 158 is ( 4,  0,  8) with scale factor 2^8
EQUB 12                \ Point ID 159 is (12,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 160 is ( 0,  0,  6) with scale factor 2^8
EQUB 6                 \ Point ID 161 is ( 6,  0,  9) with scale factor 2^9
EQUB 14                \ Point ID 162 is (14,  0, 12) with scale factor 2^8
EQUB 11                \ Point ID 163 is (11,  0,  0) with scale factor 2^7
EQUB 0                 \ Point ID 164 is ( 0,  0,  3) with scale factor 2^8
EQUB 5                 \ Point ID 165 is ( 5,  0, 12) with scale factor 2^9
EQUB 10                \ Point ID 166 is (10,  0,  9) with scale factor 2^9
EQUB 14                \ Point ID 167 is (14,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 168 is ( 0,  0, 12) with scale factor 2^8
EQUB 5                 \ Point ID 169 is ( 5,  0, 11) with scale factor 2^9
EQUB 11                \ Point ID 170 is (11,  0,  7) with scale factor 2^8
EQUB 5                 \ Point ID 171 is ( 5,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 172 is ( 0,  0,  9) with scale factor 2^8
EQUB 5                 \ Point ID 173 is ( 5,  0,  8) with scale factor 2^9
EQUB 13                \ Point ID 174 is (13,  0, 13) with scale factor 2^8
EQUB 2                 \ Point ID 175 is ( 2,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 176 is ( 0,  0,  8) with scale factor 2^8
EQUB 2                 \ Point ID 177 is ( 2,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 178 is ( 0,  0, 12) with scale factor 2^0
EQUB 12                \ Point ID 179 is (12,  0,  0) with scale factor 2^0
EQUB 14                \ Point ID 180 is (14,  0, 14) with scale factor 2^2
EQUB 5                 \ Point ID 181 is ( 5,  0,  5) with scale factor 2^8
EQUB 5                 \ Point ID 182 is ( 5,  0,  5) with scale factor 2^8
EQUB 0                 \ Point ID 183 is ( 0,  0,  3) with scale factor 2^2
EQUB 3                 \ Point ID 184 is ( 3,  0,  0) with scale factor 2^2
EQUB 14                \ Point ID 185 is (14,  0, 14) with scale factor 2^2
EQUB 3                 \ Point ID 186 is ( 3,  4,  3) with scale factor 2^2
EQUB 5                 \ Point ID 187 is ( 5,  0,  5) with scale factor 2^8
EQUB 0                 \ Point ID 188 is ( 0,  0,  3) with scale factor 2^2
EQUB 3                 \ Point ID 189 is ( 3,  0,  0) with scale factor 2^2
EQUB 14                \ Point ID 190 is (14,  0, 14) with scale factor 2^2
EQUB 3                 \ Point ID 191 is ( 3,  4,  3) with scale factor 2^2
EQUB 9                 \ Point ID 192 is ( 9,  0,  9) with scale factor 2^7
EQUB 4                 \ Point ID 193 is ( 4,  0,  5) with scale factor 2^5
EQUB 5                 \ Point ID 194 is ( 5,  0,  4) with scale factor 2^5
EQUB 9                 \ Point ID 195 is ( 9,  0,  8) with scale factor 2^6
EQUB 7                 \ Point ID 196 is ( 7,  4,  5) with scale factor 2^5
EQUB 4                 \ Point ID 197 is ( 4,  0,  0) with scale factor 2^4
EQUB 4                 \ Point ID 198 is ( 4,  3,  2) with scale factor 2^5
EQUB 0                 \ Point ID 199 is ( 0,  0,  4) with scale factor 2^4
EQUB 2                 \ Point ID 200 is ( 2,  3,  4) with scale factor 2^5
EQUB 0                 \ Point ID 201 is ( 0,  2,  0) with scale factor 2^8
EQUB 0                 \ Point ID 202 is ( 0,  2,  0) with scale factor 2^8
EQUB 0                 \ Point ID 203 is ( 0,  0, 12) with scale factor 2^4
EQUB 11                \ Point ID 204 is (11,  0,  0) with scale factor 2^5
EQUB 12                \ Point ID 205 is (12,  0,  0) with scale factor 2^4
EQUB 11                \ Point ID 206 is (11,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 207 is ( 0,  8,  0) with scale factor 2^4
EQUB 0                 \ Point ID 208 is ( 0,  8,  0) with scale factor 2^4
EQUB 0                 \ Point ID 209 is ( 0,  8,  0) with scale factor 2^4
EQUB 0                 \ Point ID 210 is ( 0,  8,  0) with scale factor 2^4
EQUB 4                 \ Point ID 211 is ( 4,  1,  4) with scale factor 2^7
EQUB 1                 \ Point ID 212 is ( 1,  0,  4) with scale factor 2^8
EQUB 0                 \ Point ID 213 is ( 0,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 214 is ( 0,  0,  5) with scale factor 2^8
EQUB 4                 \ Point ID 215 is ( 4,  2,  5) with scale factor 2^7

Type: Variable
Category: 3D geometry
Summary: Scaled y-coordinates of the points that make up objects, relative
to the object's anchor point
Deep dive: 3D objects
Rotating and translating points in 3D space
Context: See this variable on its own page
References: This variable is used as follows:
* SetObjPointCoords (Part 1 of 2) uses yObjectPoint

See xObjectPoint for an explanation of object points.

.yObjectPoint

EQUB 61                \ Point ID 0   is (13, 61, 13) with scale factor 2^0
EQUB 0                 \ Point ID 1   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 2   is ( 0,  0, 12) with scale factor 2^9
EQUB 0                 \ Point ID 3   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 4   is ( 8,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 5   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 6   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 7   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 8   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 9   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 10  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 11  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 12  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 13  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 14  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 15  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 16  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 17  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 18  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 19  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 20  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 21  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 22  is ( 0,  0,  8) with scale factor 2^4
EQUB 0                 \ Point ID 23  is ( 0,  0,  8) with scale factor 2^4
EQUB 0                 \ Point ID 24  is (10,  0,  0) with scale factor 2^6
EQUB 1                 \ Point ID 25  is ( 0,  1,  0) with scale factor 2^8
EQUB 1                 \ Point ID 26  is ( 0,  1,  0) with scale factor 2^8
EQUB 1                 \ Point ID 27  is ( 0,  1,  0) with scale factor 2^8
EQUB 1                 \ Point ID 28  is ( 0,  1,  0) with scale factor 2^8
EQUB 0                 \ Point ID 29  is ( 4,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 30  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 31  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 32  is ( 4,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 33  is ( 0,  0, 10) with scale factor 2^5
EQUB 0                 \ Point ID 34  is ( 0,  0, 12) with scale factor 2^4
EQUB 0                 \ Point ID 35  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 36  is ( 4,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 37  is ( 0,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 38  is (12,  0,  0) with scale factor 2^4
EQUB 0                 \ Point ID 39  is ( 5,  0, 10) with scale factor 2^5
EQUB 0                 \ Point ID 40  is ( 8,  0,  0) with scale factor 2^4
EQUB 0                 \ Point ID 41  is ( 0,  0,  8) with scale factor 2^3
EQUB 10                \ Point ID 42  is ( 0, 10,  0) with scale factor 2^3
EQUB 10                \ Point ID 43  is ( 0, 10,  0) with scale factor 2^3
EQUB 0                 \ Point ID 44  is ( 0,  0,  8) with scale factor 2^3
EQUB 0                 \ Point ID 45  is ( 0,  0,  0) with scale factor 2^0
EQUB 10                \ Point ID 46  is ( 0, 10,  0) with scale factor 2^3
EQUB 10                \ Point ID 47  is ( 0, 10,  0) with scale factor 2^3
EQUB 0                 \ Point ID 48  is (12,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 49  is ( 0,  0,  8) with scale factor 2^3
EQUB 0                 \ Point ID 50  is ( 0,  0,  8) with scale factor 2^3
EQUB 0                 \ Point ID 51  is (12,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 52  is (11,  0,  0) with scale factor 2^6
EQUB 10                \ Point ID 53  is ( 0, 10,  0) with scale factor 2^4
EQUB 10                \ Point ID 54  is ( 0, 10,  0) with scale factor 2^4
EQUB 10                \ Point ID 55  is ( 0, 10,  0) with scale factor 2^4
EQUB 10                \ Point ID 56  is ( 0, 10,  0) with scale factor 2^4
EQUB 0                 \ Point ID 57  is ( 2,  0, 14) with scale factor 2^8
EQUB 0                 \ Point ID 58  is ( 1,  0, 11) with scale factor 2^8
EQUB 0                 \ Point ID 59  is ( 3,  0,  9) with scale factor 2^9
EQUB 0                 \ Point ID 60  is ( 6,  0, 12) with scale factor 2^8
EQUB 0                 \ Point ID 61  is (10,  0,  1) with scale factor 2^8
EQUB 0                 \ Point ID 62  is ( 3,  0,  9) with scale factor 2^7
EQUB 0                 \ Point ID 63  is ( 9,  0, 15) with scale factor 2^6
EQUB 0                 \ Point ID 64  is ( 6,  0, 13) with scale factor 2^8
EQUB 0                 \ Point ID 65  is (13,  0,  3) with scale factor 2^4
EQUB 0                 \ Point ID 66  is ( 0,  0, 14) with scale factor 2^9
EQUB 0                 \ Point ID 67  is ( 1,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 68  is ( 5,  0, 12) with scale factor 2^9
EQUB 0                 \ Point ID 69  is ( 1,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 70  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 71  is ( 9,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 72  is ( 0,  0,  9) with scale factor 2^5
EQUB 0                 \ Point ID 73  is ( 8,  0,  6) with scale factor 2^9
EQUB 0                 \ Point ID 74  is ( 0,  0,  1) with scale factor 2^8
EQUB 0                 \ Point ID 75  is (14,  0,  7) with scale factor 2^9
EQUB 0                 \ Point ID 76  is ( 0,  0,  1) with scale factor 2^8
EQUB 0                 \ Point ID 77  is (13,  0,  2) with scale factor 2^9
EQUB 0                 \ Point ID 78  is ( 5,  0, 13) with scale factor 2^4
EQUB 0                 \ Point ID 79  is (12,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 80  is (15,  0, 15) with scale factor 2^1
EQUB 12                \ Point ID 81  is ( 0, 12,  0) with scale factor 2^2
EQUB 12                \ Point ID 82  is ( 7, 12,  7) with scale factor 2^1
EQUB 7                 \ Point ID 83  is ( 6,  7, 11) with scale factor 2^2
EQUB 8                 \ Point ID 84  is (12,  8,  5) with scale factor 2^2
EQUB 10                \ Point ID 85  is ( 0, 10,  0) with scale factor 2^0
EQUB 0                 \ Point ID 86  is ( 0,  0,  1) with scale factor 2^8
EQUB 0                 \ Point ID 87  is ( 8,  0,  0) with scale factor 2^4
EQUB 2                 \ Point ID 88  is ( 0,  2,  0) with scale factor 2^8
EQUB 0                 \ Point ID 89  is (15,  0, 15) with scale factor 2^1
EQUB 10                \ Point ID 90  is ( 0, 10,  0) with scale factor 2^2
EQUB 12                \ Point ID 91  is ( 4, 12,  4) with scale factor 2^1
EQUB 5                 \ Point ID 92  is ( 3,  5, 12) with scale factor 2^2
EQUB 7                 \ Point ID 93  is (10,  7,  8) with scale factor 2^2
EQUB 10                \ Point ID 94  is ( 0, 10,  0) with scale factor 2^0
EQUB 0                 \ Point ID 95  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 96  is ( 0,  0,  1) with scale factor 2^8
EQUB 0                 \ Point ID 97  is (10,  0,  0) with scale factor 2^1
EQUB 0                 \ Point ID 98  is ( 0,  0,  1) with scale factor 2^8
EQUB 2                 \ Point ID 99  is ( 0,  2,  0) with scale factor 2^8
EQUB 0                 \ Point ID 100 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 101 is ( 0,  0, 11) with scale factor 2^4
EQUB 0                 \ Point ID 102 is ( 0,  0, 10) with scale factor 2^4
EQUB 0                 \ Point ID 103 is (11,  0,  7) with scale factor 2^8
EQUB 0                 \ Point ID 104 is (11,  0,  4) with scale factor 2^9
EQUB 0                 \ Point ID 105 is (13,  0, 13) with scale factor 2^3
EQUB 0                 \ Point ID 106 is (14,  0,  0) with scale factor 2^9
EQUB 0                 \ Point ID 107 is ( 4,  0, 10) with scale factor 2^3
EQUB 0                 \ Point ID 108 is ( 4,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 109 is (13,  0,  3) with scale factor 2^8
EQUB 0                 \ Point ID 110 is (12,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 111 is (13,  0, 10) with scale factor 2^9
EQUB 0                 \ Point ID 112 is ( 4,  0, 12) with scale factor 2^8
EQUB 0                 \ Point ID 113 is (14,  0,  1) with scale factor 2^9
EQUB 0                 \ Point ID 114 is ( 0,  0, 12) with scale factor 2^8
EQUB 0                 \ Point ID 115 is ( 3,  0,  5) with scale factor 2^8
EQUB 0                 \ Point ID 116 is (15,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 117 is (10,  0,  5) with scale factor 2^8
EQUB 0                 \ Point ID 118 is (11,  0,  4) with scale factor 2^8
EQUB 0                 \ Point ID 119 is ( 2,  0, 14) with scale factor 2^8
EQUB 0                 \ Point ID 120 is (14,  0,  0) with scale factor 2^4
EQUB 0                 \ Point ID 121 is ( 0,  0,  9) with scale factor 2^8
EQUB 0                 \ Point ID 122 is (11,  0,  7) with scale factor 2^9
EQUB 0                 \ Point ID 123 is (10,  0,  3) with scale factor 2^9
EQUB 0                 \ Point ID 124 is (10,  0,  3) with scale factor 2^9
EQUB 0                 \ Point ID 125 is ( 5,  0,  9) with scale factor 2^9
EQUB 0                 \ Point ID 126 is (14,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 127 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 128 is ( 0,  0,  7) with scale factor 2^8
EQUB 0                 \ Point ID 129 is (11,  0, 14) with scale factor 2^8
EQUB 0                 \ Point ID 130 is (14,  0, 10) with scale factor 2^8
EQUB 0                 \ Point ID 131 is ( 5,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 132 is ( 4,  0, 14) with scale factor 2^8
EQUB 0                 \ Point ID 133 is ( 9,  0,  4) with scale factor 2^9
EQUB 0                 \ Point ID 134 is (10,  0,  2) with scale factor 2^9
EQUB 0                 \ Point ID 135 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 136 is ( 1,  0, 15) with scale factor 2^8
EQUB 0                 \ Point ID 137 is ( 5,  0, 10) with scale factor 2^9
EQUB 0                 \ Point ID 138 is (13,  0,  4) with scale factor 2^8
EQUB 0                 \ Point ID 139 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 140 is ( 0,  0, 11) with scale factor 2^8
EQUB 0                 \ Point ID 141 is (13,  0,  9) with scale factor 2^8
EQUB 0                 \ Point ID 142 is (15,  0,  0) with scale factor 2^7
EQUB 0                 \ Point ID 143 is ( 2,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 144 is ( 0,  0, 13) with scale factor 2^8
EQUB 0                 \ Point ID 145 is ( 9,  0,  9) with scale factor 2^9
EQUB 0                 \ Point ID 146 is (13,  0, 11) with scale factor 2^8
EQUB 0                 \ Point ID 147 is (15,  0,  5) with scale factor 2^8
EQUB 0                 \ Point ID 148 is (11,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 149 is ( 0,  0, 11) with scale factor 2^8
EQUB 0                 \ Point ID 150 is (11,  0, 13) with scale factor 2^8
EQUB 0                 \ Point ID 151 is (13,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 152 is ( 2,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 153 is ( 3,  0,  8) with scale factor 2^8
EQUB 0                 \ Point ID 154 is (10,  0,  7) with scale factor 2^8
EQUB 0                 \ Point ID 155 is ( 8,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 156 is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 157 is ( 0,  0,  6) with scale factor 2^8
EQUB 0                 \ Point ID 158 is ( 4,  0,  8) with scale factor 2^8
EQUB 0                 \ Point ID 159 is (12,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 160 is ( 0,  0,  6) with scale factor 2^8
EQUB 0                 \ Point ID 161 is ( 6,  0,  9) with scale factor 2^9
EQUB 0                 \ Point ID 162 is (14,  0, 12) with scale factor 2^8
EQUB 0                 \ Point ID 163 is (11,  0,  0) with scale factor 2^7
EQUB 0                 \ Point ID 164 is ( 0,  0,  3) with scale factor 2^8
EQUB 0                 \ Point ID 165 is ( 5,  0, 12) with scale factor 2^9
EQUB 0                 \ Point ID 166 is (10,  0,  9) with scale factor 2^9
EQUB 0                 \ Point ID 167 is (14,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 168 is ( 0,  0, 12) with scale factor 2^8
EQUB 0                 \ Point ID 169 is ( 5,  0, 11) with scale factor 2^9
EQUB 0                 \ Point ID 170 is (11,  0,  7) with scale factor 2^8
EQUB 0                 \ Point ID 171 is ( 5,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 172 is ( 0,  0,  9) with scale factor 2^8
EQUB 0                 \ Point ID 173 is ( 5,  0,  8) with scale factor 2^9
EQUB 0                 \ Point ID 174 is (13,  0, 13) with scale factor 2^8
EQUB 0                 \ Point ID 175 is ( 2,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 176 is ( 0,  0,  8) with scale factor 2^8
EQUB 0                 \ Point ID 177 is ( 2,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 178 is ( 0,  0, 12) with scale factor 2^0
EQUB 0                 \ Point ID 179 is (12,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 180 is (14,  0, 14) with scale factor 2^2
EQUB 0                 \ Point ID 181 is ( 5,  0,  5) with scale factor 2^8
EQUB 0                 \ Point ID 182 is ( 5,  0,  5) with scale factor 2^8
EQUB 0                 \ Point ID 183 is ( 0,  0,  3) with scale factor 2^2
EQUB 0                 \ Point ID 184 is ( 3,  0,  0) with scale factor 2^2
EQUB 0                 \ Point ID 185 is (14,  0, 14) with scale factor 2^2
EQUB 4                 \ Point ID 186 is ( 3,  4,  3) with scale factor 2^2
EQUB 0                 \ Point ID 187 is ( 5,  0,  5) with scale factor 2^8
EQUB 0                 \ Point ID 188 is ( 0,  0,  3) with scale factor 2^2
EQUB 0                 \ Point ID 189 is ( 3,  0,  0) with scale factor 2^2
EQUB 0                 \ Point ID 190 is (14,  0, 14) with scale factor 2^2
EQUB 4                 \ Point ID 191 is ( 3,  4,  3) with scale factor 2^2
EQUB 0                 \ Point ID 192 is ( 9,  0,  9) with scale factor 2^7
EQUB 0                 \ Point ID 193 is ( 4,  0,  5) with scale factor 2^5
EQUB 0                 \ Point ID 194 is ( 5,  0,  4) with scale factor 2^5
EQUB 0                 \ Point ID 195 is ( 9,  0,  8) with scale factor 2^6
EQUB 4                 \ Point ID 196 is ( 7,  4,  5) with scale factor 2^5
EQUB 0                 \ Point ID 197 is ( 4,  0,  0) with scale factor 2^4
EQUB 3                 \ Point ID 198 is ( 4,  3,  2) with scale factor 2^5
EQUB 0                 \ Point ID 199 is ( 0,  0,  4) with scale factor 2^4
EQUB 3                 \ Point ID 200 is ( 2,  3,  4) with scale factor 2^5
EQUB 2                 \ Point ID 201 is ( 0,  2,  0) with scale factor 2^8
EQUB 2                 \ Point ID 202 is ( 0,  2,  0) with scale factor 2^8
EQUB 0                 \ Point ID 203 is ( 0,  0, 12) with scale factor 2^4
EQUB 0                 \ Point ID 204 is (11,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 205 is (12,  0,  0) with scale factor 2^4
EQUB 0                 \ Point ID 206 is (11,  0,  0) with scale factor 2^5
EQUB 8                 \ Point ID 207 is ( 0,  8,  0) with scale factor 2^4
EQUB 8                 \ Point ID 208 is ( 0,  8,  0) with scale factor 2^4
EQUB 8                 \ Point ID 209 is ( 0,  8,  0) with scale factor 2^4
EQUB 8                 \ Point ID 210 is ( 0,  8,  0) with scale factor 2^4
EQUB 1                 \ Point ID 211 is ( 4,  1,  4) with scale factor 2^7
EQUB 0                 \ Point ID 212 is ( 1,  0,  4) with scale factor 2^8
EQUB 0                 \ Point ID 213 is ( 0,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 214 is ( 0,  0,  5) with scale factor 2^8
EQUB 2                 \ Point ID 215 is ( 4,  2,  5) with scale factor 2^7

Type: Variable
Category: 3D geometry
Summary: Scaled z-coordinates of the points that make up objects, relative
to the object's anchor point
Deep dive: 3D objects
Rotating and translating points in 3D space
Context: See this variable on its own page
References: This variable is used as follows:
* CheckIfAlienIsHit (Part 1 of 2) uses zObjectPoint
* ResizeFeedingAlien uses zObjectPoint
* SetObjPointCoords (Part 1 of 2) uses zObjectPoint

See xObjectPoint for an explanation of object points.

.zObjectPoint

EQUB 13                \ Point ID 0   is (13, 61, 13) with scale factor 2^0
EQUB 0                 \ Point ID 1   is ( 0,  0,  0) with scale factor 2^0
EQUB 156               \ Point ID 2   is ( 0,  0, 12) with scale factor 2^9
EQUB 0                 \ Point ID 3   is ( 0,  0,  0) with scale factor 2^0
EQUB 80                \ Point ID 4   is ( 8,  0,  0) with scale factor 2^5
EQUB 0                 \ Point ID 5   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 6   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 7   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 8   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 9   is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 10  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 11  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 12  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 13  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 14  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 15  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 16  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 17  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 18  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 19  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 20  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 21  is ( 0,  0,  0) with scale factor 2^0
EQUB 72                \ Point ID 22  is ( 0,  0,  8) with scale factor 2^4
EQUB 72                \ Point ID 23  is ( 0,  0,  8) with scale factor 2^4
EQUB 96                \ Point ID 24  is (10,  0,  0) with scale factor 2^6
EQUB 128               \ Point ID 25  is ( 0,  1,  0) with scale factor 2^8
EQUB 128               \ Point ID 26  is ( 0,  1,  0) with scale factor 2^8
EQUB 128               \ Point ID 27  is ( 0,  1,  0) with scale factor 2^8
EQUB 128               \ Point ID 28  is ( 0,  1,  0) with scale factor 2^8
EQUB 128               \ Point ID 29  is ( 4,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 30  is ( 0,  0,  0) with scale factor 2^0
EQUB 0                 \ Point ID 31  is ( 0,  0,  0) with scale factor 2^0
EQUB 128               \ Point ID 32  is ( 4,  0,  0) with scale factor 2^8
EQUB 90                \ Point ID 33  is ( 0,  0, 10) with scale factor 2^5
EQUB 76                \ Point ID 34  is ( 0,  0, 12) with scale factor 2^4
EQUB 0                 \ Point ID 35  is ( 0,  0,  0) with scale factor 2^0
EQUB 130               \ Point ID 36  is ( 4,  0,  2) with scale factor 2^8
EQUB 130               \ Point ID 37  is ( 0,  0,  2) with scale factor 2^8
EQUB 64                \ Point ID 38  is (12,  0,  0) with scale factor 2^4
EQUB 90                \ Point ID 39  is ( 5,  0, 10) with scale factor 2^5
EQUB 64                \ Point ID 40  is ( 8,  0,  0) with scale factor 2^4
EQUB 56                \ Point ID 41  is ( 0,  0,  8) with scale factor 2^3
EQUB 48                \ Point ID 42  is ( 0, 10,  0) with scale factor 2^3
EQUB 48                \ Point ID 43  is ( 0, 10,  0) with scale factor 2^3
EQUB 56                \ Point ID 44  is ( 0,  0,  8) with scale factor 2^3
EQUB 0                 \ Point ID 45  is ( 0,  0,  0) with scale factor 2^0
EQUB 48                \ Point ID 46  is ( 0, 10,  0) with scale factor 2^3
EQUB 48                \ Point ID 47  is ( 0, 10,  0) with scale factor 2^3
EQUB 80                \ Point ID 48  is (12,  0,  0) with scale factor 2^5
EQUB 56                \ Point ID 49  is ( 0,  0,  8) with scale factor 2^3
EQUB 56                \ Point ID 50  is ( 0,  0,  8) with scale factor 2^3
EQUB 80                \ Point ID 51  is (12,  0,  0) with scale factor 2^5
EQUB 96                \ Point ID 52  is (11,  0,  0) with scale factor 2^6
EQUB 64                \ Point ID 53  is ( 0, 10,  0) with scale factor 2^4
EQUB 64                \ Point ID 54  is ( 0, 10,  0) with scale factor 2^4
EQUB 64                \ Point ID 55  is ( 0, 10,  0) with scale factor 2^4
EQUB 64                \ Point ID 56  is ( 0, 10,  0) with scale factor 2^4
EQUB 142               \ Point ID 57  is ( 2,  0, 14) with scale factor 2^8
EQUB 139               \ Point ID 58  is ( 1,  0, 11) with scale factor 2^8
EQUB 153               \ Point ID 59  is ( 3,  0,  9) with scale factor 2^9
EQUB 140               \ Point ID 60  is ( 6,  0, 12) with scale factor 2^8
EQUB 129               \ Point ID 61  is (10,  0,  1) with scale factor 2^8
EQUB 121               \ Point ID 62  is ( 3,  0,  9) with scale factor 2^7
EQUB 111               \ Point ID 63  is ( 9,  0, 15) with scale factor 2^6
EQUB 141               \ Point ID 64  is ( 6,  0, 13) with scale factor 2^8
EQUB 67                \ Point ID 65  is (13,  0,  3) with scale factor 2^4
EQUB 158               \ Point ID 66  is ( 0,  0, 14) with scale factor 2^9
EQUB 128               \ Point ID 67  is ( 1,  0,  0) with scale factor 2^8
EQUB 156               \ Point ID 68  is ( 5,  0, 12) with scale factor 2^9
EQUB 128               \ Point ID 69  is ( 1,  0,  0) with scale factor 2^8
EQUB 0                 \ Point ID 70  is ( 0,  0,  0) with scale factor 2^0
EQUB 80                \ Point ID 71  is ( 9,  0,  0) with scale factor 2^5
EQUB 89                \ Point ID 72  is ( 0,  0,  9) with scale factor 2^5
EQUB 150               \ Point ID 73  is ( 8,  0,  6) with scale factor 2^9
EQUB 129               \ Point ID 74  is ( 0,  0,  1) with scale factor 2^8
EQUB 151               \ Point ID 75  is (14,  0,  7) with scale factor 2^9
EQUB 129               \ Point ID 76  is ( 0,  0,  1) with scale factor 2^8
EQUB 146               \ Point ID 77  is (13,  0,  2) with scale factor 2^9
EQUB 77                \ Point ID 78  is ( 5,  0, 13) with scale factor 2^4
EQUB 128               \ Point ID 79  is (12,  0,  0) with scale factor 2^8
EQUB 31                \ Point ID 80  is (15,  0, 15) with scale factor 2^1
EQUB 32                \ Point ID 81  is ( 0, 12,  0) with scale factor 2^2
EQUB 23                \ Point ID 82  is ( 7, 12,  7) with scale factor 2^1
EQUB 43                \ Point ID 83  is ( 6,  7, 11) with scale factor 2^2
EQUB 37                \ Point ID 84  is (12,  8,  5) with scale factor 2^2
EQUB 0                 \ Point ID 85  is ( 0, 10,  0) with scale factor 2^0
EQUB 129               \ Point ID 86  is ( 0,  0,  1) with scale factor 2^8
EQUB 64                \ Point ID 87  is ( 8,  0,  0) with scale factor 2^4
EQUB 128               \ Point ID 88  is ( 0,  2,  0) with scale factor 2^8
EQUB 31                \ Point ID 89  is (15,  0, 15) with scale factor 2^1
EQUB 32                \ Point ID 90  is ( 0, 10,  0) with scale factor 2^2
EQUB 20                \ Point ID 91  is ( 4, 12,  4) with scale factor 2^1
EQUB 44                \ Point ID 92  is ( 3,  5, 12) with scale factor 2^2
EQUB 40                \ Point ID 93  is (10,  7,  8) with scale factor 2^2
EQUB 0                 \ Point ID 94  is ( 0, 10,  0) with scale factor 2^0
EQUB 0                 \ Point ID 95  is ( 0,  0,  0) with scale factor 2^0
EQUB 129               \ Point ID 96  is ( 0,  0,  1) with scale factor 2^8
EQUB 16                \ Point ID 97  is (10,  0,  0) with scale factor 2^1
EQUB 129               \ Point ID 98  is ( 0,  0,  1) with scale factor 2^8
EQUB 128               \ Point ID 99  is ( 0,  2,  0) with scale factor 2^8
EQUB 0                 \ Point ID 100 is ( 0,  0,  0) with scale factor 2^0
EQUB 75                \ Point ID 101 is ( 0,  0, 11) with scale factor 2^4
EQUB 74                \ Point ID 102 is ( 0,  0, 10) with scale factor 2^4
EQUB 135               \ Point ID 103 is (11,  0,  7) with scale factor 2^8
EQUB 148               \ Point ID 104 is (11,  0,  4) with scale factor 2^9
EQUB 61                \ Point ID 105 is (13,  0, 13) with scale factor 2^3
EQUB 144               \ Point ID 106 is (14,  0,  0) with scale factor 2^9
EQUB 58                \ Point ID 107 is ( 4,  0, 10) with scale factor 2^3
EQUB 128               \ Point ID 108 is ( 4,  0,  0) with scale factor 2^8
EQUB 131               \ Point ID 109 is (13,  0,  3) with scale factor 2^8
EQUB 128               \ Point ID 110 is (12,  0,  0) with scale factor 2^8
EQUB 154               \ Point ID 111 is (13,  0, 10) with scale factor 2^9
EQUB 140               \ Point ID 112 is ( 4,  0, 12) with scale factor 2^8
EQUB 145               \ Point ID 113 is (14,  0,  1) with scale factor 2^9
EQUB 140               \ Point ID 114 is ( 0,  0, 12) with scale factor 2^8
EQUB 133               \ Point ID 115 is ( 3,  0,  5) with scale factor 2^8
EQUB 128               \ Point ID 116 is (15,  0,  0) with scale factor 2^8
EQUB 133               \ Point ID 117 is (10,  0,  5) with scale factor 2^8
EQUB 132               \ Point ID 118 is (11,  0,  4) with scale factor 2^8
EQUB 142               \ Point ID 119 is ( 2,  0, 14) with scale factor 2^8
EQUB 64                \ Point ID 120 is (14,  0,  0) with scale factor 2^4
EQUB 137               \ Point ID 121 is ( 0,  0,  9) with scale factor 2^8
EQUB 151               \ Point ID 122 is (11,  0,  7) with scale factor 2^9
EQUB 147               \ Point ID 123 is (10,  0,  3) with scale factor 2^9
EQUB 147               \ Point ID 124 is (10,  0,  3) with scale factor 2^9
EQUB 153               \ Point ID 125 is ( 5,  0,  9) with scale factor 2^9
EQUB 130               \ Point ID 126 is (14,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 127 is ( 0,  0,  0) with scale factor 2^0
EQUB 135               \ Point ID 128 is ( 0,  0,  7) with scale factor 2^8
EQUB 142               \ Point ID 129 is (11,  0, 14) with scale factor 2^8
EQUB 138               \ Point ID 130 is (14,  0, 10) with scale factor 2^8
EQUB 128               \ Point ID 131 is ( 5,  0,  0) with scale factor 2^8
EQUB 142               \ Point ID 132 is ( 4,  0, 14) with scale factor 2^8
EQUB 148               \ Point ID 133 is ( 9,  0,  4) with scale factor 2^9
EQUB 146               \ Point ID 134 is (10,  0,  2) with scale factor 2^9
EQUB 0                 \ Point ID 135 is ( 0,  0,  0) with scale factor 2^0
EQUB 143               \ Point ID 136 is ( 1,  0, 15) with scale factor 2^8
EQUB 154               \ Point ID 137 is ( 5,  0, 10) with scale factor 2^9
EQUB 132               \ Point ID 138 is (13,  0,  4) with scale factor 2^8
EQUB 0                 \ Point ID 139 is ( 0,  0,  0) with scale factor 2^0
EQUB 139               \ Point ID 140 is ( 0,  0, 11) with scale factor 2^8
EQUB 137               \ Point ID 141 is (13,  0,  9) with scale factor 2^8
EQUB 112               \ Point ID 142 is (15,  0,  0) with scale factor 2^7
EQUB 128               \ Point ID 143 is ( 2,  0,  0) with scale factor 2^8
EQUB 141               \ Point ID 144 is ( 0,  0, 13) with scale factor 2^8
EQUB 153               \ Point ID 145 is ( 9,  0,  9) with scale factor 2^9
EQUB 139               \ Point ID 146 is (13,  0, 11) with scale factor 2^8
EQUB 133               \ Point ID 147 is (15,  0,  5) with scale factor 2^8
EQUB 128               \ Point ID 148 is (11,  0,  0) with scale factor 2^8
EQUB 139               \ Point ID 149 is ( 0,  0, 11) with scale factor 2^8
EQUB 141               \ Point ID 150 is (11,  0, 13) with scale factor 2^8
EQUB 130               \ Point ID 151 is (13,  0,  2) with scale factor 2^8
EQUB 128               \ Point ID 152 is ( 2,  0,  0) with scale factor 2^8
EQUB 136               \ Point ID 153 is ( 3,  0,  8) with scale factor 2^8
EQUB 135               \ Point ID 154 is (10,  0,  7) with scale factor 2^8
EQUB 130               \ Point ID 155 is ( 8,  0,  2) with scale factor 2^8
EQUB 0                 \ Point ID 156 is ( 0,  0,  0) with scale factor 2^0
EQUB 134               \ Point ID 157 is ( 0,  0,  6) with scale factor 2^8
EQUB 136               \ Point ID 158 is ( 4,  0,  8) with scale factor 2^8
EQUB 128               \ Point ID 159 is (12,  0,  0) with scale factor 2^8
EQUB 134               \ Point ID 160 is ( 0,  0,  6) with scale factor 2^8
EQUB 153               \ Point ID 161 is ( 6,  0,  9) with scale factor 2^9
EQUB 140               \ Point ID 162 is (14,  0, 12) with scale factor 2^8
EQUB 112               \ Point ID 163 is (11,  0,  0) with scale factor 2^7
EQUB 131               \ Point ID 164 is ( 0,  0,  3) with scale factor 2^8
EQUB 156               \ Point ID 165 is ( 5,  0, 12) with scale factor 2^9
EQUB 153               \ Point ID 166 is (10,  0,  9) with scale factor 2^9
EQUB 128               \ Point ID 167 is (14,  0,  0) with scale factor 2^8
EQUB 140               \ Point ID 168 is ( 0,  0, 12) with scale factor 2^8
EQUB 155               \ Point ID 169 is ( 5,  0, 11) with scale factor 2^9
EQUB 135               \ Point ID 170 is (11,  0,  7) with scale factor 2^8
EQUB 128               \ Point ID 171 is ( 5,  0,  0) with scale factor 2^8
EQUB 137               \ Point ID 172 is ( 0,  0,  9) with scale factor 2^8
EQUB 152               \ Point ID 173 is ( 5,  0,  8) with scale factor 2^9
EQUB 141               \ Point ID 174 is (13,  0, 13) with scale factor 2^8
EQUB 128               \ Point ID 175 is ( 2,  0,  0) with scale factor 2^8
EQUB 136               \ Point ID 176 is ( 0,  0,  8) with scale factor 2^8
EQUB 128               \ Point ID 177 is ( 2,  0,  0) with scale factor 2^8
EQUB 12                \ Point ID 178 is ( 0,  0, 12) with scale factor 2^0
EQUB 0                 \ Point ID 179 is (12,  0,  0) with scale factor 2^0
EQUB 46                \ Point ID 180 is (14,  0, 14) with scale factor 2^2
EQUB 133               \ Point ID 181 is ( 5,  0,  5) with scale factor 2^8
EQUB 133               \ Point ID 182 is ( 5,  0,  5) with scale factor 2^8
EQUB 35                \ Point ID 183 is ( 0,  0,  3) with scale factor 2^2
EQUB 32                \ Point ID 184 is ( 3,  0,  0) with scale factor 2^2
EQUB 46                \ Point ID 185 is (14,  0, 14) with scale factor 2^2
EQUB 35                \ Point ID 186 is ( 3,  4,  3) with scale factor 2^2
EQUB 133               \ Point ID 187 is ( 5,  0,  5) with scale factor 2^8
EQUB 35                \ Point ID 188 is ( 0,  0,  3) with scale factor 2^2
EQUB 32                \ Point ID 189 is ( 3,  0,  0) with scale factor 2^2
EQUB 46                \ Point ID 190 is (14,  0, 14) with scale factor 2^2
EQUB 35                \ Point ID 191 is ( 3,  4,  3) with scale factor 2^2
EQUB 121               \ Point ID 192 is ( 9,  0,  9) with scale factor 2^7
EQUB 85                \ Point ID 193 is ( 4,  0,  5) with scale factor 2^5
EQUB 84                \ Point ID 194 is ( 5,  0,  4) with scale factor 2^5
EQUB 104               \ Point ID 195 is ( 9,  0,  8) with scale factor 2^6
EQUB 85                \ Point ID 196 is ( 7,  4,  5) with scale factor 2^5
EQUB 64                \ Point ID 197 is ( 4,  0,  0) with scale factor 2^4
EQUB 82                \ Point ID 198 is ( 4,  3,  2) with scale factor 2^5
EQUB 68                \ Point ID 199 is ( 0,  0,  4) with scale factor 2^4
EQUB 84                \ Point ID 200 is ( 2,  3,  4) with scale factor 2^5
EQUB 128               \ Point ID 201 is ( 0,  2,  0) with scale factor 2^8
EQUB 128               \ Point ID 202 is ( 0,  2,  0) with scale factor 2^8
EQUB 76                \ Point ID 203 is ( 0,  0, 12) with scale factor 2^4
EQUB 80                \ Point ID 204 is (11,  0,  0) with scale factor 2^5
EQUB 64                \ Point ID 205 is (12,  0,  0) with scale factor 2^4
EQUB 80                \ Point ID 206 is (11,  0,  0) with scale factor 2^5
EQUB 64                \ Point ID 207 is ( 0,  8,  0) with scale factor 2^4
EQUB 64                \ Point ID 208 is ( 0,  8,  0) with scale factor 2^4
EQUB 64                \ Point ID 209 is ( 0,  8,  0) with scale factor 2^4
EQUB 64                \ Point ID 210 is ( 0,  8,  0) with scale factor 2^4
EQUB 116               \ Point ID 211 is ( 4,  1,  4) with scale factor 2^7
EQUB 132               \ Point ID 212 is ( 1,  0,  4) with scale factor 2^8
EQUB 130               \ Point ID 213 is ( 0,  0,  2) with scale factor 2^8
EQUB 133               \ Point ID 214 is ( 0,  0,  5) with scale factor 2^8
EQUB 117               \ Point ID 215 is ( 4,  2,  5) with scale factor 2^7

Type: Variable
Category: Dashboard
Summary: The x-coordinates of the runway and alien on the radar
Deep dive: Line buffers
Context: See this variable on its own page
References: This variable is used as follows:

EQUB &8A               \ The x-coordinate of the runway on the radar, stored so
\ we can erase it again

EQUB &8A               \ The x-coordinate of the alien on the radar, stored so
\ we can erase it again

Type: Variable
Category: Dashboard
Summary: The y-coordinates of the runway and alien on the radar
Deep dive: Line buffers
Context: See this variable on its own page
References: This variable is used as follows:

EQUB &D0               \ The y-coordinate of the runway on the radar, stored so
\ we can erase it again

EQUB &D0               \ The y-coordinate of the alien on the radar, stored so
\ we can erase it again

Type: Variable
Category: The Theme
Summary: The distance from the alien we just hit, so we can work out
whether we get hit by turbulence
Deep dive: Explosions and turbulence
Context: See this variable on its own page
References: This variable is used as follows:
* ApplyFlightModel (Part 3 of 7) uses distanceFromHit
* ExplodeAlien uses distanceFromHit
* MainLoop (Part 6 of 15) uses distanceFromHit

.distanceFromHit

EQUB &48

Type: Variable
Category: The Theme
Summary: The feeding stage of the alien we are currently processing
Context: See this variable on its own page
References: This variable is used as follows:
* CheckIfAlienIsHit (Part 1 of 2) uses feedingStage
* ExplodeAlien uses feedingStage
* ScoreHitPoints uses feedingStage

.feedingStage

EQUB &49               \ The alien's feeding stage
\
\   * 0 = large feeding alien (full up) or flying
\   * 1 = medium feeding alien
\   * 2 = small feeding alien
\   * 3 = smallest feeding alien
\   * 4 = dormant (not feeding)

Type: Variable
Category: The Theme
Summary: The object ID of the alien we just hit (30 to 33)
Context: See this variable on its own page
References: This variable is used as follows:
* CheckAlienWeakSpot uses hitObjectId
* ExplodeAlien uses hitObjectId
* ScoreHitPoints uses hitObjectId

This is called EPTR in the original source.

.hitObjectId

EQUB &3D

Type: Variable
Category: The Theme
Summary: The time since we hit an alien, so we can time its explosion
Deep dive: Explosions and turbulence
Context: See this variable on its own page
References: This variable is used as follows:
* AlienInAcornsville uses hitTimer
* ApplyFlightModel (Part 3 of 7) uses hitTimer
* CheckAlienWeakSpot uses hitTimer
* CheckIfAlienIsHit (Part 2 of 2) uses hitTimer
* ExplodeAlien uses hitTimer
* FireGuns uses hitTimer
* MainLoop (Part 6 of 15) uses hitTimer
* ResetVariables uses hitTimer

The hit timer starts at 27 when we make a hit. While it is non-zero, the gun
can't be fired and any attacking aliens stop moving until the timer runs down.

This is called EPLO in the original source.

.hitTimer

EQUB &26               \ Zeroed in ResetVariables

Type: Variable
Category: Flight model
Summary: The low byte of the current batch of fuel used
Context: See this variable on its own page
References: This variable is used as follows:
* ApplyFlightModel (Part 7 of 7) uses fuelUsedLo

.fuelUsedLo

EQUB &34

Type: Variable
Category: Flight model
Summary: The high byte of the current batch of fuel used
Context: See this variable on its own page
References: This variable is used as follows:
* ApplyFlightModel (Part 7 of 7) uses fuelUsedHi

.fuelUsedHi

EQUB &34

Type: Variable
Category: Flight model
Summary: The current fuel level
Context: See this variable on its own page
References: This variable is used as follows:
* ApplyFlightModel (Part 7 of 7) uses fuelLevel
* FillUpFuelTank uses fuelLevel
* ResetVariables uses fuelLevel
* UpdateFuelGauge uses fuelLevel

.fuelLevel

EQUB &41               \ Current fuel level
\
\   * 0 = empty
\
\   * 65 = full

Type: Variable
Category: The Theme
Summary: The end point ID for exploding each of the four alien slots
Context: See this variable on its own page
References: This variable is used as follows:
* ExplodeAlien uses explodeTo

.explodeTo

EQUB 178               \ Alien slot 30 moves points 180 to 178 when it explodes
EQUB 183               \ Alien slot 31 moves points 186 to 183 when it explodes
EQUB 188               \ Alien slot 32 moves points 191 to 188 when it explodes
EQUB 193               \ Alien slot 33 moves points 200 to 193 when it explodes

EQUB 15                \ This byte appears to be unused

Type: Variable
Category: The Theme
Summary: The starting point ID for exploding each of the four alien slots
Context: See this variable on its own page
References: This variable is used as follows:
* ExplodeAlien uses explodeFrom

.explodeFrom

EQUB 180               \ Alien slot 30 moves points 180 to 178 when it explodes
EQUB 186               \ Alien slot 31 moves points 186 to 183 when it explodes
EQUB 191               \ Alien slot 32 moves points 191 to 188 when it explodes
EQUB 200               \ Alien slot 33 moves points 200 to 193 when it explodes

Type: Variable
Category: Scoring
Summary: Score (low byte)
Context: See this variable on its own page
References: This variable is used as follows:
* DisplayScore uses scoreLo
* ResetVariables uses scoreLo
* UpdateHighScore uses scoreLo

.scoreLo

EQUB &49               \ Score (low byte of a BCD number)
\
\ The score is displayed with an extra "0" added to the
\ end, so this contains the score divided by 10

Type: Variable
Category: Scoring
Summary: Score (high byte)
Context: See this variable on its own page
References: This variable is used as follows:
* DisplayScore uses scoreHi
* ResetVariables uses scoreHi
* UpdateHighScore uses scoreHi

.scoreHi

EQUB &3D               \ Score (high byte of a BCD number)
\
\ The score is displayed with an extra "0" added to the
\ end, so this contains the score divided by 10

Type: Variable
Category: Scoring
Summary: High score (high byte)
Context: See this variable on its own page
References: This variable is used as follows:
* DisplayScore uses highScoreLo
* StartGame uses highScoreLo
* UpdateHighScore uses highScoreLo

.highScoreLo

EQUB &26               \ High score (high byte of a BCD number)
\
\ The high score is displayed with an extra "0" added to
\ the end, so this contains the high score divided by 10

Type: Variable
Category: Scoring
Summary: High score (low byte)
Context: See this variable on its own page
References: This variable is used as follows:
* DisplayScore uses highScoreHi
* StartGame uses highScoreHi
* UpdateHighScore uses highScoreHi

.highScoreHi

EQUB &34               \ High score (low byte of a BCD number)
\
\ The high score is displayed with an extra "0" added to
\ the end, so this contains the high score divided by 10

Type: Subroutine
Category: Flight model
Summary: Set the engine status
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* ApplyFlightModel (Part 7 of 7) calls SetEngine
* MainLoop (Part 11 of 15) calls SetEngine
* ProcessLanding (Part 6 of 7) calls SetEngine

Arguments:

A                    The new status of the engine:

* 0 = engine off

* 1 = engine on

.SetEngine

CMP engineStatus       \ If the value of engineStatus is already the same as A,

STA engineStatus       \ Update the value of engineStatus to the new status in
\ A

TAX                    \ Either turn the engine sound off (if A = 0) or turn it
JSR ToggleEngineSound  \ on (if A is non-zero)

LDA forceFactor+5      \ Set A to the force factor for zLiftDrag

LDX engineStatus       \ If the engine is now on, jump to seng1
BNE seng1

CLC                    \ Set A = A + 20
\ so having the engine off increases drag

BNE seng2              \ Jump to seng2 (this BNE is effectively a JMP as A is
\ never zero)

.seng1

SEC                    \ Set A = A - 20
SBC #20                \
\ so having the engine on decreases drag

.seng2

STA forceFactor+5      \ Update the force factor for zLiftDrag, so it is
\ incremented by 20 when the engine is off, and reduced
\ by 20 when the engine is on, i.e. having the engine
\ off increases drag

.seng3

RTS                    \ Return from the subroutine

Type: Variable
Category: Scoring
Summary: Low byte of the skill zone coordinates for testing flying skills
Deep dive: Flying skills
Context: See this variable on its own page
References: This variable is used as follows:
* CheckBridgeAndTown uses skillZoneLo

.skillZoneLo

EQUB &A8, &00, &56     \ Bridge skill zone 0 coordinate = (&4CA8, &0000, &8656)
EQUB &A8, &60, &56     \ Bridge skill zone 3 coordinate = (&4CA8, &0060, &8656)
EQUB &88, &00, &56     \ Bridge skill zone 6 coordinate = (&4C88, &0000, &8656)

EQUB &30, &00, &30     \ Town skill zone  9 coordinate = (&0430, &0000, &0330)
EQUB &D0, &00, &70     \ Town skill zone 12 coordinate = (&04D0, &0000, &0470)
EQUB &10, &00, &70     \ Town skill zone 15 coordinate = (&0610, &0000, &0470)
EQUB &E0, &00, &C0     \ Town skill zone 18 coordinate = (&04E0, &0000, &03C0)

Type: Variable
Category: Scoring
Summary: High byte of the skill zone coordinates for testing flying skills
Deep dive: Flying skills
Context: See this variable on its own page
References: This variable is used as follows:
* CheckBridgeAndTown uses skillZoneHi

.skillZoneHi

EQUB &4C, &00, &86     \ Bridge skill zone 0 coordinate = (&4CA8, &0000, &8656)
EQUB &4C, &00, &86     \ Bridge skill zone 3 coordinate = (&4CA8, &0060, &8656)
EQUB &4C, &00, &86     \ Bridge skill zone 6 coordinate = (&4C88, &0000, &8656)

EQUB &04, &00, &03     \ Town skill zone  9 coordinate = (&0430, &0000, &0330)
EQUB &04, &00, &04     \ Town skill zone 12 coordinate = (&04D0, &0000, &0470)
EQUB &06, &00, &04     \ Town skill zone 15 coordinate = (&0610, &0000, &0470)
EQUB &04, &00, &03     \ Town skill zone 18 coordinate = (&04E0, &0000, &03C0)

Type: Variable
Category: Scoring
Summary: Sizes of the skill zones for testing flying skills
Deep dive: Flying skills
Context: See this variable on its own page
References: This variable is used as follows:
* CheckBridgeAndTown uses skillZoneSize

.skillZoneSize

EQUB &A8, &10, &18     \ Bridge skill zone 0 size = (&A8, &10, &18)
EQUB &A8, &16, &18     \ Bridge skill zone 3 size = (&A8, &16, &18)
EQUB &B8, &2C, &18     \ Bridge skill zone 6 size = (&B8, &2C, &18)

EQUB &A8, &44, &28     \ Town skill zone  9 size = (&A8, &44, &28)
EQUB &28, &84, &48     \ Town skill zone 12 size = (&28, &84, &48)
EQUB &60, &24, &38     \ Town skill zone 15 size = (&60, &24, &38)
EQUB &78, &20, &60     \ Town skill zone 18 size = (&78, &20, &60)

EQUB &20               \ This byte appears to be unused

Type: Variable
Category: Maths
Summary: Lookup table for shifting a byte four places to the right, to
extract the high nibble
Deep dive: Times tables and nibble arithmetic
Context: See this variable on its own page
References: This variable is used as follows:
* DivideScaled uses shift4Right
* Multiply4x16 uses shift4Right
* Multiply8x8 uses shift4Right
* ScaleUp uses shift4Right
* SetObjPointCoords (Part 1 of 2) uses shift4Right

In the table below, shift4Right,X contains the high byte of X * 16. So if X is
%XXXXxxxx, shift4Right,X contains %0000XXXX.

.shift4Right

FOR I%, 0, 255

EQUB HI(I% * 16)

NEXT

Type: Variable
Category: Maths
Summary: Lookup table for shifting a byte four places to the left, to
extract the low nibble
Deep dive: Times tables and nibble arithmetic
Context: See this variable on its own page
References: This variable is used as follows:
* DivideScaled uses shift4Left
* Multiply4x16 uses shift4Left
* Multiply8x8 uses shift4Left
* ScaleUp uses shift4Left

In the table below, shift4Left,X contains the low byte of X * 16. So if X is
%XXXXxxxx, shift4Left,X contains %xxxx0000.

.shift4Left

FOR I%, 0, 255

EQUB LO(I% * 16)

NEXT

Type: Variable
Category: Maths
Summary: Division lookup table
Context: See this variable on its own page
References: This variable is used as follows:
* ProjectPoint (Part 2 of 3) uses divisionHi

This table contains the high byte of the division lookup table, while bits 3
to 7 of divisionLo contain the low byte.

.divisionHi

EQUB &FF, &FE, &FD, &FC, &FB, &FA, &F9, &F8
EQUB &F7, &F6, &F5, &F4, &F3, &F2, &F1, &F0
EQUB &EF, &EF, &EE, &ED, &EC, &EB, &EA, &E9
EQUB &E9, &E8, &E7, &E6, &E5, &E4, &E4, &E3
EQUB &E2, &E1, &E1, &E0, &DF, &DE, &DD, &DD
EQUB &DC, &DB, &DA, &DA, &D9, &D8, &D8, &D7
EQUB &D6, &D5, &D5, &D4, &D3, &D3, &D2, &D1
EQUB &D1, &D0, &CF, &CF, &CE, &CD, &CD, &CC
EQUB &CB, &CB, &CA, &C9, &C9, &C8, &C8, &C7
EQUB &C6, &C6, &C5, &C5, &C4, &C3, &C3, &C2
EQUB &C2, &C1, &C0, &C0, &BF, &BF, &BE, &BE
EQUB &BD, &BC, &BC, &BB, &BB, &BA, &BA, &B9
EQUB &B9, &B8, &B8, &B7, &B7, &B6, &B6, &B5
EQUB &B5, &B4, &B4, &B3, &B3, &B2, &B2, &B1
EQUB &B1, &B0, &B0, &AF, &AF, &AE, &AE, &AD
EQUB &AD, &AC, &AC, &AB, &AB, &AB, &AA, &AA
EQUB &A9, &A9, &A8, &A8, &A7, &A7, &A7, &A6
EQUB &A6, &A5, &A5, &A4, &A4, &A4, &A3, &A3
EQUB &A2, &A2, &A2, &A1, &A1, &A0, &A0, &A0
EQUB &9F, &9F, &9E, &9E, &9E, &9D, &9D, &9C
EQUB &9C, &9C, &9B, &9B, &9B, &9A, &9A, &99
EQUB &99, &99, &98, &98, &98, &97, &97, &97
EQUB &96, &96, &96, &95, &95, &94, &94, &94
EQUB &93, &93, &93, &92, &92, &92, &91, &91
EQUB &91, &90, &90, &90, &90, &8F, &8F, &8F
EQUB &8E, &8E, &8E, &8D, &8D, &8D, &8C, &8C
EQUB &8C, &8B, &8B, &8B, &8B, &8A, &8A, &8A
EQUB &89, &89, &89, &88, &88, &88, &88, &87
EQUB &87, &87, &86, &86, &86, &86, &85, &85
EQUB &85, &85, &84, &84, &84, &83, &83, &83
EQUB &83, &82, &82, &82, &82, &81, &81, &81
EQUB &81, &80, &80, &80, &80, &7F, &7F, &7F

Type: Variable
Category: Maths
Summary: Lookup table for multiplication times tables
Deep dive: Times tables and nibble arithmetic
Context: See this variable on its own page
References: This variable is used as follows:
* DivideScaled uses timesTable
* Multiply4x16 uses timesTable
* Multiply8x8 uses timesTable

In the table below, timesTable+X*16,Y contains X * Y.

To put it another way, X and Y are both in the range 0 to 15, so they are
4-bit values. If, in binary, they are X = %xxxx and Y = %yyyy, then:

timesTable,%xxxxyyyy contains X * Y.

This table is used in conjunction with the highNibble and lowNibble tables to
look up multiplication results.

.timesTable

FOR I%, 0, 15

FOR J%, 0, 15

EQUB I% * J%

NEXT

NEXT

Type: Variable
Category: Visibility
Summary: The furthest distance at which each line is visible
Deep dive: Lines and points
Context: See this variable on its own page
References: This variable is used as follows:
* CheckLineDistance uses maxLineDistance

Lines are only shown if they are closer than the distance in this table, so
this table contains the maximum visible distance for each line.

The table is indexed by line ID, so for line ID X, maxLineDistance,X contains
the maximum distance at which that line is visible, in any of the individual
axes.

.maxLineDistance

EQUB 16                \ Line ID   0
EQUB 125               \ Line ID   1
EQUB 125               \ Line ID   2
EQUB 125               \ Line ID   3
EQUB 125               \ Line ID   4
EQUB 16                \ Line ID   5
EQUB 16                \ Line ID   6
EQUB 16                \ Line ID   7
EQUB 16                \ Line ID   8
EQUB 16                \ Line ID   9
EQUB 40                \ Line ID  10
EQUB 16                \ Line ID  11
EQUB 80                \ Line ID  12
EQUB 80                \ Line ID  13
EQUB 50                \ Line ID  14
EQUB 50                \ Line ID  15
EQUB 50                \ Line ID  16
EQUB 40                \ Line ID  17
EQUB 40                \ Line ID  18
EQUB 40                \ Line ID  19
EQUB 80                \ Line ID  20
EQUB 80                \ Line ID  21
EQUB 40                \ Line ID  22
EQUB 40                \ Line ID  23
EQUB 80                \ Line ID  24
EQUB 80                \ Line ID  25
EQUB 80                \ Line ID  26
EQUB 80                \ Line ID  27
EQUB 80                \ Line ID  28
EQUB 80                \ Line ID  29
EQUB 80                \ Line ID  30
EQUB 80                \ Line ID  31
EQUB 80                \ Line ID  32
EQUB 80                \ Line ID  33
EQUB 80                \ Line ID  34
EQUB 80                \ Line ID  35
EQUB 80                \ Line ID  36
EQUB 80                \ Line ID  37
EQUB 80                \ Line ID  38
EQUB 60                \ Line ID  39
EQUB 70                \ Line ID  40
EQUB 60                \ Line ID  41
EQUB 70                \ Line ID  42
EQUB 60                \ Line ID  43
EQUB 70                \ Line ID  44
EQUB 60                \ Line ID  45
EQUB 70                \ Line ID  46
EQUB 63                \ Line ID  47
EQUB 63                \ Line ID  48
EQUB 63                \ Line ID  49
EQUB 63                \ Line ID  50
EQUB 60                \ Line ID  51
EQUB 70                \ Line ID  52
EQUB 60                \ Line ID  53
EQUB 70                \ Line ID  54
EQUB 60                \ Line ID  55
EQUB 63                \ Line ID  56
EQUB 63                \ Line ID  57
EQUB 63                \ Line ID  58
EQUB 63                \ Line ID  59
EQUB 30                \ Line ID  60
EQUB 30                \ Line ID  61
EQUB 70                \ Line ID  62
EQUB 60                \ Line ID  63
EQUB 70                \ Line ID  64
EQUB 60                \ Line ID  65
EQUB 70                \ Line ID  66
EQUB 60                \ Line ID  67
EQUB 70                \ Line ID  68
EQUB 60                \ Line ID  69
EQUB 70                \ Line ID  70
EQUB 60                \ Line ID  71
EQUB 70                \ Line ID  72
EQUB 60                \ Line ID  73
EQUB 70                \ Line ID  74
EQUB 60                \ Line ID  75
EQUB 120               \ Line ID  76
EQUB 70                \ Line ID  77
EQUB 125               \ Line ID  78
EQUB 125               \ Line ID  79
EQUB 125               \ Line ID  80
EQUB 125               \ Line ID  81
EQUB 125               \ Line ID  82
EQUB 125               \ Line ID  83
EQUB 125               \ Line ID  84
EQUB 125               \ Line ID  85
EQUB 125               \ Line ID  86
EQUB 125               \ Line ID  87
EQUB 125               \ Line ID  88
EQUB 125               \ Line ID  89
EQUB 125               \ Line ID  90
EQUB 125               \ Line ID  91
EQUB 125               \ Line ID  92
EQUB 125               \ Line ID  93
EQUB 125               \ Line ID  94
EQUB 125               \ Line ID  95
EQUB 125               \ Line ID  96
EQUB 125               \ Line ID  97
EQUB 125               \ Line ID  98
EQUB 125               \ Line ID  99
EQUB 125               \ Line ID 100
EQUB 125               \ Line ID 101
EQUB 125               \ Line ID 102
EQUB 125               \ Line ID 103
EQUB 125               \ Line ID 104
EQUB 125               \ Line ID 105
EQUB 125               \ Line ID 106
EQUB 125               \ Line ID 107
EQUB 125               \ Line ID 108
EQUB 125               \ Line ID 109
EQUB 125               \ Line ID 110
EQUB 125               \ Line ID 111
EQUB 125               \ Line ID 112
EQUB 125               \ Line ID 113
EQUB 125               \ Line ID 114
EQUB 125               \ Line ID 115
EQUB 125               \ Line ID 116
EQUB 125               \ Line ID 117
EQUB 125               \ Line ID 118
EQUB 125               \ Line ID 119
EQUB 125               \ Line ID 120
EQUB 125               \ Line ID 121
EQUB 125               \ Line ID 122
EQUB 120               \ Line ID 123
EQUB 125               \ Line ID 124
EQUB 125               \ Line ID 125
EQUB 125               \ Line ID 126
EQUB 125               \ Line ID 127
EQUB 125               \ Line ID 128
EQUB 125               \ Line ID 129
EQUB 125               \ Line ID 130
EQUB 125               \ Line ID 131
EQUB 125               \ Line ID 132
EQUB 125               \ Line ID 133
EQUB 125               \ Line ID 134
EQUB 25                \ Line ID 135
EQUB 25                \ Line ID 136
EQUB 25                \ Line ID 137
EQUB 100               \ Line ID 138
EQUB 100               \ Line ID 139
EQUB 100               \ Line ID 140
EQUB 100               \ Line ID 141
EQUB 100               \ Line ID 142
EQUB 100               \ Line ID 143
EQUB 100               \ Line ID 144
EQUB 100               \ Line ID 145
EQUB 100               \ Line ID 146
EQUB 100               \ Line ID 147
EQUB 100               \ Line ID 148
EQUB 100               \ Line ID 149
EQUB 120               \ Line ID 150
EQUB 100               \ Line ID 151
EQUB 100               \ Line ID 152
EQUB 100               \ Line ID 153
EQUB 100               \ Line ID 154
EQUB 100               \ Line ID 155
EQUB 100               \ Line ID 156
EQUB 100               \ Line ID 157
EQUB 100               \ Line ID 158
EQUB 100               \ Line ID 159
EQUB 100               \ Line ID 160
EQUB 120               \ Line ID 161
EQUB 120               \ Line ID 162
EQUB 120               \ Line ID 163
EQUB 120               \ Line ID 164
EQUB 120               \ Line ID 165
EQUB 120               \ Line ID 166
EQUB 120               \ Line ID 167
EQUB 120               \ Line ID 168
EQUB 60                \ Line ID 169
EQUB 60                \ Line ID 170
EQUB 60                \ Line ID 171
EQUB 60                \ Line ID 172
EQUB 60                \ Line ID 173
EQUB 60                \ Line ID 174
EQUB 60                \ Line ID 175
EQUB 60                \ Line ID 176
EQUB 60                \ Line ID 177
EQUB 60                \ Line ID 178
EQUB 60                \ Line ID 179
EQUB 60                \ Line ID 180
EQUB 60                \ Line ID 181
EQUB 60                \ Line ID 182
EQUB 60                \ Line ID 183
EQUB 60                \ Line ID 184
EQUB 60                \ Line ID 185
EQUB 120               \ Line ID 186
EQUB 120               \ Line ID 187
EQUB 120               \ Line ID 188
EQUB 120               \ Line ID 189
EQUB 120               \ Line ID 190
EQUB 120               \ Line ID 191
EQUB 120               \ Line ID 192

EQUB &3F, &0D          \ These bytes appear to be unused
EQUB &03, &B1
EQUB &10, &2E
EQUB &64, &6C
EQUB &70, &32
EQUB &20, &53
EQUB &54, &41
EQUB &26, &37
EQUB &36, &0D
EQUB &03, &B2
EQUB &19, &2E
EQUB &64

Type: Variable
Category: Visibility
Summary: The furthest distance at which each object is visible
Context: See this variable on its own page
References: This variable is used as follows:
* CheckObjDistance uses maxObjDistance

Objects are only shown if they are closer than the distance in this table, so
this table contains the maximum visible distance for each object.

The table is indexed by object ID, so for object ID X, maxObjDistance,X
contains the maximum distance at which that object is visible, in any of the
individual axes.

The initial contents of the last five bytes of this table contains workspace
noise and is ignored. It actually contains snippets of the original source
code.

.maxObjDistance

EQUB 108               \ Object  0
EQUB 125               \ Object  1
EQUB 125               \ Object  2
EQUB 125               \ Object  3
EQUB 125               \ Object  4
EQUB 125               \ Object  5
EQUB  40               \ Object  6
EQUB  40               \ Object  7
EQUB 110               \ Object  8
EQUB 110               \ Object  9
EQUB  58               \ Object 10
EQUB  66               \ Object 11
EQUB  30               \ Object 12
EQUB  30               \ Object 13
EQUB  30               \ Object 14
EQUB  30               \ Object 15
EQUB 125               \ Object 16
EQUB 125               \ Object 17
EQUB 125               \ Object 18
EQUB 125               \ Object 19
EQUB 125               \ Object 20
EQUB 125               \ Object 21
EQUB 125               \ Object 22
EQUB 125               \ Object 23
EQUB 125               \ Object 24
EQUB 125               \ Object 25
EQUB 125               \ Object 26
EQUB 125               \ Object 27
EQUB 125               \ Object 28
EQUB 125               \ Object 29
EQUB  25               \ Object 30
EQUB  90               \ Object 31
EQUB  90               \ Object 32
EQUB  90               \ Object 33
EQUB 125               \ Object 34
EQUB  58               \ Object 35
EQUB  66               \ Object 36
EQUB  78               \ Object 37
EQUB  69               \ Object 38
EQUB  32               \ Object 39

```