Skip to navigation

Elite on the BBC Micro and NES

Version analysis of TT111

This code appears in the following versions (click to see it in the source code):

Code variations between these versions are shown below.

Name: TT111 Type: Subroutine Category: Universe Summary: Set the current system to the nearest system to a point
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

Code variation 1 of 6A variation in the comments only

This variation is blank in the Cassette, Disc (flight) and Electron versions.

ZZ The system number of the nearest system

Other entry points: TT111-1 Contains an RTS

Code variation 2 of 6A variation in the comments only

This variation is blank in the Cassette, Disc (flight), Disc (docked), 6502 Second Processor and Electron versions.

readdistnce Calculate the distance between the system with galactic coordinates (A, QQ15+1) and the system at (QQ0, QQ1), returning the result in QQ8(1 0)
.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

Code variation 3 of 6Specific to an individual platform

Store the system number in ZZ so if we want to show the extended system description for this system, the PDESC routine knows which one to display.

This variation is blank in the Cassette, Disc (flight) and Electron versions.

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

Code variation 4 of 6A variation in the labels only

This variation is blank in the Cassette, Disc (flight), Disc (docked), 6502 Second Processor and Electron versions.

.readdistnce
 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

Code variation 5 of 6Minor and very low-impact

Tap on a block to expand it, and tap it again to revert.

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)
LDA QQ15+1 \ Set A = QQ15+1 - QQ1, the vertical distance between \LDA QQ10 \ the selected system's y-coordinate (QQ15+1) and the SEC \ current system's y-coordinate (QQ1) SBC QQ1 \ \ The LDA instruction is commented out in the original \ source
 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

Code variation 6 of 6Other (e.g. bug fix, optimisation)

The Master version fixes a bug in the code to calculate the distance between two systems, which can overflow in the other versions and give an incorrect result.

Tap on a block to expand it, and tap it again to revert.

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)
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               \ 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