Elite on the BBC Micro and NES

# Bank 0 (Part 3 of 5)

## [NES version]

```       Name: TT14                                                    [Show more]
Type: Subroutine
Category: Drawing circles
Summary: Draw a circle with crosshairs on a chart
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT22 calls TT14
* TT23 calls TT14

Draw a circle with crosshairs at the current system's galactic coordinates.

.TT126

LDA #104               ; Set QQ19 = 104, for the x-coordinate of the centre of
STA QQ19               ; the fixed circle on the Short-range Chart

LDA #90                ; Set QQ19+1 = 90, for the y-coordinate of the centre of
STA QQ19+1             ; the fixed circle on the Short-range Chart

LDA #16                ; Set QQ19+2 = 16, the size of the crosshairs on the
STA QQ19+2             ; Short-range Chart

JSR TT15               ; Draw the set of crosshairs defined in QQ19, at the
; exact coordinates as this is the Short-range Chart

LDA QQ14               ; Set K = QQ14 + (QQ14 / 32)
LSR A                  ;
LSR A                  ; So K is the circle's radius, based on the fuel level
LSR A                  ; in QQ14 (so K is in the range 0 to 73, as the latter
LSR A                  ; division gets rounded up by the ADC adding in the C
LSR A                  ; flag, and QQ14 is in the range 0 to 70)
STA K

JMP TT128              ; Jump to TT128 to draw a circle with the centre at the
; same coordinates as the crosshairs, (QQ19, QQ19+1),
; and radius K that reflects the current fuel levels,
; returning from the subroutine using a tail call

.TT14

LDA QQ11               ; If the view type in QQ11 is \$9C (Short-range Chart),
CMP #\$9C               ; jump up to TT126 to draw the crosshairs and circle for
BEQ TT126              ; that view

; Otherwise this is the Long-range Chart, so we draw the
; crosshairs and circle for that view instead

LDA QQ14               ; Set K = QQ14/4 - QQ14/16
LSR A                  ;       = 0.1875 * QQ14
LSR A                  ;
STA K                  ; So K scales the fuel level in QQ14 to act as the
LSR A                  ; circle's radius, scaling the fuel level from a range
LSR A                  ; of 0 to 70 down to a range of 0 to 13, so the fuel
STA T1                 ; circle has a maximum radius of 13 pixels on the
LDA K                  ; Long-range Chart
SEC
SBC T1
STA K

; We now set the pixel coordinates of the crosshairs in
; QQ9 and QQ9+1 so they fit into the chart, with a
; 31-pixel margin on the left and an 8-pixel margin at
; the top (to which we will add another 24 pixels below)
;
; The Long-range Chart is twice as wide as it is high,
; so we need to scale the y-coordinate in QQ19+1 by an
; extra division by 2 when compared to the x-coordinate

LDA QQ0                ; Set QQ19 = 31 + QQ9 - (QQ9 / 4)
LSR A                  ;          = 31 + 0.75 * QQ9
LSR A                  ;
STA T1                 ; So this scales the x-coordinate from a range of 0 to
LDA QQ0                ; 255 into a range from 31 to 222, so it fits nicely
SEC                    ; into the Long-range Chart
SBC T1
CLC
STA QQ19

LDA QQ1                ; Set QQ19+1 = 8 + (QQ10 - (QQ10 / 4)) / 2
LSR A                  ;            = 8 + 0.375 * QQ10
LSR A                  ;
STA T1                 ; So this scales the y-coordinate from a range of 0 to
LDA QQ1                ; 255 into a range from 8 to 127, so it fits nicely
SEC                    ; into the Long-range Chart
SBC T1
LSR A
CLC
STA QQ19+1

LDA #7                 ; Set QQ19+2 = 7, the size of the crosshairs on the
STA QQ19+2             ; Long-range Chart

JSR TT15               ; Draw the set of crosshairs defined in QQ19, which will
; be drawn 24 pixels to the right of QQ19+1

LDA QQ19+1             ; Add 24 to the y-coordinate of the crosshairs in QQ19+1
CLC                    ; so that the centre of the circle matches the centre
ADC #24                ; of the crosshairs
STA QQ19+1

; Fall through into TT128 to draw a circle with the
; centre at the same coordinates as the crosshairs,
; (QQ19, QQ19+1), and radius K that reflects the
; current fuel levels

Type: Subroutine
Category: Drawing circles
Summary: Draw a circle on a chart
Deep dive: Drawing circles
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT14 calls TT128

Draw a circle with the centre at (QQ19, QQ19+1) and radius K.

Arguments:

QQ19                 The x-coordinate of the centre of the circle

QQ19+1               The y-coordinate of the centre of the circle

K                    The radius of the circle

.TT128

LDA QQ19               ; Set K3 = the x-coordinate of the centre
STA K3

LDA QQ19+1             ; Set K4 = the y-coordinate of the centre
STA K4

LDX #0                 ; Set the high bytes of K3(1 0) and K4(1 0) to 0
STX K4+1
STX K3+1

LDX #2                 ; Set STP = 2, the step size for the circle
STX STP

LDX #1                 ; Set the high byte of the pattern buffer address
JSR SetPatternBuffer   ; variables to that of pattern buffer 1, so the circle
; gets drawn into bitplane 1 only, giving a circle of
; colour %10 (2), which is green

JMP CIRCLE2_b1         ; Jump to CIRCLE2 to draw a circle with the centre at
; (K3(1 0), K4(1 0)) and radius K, returning from the
; subroutine using a tail call

Type: Subroutine
Category: Market
Summary: Show a list of current cargo in our hold, optionally to sell
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT213 calls TT210

Show a list of current cargo in our hold, either with the ability to sell (the
Sell Cargo screen) or without (the Inventory screen), depending on the current
view.

Arguments:

QQ11                 The current view:

* 4 = Sell Cargo

* 8 = Inventory

.TT210

LDY #0                 ; We're going to loop through all the available market
; items and check whether we have any in the hold (and,
; if we are in the Sell Cargo screen, whether we want
; to sell any items), so we set up a counter in Y to
; denote the current item and start it at 0

.TT211

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

STY QQ29               ; Store the current item number in QQ29

LDX QQ20,Y             ; Fetch into X the amount of the current item that we
BEQ TT212              ; have in our cargo hold, which is stored in QQ20+Y,
; and if there are no items of this type in the hold,

TYA                    ; Set Y = Y * 4, so this will act as an index into the
ASL A                  ; market prices table at QQ23 for this item (as there
ASL A                  ; are four bytes per item in the table)
TAY

LDA QQ23+1,Y           ; Fetch byte #1 from the market prices table for the
STA QQ19+1             ; current item and store it in QQ19+1, for use by the
; call to TT152 below

TXA                    ; Store the amount of item in the hold (in X) on the
PHA                    ; stack

JSR TT69               ; Call TT69 to set Sentence Case and print a newline

CLC                    ; Print recursive token 48 + QQ29, which will be in the
LDA QQ29               ; range 48 ("FOOD") to 64 ("ALIEN ITEMS"), so this
ADC #208               ; prints the current item's name
JSR TT27_b2

LDA #14                ; Move the text cursor to column 14, for the item's
STA XC                 ; quantity

PLA                    ; Restore the amount of item in the hold into X
TAX

STA QQ25               ; Store the amount of this item in the hold in QQ25

CLC                    ; Print the 8-bit number in X to 3 digits, without a
JSR pr2                ; decimal point

JSR TT152              ; Print the unit ("t", "kg" or "g") for the market item
; whose byte #1 from the market prices table is in
; QQ19+1 (which we set up above)

.TT212

LDY QQ29               ; Fetch the item number from QQ29 into Y, and increment
INY                    ; Y to point to the next item

CPY #17                ; Loop back to TT211 to print the next item in the hold
BCC TT211              ; until Y = 17 (at which point we have done the last
; item)

JSR TT69               ; Call TT69 to set Sentence Case and print a newline

LDA TRIBBLE            ; If there are any Trumbles in the hold, skip the
ORA TRIBBLE+1          ; following RTS and continue on (in the Master version,
BNE P%+5               ; there are never any Trumbles, so this value will
; always be zero)

.zebra

JMP UpdateViewWithFade ; There are no Trumbles in the hold, so update the view,
; fading the screen to black first if required, and
; return from the subroutine using a tail call

; If we get here then we have Trumbles in the hold, so
; we print out the number of Trumbles and a random

CLC                    ; Clear the C flag, so the call to TT11 below doesn't
; include a decimal point

LDA #0                 ; Set A = 0, for the call to TT11 below, so we don't pad
; out the number of Trumbles

LDX TRIBBLE            ; Fetch the number of Trumbles into (Y X)
LDY TRIBBLE+1

JSR TT11               ; Call TT11 to print the number of Trumbles in (Y X),
; with no decimal point

LDA languageNumber     ; If bit 2 of languageNumber is set then the chosen
AND #%00000100         ; language is French, so jump to carg1 to skip printing
BNE carg1              ; the Trumble adjectives

JSR DORND              ; Print out a random extended token from 111 to 114,
AND #3                 ; (" CUDDLY", " CUTE", " FURRY" or " FRIENDLY")
CLC
JSR DETOK_b2

LDA languageNumber     ; If bit 1 of languageNumber is clear then the chosen
AND #%00000010         ; language is not German, so jump to carg1 to skip the
BEQ carg1              ; following

LDA TRIBBLE            ; If the number of Trumbles in TRIBBLE(1 0) is more than
ORA TRIBBLE+1
BEQ carg1

LDA #'e'               ; Print an 'e' to pluralise the adjective in German
JSR DASC_b2

.carg1

LDA #198               ; Print extended token 198 (" LITTLE {single
JSR DETOK_b2           ; cap}SQUEAKY"

LDA TRIBBLE+1          ; If we have more than 256 Trumbles, skip to DOANS
BNE DOANS

LDX TRIBBLE            ; If we have exactly one Trumble, jump up to zebra
DEX
BEQ zebra

.DOANS

LDA #'s'               ; We have more than one Trumble, so print an 's' and
JSR DASC_b2            ; jump up to zebra
JMP zebra

Type: Subroutine
Category: Market
Summary: Show the Inventory screen
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* RedrawCurrentView calls TT213
* TT102 calls TT213
* TT167 calls TT213

.TT213

LDA #\$97               ; Clear the screen and set the view type in QQ11 to \$97
JSR SetNewViewType     ; (Inventory)

LDA #11                ; Move the text cursor to column 11 to print the screen
STA XC                 ; title

LDA #164               ; Print recursive token 4 ("INVENTORY{crlf}") followed
JSR TT60               ; by a paragraph break and Sentence Case

JSR NLIN4              ; Draw a horizontal line on tile row 2 to box in the
; title

JSR fwl                ; Call fwl to print the fuel and cash levels on two
; separate lines

LDA CRGO               ; If our ship's cargo capacity is < 26 (i.e. we do not
CMP #26                ; have a cargo bay extension), jump to inve1 to skip the
BCC inve1              ; following

LDA #12                ; Print a newline
JSR TT27_b2

LDA #107               ; We do have a cargo bay extension, so print recursive
JSR TT27_b2            ; token 107 ("LARGE CARGO{sentence case} BAY")

JMP TT210              ; Jump to TT210 to print the contents of our cargo bay
; and return from the subroutine using a tail call

.inve1

JSR TT67               ; Print a newline

JMP TT210              ; Jump to TT210 to print the contents of our cargo bay
; and return from the subroutine using a tail call

Type: Subroutine
Category: Text
Summary: An unused routine that prints a character and sets the C flag
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

.PrintCharacter

JSR DASC_b2            ; Print the character in A

SEC                    ; Set the C flag

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Charts
Summary: Move the crosshairs on a chart
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls TT16

Move the chart crosshairs by the amount in X and Y.

Arguments:

X                    The amount to move the crosshairs in the x-axis

Y                    The amount to move the crosshairs in the y-axis

.cros1

; the chart that shows the current system, returning
; from the subroutine using a tail call

.TT16

LDA controller1B       ; If the B button is being pressed, jump to cros1 to
BMI cros1              ; return from the subroutine, as the arrow buttons have
; a different meaning when the B button is held down

LDA controller1Left03  ; If none of the directional buttons have been held down
ORA controller1Right03 ; in the last four VBlanks, jump to cros1 to return from
ORA controller1Up      ; the subroutine, as we don't need to move the
ORA controller1Down    ; crosshairs
AND #%11110000
BEQ cros1

TXA                    ; Push the change in X onto the stack (let's call this
PHA                    ; the x-delta)

BNE mvcr1              ; If the x-delta is non-zero, jump to mvcr1 to update
; the icon bar if required

TYA                    ; If the y-delta is zero, then the crosshairs are not
BEQ mvcr2              ; moving, so jump to mvcr2 to skip the following,
; otherwise keep going to update the icon bar if
; required

.mvcr1

; If we get here then the crosshairs are on the move

LDX #%00000000         ; Set X to use as the new value of selectedSystemFlag
; below

LDA selectedSystemFlag ; Set A to the value of selectedSystemFlag

STX selectedSystemFlag ; Clear bits 6 and 7 of selectedSystemFlag to indicate
; that there is no currently selected system

ASL A                  ; If bit 6 of selectedSystemFlag was previously clear,
BPL mvcr2              ; then before the crosshairs moved we weren't locked
; onto a system that we could hyperspace to, so the
; Hyperspace button wouldn't have been showing on the
; icon bar, so jump to mvcr2 to skip the following as
; we don't need to update the icon bar

TYA                    ; Update the icon bar to remove the hyperspace button
PHA                    ; now that the crosshairs are no longer pointing to
JSR UpdateIconBar_b3   ; that system, preserving Y across the subroutine call
PLA
TAY

.mvcr2

DEY                    ; Negate the change in Y and push it onto the stack
TYA                    ; (let's call this the y-delta)
EOR #\$FF
PHA

LDA QQ11               ; If the view type in QQ11 is \$9C (Short-range Chart),
BEQ hair1

; This is not the Short-range Chart, so it must be the
; Long-range Chart, so we double the x-delta and y-delta
; so the crosshairs move twice as fast

PLA                    ; Set X to the y-delta from the top of the stack
TAX

PLA                    ; Fetch the x-delta from the top of the stack, double it
ASL A                  ; and put it back
PHA

TXA                    ; Double the y-delta value in X and put it back on the
ASL A                  ; stack
PHA

.hair1

JSR WaitForNMI         ; Wait until the next NMI interrupt has passed (i.e. the
; next VBlank)

PLA                    ; Store the y-delta in QQ19+3 and fetch the current
STA QQ19+3             ; y-coordinate of the crosshairs from QQ10 into A, ready
LDA QQ10               ; for the call to TT123

JSR TT123              ; Call TT123 to move the selected system's galactic
; y-coordinate by the y-delta, putting the new value in
; QQ19+4

LDA QQ19+4             ; Store the updated y-coordinate in QQ10 (the current
STA QQ10               ; y-coordinate of the crosshairs)

STA QQ19+1             ; This instruction has no effect, as QQ19+1 is
; overwritten below, both in TT103 and TT105

PLA                    ; Store the x-delta in QQ19+3 and fetch the current
STA QQ19+3             ; x-coordinate of the crosshairs from QQ10 into A, ready
LDA QQ9                ; for the call to TT123

JSR TT123              ; Call TT123 to move the selected system's galactic
; x-coordinate by the x-delta, putting the new value in
; QQ19+4

LDA QQ19+4             ; Store the updated x-coordinate in QQ9 (the current
STA QQ9                ; x-coordinate of the crosshairs)

STA QQ19               ; This instruction has no effect, as QQ19 is overwritten
; below, both in TT103 and TT105

; Now we've updated the coordinates of the crosshairs,
; fall through into TT103 to redraw them at their new
; location

Type: Subroutine
Category: Charts
Summary: Draw a small set of crosshairs on a chart
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* SetSelectedSystem calls TT103
* TT22 calls TT103
* TT23 calls TT103

Draw a small set of crosshairs on a galactic chart at the coordinates in
(QQ9, QQ10).

This routine does a similar job to the routine of the same name in the BBC
Master version of Elite, but the code is significantly different.

.TT103

LDA QQ11               ; Fetch the current view type into A

CMP #\$9C               ; If the view type in QQ11 is \$9C (Short-range Chart),
BEQ TT105              ; jump to TT105 to draw the correct crosshairs for that
; chart

; We now set the pixel coordinates of the crosshairs in
; QQ9 and QQ9+1 so they fit into the chart, with a
; 31-pixel margin on the left and a 32-pixel margin at
; the top, for the chart title
;
; The Long-range Chart is twice as wide as it is high,
; so we need to scale the y-coordinate in QQ19+1 by an
; extra division by 2 when compared to the x-coordinate

LDA QQ9                ; Set QQ19 = 31 + QQ9 - (QQ9 / 4)
LSR A                  ;          = 31 + 0.75 * QQ9
LSR A                  ;
STA T1                 ; So this scales the x-coordinate from a range of 0 to
LDA QQ9                ; 255 into a range from 31 to 222, so it fits nicely
SEC                    ; into the Long-range Chart
SBC T1
CLC
STA QQ19

LDA QQ10               ; Set QQ19+1 = 32 + (QQ10 - (QQ10 / 4)) / 2
LSR A                  ;            = 32 + 0.375 * QQ10
LSR A                  ;
STA T1                 ; So this scales the y-coordinate from a range of 0 to
LDA QQ10               ; 255 into a range from 8 to 127, so it fits nicely
SEC                    ; into the Long-range Chart
SBC T1
LSR A
CLC
STA QQ19+1

LDA #4                 ; Set QQ19+2 to 4 denote crosshairs of size 4 (though
STA QQ19+2             ; this is ignored by DrawCrosshairs, which always draws
; the crosshairs as a single-tile square reticle)

JMP DrawCrosshairs     ; Jump to TT15 to draw a square reticle at the
; crosshairs coordinates, returning from the
; subroutine using a tail call

Type: Subroutine
Category: Charts
Summary: Move galactic coordinates by a signed delta
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT16 calls TT123

Move an 8-bit galactic coordinate by a certain distance in either direction
(i.e. a signed 8-bit delta), but only if it doesn't cause the coordinate to
overflow. The coordinate is in a single axis, so it's either an x-coordinate
or a y-coordinate.

Arguments:

A                    The galactic coordinate to update

QQ19+3               The delta (can be positive or negative)

Returns:

QQ19+4               The updated coordinate after moving by the delta (this
will be 1 or 255 if moving by the delta underflows or
overflows)

Other entry points:

TT180                Contains an RTS

.TT123

CLC                    ; Set A = A + QQ19+3, so A now contains the original
ADC QQ19+3             ; coordinate, moved by the delta

BMI TT124

BCC TT125              ; If the C flag is clear, then the above addition didn't

LDA #255               ; Otherwise set A to 255 and jump to TT125 to return
BNE TT125              ; this as the updated value

.TT124

BCS TT125              ; If the C flag is set, then because the delta is
; negative, this indicates the addition (which is
; effectively a subtraction) didn't underflow, so jump
; to TT125 to return this as the updated value

LDA #1                 ; The subtraction underflowed, so set A to 1 to return
; as the updated value

.TT125

STA QQ19+4             ; Store the updated coordinate in QQ19+4

.TT180

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Charts
Summary: Draw crosshairs on the Short-range Chart, with clipping
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT103 calls TT105

Check whether the crosshairs are close enough to the current system to appear
on the Short-range Chart, and if so, draw them.

.TT105

LDA QQ9                ; Set A = QQ9 - QQ0, the horizontal distance between the
SEC                    ; crosshairs (QQ9) and the current system (QQ0)
SBC QQ0

CMP #36                ; If the horizontal distance in A < 36, then the
BCC TT179              ; crosshairs are close enough to the current system to
; check the vertical distance

CMP #233               ; If the horizontal distance in A < -23, then the
BCC HideCrosshairs     ; crosshairs are too far from the current system to
; HideCrosshairs to hide the crosshairs and return from
; the subroutine using a tail call

.TT179

ASL A                  ; Set QQ19 = 104 + A * 4
ASL A                  ;
CLC                    ; 104 is the x-coordinate of the centre of the chart,
ADC #104               ; so this sets QQ19 to the screen pixel x-coordinate
STA QQ19               ; of the crosshairs

LDA QQ10               ; Set A = QQ10 - QQ1, the vertical distance between the
SEC                    ; crosshairs (QQ10) and the current system (QQ1)
SBC QQ1

CMP #38                ; If the vertical distance in A is < 38, then the
BCC P%+6               ; crosshairs are close enough to the current system to
; appear in the Short-range Chart, so skip the next two
; instructions

CMP #220               ; If the horizontal distance in A is < -36, then the
BCC HideCrosshairs     ; crosshairs are too far from the current system to
; HideCrosshairs to hide the crosshairs and return from
; the subroutine using a tail call

ASL A                  ; Set QQ19+1 = 90 + A * 2
CLC                    ;
ADC #90                ; 90 is the y-coordinate of the centre of the chart,
STA QQ19+1             ; so this sets QQ19+1 to the screen pixel x-coordinate
; of the crosshairs

LDA #8                 ; Set QQ19+2 to 8 denote crosshairs of size 8
STA QQ19+2

; Fall through into DrawCrosshairs to draw crosshairs of
; size 8 at the crosshairs coordinates

Type: Subroutine
Category: Charts
Summary: Draw a set of moveable crosshairs as a square reticle
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT103 calls DrawCrosshairs

Arguments:

QQ19                 The pixel x-coordinate of the centre of the crosshairs

QQ19+1               The pixel y-coordinate of the centre of the crosshairs

.DrawCrosshairs

LDA #248               ; Set the pattern number for sprite 15 to 248, which
STA pattSprite15       ; contains a one-tile square outline that we can use as
; a square reticle to implement crosshairs on the chart

LDA #%00000001         ; Set the attributes for sprite 15 as follows:
STA attrSprite15       ;
;   * Bits 0-1    = sprite palette 1
;   * Bit 5 clear = show in front of background
;   * Bit 6 clear = do not flip horizontally
;   * Bit 7 clear = do not flip vertically

LDA QQ19               ; Set SC2 to the pixel x-coordinate of the centre of the
STA SC2                ; crosshairs

LDY QQ19+1             ; Set Y to the pixel y-coordinate of the centre of the
; crosshairs

LDA #15                ; Set X = 15 * 4, so X is the index of sprite 15 within
ASL A                  ; the sprite buffer, as each sprite takes up four bytes
ASL A                  ; (in other words, xSprite0 + X and ySprite0 + X are the
TAX                    ; addresses of the x- and y-coordinates of sprite 15 in
; the sprite buffer)

LDA SC2                ; Set the pixel x-coordinate of sprite 15 to SC2 - 4
SEC                    ;
SBC #4                 ; So the centre of the square reticle in sprite 15 is at
STA xSprite0,X         ; x-coordinate SC2, as the reticle is eight pixels wide

TYA                    ; Set the pixel y-coordinate of sprite 15 to Y + 10
CLC                    ;
ADC #10+YPAL           ; So the reticle is drawn 10 pixels below the coordinate
STA ySprite0,X         ; in the QQ19+1 argument (this takes the 14-pixel high
; chart title into consideration, and ensures that the
; centre of the reticle is over the correct coordinates
; as the sprite is eight pixels high)

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Charts
Summary: Hide the moveable crosshairs (i.e. the square reticle)
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT105 calls HideCrosshairs

.HideCrosshairs

LDA #240               ; Set the y-coordinate of sprite 15 to 240, so it is
STA ySprite15          ; below the bottom of the screen and is therefore hidden

RTS                    ; Return from the subroutine

Type: Variable
Category: Charts
Summary: The text column for the Short-range Chart title for each language
Deep dive: Multi-language support in NES Elite
Context: See this variable on its own page
References: This variable is used as follows:
* TT23 uses xShortRange

.xShortRange

EQUB 7                 ; English

EQUB 8                 ; German

EQUB 10                ; French

EQUB 8                 ; There is no fourth language, so this byte is ignored

Type: Subroutine
Category: Charts
Summary: Show the Short-range Chart
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* RedrawCurrentView calls TT23
* TT102 calls TT23
* TT114 calls TT23

.TT23

LDA #0                 ; Set systemsOnChart = 0 so we can use it to count the
STA systemsOnChart     ; systems as we add them to the chart

LDA #199               ; Set the number of pixel rows in the space view to 199,
STA Yx2M1              ; to cover the size of the chart part of the Short-range
; Chart view

LDA #\$9C               ; Clear the screen and set the view type in QQ11 to \$9C
JSR TT66               ; (Short-range Chart)

LDX languageIndex      ; Move the text cursor to the correct column for the
LDA xShortRange,X      ; Short-range Chart title in the chosen language
STA XC

LDA #190               ; Print recursive token 30 ("SHORT RANGE CHART") on the
JSR NLIN3              ; top row

JSR SetScreenForUpdate ; Get the screen ready for updating by hiding all
; sprites, after fading the screen to black if we are
; changing view

JSR TT14               ; Call TT14 to draw a circle with crosshairs at the
; current system's galactic coordinates

JSR TT103              ; Draw small crosshairs at coordinates (QQ9, QQ10),
; i.e. at the selected system

JSR TT81               ; Set the seeds in QQ15 to those of system 0 in the
; current galaxy (i.e. copy the seeds from QQ21 to QQ15)

LDA #0                 ; Set A = 0, which we'll use below to zero out the INWK
; workspace

STA XX20               ; We're about to start working our way through each of
; the galaxy's systems, so set up a counter in XX20 for
; each system, starting at 0 and looping through to 255

LDX #24                ; First, though, we need to zero out the 25 bytes at
; INWK so we can use them to work out which systems have
; room for a label, so set a counter in X for 25 bytes

.EE3

STA INWK,X             ; Set the X-th byte of INWK to zero

DEX                    ; Decrement the counter

BPL EE3                ; Loop back to EE3 for the next byte until we've zeroed
; all 25 bytes

; We now loop through every single system in the galaxy
; and check the distance from the current system whose
; coordinates are in (QQ0, QQ1). We get the galactic
; coordinates of each system from the system's seeds,
; like this:
;
;   x = s1_hi (which is stored in QQ15+3)
;   y = s0_hi (which is stored in QQ15+1)
;
; so the following loops through each system in the
; galaxy in turn and calculates the distance between
; (QQ0, QQ1) and (s1_hi, s0_hi) to find the closest one

.TT182

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

LDA QQ15+3             ; Set A = s1_hi - QQ0, the horizontal distance between
SEC                    ; (s1_hi, s0_hi) and (QQ0, QQ1)
SBC QQ0

BCS TT184              ; If a borrow didn't occur, i.e. s1_hi >= QQ0, then the
; following two instructions

EOR #\$FF               ; Otherwise negate the result in A, so A is always
ADC #1                 ; positive (i.e. A = |s1_hi - QQ0|)

.TT184

CMP #20                ; If the horizontal distance in A is >= 20, then this
BCS TT187              ; system is too far away from the current system to
; move on to the next system

LDA QQ15+1             ; Set A = s0_hi - QQ1, the vertical distance between
SEC                    ; (s1_hi, s0_hi) and (QQ0, QQ1)
SBC QQ1

BCS TT186              ; If a borrow didn't occur, i.e. s0_hi >= QQ1, then the
; following two instructions

EOR #\$FF               ; Otherwise negate the result in A, so A is always
ADC #1                 ; positive (i.e. A = |s0_hi - QQ1|)

.TT186

CMP #38                ; If the vertical distance in A is >= 38, then this
BCS TT187              ; system is too far away from the current system to
; move on to the next system

; This system should be shown on the Short-range Chart,
; so now we need to work out where the label should go,
; and set up the various variables we need to draw the
; system's filled circle on the chart

LDA QQ15+3             ; Set A = s1_hi - QQ0, the horizontal distance between
SEC                    ; this system and the current system, where |A| < 20.
SBC QQ0                ; Let's call this the x-delta, as it's the horizontal
; difference between the current system at the centre of
; the chart, and this system (and this time we keep the
; sign of A, so it can be negative if it's to the left
; of the chart's centre, or positive if it's to the
; right)

ASL A                  ; Set XX12 = 104 + x-delta * 4
ASL A                  ;
ADC #104               ; 104 is the x-coordinate of the centre of the chart,
STA XX12               ; so this sets XX12 to the centre 104 +/- 76, the pixel
; x-coordinate of this system

LSR A                  ; Move the text cursor to column x-delta / 2 + 1
LSR A                  ; which will be in the range 1-10
LSR A
CLC
STA XC

LDA QQ15+1             ; Set A = s0_hi - QQ1, the vertical distance between
SEC                    ; this system and the current system, where |A| < 38.
SBC QQ1                ; Let's call this the y-delta, as it's the vertical
; difference between the current system at the centre of
; the chart, and this system (and this time we keep the
; sign of A, so it can be negative if it's above the
; chart's centre, or positive if it's below)

ASL A                  ; Set K4 = 90 + y-delta * 2
STA K4                 ; 90 is the y-coordinate of the centre of the chart,
; so this sets K4 to the centre 90 +/- 74, the pixel
; y-coordinate of this system

LSR A                  ; Set Y = K4 / 8, so Y contains the number of the text
LSR A                  ; row that contains this system
LSR A
TAY

; Now to see if there is room for this system's label.
; Ideally we would print the system name on the same
; text row as the system, but we only want to print one
; label per row, to prevent overlap, so now we check
; this system's row, and if that's already occupied,
; the row above, and if that's already occupied, the
; row below... and if that's already occupied, we give
; up and don't print a label for this system

LDX INWK,Y             ; If the value in INWK+Y is 0 (i.e. the text row
BEQ EE4                ; containing this system does not already have another
; system's label on this row

INY                    ; If the value in INWK+Y+1 is 0 (i.e. the text row below
LDX INWK,Y             ; the one containing this system does not already have
BEQ EE4                ; another system's label on it), jump to EE4 to store
; this system's label on this row

DEY                    ; If the value in INWK+Y-1 is 0 (i.e. the text row above
DEY                    ; the one containing this system does not already have
LDX INWK,Y             ; another system's label on it), fall through into to
BNE ee1                ; EE4 to store this system's label on this row,
; this system (as there simply isn't room)

.EE4

TYA                    ; Now to print the label, so move the text cursor to row
STA YC                 ; Y (which contains the row where we can print this
; system's label)

CPY #3                 ; If Y < 3, then the system would clash with the chart
BCC TT187              ; title, so jump to TT187 to skip showing the system

LDA #\$FF               ; Store \$FF in INWK+Y, to denote that this row is now
STA INWK,Y             ; occupied so we don't try to print another system's
; label on this row

LDA #%10000000         ; Set bit 7 of QQ17 to switch to Sentence Case
STA QQ17

JSR cpl                ; Call cpl to print out the system name for the seeds
; in QQ15 (which now contains the seeds for the current
; system)

.ee1

LDA #0                 ; Now to plot the star, so set the high bytes of K, K3
STA K3+1               ; and K4 to 0
STA K4+1
STA K+1

LDA XX12               ; Set the low byte of K3 to XX12, the pixel x-coordinate
STA K3                 ; of this system

LDA QQ15+5             ; Fetch s2_hi for this system from QQ15+5, extract bit 0
AND #1                 ; and add 2 to get the size of the star, which we store
ADC #2                 ; in K. This will be either 2, 3 or 4, depending on the
STA K                  ; value of bit 0, and whether the C flag is set (which
; will vary depending on what happens in the above call
; to cpl). Incidentally, the planet's average radius
; also uses s2_hi, bits 0-3 to be precise, but that
; doesn't mean the two sizes affect each other

; We now have the following:
;
;   K(1 0)  = radius of star (2, 3 or 4)
;
;   K3(1 0) = pixel x-coordinate of system
;
;   K4(1 0) = pixel y-coordinate of system
;
; which we can now pass to the DrawChartSystem routine
; to draw a system on the Short-range Chart

JSR DrawChartSystem    ; Draw the system on the chart

.TT187

JSR TT20               ; We want to move on to the next system, so call TT20
; to twist the three 16-bit seeds in QQ15

INC XX20               ; Increment the counter

BEQ P%+5               ; If X = 0 then we have done all 256 systems, so skip
; the next instruction to return from the subroutine

JMP TT182              ; Otherwise jump back up to TT182 to process the next
; system

LDA #143               ; Set the number of pixel rows in the space view to 143,
STA Yx2M1              ; so the screen height is correctly set for the
; Long-range Chart in case we switch to it using the
; icon in the icon bar (which toggles between the two
; charts)

JMP UpdateView         ; Update the view, returning from the subroutine using
; a tail call

Type: Subroutine
Category: Charts
Summary: Draw system blobs on short-range chart
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT23 calls DrawChartSystem

Arguments:

K(1 0)               Radius of star (2, 3 or 4)

K3(1 0)              Pixel x-coordinate of system

K4(1 0)              Pixel y-coordinate of system

.DrawChartSystem

LDY systemsOnChart     ; Set Y to the number of this system on the chart

CPY #24                ; If systemsOnChart >= 24 then we have already drawn the
BCS csys1              ; maximum number of systems on the chart, so jump to
; csys1 to return from the subroutine

INY                    ; Otherwise increment systemsOnChart as we are about to
STY systemsOnChart     ; draw a system on the chart

TYA                    ; Set Y = Y * 4
ASL A
ASL A
TAY

LDA K3                 ; Set the x-coordinate of sprite 38 + Y to K3 - 2
SBC #3                 ;
STA xSprite38,Y        ; The SBC #3 subtracts 2 because we know the C flag is
; clear at this point
;
; Y is 1 for the first system on the chart, so this sets
; the x-coordinate of sprite 39 onwards, and we subtract
; 2 because the star sprites have a margin of at least
; two pixels along the left edge, so this aligns the
; star part of the sprite to the x-coordinate

LDA K4                 ; Set the y-coordinate of sprite 38 + Y to K4 + 10
CLC                    ;
ADC #10+YPAL           ; This sets the y-coordinate of sprite 39 onwards, and
STA ySprite38,Y        ; the 10 pixels are added to push the star sprite below
; the level of the text label, so the star appears to
; the bottom-left of the text

LDA #213               ; Set the pattern to 213 + K
CLC                    ;
ADC K                  ; The patterns for the three star sizes on the chart are
STA pattSprite38,Y     ; in patterns 215 to 217, going from small to large, so
; this sets the sprite to the correct star size in K as
; K is in the range 2 to 4

LDA #%00000010         ; Set the attributes for this sprite as follows:
STA attrSprite38,Y     ;
;   * Bits 0-1    = sprite palette 2
;   * Bit 5 clear = show in front of background
;   * Bit 6 clear = do not flip horizontally
;   * Bit 7 clear = do not flip vertically

.csys1

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Universe
Summary: Set the selected system's seeds to those of system 0
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* HME2 calls TT81
* TT111 calls TT81
* TT22 calls TT81
* TT23 calls TT81

Copy the three 16-bit seeds for the current galaxy's system 0 (QQ21) into the
seeds for the selected system (QQ15) - in other words, set the selected
system's seeds to those of system 0.

.TT81

LDX #5                 ; Set up a counter in X to copy six bytes (for three
; 16-bit numbers)

LDA QQ21,X             ; Copy the X-th byte in QQ21 to the X-th byte in QQ15
STA QQ15,X

DEX                    ; Decrement the counter

BPL TT81+2             ; Loop back up to the LDA instruction if we still have
; more bytes to copy

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Universe
Summary: Set the current system to the nearest system and update the
selected system flags accordingly
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MJP calls SelectNearbySystem
* TT102 calls SelectNearbySystem

.SelectNearbySystem

JSR TT111              ; Select the system closest to galactic coordinates
; (QQ9, QQ10)

; flags for the new system and update the icon bar if
; required

Type: Subroutine
Category: Universe
Summary: Set the selected system to the nearest system, if we don't already
have a selected system
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* STATUS calls SetSelectedSystem
* TT102 calls SetSelectedSystem
* TT16 calls SetSelectedSystem

.SetSelectedSystem

LDA selectedSystemFlag ; If bit 7 of selectedSystemFlag is set, then we already
; to ensure we keep using this system as our selected
; system, returning from the subroutine using a tail
; call

; If we get here then we do not already have a selected
; system, so now we set it up

JSR TT111              ; Select the system closest to galactic coordinates
; (QQ9, QQ10)

LDA QQ11               ; If the view in QQ11 is not %0000110x (i.e. 12 or 13,
AND #%00001110         ; which are the Short-range Chart and Long-range Chart),
CMP #%00001100         ; jump to pchm1 to skip the following as we don't need
BNE pchm1              ; to update the message on the chart view

JSR TT103              ; Draw small crosshairs at coordinates (QQ9, QQ10),
; which will draw the crosshairs at our current home
; system

LDA #0                 ; Set QQ17 = 0 to switch to ALL CAPS
STA QQ17

JSR CLYNS              ; Clear the bottom two text rows of the upper screen,
; and move the text cursor to column 1 on row 21, i.e.
; the start of the top row of the two bottom rows

JSR cpl                ; Call cpl to print out the system name for the seeds
; in QQ15

LDA #%10000000         ; Set bit 7 of QQ17 to switch standard tokens to
STA QQ17               ; Sentence Case

LDA #12                ; Print a newline
JSR DASC_b2

JSR TT146              ; If the distance to this system is non-zero, print
; "DISTANCE", then the distance, "LIGHT YEARS" and a
; paragraph break, otherwise just move the cursor down
; a line

JSR DrawMessageInNMI   ; Configure the NMI to display the updated message that
; we just printed, showing the current system name and
; distance

.pchm1

; Fall through into SetSelectionFlags to set the
; selected system flags for the new system

Type: Subroutine
Category: Universe
Summary: Set the selected system flags for the currently selected system
and update the icon bar if required
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* Main flight loop (Part 15 of 16) calls SetSelectionFlags
* SelectNearbySystem calls SetSelectionFlags

.SetSelectionFlags

LDA QQ8+1              ; If the high byte of the distance to the selected
BNE ssel3              ; system in QQ18(1 0) is non-zero, then it is a long way
; from us, so jump to ssel3 to set the selected system
; flags to indicate we can't hyperspace there

LDA QQ8                ; If the low byte of the distance to the selected
BNE ssel1              ; system in QQ18(1 0) is non-zero, then jump to ssel1
; to check whether we have enough fuel to hyperspace
; there

; If we get here then QQ18(1 0) is zero, so the selected
; system is the same as the current system

LDA MJ                 ; If MJ is zero then we are not in witchspace, so jump
BEQ ssel3              ; to ssel3 to set the selected system flags to indicate
; we can't hyperspace to the selected system (as it is
; the same as the current system)

BNE ssel2              ; MJ is non-zero so we are in witchspace, so jump to
; ssel2 to set the selected system flags to indicate we
; can hyperspace to the selected system (as we are in
; the middle of nowhere without a current system)

.ssel1

CMP QQ14               ; If the distance to the selected system is equal to the
BEQ ssel2              ; fuel level in QQ14, jump to ssel2 to set the selected
; system flags to indicate we can hyperspace to the
; selected system

BCS ssel3              ; If the distance to the selected system is greater than
; the fuel level in QQ14, jump to ssel3 to set the
; selected system flags to indicate we can't hyperspace
; to the selected system (as we don't have enough fuel)

; If we get here then the distance to the selected
; system is less than the fuel level in QQ14, so fall
; through into ssel2 to set the selected system flags to
; indicate we can hyperspace to the selected system

.ssel2

LDA #%11000000         ; Set A so we set bits 6 and 7 of the selected system
; flags below to indicate that a system is selected and
; we can hyperspace to it

BNE ssel4              ; Jump to ssel4 to skip the following instruction (this
; BNE is effectively a JMP as A is never zero)

.ssel3

LDA #%10000000         ; Set A so we set bit 7 and clear bit 6 of the selected
; system flags below to indicate that a system is
; selected but we can't hyperspace to it

.ssel4

TAX                    ; Copy A into X so we can set selectedSystemFlag to this
; value below

EOR selectedSystemFlag ; Flip bit 7 and possibly bit 6 in selectedSystemFlag
; and keep the result in A

STX selectedSystemFlag ; Set selectedSystemFlag to X

ASL A                  ; If bit 6 of the EOR result in A is clear, then the
BPL RTS6               ; state of bit 6 did not changed in the update above, so
; we don't need to update the icon bar to show or hide
; the hyperspace button, so return from the subroutine
; (as RTS6 contains an RTS)

JMP UpdateIconBar_b3   ; Otherwise the newly selected system has a different
; "can we hyperspace here?" status to the previous
; selected system, so we need to update the icon bar to
; either hide or show the Hyperspace button, returning
; from the subroutine using a tail call

Type: Subroutine
Category: Universe
Summary: Set the seeds for the selected system to the system that we last
snapped the crosshairs to
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* SetSelectedSystem calls SetCurrentSystem
* SetSelectionFlags calls via RTS6

Other entry points:

RTS6                 Contains an RTS

.SetCurrentSystem

LDX #5                 ; Set up a counter in X to copy six bytes (for three
; 16-bit numbers)

.ssys1

LDA selectedSystem,X   ; Copy the X-th byte in selectedSystem to the X-th byte
STA QQ15,X             ; in QQ15, to set the selected system to the previous
; system that we snapped the crosshairs to

DEX                    ; Decrement the counter

BPL ssys1              ; Loop back until we have copied all six seeds

.RTS6

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Universe
Summary: Set the current system to the nearest system to a point
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* BR1 calls TT111
* Ghy calls TT111
* HME2 calls TT111
* SelectNearbySystem calls TT111
* SetSelectedSystem calls TT111
* TT25 calls TT111

Given a set of galactic coordinates in (QQ9, QQ10), find the nearest system
to this point in the galaxy, and set this as the currently selected system.

Arguments:

QQ9                  The x-coordinate near which we want to find a system

QQ10                 The y-coordinate near which we want to find a system

Returns:

QQ8(1 0)             The distance from the current system to the nearest
system to the original coordinates

QQ9                  The x-coordinate of the nearest system to the original
coordinates

QQ10                 The y-coordinate of the nearest system to the original
coordinates

QQ15 to QQ15+5       The three 16-bit seeds of the nearest system to the
original coordinates

systemNumber         The system number of the nearest system

Other entry points:

TT111-1              Contains an RTS

.TT111

JSR TT81               ; Set the seeds in QQ15 to those of system 0 in the
; current galaxy (i.e. copy the seeds from QQ21 to QQ15)

; We now loop through every single system in the galaxy
; and check the distance from (QQ9, QQ10). We get the
; galactic coordinates of each system from the system's
; seeds, like this:
;
;   x = s1_hi (which is stored in QQ15+3)
;   y = s0_hi (which is stored in QQ15+1)
;
; so the following loops through each system in the
; galaxy in turn and calculates the distance between
; (QQ9, QQ10) and (s1_hi, s0_hi) to find the closest one

LDY #127               ; Set Y = T = 127 to hold the shortest distance we've
STY T                  ; found so far, which we initially set to half the
; distance across the galaxy, or 127, as our coordinate
; system ranges from (0,0) to (255, 255)

LDA #0                 ; Set A = U = 0 to act as a counter for each system in
STA U                  ; the current galaxy, which we start at system 0 and
; loop through to 255, the last system

.TT130

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

LDA QQ15+3             ; Set A = s1_hi - QQ9, the horizontal distance between
SEC                    ; (s1_hi, s0_hi) and (QQ9, QQ10)
SBC QQ9

BCS TT132              ; If a borrow didn't occur, i.e. s1_hi >= QQ9, then the
; following two instructions

EOR #\$FF               ; Otherwise negate the result in A, so A is always
ADC #1                 ; positive (i.e. A = |s1_hi - QQ9|)

.TT132

LSR A                  ; Set S = A / 2
STA S                  ;       = |s1_hi - QQ9| / 2

LDA QQ15+1             ; Set A = s0_hi - QQ10, the vertical distance between
SEC                    ; (s1_hi, s0_hi) and (QQ9, QQ10)
SBC QQ10

BCS TT134              ; If a borrow didn't occur, i.e. s0_hi >= QQ10, then the
; following two instructions

EOR #\$FF               ; Otherwise negate the result in A, so A is always
ADC #1                 ; positive (i.e. A = |s0_hi - QQ10|)

.TT134

LSR A                  ; Set A = S + A / 2
CLC                    ;       = |s1_hi - QQ9| / 2 + |s0_hi - QQ10| / 2
; So A now contains the sum of the horizontal and
; vertical distances, both divided by 2 so the result
; fits into one byte, and although this doesn't contain
; the actual distance between the systems, it's a good
; enough approximation to use for comparing distances

CMP T                  ; If A >= T, then this system's distance is bigger than
BCS TT135              ; our "minimum distance so far" stored in T, so it's no
; closer than the systems we have already found, so

STA T                  ; This system is the closest to (QQ9, QQ10) so far, so
; update T with the new "distance" approximation

LDX #5                 ; As this system is the closest we have found yet, we
; want to store the system's seeds in case it ends up
; being the closest of all, so we set up a counter in X
; to copy six bytes (for three 16-bit numbers)

.TT136

LDA QQ15,X             ; Copy the X-th byte in QQ15 to the X-th byte in QQ19,
STA QQ19,X             ; where QQ15 contains the seeds for the system we just
; found to be the closest so far, and QQ19 is temporary
; storage

DEX                    ; Decrement the counter

BPL TT136              ; Loop back to TT136 if we still have more bytes to
; copy

LDA U                  ; Store the system number U in systemNumber, so when we
STA systemNumber       ; are done looping through all the candidates, the
; winner's number will be in systemNumber

.TT135

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

JSR TT20               ; We want to move on to the next system, so call TT20
; to twist the three 16-bit seeds in QQ15

INC U                  ; Increment the system counter in U

BNE TT130              ; If U > 0 then we haven't done all 256 systems yet, so
; loop back up to TT130

; We have now finished checking all the systems in the
; galaxy, and the seeds for the closest system are in
; QQ19, so now we want to copy these seeds to QQ15,
; to set the selected system to this closest system

LDX #5                 ; So we set up a counter in X to copy six bytes (for
; three 16-bit numbers)

.TT137

LDA QQ19,X             ; Copy the X-th byte in QQ19 to the X-th byte in
STA selectedSystem,X   ; selectedSystem so we can easily change the selected
; system back to the system we just found

STA QQ15,X             ; Copy the X-th byte in QQ19 to the X-th byte in QQ15

DEX                    ; Decrement the counter

BPL TT137              ; Loop back to TT137 if we still have more bytes to
; copy

LDA QQ15+1             ; The y-coordinate of the system described by the seeds
STA QQ10               ; in QQ15 is in QQ15+1 (s0_hi), so we copy this to QQ10
; as this is where we store the selected system's
; y-coordinate

LDA QQ15+3             ; The x-coordinate of the system described by the seeds
STA QQ9                ; in QQ15 is in QQ15+3 (s1_hi), so we copy this to QQ9
; as this is where we store the selected system's
; x-coordinate

; We have now found the closest system to (QQ9, QQ10)
; and have set it as the selected system, so now we
; need to work out the distance between the selected
; system and the current system

SEC                    ; Set A = QQ9 - QQ0, the horizontal distance between
SBC QQ0                ; the selected system's x-coordinate (QQ9) and the
; current system's x-coordinate (QQ0)

BCS TT139              ; If a borrow didn't occur, i.e. QQ9 >= QQ0, then the
; following two instructions

EOR #\$FF               ; Otherwise negate the result in A, so A is always
ADC #1                 ; positive (i.e. A = |QQ9 - QQ0|)

; A now contains the difference between the two
; systems' x-coordinates, with the sign removed. We
; will refer to this as the x-delta ("delta" means
; change or difference in maths)

.TT139

JSR SQUA2              ; Set (A P) = A * A
;           = |QQ9 - QQ0| ^ 2
;           = x_delta ^ 2

STA K+1                ; Store (A P) in K(1 0)
LDA P
STA K

LDA QQ10               ; Set A = QQ10 - QQ1, the vertical distance between the
SEC                    ; selected system's y-coordinate (QQ10) and the current
SBC QQ1                ; system's y-coordinate (QQ1)

BCS TT141              ; If a borrow didn't occur, i.e. QQ10 >= QQ1, then the
; following two instructions

EOR #\$FF               ; Otherwise negate the result in A, so A is always
ADC #1                 ; positive (i.e. A = |QQ10 - QQ1|)

.TT141

LSR A                  ; Set A = A / 2

; A now contains the difference between the two
; systems' y-coordinates, with the sign removed, and
; halved. We halve the value because the galaxy in
; in Elite is rectangular rather than square, and is
; twice as wide (x-axis) as it is high (y-axis), so to
; get a distance that matches the shape of the
; long-range galaxy chart, we need to halve the
; distance between the vertical y-coordinates. We will
; refer to this as the y-delta

JSR SQUA2              ; Set (A P) = A * A
;           = (|QQ10 - QQ1| / 2) ^ 2
;           = y_delta ^ 2

; By this point we have the following results:
;
;   K(1 0) = x_delta ^ 2
;    (A P) = y_delta ^ 2
;
; so to find the distance between the two points, we
; can use Pythagoras - so first we need to add the two
; results together, and then take the square root

PHA                    ; Store the high byte of the y-axis value on the stack,
; so we can use A for another purpose

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

LDA P                  ; Set Q = P + K, which adds the low bytes of the two
CLC                    ; calculated values
STA Q

PLA                    ; Restore the high byte of the y-axis value from the
; stack into A again

ADC K+1                ; Set A = A + K+1, which adds the high bytes of the two
; calculated values

BCC P%+4               ; If the above addition overflowed, set A = 255
LDA #255

STA R                  ; Store A in R, so we now have R = A + K+1, and:
;
;   (R Q) = K(1 0) + (A P)
;         = (x_delta ^ 2) + (y_delta ^ 2)

JSR LL5                ; Set Q = SQRT(R Q), so Q now contains the distance
; between the two systems, in terms of coordinates

; We now store the distance to the selected system * 4
; in the two-byte location QQ8, by taking (0 Q) and
; shifting it left twice, storing it in QQ8(1 0)

LDA Q                  ; First we shift the low byte left by setting
ASL A                  ; A = Q * 2, with bit 7 of A going into the C flag

LDX #0                 ; Now we set the high byte in QQ8+1 to 0 and rotate
STX QQ8+1              ; the C flag into bit 0 of QQ8+1
ROL QQ8+1

ASL A                  ; And then we repeat the shift left of (QQ8+1 A)
ROL QQ8+1

STA QQ8                ; And store A in the low byte, QQ8, so QQ8(1 0) now
; contains Q * 4. Given that the width of the galaxy is
; 256 in coordinate terms, the width of the galaxy
; would be 1024 in the units we store in QQ8

JMP TT24_b6            ; Call TT24 to calculate system data from the seeds in
; QQ15 and store them in the relevant locations, so our
; new selected system is fully set up, and return from
; the subroutine using a tail call

Type: Subroutine
Category: Flight
Summary: Print a message to say there is no hyperspacing allowed inside the
station
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* GalacticHyperdrive calls dockEd
* hyp calls dockEd

Print "Docked" at the bottom of the screen to indicate we can't hyperspace
when docked.

.dockEd

JSR CLYNS              ; Clear the bottom two text rows of the upper screen,
; and move the text cursor to column 1 on row 21, i.e.
; the start of the top row of the two bottom rows

LDA #15                ; Move the text cursor to column 15 (the middle of the
STA XC                 ; screen), setting A to 15 at the same time for the
; following call to TT27

LDA #205               ; Print extended token 205 ("DOCKED") and return from
JMP DETOK_b2           ; the subroutine using a tail call

Type: Subroutine
Category: Flight
Summary: If we are in space and the countdown has ended, activate the
galactic hyperdrive
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls GalacticHyperdrive

.GalacticHyperdrive

LDA QQ12               ; If we are docked (QQ12 = \$FF) then jump to dockEd to
BNE dockEd             ; print an error message and return from the subroutine
; using a tail call (as we can't hyperspace when docked)

LDA QQ22+1             ; Fetch QQ22+1, which contains the number that's shown
; on-screen during hyperspace countdown

BEQ Ghy                ; If the countdown is zero, then the galactic hyperdrive

RTS                    ; Otherwise return from the subroutine

Type: Subroutine
Category: Flight
Summary: Start the hyperspace process
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls hyp

Called when the hyperspace icon is chosen during flight. Checks the following:

* We are in space

* We are not already in a hyperspace countdown

and if all the pre-jump checks are passed, we print the destination on-screen
and start the countdown.

.hyp

LDA QQ12               ; If we are docked (QQ12 = \$FF) then jump to dockEd to
BNE dockEd             ; print an error message and return from the subroutine
; using a tail call (as we can't hyperspace when docked)

LDA QQ22+1             ; Fetch QQ22+1, which contains the number that's shown
; on-screen during hyperspace countdown

BEQ P%+3               ; If it is zero, skip the next instruction

RTS                    ; The count is non-zero, so return from the subroutine

LDA selectedSystemFlag ; If bit 6 of selectedSystemFlag is set, then we can
ASL A                  ; hyperspace to the currently selected system, so jump
BMI hyps1              ; to hyps1 to skip the following instruction and keep
; going

RTS                    ; Bit 6 of selectedSystemFlag is clear, so we can't
; hyperspace to the currently selected system (we may
; not have enough fuel, or it might be the same as the
; current system), so return from the subroutine

.hyps1

LDX #5                 ; We now want to copy those seeds into safehouse, so we
; so set a counter in X to copy 6 bytes

.sob

LDA QQ15,X             ; Copy the X-th byte of QQ15 into the X-th byte of
STA safehouse,X        ; safehouse

DEX                    ; Decrement the loop counter

BPL sob                ; Loop back to copy the next byte until we have copied
; all six seed bytes

Type: Subroutine
Category: Flight
Summary: Start a hyperspace countdown
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* Ghy calls via wW2

Start the hyperspace countdown (for both inter-system hyperspace and the
galactic hyperdrive).

Other entry points:

wW2                  Start the hyperspace countdown, starting the countdown
from the value in A

.wW

LDA #16                ; The hyperspace countdown starts from 16, so set A to
; 15 so we can set the two hyperspace counters

.wW2

STA QQ22+1             ; Set the number in QQ22+1 to A, which is the number
; that's shown on-screen during the hyperspace countdown

LDA #1                 ; Set the number in QQ22 to 11, which is the internal
STA QQ22               ; counter that counts down by 1 each iteration of the
; main game loop, and each time it reaches zero, the
; on-screen counter gets decremented, and QQ22 gets set
; to 5, so setting QQ22 to 1 here makes the first tick
; of the hyperspace counter shorter than subsequent
; ticks

JMP UpdateIconBar_b3   ; Update the icon bar to remove the Hyperspace button,
; as we are now commit to our hyperspace jump, and
; return from the subroutine using a tail call

Type: Subroutine
Category: Flight
Summary: Perform a galactic hyperspace jump
Deep dive: Twisting the system seeds
Galaxy and system seeds
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* GalacticHyperdrive calls Ghy

Engage the galactic hyperdrive. Called from the hyp routine above if CTRL-H is
being pressed.

This routine also updates the galaxy seeds to point to the next galaxy. Using
a galactic hyperdrive rotates each seed byte to the left, rolling each byte
left within itself like this:

01234567 -> 12345670

to get the seeds for the next galaxy. So after 8 galactic jumps, the seeds
roll round to those of the first galaxy again.

We always arrive in a new galaxy at galactic coordinates (96, 96), and then
find the nearest system and set that as our location.

Other entry points:

zZ+1                 Contains an RTS

.Ghy

LDX GHYP               ; Fetch GHYP, which tells us whether we own a galactic
BEQ hy5                ; hyperdrive, and if it is zero, which means we don't,
; return from the subroutine (as hy5 contains an RTS)

INX                    ; We own a galactic hyperdrive, so X is \$FF, so this
; instruction sets X = 0

STX GHYP               ; The galactic hyperdrive is a one-use item, so set GHYP
; to 0 so we no longer have one fitted

STX FIST               ; Changing galaxy also clears our criminal record, so
; set our legal status in FIST to 0 ("clean")

JSR UpdateIconBar_b3   ; Update the icon bar to remove the galactic hyperdrive
; button as we no longer have one

LDA #1                 ; Call wW2 with A = 1 to start the hyperspace countdown,
JSR wW2                ; but starting the countdown from 1

LDX #5                 ; To move galaxy, we rotate the galaxy's seeds left, so
; set a counter in X for the 6 seed bytes

INC GCNT               ; Increment the current galaxy number in GCNT

LDA GCNT               ; Clear bit 3 of GCNT, so we jump from galaxy 7 back
AND #%11110111         ; to galaxy 0 (shown in-game as going from galaxy 8 back
STA GCNT               ; to the starting point in galaxy 1). We also retain any
; set bits in the high nibble, so if the galaxy number
; is manually set to 16 or higher, it will stay high
; (though the high nibble doesn't seem to get set by
; the game at any point, so it isn't clear what this is
; for, though Lave in galaxy 16 does show a unique
; system description override, so something is going on
; here...)

.G1

LDA QQ21,X             ; Load the X-th seed byte into A

ASL A                  ; Set the C flag to bit 7 of the seed

ROL QQ21,X             ; Rotate the seed in memory, which will add bit 7 back
; in as bit 0, so this rolls the seed around on itself

DEX                    ; Decrement the counter

BPL G1                 ; Loop back for the next seed byte, until we have
; rotated them all

.zZ

LDA #96                ; Set (QQ9, QQ10) to (96, 96), which is where we always
STA QQ9                ; arrive in a new galaxy (the selected system will be
STA QQ10               ; set to the nearest actual system later on)

JSR TT110              ; Call TT110 to show the front space view

JSR TT111              ; Call TT111 to set the current system to the nearest
; system to (QQ9, QQ10), and put the seeds of the
; nearest system into QQ15 to QQ15+5
;
; This call fixes a bug in the cassette version, where
; the galactic hyperdrive will take us to coordinates
; (96, 96) in the new galaxy, even if there isn't
; actually a system there, so if we jump when we are
; low on fuel, it is possible to get stuck in the
; middle of nowhere when changing galaxy
;
; This call sets the current system correctly, so we
; always arrive at the nearest system to (96, 96)

LDX #5                 ; We now want to copy those seeds into safehouse, so we
; so set a counter in X to copy 6 bytes

.dumdeedum

LDA QQ15,X             ; Copy the X-th byte of QQ15 into the X-th byte of
STA safehouse,X        ; safehouse

DEX                    ; Decrement the loop counter

BPL dumdeedum          ; Loop back to copy the next byte until we have copied
; all six seed bytes

LDX #0                 ; Set the distance to the selected system in QQ8(1 0)
STX QQ8                ; to 0
STX QQ8+1

LDY #22                ; Call the NOISE routine with Y = 22 to make the
JSR NOISE              ; galactic hyperspace sound

; Fall through into jmp to set the system to the
; current system and return from the subroutine there

Type: Subroutine
Category: Universe
Summary: Set the current system to the selected system
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* BR1 calls jmp
* hyp1 calls jmp
* Ghy calls via hy5

Returns:

(QQ0, QQ1)           The galactic coordinates of the new system

Other entry points:

hy5                  Contains an RTS

.jmp

LDA QQ9                ; Set the current system's galactic x-coordinate to the
STA QQ0                ; x-coordinate of the selected system

LDA QQ10               ; Set the current system's galactic y-coordinate to the
STA QQ1                ; y-coordinate of the selected system

.hy5

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Text
Summary: Print 16-bit number, left-padded to 5 digits, no point
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

Print the 16-bit number in (Y X) to 5 digits, left-padding with spaces for
numbers with fewer than 3 digits (so numbers < 10000 are right-aligned),
with no decimal point.

Arguments:

X                    The low byte of the number to print

Y                    The high byte of the number to print

.pr6

CLC                    ; Do not display a decimal point when printing

; Fall through into pr5 to print X to 5 digits

Type: Subroutine
Category: Text
Summary: Print a 16-bit number, left-padded to 5 digits, and optional point
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT146 calls pr5
* TT151 calls pr5

Print the 16-bit number in (Y X) to 5 digits, left-padding with spaces for
numbers with fewer than 3 digits (so numbers < 10000 are right-aligned).
Optionally include a decimal point.

Arguments:

X                    The low byte of the number to print

Y                    The high byte of the number to print

C flag               If set, include a decimal point

.pr5

LDA #5                 ; Set the number of digits to print to 5

JMP TT11               ; Call TT11 to print (Y X) to 5 digits and return from
; the subroutine using a tail call

Type: Subroutine
Category: Flight
Summary: Print an error when a system is out of hyperspace range
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

Print "RANGE?" for when the hyperspace distance is too far

.TT147

JSR CLYNS              ; Clear the bottom two text rows of the upper screen,
; and move the text cursor to column 1 on row 21, i.e.
; the start of the top row of the two bottom rows

LDA #189               ; Print token 29 ("HYPERSPACE ")
JSR TT27_b2

JSR TT162              ; Print a space

LDA #202               ; Print token 42 ("RANGE") followed by a question mark
JSR prq

JMP DrawScreenInNMI    ; Configure the NMI handler to draw the screen,
; returning from the subroutine using a tail call

Type: Subroutine
Category: Text
Summary: Print a text token followed by a question mark
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* eq calls prq
* TT147 calls prq

Arguments:

A                    The text token to be printed

.prq

JSR TT27_b2            ; Print the text token in A

LDA #'?'               ; Print a question mark and return from the
JMP TT27_b2            ; subroutine using a tail call

Type: Subroutine
Category: Market
Summary: Print the name, price and availability of a market item
Deep dive: Market item prices and availability
Galaxy and system seeds
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* HighlightSaleItem calls TT151
* PrintMarketItem calls TT151
* TT167 calls TT151

Arguments:

A                    The number of the market item to print, 0-16 (see QQ23
for details of item numbers)

Returns:

QQ19+1               Byte #1 from the market prices table for this item

QQ24                 The item's price / 4

QQ25                 The item's availability

.TT151q

; We jump here from below if we are in witchspace

PLA                    ; Restore the item number from the stack

RTS                    ; Return from the subroutine

.TT151

PHA                    ; Store the item number on the stack and in QQ19+4
STA QQ19+4

ASL A                  ; Store the item number * 4 in QQ19, so this will act as
ASL A                  ; an index into the market prices table at QQ23 for this
STA QQ19               ; item (as there are four bytes per item in the table)

JSR SetupPPUForIconBar ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

LDA MJ                 ; If we are in witchspace, we can't trade items, so jump
BNE TT151q             ; up to TT151q to return from the subroutine

LDA #1                 ; Move the text cursor to column 1, for the item's name
STA XC

LDA #%10000000         ; Set bit 7 of QQ17 to switch to Sentence Case
STA QQ17

PLA                    ; Restore the item number

CLC                    ; Print recursive token 48 + A, which will be in the
ADC #208               ; range 48 ("FOOD") to 64 ("ALIEN ITEMS"), so this
JSR TT27_b2            ; prints the item's name

; We now move the text cursor to column 14 by printing
; spaces until the cursor column in XC reaches 14

.aval1

LDA #' '               ; Print a space
JSR TT27_b2

LDA XC                 ; Loop back to print another space until XC = 14
CMP #14
BNE aval1

LDX QQ19               ; Fetch byte #1 from the market prices table (units and
LDA QQ23+1,X           ; economic_factor) for this item and store in QQ19+1
STA QQ19+1

LDA QQ26               ; Fetch the random number for this system visit and
AND QQ23+3,X           ; AND with byte #3 from the market prices table (mask)
; to give:
;
;   A = random AND mask

CLC                    ; Add byte #0 from the market prices table (base_price),
ADC QQ23,X             ; so we now have:
STA QQ24               ;
;   A = base_price + (random AND mask)

JSR TT152              ; Call TT152 to print the item's unit ("t", "kg" or
; "g"), padded to a width of two characters

JSR var                ; Call var to set QQ19+3 = economy * |economic_factor|
; (and set the availability of alien items to 0)

LDA QQ19+1             ; Fetch the byte #1 that we stored above and jump to
BMI TT155              ; TT155 if it is negative (i.e. if the economic_factor
; is negative)

LDA QQ24               ; Set A = QQ24 + QQ19+3
;       = base_price + (random AND mask)
;         + (economy * |economic_factor|)
;
; which is the result we want, as the economic_factor
; is positive

JMP TT156              ; Jump to TT156 to multiply the result by 4

.TT155

LDA QQ24               ; Set A = QQ24 - QQ19+3
SEC                    ;
SBC QQ19+3             ;       = base_price + (random AND mask)
;         - (economy * |economic_factor|)
;
; which is the result we want, as economic_factor
; is negative

.TT156

STA QQ24               ; Store the result in QQ24 and P
STA P

LDA #0                 ; Set A = 0 and call GC2 to calculate (Y X) = (A P) * 4,
JSR GC2                ; which is the same as (Y X) = P * 4 because A = 0

SEC                    ; We now have our final price, * 10, so we can call pr5
JSR pr5                ; to print (Y X) to 5 digits, including a decimal
; point, as the C flag is set

LDY QQ19+4             ; We now move on to availability, so fetch the market
; item number that we stored in QQ19+4 at the start

LDA #3                 ; Set A to 3 so we can print the availability to 3

LDX AVL,Y              ; Set X to the item's availability, which is given in
; the AVL table

STX QQ25               ; Store the availability in QQ25

CLC                    ; Clear the C flag

BEQ TT172              ; If none are available, jump to TT172 to print a tab
; and a "-"

JSR pr2+2              ; Otherwise print the 8-bit number in X to 5 digits,
; right-aligned with spaces. This works because we set
; A to 5 above, and we jump into the pr2 routine just
; after the first instruction, which would normally
; set the number of digits to 3

JSR TT152              ; Print the unit ("t", "kg" or "g") for the market item,
; with a following space if required to make it two
; characters long

JMP PrintNumberInHold  ; Print the number of units of this item that we have in
; the hold, returning from the subroutine using a tail
; call

.TT172

JSR PrintSpacedHyphen  ; Print two spaces, then a "-", and then another two
; spaces

JMP PrintNumberInHold  ; Print the number of units of this item that we have in
; the hold, returning from the subroutine using a tail
; call

Type: Subroutine
Category: Text
Summary: Print two spaces, then a "-", and then another two spaces
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* PrintNumberInHold calls PrintSpacedHyphen
* TT151 calls PrintSpacedHyphen

.PrintSpacedHyphen

JSR TT162              ; Print two spaces
JSR TT162

LDA #'-'               ; Print a "-" character
JSR TT27_b2

JSR TT162              ; Print two spaces, returning from the subroutine using
JMP TT162              ; a tail call

Type: Subroutine
Category: Market
Summary: Print the unit ("t", "kg" or "g") for a market item
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* PrintNumberInHold calls TT152
* TT151 calls TT152
* TT210 calls TT152

Print the unit ("t", "kg" or "g") for the market item whose byte #1 from the
market prices table is in QQ19+1, right-padded with spaces to a width of two
characters (so that's "t ", "kg" or "g ").

.TT152

LDA QQ19+1             ; Fetch the economic_factor from QQ19+1

AND #96                ; If bits 5 and 6 are both clear, jump to TT160 to
BEQ TT160              ; print "t" for tonne, followed by a space, and return
; from the subroutine using a tail call

CMP #32                ; If bit 5 is set, jump to TT161 to print "kg" for
BEQ TT161              ; kilograms, and return from the subroutine using a tail
; call

JSR TT16a              ; Otherwise call TT16a to print "g" for grams, and fall
; through into TT162 to print a space and return from
; the subroutine

Type: Subroutine
Category: Text
Summary: Print a space
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* csh calls TT162
* eq calls TT162
* EQSHP calls TT162
* fwl calls TT162
* MESS calls TT162
* Print2Spaces calls TT162
* PrintCombatRank calls TT162
* PrintEquipment calls TT162
* PrintLaserView calls TT162
* PrintSpaceAndToken calls TT162
* PrintSpacedHyphen calls TT162
* spc calls TT162
* TT147 calls TT162
* TT160 calls TT162
* TT25 calls TT162
* TT66 calls TT162
* TT163 calls via TT162+2

Other entry points:

.TT162

LDA #' '               ; Load a space character into A

JMP TT27_b2            ; Print the text token in A and return from the
; subroutine using a tail call

Type: Subroutine
Category: Market
Summary: Print "t" (for tonne) and a space
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT152 calls TT160

.TT160

LDA #'t'               ; Load a "t" character into A

JSR DASC_b2            ; Print the character

JMP TT162              ; Jump to TT162 to print a space and return from the
; subroutine using a tail call

Type: Subroutine
Category: Market
Summary: Print "kg" (for kilograms)
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT152 calls TT161

.TT161

LDA #'k'               ; Load a "k" character into A

JSR DASC_b2            ; Print the character and fall through into TT16a to
; print a "g" character

Type: Subroutine
Category: Market
Summary: Print "g" (for grams)
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT152 calls TT16a

.TT16a

LDA #'g'               ; Load a "g" character into A

JMP DASC_b2            ; Print the character and return from the subroutine
; using a tail call

Type: Subroutine
Category: Market
Summary: Print the headers for the table of market prices
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT167 calls TT163

Print the column headers for the prices table in the Buy Cargo and Market
Price screens.

.TT163

LDA #1                 ; Move the text cursor in XC to column 1
STA XC

LDA #255               ; Print recursive token 95 token ("UNIT  QUANTITY
BNE TT162+2            ; {crlf} PRODUCT   UNIT PRICE FOR SALE{crlf}{lf}") by
; jumping to TT162+2, which contains JMP TT27 (this BNE
; is effectively a JMP as A will never be zero), and
; return from the subroutine using a tail call

Type: Subroutine
Category: Market
Summary: Print the number of units of a specified item that we have in the
hold
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT151 calls PrintNumberInHold

Arguments:

QQ29                 The item number

.PrintNumberInHold

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

LDY QQ29               ; Set Y to the current item number

LDA #3                 ; Set A = 3 to use as the number of digits below

LDX QQ20,Y             ; Set X to the number of units of this item that we
; already have in the hold

BEQ PrintSpacedHyphen  ; If we don't have any units of this item in the hold,
; and two spaces

CLC                    ; Otherwise print the 8-bit number in X to 3 digits, as
JSR pr2+2              ; we set A to 3 above

JMP TT152              ; Print the unit ("t", "kg" or "g") for the market item,
; with a following space if required to make it two
; characters long, and return from the subroutine using
; a tail call

Type: Variable
Category: Market
Summary: The text row for the Market Price title for each language
Deep dive: Multi-language support in NES Elite
Context: See this variable on its own page
References: This variable is used as follows:
* HighlightSaleItem uses yMarketPrice
* PrintMarketItem uses yMarketPrice
* TT167 uses yMarketPrice

.yMarketPrice

EQUB 4                 ; English

EQUB 5                 ; German

EQUB 4                 ; French

EQUB 4                 ; There is no fourth language, so this byte is ignored

Type: Subroutine
Category: Market
Summary: Show the Market Price screen
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* RedrawCurrentView calls TT167
* TT102 calls TT167

; the Market Price screen

.TT167

LDA #\$BA               ; If we are already showing the Market Price screen
CMP QQ11               ; (i.e. QQ11 is \$BA), then jump to TT213 to show the
BEQ TT167-3            ; Inventory screen, so the icon bar button toggles
; between the two

JSR SetNewViewType     ; We are not already showing the Market Price screen,
; so that's what we do now, by clearing the screen and
; setting the view type in QQ11 to \$BA (Market Price)

LDA #5                 ; Move the text cursor to column 5
STA XC

LDA #167               ; Print recursive token 7 ("{current system name} MARKET
JSR NLIN3              ; PRICES") on the top row

LDA #2                 ; Move the text cursor to row 2
STA YC

JSR TT163              ; Print the column headers for the prices table

LDX languageIndex      ; Move the text cursor to the correct row for the Market
LDA yMarketPrice,X     ; Prices title in the chosen language
STA YC

LDA #0                 ; We're going to loop through all the available market
STA QQ29               ; items, so we set up a counter in QQ29 to denote the
; current item and start it at 0

.TT168

JSR SetupPPUForIconBar ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

JSR TT151              ; Call TT151 to print the item name, market price and
; availability of the current item, and set QQ24 to the
; item's price / 4, QQ25 to the quantity available and
; QQ19+1 to byte #1 from the market prices table for
; this item

INC YC                 ; Move the text cursor down one row

INC QQ29               ; Increment QQ29 to point to the next item

LDA QQ29               ; If QQ29 >= 17 then jump to TT168 as we have done the
CMP #17                ; last item
BCC TT168

; Fall through into BuyAndSellCargo to process the
; buying and selling of cargo on the Market Price
; screen

Type: Subroutine
Category: Market
Summary: Process the buying and selling of cargo on the Market Price screen
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

LDA QQ12               ; If we are docked (QQ12 = \$FF) then jump to sell3 to
BNE sell3              ; show the buy/sell screen

.sell1

; If we get here then we are in space, so we just
; display the view as we can't buy or sell cargo in
; space

JSR SetScreenForUpdate ; Get the screen ready for updating by hiding all
; sprites, after fading the screen to black if we are
; changing view

JSR DrawInventoryIcon  ; Draw the inventory icon on top of the second button
; in the icon bar

JMP UpdateView         ; Update the view, returning from the subroutine using
; a tail call

.sell2

JMP sell13             ; Jump to sell13 to process the left button being
; pressed

.sell3

LDA #0                 ; We're going to highlight the current market item and
STA QQ29               ; let the player move the highlight up and down, so use
; QQ29 to denote the number of the currently selected
; item, starting with item 0 at the top of the list

JSR HighlightSaleItem  ; Highlight the name, price and availability of market
; item 0 on the correct row for the chosen language

JSR PrintCash          ; Print our cash levels in the correct place for the
; chosen language

JSR sell1              ; Call sell1 above to clear the screen and update the
; view

.sell4

JSR SetupPPUForIconBar ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

LDA controller1B       ; If the B button is being pressed, jump to sell6
BMI sell6

LDA controller1Up      ; If neither of the up or down buttons are being
BEQ sell5

LDA controller1Left    ; If neither of the left or right buttons are being
BNE sell6

.sell5

; If we get here then at least one of the direction
; buttons is being pressed

LDA controller1Up      ; If the up button is being pressed and has been held
AND #%11110000         ; down for at least four VBlanks, jump to sell7
CMP #%11110000
BEQ sell7

LDA controller1Down    ; If the down button is being pressed and has been held
AND #%11110000         ; down for at least four VBlanks, jump to sell10
CMP #%11110000
BEQ sell10

LDA controller1Left03  ; If the left button was being held down four VBlanks
CMP #%11110000         ; ago for at least four VBlanks, jump to sell13 via
BEQ sell2              ; sell2

LDA controller1Right03 ; If the right button was being held down four VBlanks
CMP #%11110000         ; ago for at least four VBlanks, jump to sell12
BEQ sell12

.sell6

; If we get here then either the B button is being
; pressed or no directional buttons are being pressed

LDA iconBarChoice      ; If iconBarChoice = 0 then nothing has been chosen on
BEQ sell4              ; the icon bar (if it had, iconBarChoice would contain
; the number of the chosen icon bar button), so loop
; back to sell4 to keep listening for button presses

; If we get here then either a choice has been made on
; the icon bar during NMI and the number of the icon bar
; button is in iconBarChoice, or the Start button has
; been pressed and iconBarChoice is 80

JSR CheckForPause-3    ; If the Start button has been pressed then process the
; pause menu and set the C flag, otherwise clear it

BCS sell4              ; If it was the pause button, loop back to sell4 to pick
; up where we left off and keep listening for button
; presses

RTS                    ; Otherwise a choice has been made from the icon bar, so
; return from the subroutine

.sell7

; If we get here then the up button is being pressed

LDA QQ29               ; Set A to the number of the currently selected item in
; QQ29

JSR PrintMarketItem    ; Print the name, price and availability of market item
; item A on the correct row for the chosen language, to
; remove the highlight from the current item

LDA QQ29               ; Set A = QQ29 - 1
SEC                    ;
SBC #1                 ; So A is the number of the item above the currently
; selected item

BPL sell8              ; If A is negative, set A = 0, so 0 is the minimum value
LDA #0                 ; of A (so we can't move the highlight off the top of
; the list of items)

.sell8

STA QQ29               ; Store the updated item number in QQ29

.sell9

LDA QQ29               ; Set A to the number of the currently selected item in
; QQ29 (we do this so we can jump here)

JSR HighlightSaleItem  ; Highlight the name, price and availability of market
; item A on the correct row for the chosen language

JSR DrawScreenInNMI    ; Configure the NMI handler to draw the screen, so the
; screen gets updated

JSR WaitForPPUToFinish ; Wait until both bitplanes of the screen have been
; sent to the PPU, so the screen is fully updated and
; there is no more data waiting to be sent to the PPU

JMP sell4              ; Jump back to sell4 to keep listening for button
; presses

.sell10

; If we get here then the down button is being pressed

LDA QQ29               ; Set A to the number of the currently selected item in
; QQ29

JSR PrintMarketItem    ; Print the name, price and availability of market item
; item A on the correct row for the chosen language, to
; remove the highlight from the current item

LDA QQ29               ; Set A = QQ29 + 1
CLC                    ;
ADC #1                 ; So A is the number of the item below the currently
; selected item

CMP #17                ; If A = 17, set A = 16, so 16 is the maximum value of
BNE sell11             ; A (so we can't move the highlight off the bottom of
LDA #16                ; the list of items)

.sell11

STA QQ29               ; Store the updated item number in QQ29

JMP sell9              ; Jump up to sell9 to highlight the newly selected item
; and go back to listening for button presses

.sell12

; If we get here then the right button is being pressed,
; so we process buying an item

LDA #1                 ; Call tnpr with the selected market item in QQ29 and
JSR tnpr               ; A set to 1, to work out whether we have room in the
; hold for the selected item (A is preserved by this
; call, and the C flag contains the result)

BCS sell14             ; If the C flag is set then we have no room in the hold
; for the selected item, so jump to sell4 via sell14 to
; abort the sale and keep listening for button presses

LDY QQ29               ; Fetch the currently selected market item number from
; QQ29 into Y

LDA AVL,Y              ; Set A to the number of available units of the market
; item in Y

BEQ sell14             ; If there are no units available, jump to sell4 via
; sell14 to abort the sale and keep listening for button
; presses

LDA QQ24               ; Set P to the item's price / 4
STA P

LDA #0                 ; Set A = 0, so (A P) contains the item's price / 4

JSR GC2                ; Call GC2 to calculate:
;
;   (Y X) = (A P) * 4
;
; which will be the total price of this transaction, as
; (A P) contains the item's price / 4

JSR LCASH              ; Subtract (Y X) cash from the cash pot in CASH

BCC sell14             ; If the C flag is clear, we didn't have enough cash,
; so jump to sell4 via sell14 to abort the sale and keep
; listening for button presses

JSR UpdateSaveCount    ; Update the save counter for the current commander

LDY #28                ; Call the NOISE routine with Y = 28 to make a trill
JSR NOISE              ; sound to indicate that we have bought something

LDY QQ29               ; Fetch the currently selected market item number from
; QQ29 into Y

LDA AVL,Y              ; Set A to the number of available units of the market
; item in Y

SEC                    ; Subtract 1 from the market availability, as we just
SBC #1                 ; bought one unit
STA AVL,Y

LDA QQ20,Y             ; Set A to the number of units of this item that we
; already have in the hold

CLC                    ; Add 1 to the number of units and update the number in
STA QQ20,Y

JSR PrintCash          ; Print our cash levels in the correct place for the
; chosen language

JMP sell9              ; Jump up to sell9 to update the highlighted item with
; the new availability and go back to listening for
; button presses

.sell13

; If we get here then the left button is being pressed,
; so we process selling an item

LDY QQ29               ; Fetch the currently selected market item number from
; QQ29 into Y

LDA AVL,Y              ; If there are 99 or more units available on the market,
BCS sell14             ; via sell14 to abort the sale and keep listening for
; button presses

LDA QQ20,Y             ; Set A to the number of units of this item that we
; already have in the hold

BEQ sell14             ; If we don't have any items of this type in the hold,
; jump to sell4 via sell14 to abort the sale and keep
; listening for button presses

JSR UpdateSaveCount    ; Update the save counter for the current commander

SEC                    ; Subtract 1 from the number of units and update the
SBC #1                 ; number in the hold
STA QQ20,Y

LDA AVL,Y              ; Add 1 to the market availability, as we just sold
CLC                    ; one unit into the market
STA AVL,Y

LDA QQ24               ; Set P to the item's price / 4
STA P

LDA #0                 ; Set A = 0, so (A P) contains the item's price / 4

JSR GC2                ; Call GC2 to calculate:
;
;   (Y X) = (A P) * 4
;
; which will be the total price of this transaction, as
; (A P) contains the item's price / 4

JSR MCASH              ; Add (Y X) cash to the cash pot in CASH

JSR PrintCash          ; Print our cash levels in the correct place for the
; chosen language

LDY #3                 ; Call the NOISE routine with Y = 3 to make a short,
JSR NOISE              ; high beep to indicate that we have made a sale

JMP sell9              ; Jump up to sell9 to update the highlighted item with
; the new availability and go back to listening for
; button presses

.sell14

JMP sell4              ; Jump up to sell4 to keep listening for button presses

Type: Subroutine
Category: Market
Summary: Highlight the name, price and availability of a market item on the
correct row for the chosen language
Context: See this subroutine on its own page
References: This subroutine is called as follows:

Arguments:

A                    The item number of the market item to display

.HighlightSaleItem

TAY                    ; Set Y to the market item number

LDX #2                 ; Set the font style to print in the highlight font
STX fontStyle

CLC                    ; Move the text cursor to the row for this market item,
LDX languageIndex      ; starting from item 0 at the top, on the correct row
ADC yMarketPrice,X     ; for the chosen language
STA YC

TYA                    ; Call TT151 to print the item name, market price and
JSR TT151              ; availability of the current item, and set QQ24 to the
; item's price / 4, QQ25 to the quantity available and
; QQ19+1 to byte #1 from the market prices table for
; this item

LDX #1                 ; Set the font style to print in the normal font
STX fontStyle

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Market
Summary: Print the name, price and availability of a market item on the
correct row for the chosen language
Context: See this subroutine on its own page
References: This subroutine is called as follows:

Arguments:

A                    The item number of the market item to display

.PrintMarketItem

TAY                    ; Set Y to the market item number

CLC                    ; Move the text cursor to the row for this market item,
LDX languageIndex      ; starting from item 0 at the top, on the correct row
ADC yMarketPrice,X     ; for the chosen language
STA YC

TYA                    ; Call TT151 to print the item name, market price and
JMP TT151              ; availability of the current item, and set QQ24 to the
; item's price / 4, QQ25 to the quantity available and
; QQ19+1 to byte #1 from the market prices table for
; this item
;
; When done, return from the subroutine using a tail
; call

Type: Subroutine
Category: Market
Summary: Print our cash levels in the correct place for the chosen language
Context: See this subroutine on its own page
References: This subroutine is called as follows:

.PrintCash

LDA #%10000000         ; Set bit 7 of QQ17 to switch standard tokens to
STA QQ17               ; Sentence Case

LDX languageIndex      ; Move the text cursor to the correct row for the chosen
LDA yCash,X            ; language, as given in the yCash table
STA YC

LDA xCash,X            ; Move the text cursor to the correct column for the
STA XC                 ; chosen, as given in the xCash table

; ("CASH:{cash} CR{crlf}"), followed by a space, and
; return from the subroutine using a tail call

Type: Variable
Category: Market
Summary: The text column for our cash levels on the Market Price page
Deep dive: Multi-language support in NES Elite
Context: See this variable on its own page
References: This variable is used as follows:
* PrintCash uses xCash

.xCash

EQUB 5                 ; English

EQUB 5                 ; German

EQUB 3                 ; French

EQUB 5                 ; There is no fourth language, so this byte is ignored

Type: Variable
Category: Market
Summary: The text row for the cash levels on the Market Price page
Deep dive: Multi-language support in NES Elite
Context: See this variable on its own page
References: This variable is used as follows:
* PrintCash uses yCash

.yCash

EQUB 22                ; English

EQUB 23                ; German

EQUB 22                ; French

EQUB 22                ; There is no fourth language, so this byte is ignored

Type: Subroutine
Category: Market
Summary: Calculate QQ19+3 = economy * |economic_factor|
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* GVL calls var
* TT151 calls var

Set QQ19+3 = economy * |economic_factor|, given byte #1 of the market prices
table for an item. Also sets the availability of alien items to 0.

This routine forms part of the calculations for market item prices (TT151)
and availability (GVL).

Arguments:

QQ19+1               Byte #1 of the market prices table for this market item
(which contains the economic_factor in bits 0-5, and the
sign of the economic_factor in bit 7)

.var

LDA QQ19+1             ; Extract bits 0-5 from QQ19+1 into A, to get the
AND #31                ; economic_factor without its sign, in other words:
;
;   A = |economic_factor|

LDY QQ28               ; Set Y to the economy byte of the current system

STA QQ19+2             ; Store A in QQ19+2

CLC                    ; Clear the C flag so we can do additions below

LDA #0                 ; Set AVL+16 (availability of alien items) to 0,
STA AVL+16             ; setting A to 0 in the process

.TT153

; We now do the multiplication by doing a series of
; additions in a loop, building the result in A. Each
; loop adds QQ19+2 (|economic_factor|) to A, and it
; loops the number of times given by the economy byte;
; in other words, because A starts at 0, this sets:
;
;   A = economy * |economic_factor|

DEY                    ; Decrement the economy in Y, exiting the loop when it
BMI TT154              ; becomes negative

JMP TT153              ; Loop back to TT153 to do another addition

.TT154

STA QQ19+3             ; Store the result in QQ19+3

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Universe
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT18 calls hyp1

(QQ9, QQ10), and set up the current system's state to those of the new system.

Returns:

(QQ0, QQ1)           The galactic coordinates of the new system

QQ2 to QQ2+6         The seeds of the new system

EV                   Set to 0

QQ28                 The new system's economy

tek                  The new system's tech level

gov                  The new system's government

Other entry points:

hyp1+3               Jump straight to the system at (QQ9, QQ10) without
first calculating which system is closest. We do this
if we already know that (QQ9, QQ10) points to a system

.hyp1

JSR jmp                ; Set the current system to the selected system

LDX #5                 ; We now want to copy the seeds for the selected system
; in QQ15 into QQ2, where we store the seeds for the
; current system, so set up a counter in X for copying
; 6 bytes (for three 16-bit seeds)

.TT112

LDA safehouse,X        ; Copy the X-th byte in safehouse to the X-th byte in
STA QQ2,X              ; QQ2

STA QQ15,X             ; Copy the X-th byte in safehouse to the X-th byte in
; QQ15 as well, to set the selected system

DEX                    ; Decrement the counter

BPL TT112              ; Loop back to TT112 if we still have more bytes to
; copy

INX                    ; Set X = 0 (as we ended the above loop with X = \$FF)

STX EV                 ; Set EV, the extra vessels spawning counter, to 0, as
; we are entering a new system with no extra vessels
; spawned

LDA #%10000000         ; Set bit 7 and clear bit 6 of selectedSystemFlag, to
STA selectedSystemFlag ; indicate that there is a currently selected system
; but we can't hyperspace to it (because it is the same
; as the currently selected system)

JSR UpdateIconBar_b3   ; Update the icon bar to remove the Hyperspace button
; if present

JSR TT24_b6            ; Call TT24 to calculate system data from the seeds in
; QQ15 and store them in the relevant locations, so our
; new selected system is fully set up

LDA QQ3                ; Set the current system's economy in QQ28 to the
STA QQ28               ; selected system's economy from QQ3

LDA QQ5                ; Set the current system's tech level in tek to the
STA tek                ; selected system's economy from QQ5

LDA QQ4                ; Set the current system's government in gov to the
STA gov                ; selected system's government from QQ4

; Fall through into GVL to calculate the availability of
; market items in the new system

Type: Subroutine
Category: Universe
Summary: Calculate the availability of market items
Deep dive: Market item prices and availability
Galaxy and system seeds
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

Calculate the availability for each market item and store it in AVL. This is
called on arrival in a new system.

Other entry points:

hyR                  Contains an RTS

.GVL

JSR DORND              ; Set A and X to random numbers

STA QQ26               ; Set QQ26 to the random byte that's used in the market
; calculations

LDX #0                 ; We are now going to loop through the market item
STX XX4                ; availability table in AVL, so set a counter in XX4
; (and X) for the market item number, starting with 0

.hy9

LDA QQ23+1,X           ; Fetch byte #1 from the market prices table (units and
STA QQ19+1             ; economic_factor) for item number X and store it in
; QQ19+1

JSR var                ; Call var to set QQ19+3 = economy * |economic_factor|
; (and set the availability of alien items to 0)

LDA QQ23+3,X           ; Fetch byte #3 from the market prices table (mask) and
AND QQ26               ; AND with the random number for this system visit
; to give:
;
;   A = random AND mask

CLC                    ; Add byte #2 from the market prices table
ADC QQ23+2,X           ; (base_quantity) so we now have:
;
;   A = base_quantity + (random AND mask)

LDY QQ19+1             ; Fetch the byte #1 that we stored above and jump to
BMI TT157              ; TT157 if it is negative (i.e. if the economic_factor
; is negative)

SEC                    ; Set A = A - QQ19+3
SBC QQ19+3             ;
;       = base_quantity + (random AND mask)
;         - (economy * |economic_factor|)
;
; which is the result we want, as the economic_factor
; is positive

.TT157

CLC                    ; Set A = A + QQ19+3
;       = base_quantity + (random AND mask)
;         + (economy * |economic_factor|)
;
; which is the result we want, as the economic_factor
; is negative

.TT158

BPL TT159              ; If A < 0, then set A = 0, so we don't have negative
LDA #0                 ; availability

.TT159

LDY XX4                ; Fetch the counter (the market item number) into Y

AND #%00111111         ; Take bits 0-5 of A, i.e. A mod 64, and store this as
STA AVL,Y              ; this item's availability in the Y=th byte of AVL, so
; each item has a maximum availability of 63t

INY                    ; Increment the counter into XX44, Y and A
TYA
STA XX4

ASL A                  ; Set X = counter * 4, so that X points to the next
ASL A                  ; item's entry in the four-byte market prices table,
TAX                    ; ready for the next loop

CMP #63                ; If A < 63, jump back up to hy9 to set the availability
BCC hy9                ; for the next market item

.hyR

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Universe
Summary: Spawn a Thargoid ship and a Thargon companion
Deep dive: Fixing ship positions
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MJP calls GTHG
* Main game loop (Part 4 of 6) calls via GTHG+15

Other entry points:

GTHG+15              Spawn a lone Thargoid, without a Thargon companion and
with slightly less aggression than normal

.GTHG

JSR Ze                 ; Call Ze to initialise INWK
;
; Note that because Ze uses the value of X returned by
; DORND, and X contains the value of A returned by the
; previous call to DORND, this does not set the new ship
; to a totally random location. See the deep dive on
; "Fixing ship positions" for details

LDA #%11111111         ; Set the AI flag in byte #32 so that the ship has AI,
STA INWK+32            ; is extremely and aggressively hostile, and has E.C.M.

LDA #TGL               ; Call NWSHP to add a new Thargon ship to our local
JSR NWSHP              ; bubble of universe

JMP gthg1              ; Skip the following to add a Thargoid

; We jump straight here if we call GTHG+15

JSR Ze                 ; Call Ze to initialise INWK

LDA #%11111001         ; Set the AI flag in byte #32 so that the ship has AI,
STA INWK+32            ; is hostile and pretty aggressive (though not quite as
; aggressive as the Thargoid we add if we get here via
; GTHG), and has E.C.M.

.gthg1

LDA #THG               ; Call NWSHP to add a new Thargoid ship to our local
JMP NWSHP              ; bubble of universe, and return from the subroutine
; using a tail call

Type: Subroutine
Category: Flight
Summary: Process a mis-jump into witchspace
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT18 calls MJP

Process a mis-jump into witchspace (which happens very rarely). Witchspace has
a strange, almost dust-free aspect to it, and it is populated by hostile
Thargoids. Using our escape pod will be fatal, and our position on the
galactic chart is in-between systems. It is a scary place...

There is a 0.78% chance that this routine is called from TT18 instead of doing
a normal hyperspace, or we can manually trigger a mis-jump by holding down
either the up or down button at the point that the hyperspace countdown
reaches zero.

Other entry points:

.MJP

LDY #29                ; Call the NOISE routine with Y = 29 to make the first
JSR NOISE              ; sound of a mis-jump

JSR RES2               ; Reset a number of flight variables and workspaces, as
; well as setting Y to \$FF

STY MJ                 ; Set the mis-jump flag in MJ to \$FF, to indicate that
; we are now in witchspace

LDA QQ1                ; Fetch the current system's galactic y-coordinate in
EOR #%00011111         ; QQ1 and flip bits 0-5, so we end up somewhere in the
STA QQ1                ; vicinity of our original destination, but above or
; below it in the galactic chart

.MJP1

JSR GTHG               ; Call GTHG three times to spawn three Thargoid ships
JSR GTHG               ; and three Thargon companions
JSR GTHG

LDA #3                 ; Set NOSTM (the maximum number of stardust particles)
STA NOSTM              ; to 3, so there are fewer bits of stardust in
; witchspace (normal space has a maximum of 18)

JSR SelectNearbySystem ; Set the current system to the nearest system to
; (QQ9, QQ10) and update the selected system flags
; accordingly

JSR UpdateIconBar_b3   ; Update the icon bar to show the hyperspace icon

LDY #30                ; Call the NOISE routine with Y = 30 to make the second
JSR NOISE              ; sound of a mis-jump

JMP RedrawCurrentView  ; Update the current view for when we arrive in a new
; system, returning from the subroutine using a tail
; call

Type: Subroutine
Category: Flight
Summary: Try to initiate a jump into hyperspace
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls TT18

Try to go through hyperspace. Called from TT102 in the main loop when the
hyperspace countdown has finished.

.TT18

JSR ResetMusicAfterNMI ; Wait for the next NMI before resetting the current
; tune to 0 (no tune) and stopping the music

LDA QQ14               ; Subtract the distance to the selected system (in QQ8)
SEC                    ; from the amount of fuel in our tank (in QQ14) into A
SBC QQ8

BCS P%+4               ; If the subtraction didn't overflow, skip the next
; instruction

LDA #0                 ; The subtraction overflowed, so set A = 0 so we don't
; end up with a negative amount of fuel

STA QQ14               ; Store the updated fuel amount in QQ14

LDA QQ11               ; If this is not the space view, then jump to hypr1 to
BNE hypr1              ; skip drawing the hyperspace tunnel, but still make the
; hyperspace sound

JSR ClearScanner       ; Remove all ships from the scanner and hide the scanner
; sprites

JSR LL164_b6           ; Call LL164 to show the hyperspace tunnel and make the
; hyperspace sound

; the hyperspace sound in LL164

.hypr1

JSR MakeHyperSound     ; Make the hyperspace sound for when we are not in the
; space view

.hypr2

LDA controller1Up      ; If either of the up or down buttons are being pressed,
BMI MJP

.ee5

JSR DORND              ; Set A and X to random numbers

CMP #253               ; If A >= 253 (0.78% chance) then jump to MJP to trigger
BCS MJP                ; a mis-jump into witchspace

JSR hyp1               ; Jump straight to the system at (QQ9, QQ10)

JSR WaitForNMI         ; Wait until the next NMI interrupt has passed (i.e. the
; next VBlank)

JSR RES2               ; Reset a number of flight variables and workspaces

JSR SOLAR              ; Halve our legal status, update the missile indicators,
; and set up data blocks and slots for the planet and
; sun

Type: Subroutine
Category: Drawing the screen
Summary: Update the current view when we arrive in a new system
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MJP calls RedrawCurrentView

.RedrawCurrentView

LDA QQ11               ; If this is the space view (i.e. QQ11 is zero), jump to
BEQ witc5              ; witc5 to set the current space view type to 4 and show
; the front space view

LDA QQ11               ; If the view in QQ11 is not %0000110x (i.e. 12 or 13,
AND #%00001110         ; which are the Short-range Chart and Long-range Chart),
CMP #%00001100         ; jump to witc2 to keep checking for other view types
BNE witc2

LDA QQ11               ; If the view type in QQ11 is not \$9C (Short-range
CMP #\$9C               ; Chart), then this must be the Long-range Chart, so
BNE witc1              ; jump to TT22 via witc1 to show the Long-range Chart

JMP TT23               ; Otherwise this is the Short-range Chart, so jump to
; TT23 to show the Short-range Chart, returning from the
; subroutine using a tail call

.witc1

JMP TT22               ; This is the Long-range Chart, so jump to TT22 to show
; it, returning from the subroutine using a tail call

.witc2

LDA QQ11               ; If the view type in QQ11 is not \$97 (Inventory), then
CMP #\$97               ; jump to witc3 to keep checking for other view types
BNE witc3

JMP TT213              ; This is the Inventory screen, so jump to TT213 to show
; it, returning from the subroutine using a tail call

.witc3

CMP #\$BA               ; If the view type in QQ11 is not \$BA (Market Price),
BNE witc4              ; then jump to witc4 to display the Status Mode screen

LDA #\$97               ; Set the view type in QQ11 to \$97 (Inventory), so the
STA QQ11               ; call to TT167 toggles this to the Market Price screen

JMP TT167              ; Jump to TT167 to show the Market Price screen,
; returning from the subroutine using a tail call

.witc4

JMP STATUS             ; Jump to STATUS to display the Status Mode screen,
; returning from the subroutine using a tail call

.witc5

LDX #4                 ; If we get here then this is the space view, so set the
STX VIEW               ; current space view to 4 to denote that we are
; generating a new space view and fall through into
; TT110 to show the front space view (at which point
; VIEW will change to 0)

Type: Subroutine
Category: Flight
Summary: Launch from a station or show the front space view
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* Ghy calls TT110
* TT102 calls TT110

Launch the ship (if we are docked), or show the front space view (if we are

new galaxy, or after a hyperspace if the current view is a space view.

.TT110

LDX QQ12               ; If we are not docked (QQ12 = 0) then jump to NLUNCH
BEQ NLUNCH             ; to skip the launch tunnel and setup process

LDA #0                 ; Set VIEW = 0 to switch to the front view
STA VIEW

STA QQ12               ; Set QQ12 = 0 to indicate that we are not docked

LDA allowInSystemJump  ; Set bit 7 of allowInSystemJump to prevent us from
ORA #%10000000         ; being able to do an in-system jump, as you can't jump
STA allowInSystemJump  ; when you're in the space station's safe zone

JSR ResetShipStatus    ; Reset the ship's speed, hyperspace counter, laser
; temperature, shields and energy banks

JSR NWSTARS            ; Set up a new stardust field

JSR LAUN               ; Show the space station launch tunnel

JSR RES2               ; Reset a number of flight variables and workspaces

JSR UpdateSaveCount    ; Update the save counter for the current commander

JSR WaitForNMI         ; Wait until the next NMI interrupt has passed (i.e. the
; next VBlank)

INC INWK+8             ; Increment z_sign ready for the call to SOS, so the
; planet appears at a z_sign of 1 in front of us when
; we launch

JSR SOS1               ; Call SOS1 to set up the planet's data block and add it
; to FRIN, where it will get put in the first slot as
; it's the first one to be added to our local bubble of
; universe following the call to RES2 above

LDA #128               ; For the space station, set z_sign to \$80, so it's
STA INWK+8             ; behind us (\$80 is negative)

INC INWK+7             ; And increment z_hi, so it's only just behind us

JSR NWSPS              ; Add a new space station to our local bubble of
; universe

LDA #12                ; Set our launch speed in DELTA to 12
STA DELTA

JSR BAD                ; Call BAD to work out how much illegal contraband we
; are carrying in our hold (A is up to 40 for a
; standard hold crammed with contraband, up to 70 for
; an extended cargo hold full of narcotics and slaves)

ORA FIST               ; OR the value in A with our legal status in FIST to
; get a new value that is at least as high as both
; values, to reflect the fact that launching with a
; hold full of contraband can only make matters worse

STA FIST               ; Update our legal status with the new value

JSR NWSTARS            ; Set up a new stardust field

JSR WaitForNMI         ; Wait until the next NMI interrupt has passed (i.e. the
; next VBlank)

LDX #4                 ; Set the current space view to 4, which indicates that
STX VIEW               ; we are in the process of generating a new space view

.NLUNCH

LDX #0                 ; Set QQ12 to 0 to indicate we are not docked
STX QQ12

JMP LOOK1              ; Jump to LOOK1 to switch to the front view (X = 0),
; returning from the subroutine using a tail call

Type: Subroutine
Category: Charts
Summary: Display either the Long-range or Short-range Chart
Context: See this subroutine on its own page
References: No direct references to this subroutine in this source file

Display either the Long-range or Short-range Chart, depending on the current
view setting. Called from TT18 once we know the current view is one of the
charts.

Arguments:

A                    The current view, loaded from QQ11

.TT114

CMP #\$9C               ; If this is the Short-range Chart, skip to TT115 below

JMP TT22               ; Otherwise the current view is the Long-range Chart, so

.TT115

Type: Subroutine
Category: Maths (Arithmetic)
Summary: Subtract an amount of cash from the cash pot
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* eq calls LCASH
* TBRIEF calls LCASH
* TT102 calls LCASH

Subtract (Y X) cash from the cash pot in CASH, but only if there is enough
cash in the pot. As CASH is a four-byte number, this calculates:

CASH(0 1 2 3) = CASH(0 1 2 3) - (0 0 Y X)

Returns:

C flag               If set, there was enough cash to do the subtraction

If clear, there was not enough cash to do the
subtraction

.LCASH

STX T1                 ; Subtract the least significant bytes:
LDA CASH+3             ;
SEC                    ;   CASH+3 = CASH+3 - X
SBC T1
STA CASH+3

STY T1                 ; Then the second most significant bytes:
LDA CASH+2             ;
SBC T1                 ;   CASH+2 = CASH+2 - Y
STA CASH+2

LDA CASH+1             ; Then the third most significant bytes (which are 0):
SBC #0                 ;
STA CASH+1             ;   CASH+1 = CASH+1 - 0

LDA CASH               ; And finally the most significant bytes (which are 0):
SBC #0                 ;
STA CASH               ;   CASH = CASH - 0

BCS TT113              ; If the C flag is set then the subtraction didn't
; underflow, so the value in CASH is correct and we can
; C flag set to indicate success (as TT113 contains an
; RTS)

; Otherwise we didn't have enough cash in CASH to
; subtract (Y X) from it, so fall through into
; MCASH to reverse the sum and restore the original
; value in CASH, and returning with the C flag clear

Type: Subroutine
Category: Maths (Arithmetic)
Summary: Add an amount of cash to the cash pot
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* DEBRIEF calls MCASH
* EQSHP calls MCASH
* Main flight loop (Part 12 of 16) calls MCASH
* refund calls MCASH
* LCASH calls via TT113

Add (Y X) cash to the cash pot in CASH. As CASH is a four-byte number, this
calculates:

CASH(0 1 2 3) = CASH(0 1 2 3) + (Y X)

Other entry points:

TT113                Contains an RTS

.MCASH

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

TXA                    ; Add the least significant bytes:
CLC                    ;
ADC CASH+3             ;   CASH+3 = CASH+3 + X
STA CASH+3

TYA                    ; Then the second most significant bytes:
STA CASH+2             ;   CASH+2 = CASH+2 + Y

LDA CASH+1             ; Then the third most significant bytes (which are 0):
STA CASH+1             ;   CASH+1 = CASH+1 + 0

LDA CASH               ; And finally the most significant bytes (which are 0):
STA CASH               ;   CASH = CASH + 0

CLC                    ; Clear the C flag, so if the above was done following
; a failed LCASH call, the C flag correctly indicates
; failure

.TT113

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Maths (Arithmetic)
Summary: Calculate (Y X) = (A P) * 4
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT151 calls GC2

Calculate the following multiplication of unsigned 16-bit numbers:

(Y X) = (A P) * 4

.GC2

ASL P                  ; Set (A P) = (A P) * 4
ROL A
ASL P
ROL A

TAY                    ; Set (Y X) = (A P)
LDX P

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Start and end
Summary: Configure the game following a commander file load
Context: See this subroutine on its own page
References: This subroutine is called as follows:

This routine is very similar to the BR1 routine.

JSR ping               ; Set the target system coordinates (QQ9, QQ10) to the
; current system coordinates (QQ0, QQ1) we just loaded

JSR TT111              ; Select the system closest to galactic coordinates
; (QQ9, QQ10)

JSR jmp                ; Set the current system to the selected system

LDX #5                 ; We now want to copy the seeds for the selected system
; in QQ15 into QQ2, where we store the seeds for the
; current system, so set up a counter in X for copying
; 6 bytes (for three 16-bit seeds)

.stal1

LDA QQ15,X             ; Copy the X-th byte in QQ15 to the X-th byte in QQ2
STA QQ2,X

DEX                    ; Decrement the counter

BPL stal1              ; Loop back to stal1 if we still have more bytes to copy

INX                    ; Set X = 0 (as we ended the above loop with X = \$FF)

STX EV                 ; Set EV, the extra vessels spawning counter, to 0, as
; we are entering a new system with no extra vessels
; spawned

LDA QQ3                ; Set the current system's economy in QQ28 to the
STA QQ28               ; selected system's economy from QQ3

LDA QQ5                ; Set the current system's tech level in tek to the
STA tek                ; selected system's economy from QQ5

LDA QQ4                ; Set the current system's government in gov to the
STA gov                ; selected system's government from QQ4

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Equipment
Summary: Draw the Cobra Mk III on the Equip Ship screen
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* EQSHP calls DrawCobraMkIII

.DrawCobraMkIII

LDA #20                ; Set XC and YC so the call to DrawImageNames draws the
STA YC                 ; Cobra Mk III at text column 2 on row 20
LDA #2
STA XC

LDA #26                ; Set K = 26 so the call to DrawImageNames draws 26
STA K                  ; tiles in each row

LDA #5                 ; Set K+1 = 5 so the call to DrawImageNames draws 5 rows
STA K+1                ; of tiles

LDA #HI(cobraNames)    ; Set V(1 0) = cobraNames, so the call to DrawImageNames
STA V+1                ; draws the Cobra Mk III
LDA #LO(cobraNames)
STA V

LDA #0                 ; Set K+2 = 0, so the call to DrawImageNames copies the
STA K+2                ; entries directly from cobraNames to the nametable
; buffer without adding an offset

JSR DrawImageNames_b4  ; Draw the Cobra Mk III at text column 2 on row 20

JMP DrawEquipment_b6   ; Draw the currently fitted equipment onto the Cobra Mk
; III image, returning from the subroutine using a tail
; call

Type: Subroutine
Category: Equipment
Summary: Highlight an item of equipment on the Equip Ship screen
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* EQSHP calls HighlightEquipment
* UpdateEquipment calls HighlightEquipment

.HighlightEquipment

LDX #2                 ; Set the font style to print in the highlight font
STX fontStyle

LDX XX13               ; Set X to the item number to print

JSR PrintEquipment+2   ; Print the name and price for the equipment item in X

LDX #1                 ; Set the font style to print in the normal font
STX fontStyle

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Equipment
Summary: Print the name and price for a specified item of equipment
Deep dive: Multi-language support in NES Elite
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* MoveEquipmentDown calls PrintEquipment
* MoveEquipmentUp calls PrintEquipment
* EQSHP calls via PrintEquipment+2
* HighlightEquipment calls via PrintEquipment+2

Arguments:

XX13                 The item number + 1 (i.e. 1 for fuel)

Q                    The highest item number on sale + 1

Other entry points:

PrintEquipment+2     Print the item number in X

.PrintEquipment

LDX XX13               ; Set X to the item number to print

JSR SetupPPUForIconBar ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

STX XX13               ; Store the item number in XX13, in case we entered the
; routine at PrintEquipment+2

TXA                    ; Set A = X + 2
CLC                    ;
ADC #2                 ; So the first item (item 1) will be on row 3, and so on

LDX Q                  ; If Q >= 12, set A = A - 1 so we move everything up the
CPX #12                ; screen by one line when the highest item number on
BCC preq1              ; sale is at least 11
SEC
SBC #1

.preq1

STA YC                 ; Move the text cursor to row A

LDA #1                 ; Move the text cursor to column 1
STA XC

LDA languageNumber     ; If bit 1 of languageNumber is set then the chosen
AND #%00000010         ; language is French, so jump to preq2 to skip the
BNE preq2              ; following

JSR TT162              ; Print a space

.preq2

JSR TT162              ; Print a space

LDA XX13               ; Print recursive token 104 + XX13, which will be in the
CLC                    ; range 105 ("FUEL") to 116 ("GALACTIC HYPERSPACE ")
ADC #104               ; so this prints the current item's name
JSR TT27_b2

JSR WaitForIconBarPPU  ; Wait until the PPU starts drawing the icon bar

LDA XX13               ; If the current item number in XX13 is not 1, then it
CMP #1                 ; is not the fuel level, so jump to preq3 to skip the
BNE preq3              ; following (which prints the fuel level)

LDA #' '               ; Print a space
JSR TT27_b2

LDA #'('               ; Print an open bracket
JSR TT27_b2

LDX QQ14               ; Set X to the current fuel level * 10

SEC                    ; Set the C flag so the call to pr2+2 prints a decimal
; point

LDA #0                 ; Set the number of digits to 0 for the call to pr2+2,
; so the number is not padded with spaces

JSR pr2+2              ; Print the fuel level with a decimal point and no

LDA #195               ; Print recursive token 35 ("LIGHT YEARS")
JSR TT27_b2

LDA #')'               ; Print a closing bracket
JSR TT27_b2

LDA languageNumber     ; If bit 2 of languageNumber is set then the chosen
AND #%00000100         ; language is French, so jump to preq3 to skip the
BNE preq3              ; following (which prints the price)

; Bit 2 of languageNumber is clear, so the chosen
; language is English or German, so now we print the
; price

LDA XX13               ; Call prx-3 to set (Y X) to the price of the item with
JSR prx-3              ; number XX13 - 1 (as XX13 contains the item number + 1)

SEC                    ; Set the C flag so we will print a decimal point when
; we print the price

LDA #5                 ; Print the number in (Y X) to 5 digits, left-padding
JSR TT11               ; with spaces and including a decimal point, which will
; be the correct price for this item as (Y X) contains
; the price * 10, so the trailing zero will go after the
; decimal point (i.e. 5250 will be printed as 525.0)

LDA #' '               ; Print a space
JMP TT27_b2

.preq3

LDA #' '               ; Print a space
JSR TT27_b2

LDA XC                 ; Loop back to print another space until XC = 24, so
CMP #24                ; so this tabs the text cursor to column 24
BNE preq3

LDA XX13               ; Call prx-3 to set (Y X) to the price of the item with
JSR prx-3              ; number XX13 - 1 (as XX13 contains the item number + 1)

SEC                    ; Set the C flag so we will print a decimal point when
; we print the price

LDA #6                 ; Print the number in (Y X) to 6 digits, left-padding
JSR TT11               ; with spaces and including a decimal point, which will
; be the correct price for this item as (Y X) contains
; the price * 10, so the trailing zero will go after the
; decimal point (i.e. 5250 will be printed as 525.0)

JMP TT162              ; Print a space and return from the subroutine using a
; tail call

Type: Subroutine
Category: Equipment
Summary: Move the currently selected item up the list of equipment
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* EQSHP calls MoveEquipmentUp

.MoveEquipmentUp

JSR PrintEquipment     ; Print the name and price for the equipment item in
; XX13

LDA XX13               ; Set A = XX13 - 1, so A contains the item number above
SEC                    ; the currently selected item in the equipment list
SBC #1

BNE equp1              ; If XX13 is non-zero then we have not just tried to
; move off the top of the list, so jump to equp1 to skip
; the following instruction

LDA #1                 ; Set A = 1 to set the currently selected item to the
; first item in the list, so we don't go past the top
; of the list

.equp1

STA XX13               ; Store the new item number in XX13, so we move up the
; equipment list

; Fall through into UpdateEquipment to highlight the
; newly chosen item of equipment, update the Cobra Mk
; III, redraw the screen and rejoin the main EQSHP
; routine to continue checking for button presses

Type: Subroutine
Category: Equipment
Summary: Highlight the newly chosen item of equipment, update the Cobra Mk
III, redraw the screen and rejoin the main EQSHP routine
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* EQSHP calls UpdateEquipment
* MoveEquipmentDown calls UpdateEquipment

.UpdateEquipment

JSR HighlightEquipment ; Highlight the item of equipment in XX13

JSR DrawEquipment_b6   ; Draw the currently fitted equipment onto the Cobra Mk
; III image

JSR DrawScreenInNMI    ; Configure the NMI handler to draw the screen, so the
; screen gets updated

JSR WaitForPPUToFinish ; Wait until both bitplanes of the screen have been
; sent to the PPU, so the screen is fully updated and
; there is no more data waiting to be sent to the PPU

JMP equi1              ; Rejoin the main EQSHP routine at equi1 to continue
; checking for button presses

Type: Subroutine
Category: Equipment
Summary: Move the currently selected item down the list of equipment
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* EQSHP calls MoveEquipmentDown

.MoveEquipmentDown

JSR PrintEquipment     ; Print the name and price for the equipment item in
; XX13

LDA XX13               ; Set A = XX13 + 1, so A contains the item number below
CLC                    ; the currently selected item in the equipment list

CMP Q                  ; If A has not reached Q, which contains the number of
BNE eqdn1              ; items in the list plus 1, then we have not fallen off
; the bottom of the list, so jump to eqdn1 to skip the
; following

LDA Q                  ; Set A = Q - 1 to set the currently selected item to
SBC #1                 ; the bottom item in the list, so we don't go past the
; bottom of the list (the subtraction works because we
; just passed through a BNE, so the comparison was
; equal which sets the C flag)

.eqdn1

STA XX13               ; Store the new item number in XX13, so we move down the
; equipment list

JMP UpdateEquipment    ; Jump up to UpdateEquipment to highlight the newly
; chosen item of equipment, update the Cobra Mk III,
; redraw the screen and rejoin the main EQSHP routine to
; continue checking for button presses

Type: Variable
Category: Equipment
Summary: The text column for the Equip Ship title for each language
Context: See this variable on its own page
References: This variable is used as follows:
* EQSHP uses xEquipShip

.xEquipShip

EQUB 12                ; English

EQUB 8                 ; German

EQUB 10                ; French

Type: Subroutine
Category: Equipment
Summary: Show the Equip Ship screen
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* refund calls EQSHP
* TT102 calls EQSHP
* UpdateEquipment calls via equi1

Other entry points:

pres                 Given an item number A with the item name in recursive
token Y, show an error to say that the item is already
present, refund the cost of the item, and then beep and
exit to the docking bay (i.e. show the Status Mode
screen)

equi1                A re-entry point into the key-pressing loop, used when
processing key presses in subroutines

.EQSHP

LDA #\$B9               ; Clear the screen and set the view type in QQ11 to \$B9
JSR SetNewViewType     ; (Equip Ship)

LDX languageIndex      ; Move the text cursor to the correct column for the
LDA xEquipShip,X       ; Equip Ship title in the chosen language
STA XC

LDA #207               ; Print recursive token 47 ("EQUIP") on the top row
JSR NLIN3

LDA #%10000000         ; Set bit 7 of QQ17 to switch to Sentence Case, with the
STA QQ17               ; next letter in capitals

LDA tek                ; Fetch the tech level of the current system from tek
CLC                    ; and add 3 (the tech level is stored as 0-14, so A is
ADC #3                 ; now set to between 3 and 17)

CMP #12                ; If A >= 12 then set A = 14, so A is now set to between
BCC P%+4               ; 3 and 14
LDA #14

STA Q                  ; Set QQ25 = A (so QQ25 is in the range 3-14 and
STA QQ25               ; represents number of the most advanced item available
INC Q                  ; in this system, which we can pass to gnum below when
;
; Set Q = A + 1 (so Q is in the range 4-15 and contains
; QQ25 + 1, i.e. the highest item number on sale + 1)

LDA #70                ; Set A = 70 - QQ14, where QQ14 contains the current
SEC                    ; fuel in light years * 10, so this leaves the amount
SBC QQ14               ; of fuel we need to fill 'er up (in light years * 10)

LDX #1                 ; We are now going to work our way through the equipment
; price list at PRXS, printing out the equipment that is
; available at this station, so set a counter in X,
; starting at 1, to hold the number of the current item
; plus 1 (so the item number in X loops through 1-13)

.EQL1

JSR PrintEquipment+2   ; Print the name and price for the equipment item in X

LDX XX13               ; Increment the current item number in XX13
INX

CPX Q                  ; If X < Q, loop back up to print the next item on the
BCC EQL1               ; list of equipment available at this station

LDX #1                 ; Set XX13 = 1 to pass to the HighlightEquipment routine
STX XX13               ; so we highlight the first item on the list (Fuel)

JSR HighlightEquipment ; Highlight the item of equipment in XX13, i.e. Fuel

JSR dn                 ; Print the amount of money we have left in the cash pot

JSR SetScreenForUpdate ; Get the screen ready for updating by hiding all
; sprites, after fading the screen to black if we are
; changing view

JSR DrawCobraMkIII     ; Draw the Cobra Mk III that we embellish with our
; fitted equipment

JSR UpdateView         ; Update the view

; The Equip Ship view is now on-screen, so we move on to
; checking for key presses

.equi1

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

LDA controller1Up      ; If the up button has not been pressed, jump to equi2
BPL equi2              ; to keep checking for other buttons

JMP MoveEquipmentUp    ; Move the currently selected item up the list of
; equipment and rejoin the loop by jumping up to equi1
; to keep checking for other buttons

.equi2

LDA controller1Down    ; If the down button has not been pressed, jump to equi3
BPL equi3              ; to keep checking for other buttons

JMP MoveEquipmentDown  ; Move the currently selected item down the list of
; equipment and rejoin the loop by jumping up to equi1
; to keep checking for other buttons

.equi3

LDA controller1A       ; If the A button has been pressed, jump to equi4 to
BMI equi4              ; process a purchase

LDA iconBarChoice      ; If iconBarChoice = 0 then nothing has been chosen on
BEQ equi1              ; the icon bar (if it had, iconBarChoice would contain
; the number of the chosen icon bar button), so loop
; back to equi1 to keep checking for button presses

; If we get here then either a choice has been made on
; the icon bar during NMI and the number of the icon bar
; button is in iconBarChoice, or the Start button has
; been pressed to pause the game and iconBarChoice is 80

JSR CheckForPause      ; If the Start button has been pressed then process the
; pause menu and set the C flag, otherwise clear it

BCS equi1              ; If it was the pause button, loop back to equi1 to pick
; up where we left off and keep checking for button
; presses

RTS                    ; Otherwise a choice has been made from the icon bar, so
; return from the subroutine

.equi4

JSR UpdateSaveCount    ; Update the save counter for the current commander

LDA XX13               ; Set A = XX13 - 1, so A contains the item number of the
SEC                    ; currently selected item, less 1, which will be the
SBC #1                 ; actual number of the item we want to buy

PHA                    ; Store the value of A on the stack, so we can retrieve
; it after the call to eq

JSR eq                 ; Call eq to subtract the price of the item we want to
; buy (which is in A) from our cash pot

BCS equi5              ; If we had enough cash to make the purchase, then the C
; flag will be set by eq, so jump to equi5 with the
; original value of A still on the stack

; If we get here then we didn't have enough cash to make
; the purchase

PLA                    ; Retrieve the value of A from the stack, so A contains
; the number of the item we couldn't afford

JSR DrawScreenInNMI    ; Configure the NMI handler to draw the screen, so the
; screen gets updated

JMP equi1              ; Loop back up to equi1 to keep checking for button
; presses

.equi5

; If we get here then we just successfully bought an
; item of equipment

PLA                    ; Retrieve the value of A from the stack, so A contains
; the number of the item we just bought

BNE et0                ; If A is not 0 (i.e. the item we've just bought is not

PHA                    ; Store the value of A on the stack, so we can retrieve
; it after the following calculation

LDA QQ14               ; Fetch our current fuel level from Q114 into A

CLC                    ; Increment our fuel level in A

CMP #71                ; If A < 71 then the tank is not overflowing, so jump to
BCC equi6              ; equi6 to store the updated fuel level

LDY #105               ; Set Y to recursive token 105 ("FUEL") to display as
; the error in the call to pres

PLA                    ; Restore A from the stack

JMP pres               ; Jump to pres to show the error "Fuel Present", beep
; and exit to the docking bay (i.e. show the Status Mode
; screen)

.equi6

STA QQ14               ; Update the fuel level in QQ14 to the value in A, as we
; have just bought some fuel

PLA                    ; Restore A from the stack, so it once again contains
; the number of the item we are buying

.et0

CMP #1                 ; If A is not 1 (i.e. the item we've just bought is not

LDX NOMSL              ; Fetch the current number of missiles from NOMSL into X

INX                    ; Increment X to the new number of missiles

LDY #124               ; Set Y to recursive token 124 ("ALL")

CPX #5                 ; If buying this missile would give us 5 missiles, this
BCS pres               ; is more than the maximum of 4 missiles that we can
; fit, so jump to pres to show the error "All Present",
; beep and exit to the docking bay (i.e. show the Status
; Mode screen)

STX NOMSL              ; Otherwise update the number of missiles in NOMSL

LDA #1                 ; Set A to 1 as the call to msblob will have overwritten
; the original value, and we still need it set
; correctly so we can continue through the conditional
; statements for all the other equipment

.et1

LDY #107               ; Set Y to recursive token 107 ("LARGE CARGO{sentence
; case} BAY")

CMP #2                 ; If A is not 2 (i.e. the item we've just bought is not

LDX #37                ; If our current cargo capacity in CRGO is 37, then we
BEQ pres               ; to show the error "Large Cargo Bay Present", beep and
; exit to the docking bay (i.e. show the Status Mode
; screen)

STX CRGO               ; Otherwise we just scored ourselves a large cargo bay,
; so update our current cargo capacity in CRGO to 37

.et2

CMP #3                 ; If A is not 3 (i.e. the item we've just bought is not

INY                    ; Increment Y to recursive token 108 ("E.C.M.SYSTEM")

LDX ECM                ; If we already have an E.C.M. fitted (i.e. ECM is
BNE pres               ; non-zero), jump to pres to show the error "E.C.M.
; System Present", beep and exit to the docking bay
; (i.e. show the Status Mode screen)

DEC ECM                ; Otherwise we just took delivery of a brand new E.C.M.
; system, so set ECM to \$FF (as ECM was 0 before the DEC
; instruction)

.et3

CMP #4                 ; If A is not 4 (i.e. the item we've just bought is not

JSR qv                 ; Print a menu listing the four views, with a "View ?"
; prompt, and ask for a view number, which is returned
; in X (which now contains 0-3)

LDA #POW+9             ; Call refund with A set to the power of the new pulse
JMP refund             ; laser to install the new laser and process a refund if
; we already have a laser fitted to this view
;
; The refund routine jumps back to EQSHP, so this also
; redisplays the Equip Ship screen

LDA #4                 ; Set A to 4 as we just overwrote the original value,
; and we still need it set correctly so we can continue
; through the conditional statements for all the other
; equipment

.et4

CMP #5                 ; If A is not 5 (i.e. the item we've just bought is not

JSR qv                 ; Print a menu listing the four views, with a "View ?"
; prompt, and ask for a view number, which is returned
; in X (which now contains 0-3)

LDA #POW+128           ; Call refund with A set to the power of the new beam
JMP refund             ; laser to install the new laser and process a refund if
; we already have a laser fitted to this view
;
; The refund routine jumps back to EQSHP, so this also
; redisplays the Equip Ship screen

.et5

LDY #111               ; Set Y to recursive token 107 ("FUEL SCOOPS")

CMP #6                 ; If A is not 6 (i.e. the item we've just bought is not

LDX BST                ; If we already have fuel scoops fitted (i.e. BST is
BEQ ed9                ; zero), jump to ed9, otherwise fall through into pres
; to show the error "Fuel Scoops Present", beep and
; exit to the docking bay (i.e. show the Status Mode
; screen)

.pres

; If we get here we need to show an error to say that
; the item whose name is in recursive token Y is already
; present, and then process a refund for the cost of
; item number A

STY K                  ; Store the item's name in K

PHA                    ; Wait until the next NMI interrupt has passed (i.e. the
JSR WaitForNMI         ; next VBlank), preserving the value in A via the stack
PLA

JSR prx                ; Call prx to set (Y X) to the price of equipment item
; number A

JSR MCASH              ; Add (Y X) cash to the cash pot in CASH, as the station
; already took the money for this item in the JSR eq
; instruction above, but we can't fit the item, so need
; our money back

LDA #2                 ; Move the text cursor to column 2 on row 17
STA XC
LDA #17
STA YC

LDA K                  ; Print the recursive token in K (the item's name)
JSR spc                ; followed by a space

LDA #31                ; Print recursive token 145 ("PRESENT")
JSR TT27_b2

.equi7

JSR TT162              ; Print a space

LDA XC                 ; If the text cursor is not in column 31, loop back to
CMP #31                ; equi7 to keep printing spaces until it reaches column
BNE equi7              ; 31 at the right end of the screen, so we clear up to
; the end of the line containing the error message

JSR BOOP               ; Call the BOOP routine to make a low, long beep to
; indicate an error

JSR DrawScreenInNMI    ; Configure the NMI handler to draw the screen, so the
; screen gets updated

LDY #40                ; Wait until 40 NMI interrupts have passed (i.e. the
JSR DELAY              ; next 40 VBlanks)

LDA #6                 ; Move the text cursor to column 6
STA XC

LDA #17                ; Move the text cursor to row 17
STA YC

.equi8

JSR TT162              ; Print a space

LDA XC                 ; If the text cursor is not in column 31, loop back to
CMP #31                ; equi8 to keep printing spaces until it reaches column
BNE equi8              ; 31 at the right end of the screen, so we clear the
; whole line containing the error message

JSR dn                 ; Print the amount of money we have left in the cash pot

JSR DrawEquipment_b6   ; Draw the currently fitted equipment onto the Cobra Mk
; III image

JSR DrawScreenInNMI    ; Configure the NMI handler to draw the screen, so the
; screen gets updated

JMP equi1              ; Loop back up to equi1 to keep checking for button
; presses

.equi9

JMP pres               ; Jump to pres to show an error, beep and exit to the
; docking bay (i.e. show the Status Mode screen)

JSR DrawScreenInNMI    ; Configure the NMI handler to draw the screen, so the
; screen gets updated

JMP equi1              ; Loop back up to equi1 to keep checking for button
; presses

.ed9

DEC BST                ; We just bought a shiny new fuel scoop, so set BST to
; \$FF (as BST was 0 before the jump to ed9 above)

.et6

INY                    ; Increment Y to recursive token 112 ("E.C.M.SYSTEM")

CMP #7                 ; If A is not 7 (i.e. the item we've just bought is not

LDX ESCP               ; If we already have an escape pod fitted (i.e. ESCP is
BNE pres               ; non-zero), jump to pres to show the error "Escape Pod
; Present", beep and exit to the docking bay (i.e. show
; the Status Mode screen)

DEC ESCP               ; Otherwise we just bought an escape pod, so set ESCP
; to \$FF (as ESCP was 0 before the DEC instruction)

.et7

INY                    ; Increment Y to recursive token 113 ("ENERGY BOMB")

CMP #8                 ; If A is not 8 (i.e. the item we've just bought is not

LDX BOMB               ; If we already have an energy bomb fitted (i.e. BOMB
BNE pres               ; is non-zero), jump to pres to show the error "Energy
; Bomb Present", beep and exit to the docking bay (i.e.
; show the Status Mode screen)

LDX #\$7F               ; Otherwise we just bought an energy bomb, so set BOMB
STX BOMB               ; to \$7F

.et8

INY                    ; Increment Y to recursive token 114 ("ENERGY UNIT")

CMP #9                 ; If A is not 9 (i.e. the item we've just bought is not

LDX ENGY               ; If we already have an energy unit fitted (i.e. ENGY is
BNE equi9              ; non-zero), jump to pres via equi9 to show the error
; "Energy Unit Present", beep and exit to the docking
; bay (i.e. show the Status Mode screen)

INC ENGY               ; Otherwise we just picked up an energy unit, so set
; ENGY to 1 (as ENGY was 0 before the INC instruction)

.etA

INY                    ; Increment Y to recursive token 115 ("DOCKING
; COMPUTERS")

CMP #10                ; If A is not 10 (i.e. the item we've just bought is not

LDX DKCMP              ; If we already have a docking computer fitted (i.e.
BNE equi9              ; DKCMP is non-zero), jump to pres via equi9 to show the
; error "Docking Computer Present", beep and exit to the
; docking bay (i.e. show the Status Mode screen)

DEC DKCMP              ; Otherwise we just got hold of a docking computer, so
; set DKCMP to \$FF (as DKCMP was 0 before the DEC
; instruction)

.etB

INY                    ; Increment Y to recursive token 116 ("GALACTIC
; HYPERSPACE ")

CMP #11                ; If A is not 11 (i.e. the item we've just bought is not

LDX GHYP               ; If we already have a galactic hyperdrive fitted (i.e.
BNE equi9              ; GHYP is non-zero), jump to pres via equi9 to show the
; error "Galactic Hyperspace Present", beep and exit to
; the docking bay (i.e. show the Status Mode screen)

DEC GHYP               ; Otherwise we just splashed out on a galactic
; hyperdrive, so set GHYP to \$FF (as GHYP was 0 before
; the DEC instruction)

.et9

INY                    ; Increment Y to recursive token 117 ("MILITARY  LASER")

CMP #12                ; If A is not 12 (i.e. the item we've just bought is not

JSR qv                 ; Print a menu listing the four views, with a "View ?"
; prompt, and ask for a view number, which is returned
; in X (which now contains 0-3)

LDA #Armlas            ; Call refund with A set to the power of the new
JMP refund             ; military laser to install the new laser and process a
; refund if we already have a laser fitted to this view
;
; The refund routine jumps back to EQSHP, so this also
; redisplays the Equip Ship screen

.et10

INY                    ; Increment Y to recursive token 118 ("MINING  LASER")

CMP #13                ; If A is not 13 (i.e. the item we've just bought is not

JSR qv                 ; Print a menu listing the four views, with a "View ?"
; prompt, and ask for a view number, which is returned
; in X (which now contains 0-3)

LDA #Mlas              ; Call refund with A set to the power of the new mining
JMP refund             ; laser to install the new laser and process a refund if
; we already have a laser fitted to this view
;
; The refund routine jumps back to EQSHP, so this also
; redisplays the Equip Ship screen

.et11

JSR equi10             ; Call equi10 below to print the amount of money we have
; left and make a short, high beep to indicate that the
; transaction was successful

JMP UpdateEquipment    ; Jump up to UpdateEquipment to highlight the newly
; bought item of equipment, update the Cobra Mk III,
; redraw the screen and rejoin the main EQSHP routine to
; continue checking for button presses

.equi10

SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure
; the PPU to use nametable 0 and pattern table 0

JSR dn                 ; Print the amount of money we have left in the cash pot

JMP BEEP_b7            ; Call the BEEP subroutine to make a short, high beep
; and return from the subroutine using a tail call

Type: Subroutine
Category: Market
Summary: Print the amount of money we have left in the cash pot
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* eq calls dn
* EQSHP calls dn

.dn

LDA #17                ; Move the text cursor to column 2 on row 17
STA YC
LDA #2
STA XC

; ("CASH:{cash} CR{crlf}"), followed by a space, and
; return from the subroutine using a tail call

Type: Subroutine
Category: Equipment
Summary: Subtract the price of equipment from the cash pot
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* EQSHP calls eq

If we have enough cash, subtract the price of a specified piece of equipment
from our cash pot and return from the subroutine. If we don't have enough
cash, exit to the docking bay (i.e. show the Status Mode screen).

Arguments:

A                    The item number of the piece of equipment (0-11) as
shown in the table at PRXS

Returns:

C flag               The status of the transaction:

* Clear if we didn't have enough cash for the purchase

* Set if we did have enough cash for the purchase

.eq

JSR prx                ; Call prx to set (Y X) to the price of equipment item
; number A

JSR LCASH              ; Subtract (Y X) cash from the cash pot, but only if
; we have enough cash

BCS c                  ; If the C flag is set then we did have enough cash for
; subroutine (as c contains an RTS)

LDA #17                ; Move the text cursor to column 2 on row 17
STA YC
LDA #2
STA XC

LDA #197               ; Otherwise we don't have enough cash to buy this piece
JSR prq                ; of equipment, so print recursive token 37 ("CASH")
; followed by a question mark

JSR BOOP               ; Call the BOOP routine to make a low, long beep to
; indicate that we don't have enough cash

LDY #20                ; We now print 21 spaces, so set a counter in Y

.eqeq1

JSR TT162              ; Print a space

DEY                    ; Decrement the loop counter

BPL eqeq1              ; Loop back until we have printed 21 spaces

JSR DrawScreenInNMI    ; Configure the NMI handler to draw the screen, so the
; screen gets updated

LDY #40                ; Delay for 40 vertical syncs (40/50 = 0.8 seconds)
JSR DELAY

JSR dn                 ; Print the amount of money we have left in the cash pot

CLC                    ; Clear the C flag to indicate that we didn't make the
; purchase

RTS                    ; Return from the subroutine

Type: Subroutine
Category: Equipment
Summary: Return the price of a piece of equipment
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* eq calls prx
* EQSHP calls prx
* refund calls prx
* PrintEquipment calls via prx-3
* eq calls via c

This routine returns the price of equipment as listed in the table at PRXS.

Arguments:

A                    The item number of the piece of equipment (0-13) as
shown in the table at PRXS

Returns:

(Y X)                The item price in Cr * 10 (Y = high byte, X = low byte)

Other entry points:

prx-3                Return the price of the item with number A - 1

c                    Contains an RTS

SEC                    ; Decrement A (for when this routine is called via
SBC #1                 ; prx-3)

.prx

ASL A                  ; Set Y = A * 2, so it can act as an index into the
TAY                    ; PRXS table, which has two bytes per entry

LDX PRXS,Y             ; Fetch the low byte of the price into X

LDA PRXS+1,Y           ; Fetch the high byte of the price into A and transfer
TAY                    ; it to X, so the price is now in (Y X)

.c

RTS                    ; Return from the subroutine

LDX priceDebug         ; This code is never run, but it looks like it might
LDA #0                 ; have been used to override the price of equipment
TAY                    ; during testing, as it sets (Y X) to (0 priceDebug)
RTS                    ; before returning from the subroutine

```