Skip to navigation

Elite on the BBC Micro

# Elite D encyclopedia source [Elite-A]

``` ELITE D FILE

CODE_D% = P%
LOAD_D% = LOAD% + P% - CODE%

Name: TT20                                                    [Show more]
Type: Subroutine
Category: Universe
Summary: Twist the selected system's seeds four times
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:
* HME2 calls TT20
* TT111 calls TT20
* TT22 calls TT20
* TT23 calls TT20

Twist the three 16-bit seeds in QQ15 (selected system) four times, to
generate the next system.

.TT20

JSR P%+3               \ This line calls the line below as a subroutine, which
\ does two twists before returning here, and then we
\ fall through to the line below for another two
\ twists, so the net effect of these two consecutive
\ JSR calls is four twists, not counting the ones
\ inside your head as you try to follow this process

JSR P%+3               \ This line calls TT54 as a subroutine to do a twist,
\ and then falls through into TT54 to do another twist
\ before returning from the subroutine

Name: TT54                                                    [Show more]
Type: Subroutine
Category: Universe
Summary: Twist the selected system's seeds
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:
* cpl calls TT54

This routine twists the three 16-bit seeds in QQ15 once.

.TT54

LDA QQ15               \ X = tmp_lo = s0_lo + s1_lo
CLC
ADC QQ15+2
TAX

LDA QQ15+1             \ Y = tmp_hi = s1_hi + s1_hi + C
ADC QQ15+3
TAY

LDA QQ15+2             \ s0_lo = s1_lo
STA QQ15

LDA QQ15+3             \ s0_hi = s1_hi
STA QQ15+1

LDA QQ15+5             \ s1_hi = s2_hi
STA QQ15+3

LDA QQ15+4             \ s1_lo = s2_lo
STA QQ15+2

CLC                    \ s2_lo = X + s1_lo
TXA
ADC QQ15+2
STA QQ15+4

TYA                    \ s2_hi = Y + s1_hi + C
ADC QQ15+3
STA QQ15+5

RTS                    \ The twist is complete so return from the subroutine

Name: TT146                                                   [Show more]
Type: Subroutine
Category: Text
Summary: Print the distance to the selected system in light years
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls TT146
* TT25 calls TT146

If it is non-zero, print the distance to the selected system in light years.
If it is zero, just move the text cursor down a line.

Specifically, if the distance in QQ8 is non-zero, print token 31 ("DISTANCE"),
then a colon, then the distance to one decimal place, then token 35 ("LIGHT
YEARS"). If the distance is zero, move the cursor down one line.

.TT146

LDA QQ8                \ Take the two bytes of the 16-bit value in QQ8 and
ORA QQ8+1              \ OR them together to check whether there are any
BNE TT63               \ non-zero bits, and if so, jump to TT63 to print the
\ distance

INC YC                 \ The distance is zero, so we just move the text cursor
RTS                    \ in YC down by one line and return from the subroutine

.TT63

LDA #191               \ Print recursive token 31 ("DISTANCE") followed by
JSR TT68               \ a colon

LDX QQ8                \ Load (Y X) from QQ8, which contains the 16-bit
LDY QQ8+1              \ distance we want to show

SEC                    \ Set the C flag so that the call to pr5 will include a
\ decimal point, and display the value as (Y X) / 10

JSR pr5                \ Print (Y X) to 5 digits, including a decimal point

LDA #195               \ Set A to the recursive token 35 (" LIGHT YEARS") and
\ fall through into TT60 to print the token followed
\ by a paragraph break

Name: TT60                                                    [Show more]
Type: Subroutine
Category: Text
Summary: Print a text token and a paragraph break
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT25 calls TT60

Print a text token (i.e. a character, control code, two-letter token or
recursive token). Then print a paragraph break (a blank line between
paragraphs) by moving the cursor down a line, setting Sentence Case, and then
printing a newline.

Arguments:

A                    The text token to be printed

.TT60

JSR TT27               \ Print the text token in A and fall through into TTX69
\ to print the paragraph break

Name: TTX69                                                   [Show more]
Type: Subroutine
Category: Text
Summary: Print a paragraph break
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT25 calls TTX69

Print a paragraph break (a blank line between paragraphs) by moving the cursor
down a line, and then printing a newline.

.TTX69

INC YC                 \ Move the text cursor down a line

\ Fall through into TT67 to print a newline

Name: TT67                                                    [Show more]
Type: Subroutine
Category: Text
Summary: Print a newline
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* CLYNS calls TT67
* menu calls TT67
* plf calls TT67

.TT67

LDA #12                \ Load a newline character into A

JMP TT27               \ Print the text token in A and return from the
\ subroutine using a tail call

Name: TT70                                                    [Show more]
Type: Subroutine
Category: Text
Summary: Display "MAINLY " and jump to TT72
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT25 calls TT70

This subroutine is called by TT25 when displaying a system's economy.

.TT70

LDA #173               \ Print recursive token 13 ("MAINLY ")
JSR TT27

JMP TT72               \ Jump to TT72 to continue printing system data as part
\ of routine TT25

Name: spc                                                     [Show more]
Type: Subroutine
Category: Text
Summary: Print a text token followed by a space
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT25 calls spc

Print a text token (i.e. a character, control code, two-letter token or
recursive token) followed by a space.

Arguments:

A                    The text token to be printed

.spc

JSR TT27               \ Print the text token in A

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

Name: TT25                                                    [Show more]
Type: Subroutine
Category: Universe
Summary: Show the Data on System screen (red key f6) or Encyclopedia screen
(CTRL-f6)
Deep dive: Generating system data
Galaxy and system seeds
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls TT25
* TT70 calls entry point TT72

Other entry points:

TT72                 Used by TT70 to re-enter the routine after displaying
"MAINLY" for the economy type

.TT25

LDA #1                 \ Clear the top part of the screen, draw a white border,
JSR TT66               \ and set the current view type in QQ11 to 1

LDA #9                 \ Move the text cursor to column 9
STA XC

LDA #163               \ Print recursive token 3 ("DATA ON {selected system
JSR NLIN3              \ name}" and draw a horizontal line at pixel row 19
\ to box in the title

JSR TTX69              \ Print a paragraph break and set Sentence Case

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

LDA #194               \ Print recursive token 34 ("ECONOMY") followed by
JSR TT68               \ a colon

LDA QQ3                \ The system economy is determined by the value in QQ3,
\ so fetch it into A. First we work out the system's
\ prosperity as follows:
\
\   QQ3 = 0 or 5 = %000 or %101 = Rich
\   QQ3 = 1 or 6 = %001 or %110 = Average
\   QQ3 = 2 or 7 = %010 or %111 = Poor
\   QQ3 = 3 or 4 = %011 or %100 = Mainly

CLC                    \ If (QQ3 + 1) >> 1 = %10, i.e. if QQ3 = %011 or %100
ADC #1                 \ (3 or 4), then call TT70, which prints "MAINLY " and
LSR A                  \ jumps down to TT72 to print the type of economy
CMP #%00000010
BEQ TT70

LDA QQ3                \ The LSR A above shifted bit 0 of QQ3 into the C flag,
BCC TT71               \ so this jumps to TT71 if bit 0 of QQ3 is 0, in other
\ words if QQ3 = %000, %001 or %010 (0, 1 or 2)

SBC #5                 \ Here QQ3 = %101, %110 or %111 (5, 6 or 7), so subtract
CLC                    \ 5 to bring it down to 0, 1 or 2 (the C flag is already
\ set so the SBC will be correct)

.TT71

ADC #170               \ A is now 0, 1 or 2, so print recursive token 10 + A.
JSR TT27               \ This means that:
\
\   QQ3 = 0 or 5 prints token 10 ("RICH ")
\   QQ3 = 1 or 6 prints token 11 ("AVERAGE ")
\   QQ3 = 2 or 7 prints token 12 ("POOR ")

.TT72

LDA QQ3                \ Now to work out the type of economy, which is
LSR A                  \ determined by bit 2 of QQ3, as follows:
LSR A                  \
\   QQ3 bit 2 = 0 = Industrial
\   QQ3 bit 2 = 1 = Agricultural
\
\ So we fetch QQ3 into A and set A = bit 2 of QQ3 using
\ two right shifts (which will work as QQ3 is only a
\ 3-bit number)

CLC                    \ Print recursive token 8 + A, followed by a paragraph
ADC #168               \ break and Sentence Case, so:
JSR TT60               \
\   QQ3 bit 2 = 0 prints token 8 ("INDUSTRIAL")
\   QQ3 bit 2 = 1 prints token 9 ("AGRICULTURAL")

LDA #162               \ Print recursive token 2 ("GOVERNMENT") followed by
JSR TT68               \ a colon

LDA QQ4                \ The system economy is determined by the value in QQ4,
\ so fetch it into A

CLC                    \ Print recursive token 17 + A, followed by a paragraph
ADC #177               \ break and Sentence Case, so:
JSR TT60               \
\   QQ4 = 0 prints token 17 ("ANARCHY")
\   QQ4 = 1 prints token 18 ("FEUDAL")
\   QQ4 = 2 prints token 19 ("MULTI-GOVERNMENT")
\   QQ4 = 3 prints token 20 ("DICTATORSHIP")
\   QQ4 = 4 prints token 21 ("COMMUNIST")
\   QQ4 = 5 prints token 22 ("CONFEDERACY")
\   QQ4 = 6 prints token 23 ("DEMOCRACY")
\   QQ4 = 7 prints token 24 ("CORPORATE STATE")

LDA #196               \ Print recursive token 36 ("TECH.LEVEL") followed by a
JSR TT68               \ colon

LDX QQ5                \ Fetch the tech level from QQ5 and increment it, as it
INX                    \ is stored in the range 0-14 but the displayed range
\ should be 1-15

CLC                    \ Call pr2 to print the technology level as a 3-digit
JSR pr2                \ number without a decimal point (by clearing the C
\ flag)

JSR TTX69              \ Print a paragraph break and set Sentence Case

LDA #192               \ Print recursive token 32 ("POPULATION") followed by a
JSR TT68               \ colon

SEC                    \ Call pr2 to print the population as a 3-digit number
LDX QQ6                \ with a decimal point (by setting the C flag), so the
JSR pr2                \ number printed will be population / 10

LDA #198               \ Print recursive token 38 (" BILLION"), followed by a
JSR TT60               \ paragraph break and Sentence Case

LDA #'('               \ Print an opening bracket
JSR TT27

LDA QQ15+4             \ Now to calculate the species, so first check bit 7 of
BMI TT75               \ s2_lo, and if it is set, jump to TT75 as this is an
\ alien species

LDA #188               \ Bit 7 of s2_lo is clear, so print recursive token 28
JSR TT27               \ ("HUMAN COLONIAL")

JMP TT76               \ Jump to TT76 to print "S)" and a paragraph break, so
\ the whole species string is "(HUMAN COLONIALS)"

.TT75

LDA QQ15+5             \ This is an alien species, and we start with the first
LSR A                  \ adjective, so fetch bits 2-7 of s2_hi into A and push
LSR A                  \ onto the stack so we can use this later
PHA

AND #%00000111         \ Set A = bits 0-2 of A (so that's bits 2-4 of s2_hi)

CMP #3                 \ If A >= 3, jump to TT205 to skip the first adjective,
BCS TT205

ADC #227               \ Otherwise A = 0, 1 or 2, so print recursive token
JSR spc                \ 67 + A, followed by a space, so:
\
\   A = 0 prints token 67 ("LARGE") and a space
\   A = 1 prints token 67 ("FIERCE") and a space
\   A = 2 prints token 67 ("SMALL") and a space

.TT205

PLA                    \ Now for the second adjective, so restore A to bits
LSR A                  \ 2-7 of s2_hi, and throw away bits 2-4 to leave
LSR A                  \ A = bits 5-7 of s2_hi
LSR A

CMP #6                 \ If A >= 6, jump to TT206 to skip the second adjective
BCS TT206

ADC #230               \ Otherwise A = 0 to 5, so print recursive token
JSR spc                \ 70 + A, followed by a space, so:
\
\   A = 0 prints token 70 ("GREEN") and a space
\   A = 1 prints token 71 ("RED") and a space
\   A = 2 prints token 72 ("YELLOW") and a space
\   A = 3 prints token 73 ("BLUE") and a space
\   A = 4 prints token 74 ("BLACK") and a space
\   A = 5 prints token 75 ("HARMLESS") and a space

.TT206

LDA QQ15+3             \ Now for the third adjective, so EOR the high bytes of
EOR QQ15+1             \ s0 and s1 and extract bits 0-2 of the result:
AND #%00000111         \
STA QQ19               \   A = (s0_hi EOR s1_hi) AND %111
\
\ storing the result in QQ19 so we can use it later

CMP #6                 \ If A >= 6, jump to TT207 to skip the third adjective
BCS TT207

ADC #236               \ Otherwise A = 0 to 5, so print recursive token
JSR spc                \ 76 + A, followed by a space, so:
\
\   A = 0 prints token 76 ("SLIMY") and a space
\   A = 1 prints token 77 ("BUG-EYED") and a space
\   A = 2 prints token 78 ("HORNED") and a space
\   A = 3 prints token 79 ("BONY") and a space
\   A = 4 prints token 80 ("FAT") and a space
\   A = 5 prints token 81 ("FURRY") and a space

.TT207

LDA QQ15+5             \ Now for the actual species, so take bits 0-1 of
AND #%00000011         \ s2_hi, add this to the value of A that we used for
CLC                    \ the third adjective, and take bits 0-2 of the result
ADC QQ19
AND #%00000111

ADC #242               \ A = 0 to 7, so print recursive token 82 + A, so:
JSR TT27               \
\   A = 0 prints token 76 ("RODENT")
\   A = 1 prints token 76 ("FROG")
\   A = 2 prints token 76 ("LIZARD")
\   A = 3 prints token 76 ("LOBSTER")
\   A = 4 prints token 76 ("BIRD")
\   A = 5 prints token 76 ("HUMANOID")
\   A = 6 prints token 76 ("FELINE")
\   A = 7 prints token 76 ("INSECT")

.TT76

LDA #'S'               \ Print an "S" to pluralise the species
JSR TT27

LDA #')'               \ And finally, print a closing bracket, followed by a
JSR TT60               \ paragraph break and Sentence Case, to end the species
\ section

LDA #193               \ Print recursive token 33 ("GROSS PRODUCTIVITY"),
JSR TT68               \ followed by colon

LDX QQ7                \ Fetch the 16-bit productivity value from QQ7 into
LDY QQ7+1              \ (Y X)

JSR pr6                \ Print (Y X) to 5 digits with no decimal point

JSR TT162              \ Print a space

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

LDA #'M'               \ Print "M"
JSR TT27

LDA #226               \ Print recursive token 66 (" CR"), followed by a
JSR TT60               \ paragraph break and Sentence Case

LDA #250               \ Print recursive token 90 ("AVERAGE RADIUS"), followed
JSR TT68               \ by a colon

\ The average radius is calculated like this:
\
\   ((s2_hi AND %1111) + 11) * 256 + s1_hi
\
\ or, in terms of memory locations:
\
\   ((QQ15+5 AND %1111) + 11) * 256 + QQ15+3
\
\ Because the multiplication is by 256, this is the
\ same as saying a 16-bit number, with high byte:
\
\   (QQ15+5 AND %1111) + 11
\
\ and low byte:
\
\   QQ15+3
\
\ so we can set this up in (Y X) and call the pr5
\ routine to print it out

LDA QQ15+5             \ Set A = QQ15+5
LDX QQ15+3             \ Set X = QQ15+3

AND #%00001111         \ Set Y = (A AND %1111) + 11
CLC
ADC #11
TAY

JSR pr5                \ Print (Y X) to 5 digits, not including a decimal
\ point, as the C flag will be clear (as the maximum
\ radius will always fit into 16 bits)

JSR TT162              \ Print a space

LDA #'k'               \ Print "km"
JSR TT26
LDA #'m'
JSR TT26

JSR TTX69              \ Print a paragraph break and set Sentence Case

\ By this point, ZZ contains the current system number
\ which PDESC requires. It gets put there in the TT102
\ routine, which calls TT111 to populate ZZ before
\ calling TT25 (this routine)

\ --- Mod: Original Acornsoft code removed: ----------->

\ JMP PDESC             \ Jump to PDESC to print the system's extended
\                       \ description, returning from the subroutine using a
\                       \ tail call

\                       \ The following code doesn't appear to be called from
\                       \ anywhere, so it's presumably a remnant of code from
\                       \ an earlier version of the extended description code

\ LDX ZZ                \ Fetch the system number from ZZ into X

\ RTS                   \ Return from the subroutine

\ --- And replaced by: -------------------------------->

JMP PD1                \ Jump to PD1 to print the standard "goat soup" system
\ description without checking for overrides, returning
\ from the subroutine using a tail call

\ --- End of replacement ------------------------------>

Name: TT24                                                    [Show more]
Type: Subroutine
Category: Universe
Summary: Calculate system data from the system seeds
Deep dive: Generating system data
Galaxy and system seeds
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT111 calls TT24

Calculate system data from the seeds in QQ15 and store them in the relevant
locations. Specifically, this routine calculates the following from the three
16-bit seeds in QQ15 (using only s0_hi, s1_hi and s1_lo):

QQ3 = economy (0-7)
QQ4 = government (0-7)
QQ5 = technology level (0-14)
QQ6 = population * 10 (1-71)
QQ7 = productivity (96-62480)

The ranges of the various values are shown in brackets. Note that the radius
and type of inhabitant are calculated on-the-fly in the TT25 routine when
the system data gets displayed, so they aren't calculated here.

.TT24

LDA QQ15+1             \ Fetch s0_hi and extract bits 0-2 to determine the
AND #%00000111         \ system's economy, and store in QQ3
STA QQ3

LDA QQ15+2             \ Fetch s1_lo and extract bits 3-5 to determine the
LSR A                  \ system's government, and store in QQ4
LSR A
LSR A
AND #%00000111
STA QQ4

LSR A                  \ If government isn't anarchy or feudal, skip to TT77,
BNE TT77               \ as we need to fix the economy of anarchy and feudal
\ systems so they can't be rich

LDA QQ3                \ Set bit 1 of the economy in QQ3 to fix the economy
ORA #%00000010         \ for anarchy and feudal governments
STA QQ3

.TT77

LDA QQ3                \ Now to work out the tech level, which we do like this:
EOR #%00000111         \
CLC                    \   flipped_economy + (s1_hi AND %11) + (government / 2)
STA QQ5                \
\ or, in terms of memory locations:
\
\   QQ5 = (QQ3 EOR %111) + (QQ15+3 AND %11) + (QQ4 / 2)
\
\ We start by setting QQ5 = QQ3 EOR %111

LDA QQ15+3             \ We then take the first 2 bits of s1_hi (QQ15+3) and
AND #%00000011         \ add it into QQ5
ADC QQ5
STA QQ5

LDA QQ4                \ And finally we add QQ4 / 2 and store the result in
LSR A                  \ QQ5, using LSR then ADC to divide by 2, which rounds
ADC QQ5                \ up the result for odd-numbered government types
STA QQ5

ASL A                  \ Now to work out the population, like so:
ASL A                  \
ADC QQ3                \   (tech level * 4) + economy + government + 1
ADC QQ4                \
ADC #1                 \ or, in terms of memory locations:
STA QQ6                \
\   QQ6 = (QQ5 * 4) + QQ3 + QQ4 + 1

LDA QQ3                \ Finally, we work out productivity, like this:
EOR #%00000111         \
ADC #3                 \  (flipped_economy + 3) * (government + 4)
STA P                  \                        * population
LDA QQ4                \                        * 8
ADC #4                 \
STA Q                  \ or, in terms of memory locations:
JSR MULTU              \
\   QQ7 = (QQ3 EOR %111 + 3) * (QQ4 + 4) * QQ6 * 8
\
\ We do the first step by setting P to the first
\ expression in brackets and Q to the second, and
\ calling MULTU, so now (A P) = P * Q. The highest this
\ can be is 10 * 11 (as the maximum values of economy
\ and government are 7), so the high byte of the result
\ will always be 0, so we actually have:
\
\   P = P * Q
\     = (flipped_economy + 3) * (government + 4)

LDA QQ6                \ We now take the result in P and multiply by the
STA Q                  \ population to get the productivity, by setting Q to
JSR MULTU              \ the population from QQ6 and calling MULTU again, so
\ now we have:
\
\   (A P) = P * population

ASL P                  \ Next we multiply the result by 8, as a 16-bit number,
ROL A                  \ so we shift both bytes to the left three times, using
ASL P                  \ the C flag to carry bits from bit 7 of the low byte
ROL A                  \ into bit 0 of the high byte
ASL P
ROL A

STA QQ7+1              \ Finally, we store the productivity in two bytes, with
LDA P                  \ the low byte in QQ7 and the high byte in QQ7+1
STA QQ7

RTS                    \ Return from the subroutine

Name: TT22                                                    [Show more]
Type: Subroutine
Category: Charts
Summary: Show the Long-range Chart (red key f4)
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls TT22

.TT22

LDA #64                \ Clear the top part of the screen, draw a white border,
JSR TT66               \ and set the current view type in QQ11 to 32 (Long-
\ range Chart)

LDA #7                 \ Move the text cursor to column 7
STA XC

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 #199               \ Print recursive token 39 ("GALACTIC CHART{galaxy
JSR TT27               \ number right-aligned to width 3}")

JSR NLIN               \ Draw a horizontal line at pixel row 23 to box in the
\ title and act as the top frame of the chart, and move
\ the text cursor down one line

LDA #152               \ Draw a screen-wide horizontal line at pixel row 152
JSR NLIN2              \ for the bottom edge of the chart, so the chart itself
\ is 128 pixels high, starting on row 24 and ending on
\ row 151

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

LDX #0                 \ We're now going to plot each of the galaxy's systems,
\ so set up a counter in X for each system, starting at
\ 0 and looping through to 255

.TT83

STX XSAV               \ Store the counter in XSAV

LDX QQ15+3             \ Fetch the s1_hi seed into X, which gives us the
\ galactic x-coordinate of this system

LDY QQ15+4             \ Fetch the s2_lo seed and set bits 4 and 6, storing the
TYA                    \ result in ZZ to give a random number between 80 and
ORA #%01010000         \ (but which will always be the same for this system).
STA ZZ                 \ We use this value to determine the size of the point
\ for this system on the chart by passing it as the
\ distance argument to the PIXEL routine below

LDA QQ15+1             \ Fetch the s0_hi seed into A, which gives us the
\ galactic y-coordinate of this system

LSR A                  \ We halve the y-coordinate 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 the
\ chart is 256 pixels wide and 128 high

CLC                    \ Add 24 to the halved y-coordinate and store in XX15+1
ADC #24                \ (as the top of the chart is on pixel row 24, just
STA XX15+1             \ below the line we drew on row 23 above)

JSR PIXEL              \ Call PIXEL to draw a point at (X, A), with the size of
\ the point dependent on the distance specified in ZZ
\ (so a high value of ZZ will produce a 1-pixel point,
\ a medium value will produce a 2-pixel dash, and a
\ small value will produce a 4-pixel square)

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

LDX XSAV               \ Restore the loop counter from XSAV

INX                    \ Increment the counter

BNE TT83               \ If X > 0 then we haven't done all 256 systems yet, so
\ loop back up to TT83

LDA QQ9                \ Set QQ19 to the selected system's x-coordinate
STA QQ19

LDA QQ10               \ Set QQ19+1 to the selected system's y-coordinate,
LSR A                  \ halved to fit it into the chart
STA QQ19+1

LDA #4                 \ Set QQ19+2 to size 4 for the crosshairs size
STA QQ19+2

\ Fall through into TT15 to draw crosshairs of size 4 at
\ the selected system's coordinates

Name: TT15                                                    [Show more]
Type: Subroutine
Category: Drawing lines
Summary: Draw a set of crosshairs
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT103 calls TT15
* TT105 calls TT15
* TT14 calls TT15

For all views except the Short-range Chart, the centre is drawn 24 pixels to
the right of the y-coordinate given.

Arguments:

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

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

QQ19+2               The size of the crosshairs

.TT15

LDA #24                \ Set A to 24, which we will use as the minimum
\ screen indent for the crosshairs (i.e. the minimum
\ distance from the top-left corner of the screen)

LDX QQ11               \ If the current view is not the Short-range Chart,
BPL P%+4               \ which is the only view with bit 7 set, then skip the
\ following instruction

LDA #0                 \ This is the Short-range Chart, so set A to 0, so the
\ crosshairs can go right up against the screen edges

STA QQ19+5             \ Set QQ19+5 to A, which now contains the correct indent
\ for this view

LDA QQ19               \ Set A = crosshairs x-coordinate - crosshairs size
SEC                    \ to get the x-coordinate of the left edge of the
SBC QQ19+2             \ crosshairs

BCS TT84               \ If the above subtraction didn't underflow, then A is
\ positive, so skip the next instruction

LDA #0                 \ The subtraction underflowed, so set A to 0 so the
\ crosshairs don't spill out of the left of the screen

.TT84

\ In the following, the authors have used XX15 for
\ temporary storage. XX15 shares location with X1, Y1,
\ X2 and Y2, so in the following, you can consider
\ the variables like this:
\
\   XX15   is the same as X1
\   XX15+1 is the same as Y1
\   XX15+2 is the same as X2
\   XX15+3 is the same as Y2
\
\ Presumably this routine was written at a different
\ time to the line-drawing routine, before the two
\ workspaces were merged to save space

STA XX15               \ Set XX15 (X1) = A (the x-coordinate of the left edge
\ of the crosshairs)

LDA QQ19               \ Set A = crosshairs x-coordinate + crosshairs size
CLC                    \ to get the x-coordinate of the right edge of the
ADC QQ19+2             \ crosshairs

BCC P%+4               \ If the above addition didn't overflow, then A is
\ correct, so skip the next instruction

LDA #255               \ The addition overflowed, so set A to 255 so the
\ crosshairs don't spill out of the right of the screen
\ (as 255 is the x-coordinate of the rightmost pixel
\ on-screen)

STA XX15+2             \ Set XX15+2 (X2) = A (the x-coordinate of the right
\ edge of the crosshairs)

LDA QQ19+1             \ Set XX15+1 (Y1) = crosshairs y-coordinate + indent
CLC                    \ to get the y-coordinate of the centre of the
ADC QQ19+5             \ crosshairs
STA XX15+1

JSR HLOIN              \ Draw a horizontal line from (X1, Y1) to (X2, Y1),
\ which will draw from the left edge of the crosshairs
\ to the right edge, through the centre of the
\ crosshairs

LDA QQ19+1             \ Set A = crosshairs y-coordinate - crosshairs size
SEC                    \ to get the y-coordinate of the top edge of the
SBC QQ19+2             \ crosshairs

BCS TT86               \ If the above subtraction didn't underflow, then A is
\ correct, so skip the next instruction

LDA #0                 \ The subtraction underflowed, so set A to 0 so the
\ crosshairs don't spill out of the top of the screen

.TT86

CLC                    \ Set XX15+1 (Y1) = A + indent to get the y-coordinate
ADC QQ19+5             \ of the top edge of the indented crosshairs
STA XX15+1

LDA QQ19+1             \ Set A = crosshairs y-coordinate + crosshairs size
CLC                    \ + indent to get the y-coordinate of the bottom edge
ADC QQ19+2             \ of the indented crosshairs
ADC QQ19+5

CMP #152               \ If A < 152 then skip the following, as the crosshairs
BCC TT87               \ won't spill out of the bottom of the screen

LDX QQ11               \ A >= 152, so we need to check whether this will fit in
\ this view, so fetch the view number

BMI TT87               \ If this is the Short-range Chart then the y-coordinate
\ is fine, so skip to TT87

LDA #151               \ Otherwise this is the Long-range Chart, so we need to
\ clip the crosshairs at a maximum y-coordinate of 151

.TT87

STA XX15+3             \ Set XX15+3 (Y2) = A (the y-coordinate of the bottom
\ edge of the crosshairs)

LDA QQ19               \ Set XX15 (X1) = the x-coordinate of the centre of the
STA XX15               \ crosshairs

STA XX15+2             \ Set XX15+2 (X2) = the x-coordinate of the centre of
\ the crosshairs

JMP LL30               \ Draw a vertical line (X1, Y1) to (X2, Y2), which will
\ draw from the top edge of the crosshairs to the bottom
\ edge, through the centre of the crosshairs, returning
\ from the subroutine using a tail call

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 to the fuel level from QQ14, so this can act as
STA K                  \ the circle's radius (70 being a full tank)

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 current view is the Short-range Chart, which
BMI TT126              \ is the only view with bit 7 set, then jump up to TT126
\ to draw the crosshairs and circle for that view

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

LDA QQ14               \ Set K to the fuel level from QQ14 divided by 4, so
LSR A                  \ this can act as the circle's radius (70 being a full
LSR A                  \ tank, which divides down to a radius of 17)
STA K

LDA QQ0                \ Set QQ19 to the x-coordinate of the current system,
STA QQ19               \ which will be the centre of the circle and crosshairs
\ we draw

LDA QQ1                \ Set QQ19+1 to the y-coordinate of the current system,
LSR A                  \ halved because the galactic chart is half as high as
STA QQ19+1             \ it is wide, which will again be the centre of the
\ circle and crosshairs we draw

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

Name: TT128                                                   [Show more]
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

INX                    \ Set LSP = 1 to reset the ball line heap
STX LSP

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

JMP CIRCLE2            \ 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

Name: TT16                                                    [Show more]
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

.TT16

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

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

JSR WSCAN              \ Call WSCAN to wait for the vertical sync, so the whole
\ screen gets drawn and we can move the crosshairs with
\ no screen flicker

JSR TT103              \ Draw small crosshairs at coordinates (QQ9, QQ10),
\ which will erase the crosshairs currently there

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

Name: TT103                                                   [Show more]
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:
* HME2 calls TT103
* TT102 calls TT103
* TT16 calls TT103
* TT23 calls TT103
* hm calls TT103

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

.TT103

LDA QQ11               \ Fetch the current view type into A

BMI TT105              \ If this is the Short-range Chart screen, jump to TT105

LDA QQ9                \ Store the crosshairs x-coordinate in QQ19
STA QQ19

LDA QQ10               \ Halve the crosshairs y-coordinate and store it in QQ19
LSR A                  \ (we halve it because the Long-range Chart is half as
STA QQ19+1             \ high as it is wide)

LDA #4                 \ Set QQ19+2 to 4 denote crosshairs of size 4
STA QQ19+2

JMP TT15               \ Jump to TT15 to draw crosshairs of size 4 at the
\ crosshairs coordinates, returning from the subroutine
\ using a tail call

Name: TT123                                                   [Show more]
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
* TT105 calls entry point TT180

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 the same as A if moving by the delta overflows)

Other entry points:

TT180                Contains an RTS

.TT123

STA QQ19+4             \ Store the original coordinate in temporary storage at
\ QQ19+4

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

LDX QQ19+3             \ If the delta is negative, jump to TT124
BMI TT124

BCC TT125              \ If the C flag is clear, then the above addition didn't
\ overflow, so jump to TT125 to return the updated value

RTS                    \ Otherwise the C flag is set and the above addition
\ overflowed, so do not update the return value

.TT124

BCC TT180              \ If the C flag is clear, then because the delta is
\ negative, this indicates the addition (which is
\ effectively a subtraction) underflowed, so jump to
\ TT180 to return from the subroutine without updating
\ the return value

.TT125

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

.TT180

RTS                    \ Return from the subroutine

Name: TT105                                                   [Show more]
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 #38                \ If the horizontal distance in A < 38, then the
BCC TT179              \ crosshairs are close enough to the current system to
\ appear in the Short-range Chart, so jump to TT179 to
\ check the vertical distance

CMP #230               \ If the horizontal distance in A < -26, then the
BCC TT180              \ crosshairs are too far from the current system to
\ appear in the Short-range Chart, so jump to TT180 to
\ return from the subroutine (as TT180 contains an RTS)

.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 TT180              \ crosshairs are too far from the current system to
\ appear in the Short-range Chart, so jump to TT180 to
\ return from the subroutine (as TT180 contains an RTS)

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

JMP TT15               \ Jump to TT15 to draw crosshairs of size 8 at the
\ crosshairs coordinates, returning from the subroutine
\ using a tail call

Name: TT23                                                    [Show more]
Type: Subroutine
Category: Charts
Summary: Show the Short-range Chart (red key f5)
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls TT23

.TT23

LDA #128               \ Clear the top part of the screen, draw a white border,
JSR TT66               \ and set the current view type in QQ11 to 128 (Short-
\ range Chart)

LDA #7                 \ Move the text cursor to column 7
STA XC

LDA #190               \ Print recursive token 30 ("SHORT RANGE CHART") and
JSR NLIN3              \ draw a horizontal line at pixel row 19 to box in the
\ title

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

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
\ result is positive, so jump to TT184 and skip 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
\ appear in the Short-range Chart, so jump to TT187 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
\ result is positive, so jump to TT186 and skip 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
\ appear in the Short-range Chart, so jump to TT187 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
STA XC
INC 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
ADC #90                \
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 it), jump to EE4 to store this
\ 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,
\ otherwise jump to ee1 to skip printing a label for
\ this system (as there simply isn't room)

.EE4

STY YC                 \ Now to print the label, so move the text cursor to row
\ 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 SUN routine to draw a
\ small "sun" on the Short-range Chart for this system

JSR FLFLLS             \ Call FLFLLS to reset the LSO block

JSR SUN                \ Call SUN to plot a sun with radius K at pixel
\ coordinate (K3, K4)

JSR FLFLLS             \ Call FLFLLS to reset the LSO block

.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 TT111-1            \ If X = 0 then we have done all 256 systems, so return
\ from the subroutine (as TT111-1 contains an RTS)

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

Name: TT81                                                    [Show more]
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

Name: TT111                                                   [Show more]
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:
* HME2 calls TT111
* TT102 calls TT111
* hm calls TT111
* TT23 calls entry point TT111-1

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

ZZ                   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

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
\ result is positive, so jump to TT132 and skip 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
\ result is positive, so jump to TT134 and skip 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
ADC S                  \
\ 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
\ skip to TT135 to move on to the next system

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 ZZ, so when we are done
STA ZZ                 \ looping through all the candidates, the winner's
\ number will be in ZZ

.TT135

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 QQ15,
STA QQ15,X

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
\ result is positive, so jump to TT139 and skip 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
\ result is positive, so jump to TT141 and skip 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

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

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

ADC K+1                \ Set R = A + K+1, which adds the high bytes of the two
STA R                  \ calculated values, so we now have:
\
\   (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               \ 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

Name: pr6                                                     [Show more]
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: This subroutine is called as follows:
* TT25 calls pr6

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

Name: pr5                                                     [Show more]
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
* TT25 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

Name: TT162                                                   [Show more]
Type: Subroutine
Category: Text
Summary: Print a space

Other entry points:

TT162+2              Jump to TT27 to print the text token in A
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT25 calls TT162
* TTX66 calls TT162
* menu calls TT162
* spc calls TT162

.TT162

LDA #' '               \ Load a space character into A

JMP TT27               \ Print the text token in A and return from the
\ subroutine using a tail call

Name: func_tab                                                [Show more]
Type: Variable
Category: Keyboard
Summary: Lookup table for internal numbers of red function keys
Context: See this variable on its own page
References: This variable is used as follows:
* buy_invnt calls func_tab

\ --- Mod: Whole section added for Elite-A: ----------->

.func_tab

EQUB f0, f1, f2, f3, f4, f5, f6, f7, f8, f9

\ --- End of added section ---------------------------->

Name: buy_invnt                                               [Show more]
Type: Subroutine
Category: Buying ships
Summary: Process key presses in the encyclopedia
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* gnum calls buy_invnt

Arguments:

A                    The ASCII value of the key pressed, minus ASCII "0"

\ --- Mod: Whole section added for Elite-A: ----------->

.buy_invnt

SBC #(128 - '0')       \ We already subtracted ASCII "0" from the ASCII value
\ of the key pressed, so this subtracts 128 from the
\ original ASCII value of the key pressed. As red key f0
\ is given ASCII value 128, and f1 is 129 and so on,
\ this reduces a key press of f0 to A = 0, a key press
\ of f1 to A = 1, and so on

BCC buy_top            \ If the subtraction just underflowed, then the key
\ pressed was not a red function key, so jump to buy_top
\ to "press" red key f1 (Encyclopedia screen)

CMP #10                \ If A < 10, then the key pressed was a red function
BCC buy_func           \ key, so jump to buy_func so we press the red key whose
\ number is in A (so A = 0 "presses" red key f0, A = 1
\ "presses" red key f1, and so on)

\ Otherwise A >= 10, so the key pressed is something
\ else, so fall through into buy_top to "press" red key
\ f1 (Encyclopedia screen)

.buy_top

LDA #1                 \ Set A = 1 so we "press" red key f1 (Encyclopedia
\ screen) in the following

.buy_func

TAX                    \ Jump into the main loop at FRCE, setting the key to
LDA func_tab,X         \ the X-th red key (so X = 0 "presses" red key f0, X = 1
JMP FRCE               \ "presses" red key f1, and so on)

\ --- End of added section ---------------------------->

Name: gnum                                                    [Show more]
Type: Subroutine
Category: Market
Summary: Get a number from the keyboard
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* menu calls gnum

Get a number from the keyboard, up to the maximum number in QQ25, for the
buying and selling of cargo and equipment.

Pressing "Y" will return the maximum number (i.e. buy/sell all items), while
pressing "N" will abort the sale and return a 0.

Pressing a key with an ASCII code less than ASCII "0" will return a 0 in A (so
that includes pressing Space or Return), while pressing a key with an ASCII
code greater than ASCII "9" will jump to the Inventory screen (so that
includes all letters and most punctuation).

Arguments:

QQ25                 The maximum number allowed

Returns:

A                    The number entered

R                    Also contains the number entered

C flag               Set if the number is too large (> QQ25), clear otherwise

.gnum

LDX #0                 \ We will build the number entered in R, so initialise
STX R                  \ it with 0

LDX #12                \ We will check for up to 12 key presses, so set a
STX T1                 \ counter in T1

.TT223

JSR TT217              \ Scan the keyboard until a key is pressed, and return
\ the key's ASCII code in A (and X)

LDX R                  \ If R is non-zero then skip to NWDAV2, as we are
BNE NWDAV2             \ already building a number

\ --- Mod: Original Acornsoft code removed: ----------->

\ CMP #'y'              \ If "Y" was pressed, jump to NWDAV1 to return the
\ BEQ NWDAV1            \ maximum number allowed (i.e. buy/sell the whole stock)

\ CMP #'n'              \ If "N" was pressed, jump to NWDAV3 to return from the
\ BEQ NWDAV3            \ subroutine with a result of 0 (i.e. abort transaction)

\ --- End of removed code ----------------------------->

.NWDAV2

STA Q                  \ Store the key pressed in Q

SEC                    \ Subtract ASCII "0" from the key pressed, to leave the
SBC #'0'               \ numeric value of the key in A (if it was a number key)

BCC OUT                \ If A < 0, jump to OUT to return from the subroutine
\ with a result of 0, as the key pressed was not a
\ number or letter and is less than ASCII "0"

\ --- Mod: Original Acornsoft code removed: ----------->

\ CMP #10               \ If A >= 10, jump to BAY2 to display the Inventory
\ BCS BAY2              \ screen, as the key pressed was a letter or other
\                       \ non-digit and is greater than ASCII "9"

\ --- And replaced by: -------------------------------->

CMP #10                \ If A >= 10, jump to buy_invnt to decide which screen
BCS buy_invnt          \ to display, as the key pressed was a letter or other
\ non-digit and is greater than ASCII "9" (so it could
\ be a red function key, for example)

\ --- End of replacement ------------------------------>

STA S                  \ Store the numeric value of the key pressed in S

LDA R                  \ Fetch the result so far into A

CMP #26                \ If A >= 26, where A is the number entered so far, then
BCS OUT                \ adding a further digit will make it bigger than 256,
\ so jump to OUT to return from the subroutine with the
\ result in R (i.e. ignore the last key press)

ASL A                  \ Set A = (A * 2) + (A * 8) = A * 10
STA T
ASL A
ASL A
ADC T

ADC S                  \ Add the pressed digit to A and store in R, so R now
STA R                  \ contains its previous value with the new key press
\ tacked onto the end

CMP QQ25               \ If the result in R = the maximum allowed in QQ25, jump
BEQ TT226              \ to TT226 to print the key press and keep looping (the
\ BEQ is needed because the BCS below would jump to OUT
\ if R >= QQ25, which we don't want)

BCS OUT                \ If the result in R > QQ25, jump to OUT to return from
\ the subroutine with the result in R

.TT226

LDA Q                  \ Print the character in Q (i.e. the key that was
JSR TT26               \ pressed, as we stored the ASCII value in Q earlier)

DEC T1                 \ Decrement the loop counter

BNE TT223              \ Loop back to TT223 until we have checked for 12 digits

.OUT

LDA R                  \ Set A to the result we have been building in R

RTS                    \ Return from the subroutine

\ --- Mod: Original Acornsoft code removed: ----------->

\.NWDAV1

\                       \ If we get here then "Y" was pressed, so we return the
\                       \ maximum number allowed, which is in QQ25

\ JSR TT26              \ Print the character for the key that was pressed

\ LDA QQ25              \ Set R = QQ25, so we return the maximum value allowed
\ STA R

\ RTS                   \ Return from the subroutine

\.NWDAV3

\                       \ If we get here then "N" was pressed, so we return 0

\ JSR TT26              \ Print the character for the key that was pressed

\ LDA #0                \ Set R = 0, so we return 0
\ STA R

\ RTS                   \ Return from the subroutine

\ --- End of removed code ----------------------------->

Name: dn2                                                     [Show more]
Type: Subroutine
Category: Text
Summary: Make a short, high beep and delay for 1 second
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* info_menu calls dn2

.dn2

JSR BEEP               \ Call the BEEP subroutine to make a short, high beep

LDY #50                \ Delay for 50 vertical syncs (50/50 = 1 second) and
JMP DELAY              \ return from the subroutine using a tail call

Name: hm                                                      [Show more]
Type: Subroutine
Category: Charts
Summary: Select the closest system and redraw the chart crosshairs
Context: See this subroutine on its own page
References: This subroutine is called as follows:
* TT102 calls hm

Set the system closest to galactic coordinates (QQ9, QQ10) as the selected
system, redraw the crosshairs on the chart accordingly (if they are being
shown), and, if this is not a space view, clear the bottom three text rows of
the screen.

.hm

JSR TT103              \ Draw small crosshairs at coordinates (QQ9, QQ10),
\ which will erase the crosshairs currently there

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

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

JMP CLYNS              \ Clear the bottom three 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 three bottom rows

\ Return from the subroutine using a tail call

Save ELTD.bin

PRINT "ELITE D"
PRINT "Assembled at ", ~CODE_D%
PRINT "Ends at ", ~P%
PRINT "Code size is ", ~(P% - CODE_D%)
PRINT "Execute at ", ~LOAD%
PRINT "Reload at ", ~LOAD_D%

PRINT "S.F.ELTD ", ~CODE_D%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_D%
SAVE "3-assembled-output/F.ELTD.bin", CODE_D%, P%, LOAD%

```