Skip to navigation

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) ADC QQ14 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 ADC #31 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 ADC #8 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
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 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
Name: TT210 [Show more] 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, ; jump down to TT212 to skip to the next item 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 ; adjective 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 ADC #111 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 AND #%11111110 ; one, jump to carg1 to skip the following 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
Name: TT213 [Show more] 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
Name: PrintCharacter [Show more] 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
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
.cros1 JMP SetSelectedSystem ; Jump to SetSelectedSystem to update the message on ; 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), CMP #$9C ; jump to hair1 to skip the following 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
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: * 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 ADC #31 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 ADC #32 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
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

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 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 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
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 #36 ; If the horizontal distance in A < 36, 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 #233 ; If the horizontal distance in A < -23, then the BCC HideCrosshairs ; crosshairs are too far from the current system to ; appear in the Short-range Chart, so jump 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 ; appear in the Short-range Chart, so jump 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
Name: DrawCrosshairs [Show more] 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
Name: HideCrosshairs [Show more] 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
Name: xShortRange [Show more] 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
Name: TT23 [Show more] 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 ; 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 CLC ADC #1 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 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 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
Name: DrawChartSystem [Show more] 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
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: SelectNearbySystem [Show more] 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) JMP SetSelectionFlags ; Jump to SetSelectionFlags to set the selected system ; flags for the new system and update the icon bar if ; required
Name: SetSelectedSystem [Show more] 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 BMI SetCurrentSystem ; have a selected system, so jump to SetCurrentSystem ; 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
Name: SetSelectionFlags [Show more] 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
Name: SetCurrentSystem [Show more] 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
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: * BR1 calls TT111 * Ghy calls TT111 * HME2 calls TT111 * SelectNearbySystem calls TT111 * SetSelectedSystem calls TT111 * SetupAfterLoad 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 ; 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 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 ; 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 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 ADC K 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
Name: dockEd [Show more] 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
Name: GalacticHyperdrive [Show more] 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 ; has been activated, so jump to Ghy to process it RTS ; Otherwise return from the subroutine
Name: hyp [Show more] 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
Name: wW [Show more] 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
Name: Ghy [Show more] 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
Name: jmp [Show more] 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 * SetupAfterLoad 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
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: 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
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 * 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
Name: TT147 [Show more] 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
Name: prq [Show more] 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
Other entry points: prq+3 Print a question mark
.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
Name: TT151 [Show more] 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 ADC 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 ; digits (right-padded with spaces) 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
Name: PrintSpacedHyphen [Show more] 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
Name: TT152 [Show more] 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
Name: TT162 [Show more] 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+2 Jump to TT27 to print the text token in A
.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
Name: TT160 [Show more] 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
Name: TT161 [Show more] 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
Name: TT16a [Show more] 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
Name: TT163 [Show more] 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
Name: PrintNumberInHold [Show more] 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, ; jump to PrintSpacedHyphen to print two spaces, a "-", ; 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
Name: yMarketPrice [Show more] 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
Name: TT167 [Show more] 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
JMP TT213 ; Jump to TT213 to show the Inventory screen instead of ; 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
Name: BuyAndSellCargo [Show more] 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
.BuyAndSellCargo 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 ORA controller1Down ; pressed, jump to sell5 BEQ sell5 LDA controller1Left ; If neither of the left or right buttons are being ORA controller1Right ; pressed, jump to sell6 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 ADC #1 ; the hold 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, CMP #99 ; then the market is already saturated, so jump to sell4 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 ADC #1 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
Name: HighlightSaleItem [Show more] 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: * BuyAndSellCargo calls HighlightSaleItem

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
Name: PrintMarketItem [Show more] 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: * BuyAndSellCargo calls PrintMarketItem

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
Name: PrintCash [Show more] 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: * BuyAndSellCargo calls PrintCash
.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 JMP PCASH ; Jump to PCASH to print recursive token 119 ; ("CASH:{cash} CR{crlf}"), followed by a space, and ; return from the subroutine using a tail call
Name: xCash [Show more] 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
Name: yCash [Show more] 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
Name: var [Show more] 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 ADC QQ19+2 ; Add QQ19+2 to A 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
Name: hyp1 [Show more] Type: Subroutine Category: Universe Summary: Process a jump to the system closest to (QQ9, QQ10)
Context: See this subroutine on its own page References: This subroutine is called as follows: * TT18 calls hyp1

Do a hyperspace jump to the system closest to galactic coordinates (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
Name: GVL [Show more] 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 JMP TT158 ; Jump to TT158 to skip TT157 .TT157 CLC ; Set A = A + QQ19+3 ADC 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
Name: GTHG [Show more] 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
Name: MJP [Show more] 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
Name: TT18 [Show more] 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 JMP hypr2 ; Jump to hypr2 to skip the following, as we already ; 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, ORA controller1Down ; then jump to MJP to force a mis-jump 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
Name: RedrawCurrentView [Show more] 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)
Name: TT110 [Show more] 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 already in space). 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
Name: TT114 [Show more] 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 BEQ TT115 ; to jump to TT23 to display the chart JMP TT22 ; Otherwise the current view is the Long-range Chart, so ; jump to TT22 to display it .TT115 JMP TT23 ; Jump to TT23 to display the Short-range Chart
Name: LCASH [Show more] 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: * BuyAndSellCargo calls LCASH * 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 ; jump to TT113 to return from the subroutine with the ; 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
Name: MCASH [Show more] 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: * BuyAndSellCargo calls MCASH * 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: ADC CASH+2 ; STA CASH+2 ; CASH+2 = CASH+2 + Y LDA CASH+1 ; Then the third most significant bytes (which are 0): ADC #0 ; STA CASH+1 ; CASH+1 = CASH+1 + 0 LDA CASH ; And finally the most significant bytes (which are 0): ADC #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
Name: GC2 [Show more] 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: * BuyAndSellCargo calls GC2 * 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
Name: SetupAfterLoad [Show more] 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: * SetupAfterLoad_b0 calls SetupAfterLoad

This routine is very similar to the BR1 routine.
.SetupAfterLoad 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
Name: DrawCobraMkIII [Show more] 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
Name: HighlightEquipment [Show more] 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
Name: PrintEquipment [Show more] 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 ; padding 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
Name: MoveEquipmentUp [Show more] 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
Name: UpdateEquipment [Show more] 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
Name: MoveEquipmentDown [Show more] 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 ADC #1 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
Name: xEquipShip [Show more] 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
Name: EQSHP [Show more] 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 ; asking which item we want to buy) ; ; 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 ; fuel), skip to et0 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 ADC #1 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 BNE et1 ; a missile), skip to et1 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 BNE et2 ; a large cargo bay), skip to et2 LDX #37 ; If our current cargo capacity in CRGO is 37, then we CPX CRGO ; already have a large cargo bay fitted, so jump to pres 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 BNE et3 ; an E.C.M. system), skip to et3 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 BNE et4 ; an extra pulse laser), skip to et4 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 BNE et5 ; an extra beam laser), skip to et5 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 BNE et6 ; a fuel scoop), skip to et6 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 BNE et7 ; an escape pod), skip to et7 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 BNE et8 ; an energy bomb), skip to et8 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 BNE etA ; an energy unit), skip to etA 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 BNE etB ; a docking computer), skip to etB 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 BNE et9 ; a galactic hyperdrive), skip to et9 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 BNE et10 ; a military laser), skip to et10 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 BNE et11 ; a mining laser), skip to et11 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
Name: dn [Show more] 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 JMP PCASH ; Jump to PCASH to print recursive token 119 ; ("CASH:{cash} CR{crlf}"), followed by a space, and ; return from the subroutine using a tail call
Name: eq [Show more] 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 ; the transaction, so jump to c to return from the ; 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
Name: prx [Show more] 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