CODE_G% = P% LOAD_G% = LOAD% + P% - CODE%ELITE G FILE.SHPPT JSR EE51 \ Call EE51 to remove the ship's wireframe from the \ screen, if there is one JSR PROJ \ Project the ship onto the screen, returning: \ \ * K3(1 0) = the screen x-coordinate \ * K4(1 0) = the screen y-coordinate \ * A = K4+1 ORA K3+1 \ If either of the high bytes of the screen coordinates BNE nono \ are non-zero, jump to nono as the ship is off-screen LDA K4 \ Set A = the y-coordinate of the dot CMP #Y*2-2 \ If the y-coordinate is bigger than the y-coordinate of BCS nono \ the bottom of the screen, jump to nono as the ship's \ dot is off the bottom of the space view LDY #2 \ Call Shpt with Y = 2 to set up bytes 1-4 in the ship JSR Shpt \ lines space, aborting the call to LL9 if the dot is \ off the side of the screen. This call sets up the \ first row of the dot (i.e. a four-pixel dash) LDY #6 \ Set Y to 6 for the next call to Shpt LDA K4 \ Set A = y-coordinate of dot + 1 (so this is the second ADC #1 \ row of the two-pixel-high dot) JSR Shpt \ Call Shpt with Y = 6 to set up bytes 5-8 in the ship \ lines space, aborting the call to LL9 if the dot is \ off the side of the screen. This call sets up the \ second row of the dot (i.e. another four-pixel dash, \ on the row below the first one) LDA #%00001000 \ Set bit 3 of the ship's byte #31 to record that we ORA XX1+31 \ have now drawn something on-screen for this ship STA XX1+31 LDA #8 \ Set A = 8 so when we call LL18+2 next, byte #0 of the \ heap gets set to 8, for the 8 bytes we just stuck on \ the heap JMP LL81+2 \ Call LL81+2 to draw the ship's dot, returning from the \ subroutine using a tail call PLA \ Pull the return address from the stack, so the RTS PLA \ below actually returns from the subroutine that called \ LL9 (as we called SHPPT from LL9 with a JMP) .nono LDA #%11110111 \ Clear bit 3 of the ship's byte #31 to record that AND XX1+31 \ nothing is being drawn on-screen for this ship STA XX1+31 RTS \ Return from the subroutine .Shpt \ This routine sets up four bytes in the ship line heap, \ from byte Y-1 to byte Y+2. If the ship's screen point \ turns out to be off-screen, then this routine aborts \ the entire call to LL9, exiting via nono. The four \ bytes define a horizontal 4-pixel dash, for either the \ top or the bottom of the ship's dot STA (XX19),Y \ Store A in byte Y of the ship line heap INY \ Store A in byte Y+2 of the ship line heap INY STA (XX19),Y LDA K3 \ Set A = screen x-coordinate of the ship dot DEY \ Store A in byte Y+1 of the ship line heap STA (XX19),Y ADC #3 \ Set A = screen x-coordinate of the ship dot + 3 BCS nono-2 \ If the addition pushed the dot off the right side of \ the screen, jump to nono-2 to return from the parent \ subroutine early (i.e. LL9). This works because we \ called Shpt from above with a JSR, so nono-2 removes \ that return address from the stack, leaving the next \ return address exposed. LL9 called SHPPT with a JMP. \ so the next return address is the one that was put on \ the stack by the original call to LL9. So the RTS in \ nono will actually return us from the original call \ to LL9, thus aborting the entire drawing process DEY \ Store A in byte Y-1 of the ship line heap DEY STA (XX19),Y RTS \ Return from the subroutineName: SHPPT [Show more] Type: Subroutine Category: Drawing ships Summary: Draw a distant ship as a point rather than a full wireframeContext: See this subroutine on its own page References: This subroutine is called as follows: * LL9 (Part 2 of 12) calls SHPPT.LL5 LDY R \ Set (Y S) = (R Q) LDA Q STA S \ So now to calculate Q = SQRT(Y S) LDX #0 \ Set X = 0, to hold the remainder STX Q \ Set Q = 0, to hold the result LDA #8 \ Set T = 8, to use as a loop counter STA T .LL6 CPX Q \ If X < Q, jump to LL7 BCC LL7 BNE LL8 \ If X > Q, jump to LL8 CPY #64 \ If Y < 64, jump to LL7 with the C flag clear, BCC LL7 \ otherwise fall through into LL8 with the C flag set .LL8 TYA \ Set Y = Y - 64 SBC #64 \ TAY \ This subtraction will work as we know C is set from \ the BCC above, and the result will not underflow as we \ already checked that Y >= 64, so the C flag is also \ set for the next subtraction TXA \ Set X = X - Q SBC Q TAX .LL7 ROL Q \ Shift the result in Q to the left, shifting the C flag \ into bit 0 and bit 7 into the C flag ASL S \ Shift the dividend in (Y S) to the left, inserting TYA \ bit 7 from above into bit 0 ROL A TAY TXA \ Shift the remainder in X to the left ROL A TAX ASL S \ Shift the dividend in (Y S) to the left TYA ROL A TAY TXA \ Shift the remainder in X to the left ROL A TAX DEC T \ Decrement the loop counter BNE LL6 \ Loop back to LL6 until we have done 8 loops RTS \ Return from the subroutineName: LL5 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate Q = SQRT(R Q) Deep dive: Calculating square rootsContext: See this subroutine on its own page References: This subroutine is called as follows: * HAS1 calls LL5 * Main flight loop (Part 15 of 16) calls LL5 * NORM calls LL5 * SUN (Part 3 of 4) calls LL5 * TT111 calls LL5 * cour_count calls LL5

Calculate the following square root: Q = SQRT(R Q).LL28 CMP Q \ If A >= Q, then the answer will not fit in one byte, BCS LL2 \ so jump to LL2 to return 255 LDX #%11111110 \ Set R to have bits 1-7 set, so we can rotate through 7 STX R \ loop iterations, getting a 1 each time, and then \ getting a 0 on the 8th iteration... and we can also \ use R to catch our result bits into bit 0 each time .LL31 ASL A \ Shift A to the left BCS LL29 \ If bit 7 of A was set, then jump straight to the \ subtraction CMP Q \ If A < Q, skip the following subtraction BCC P%+4 SBC Q \ A >= Q, so set A = A - Q ROL R \ Rotate the counter in R to the left, and catch the \ result bit into bit 0 (which will be a 0 if we didn't \ do the subtraction, or 1 if we did) BCS LL31 \ If we still have set bits in R, loop back to LL31 to \ do the next iteration of 7 RTS \ R left with remainder of division .LL29 SBC Q \ A >= Q, so set A = A - Q SEC \ Set the C flag to rotate into the result in R ROL R \ Rotate the counter in R to the left, and catch the \ result bit into bit 0 (which will be a 0 if we didn't \ do the subtraction, or 1 if we did) BCS LL31 \ If we still have set bits in R, loop back to LL31 to \ do the next iteration of 7 RTS \ Return from the subroutine with R containing the \ remainder of the division .LL2 LDA #255 \ The division is very close to 1, so return the closest STA R \ possible answer to 256, i.e. R = 255 RTS \ Return from the subroutineName: LL28 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate R = 256 * A / Q Deep dive: Shift-and-subtract divisionContext: See this subroutine on its own page References: This subroutine is called as follows: * ARCTAN calls LL28 * LL145 (Part 3 of 4) calls LL28 * LL61 calls LL28 * LL9 (Part 3 of 12) calls LL28 * LL9 (Part 8 of 12) calls LL28 * DVID4 calls entry point LL28+4 * DVID3B2 calls entry point LL31

Calculate the following, where A < Q: R = 256 * A / Q This is a sister routine to LL61, which does the division when A >= Q. If A >= Q then 255 is returned and the C flag is set to indicate an overflow (the C flag is clear if the division was a success). The result is returned in one byte as the result of the division multiplied by 256, so we can return fractional results using integers. This routine uses the same shift-and-subtract algorithm that's documented in TIS2, but it leaves the fractional result in the integer range 0-255. Returns: C flag Set if the answer is too big for one byte, clear if the division was a success Other entry points: LL28+4 Skips the A >= Q check and always returns with C flag cleared, so this can be called if we know the division will work LL31 Skips the A >= Q check and does not set the R counter, so this can be used for jumping straight into the division loop if R is already set to 254 and we know the division will work.LL38 EOR S \ If the sign of A * S is negative, skip to LL35, as BMI LL39 \ A and S have different signs so we need to subtract LDA Q \ Otherwise set A = R + Q, which is the result we need, CLC \ as S already contains the correct sign ADC R RTS \ Return from the subroutine .LL39 LDA R \ Set A = R - Q SEC SBC Q BCC P%+4 \ If the subtraction underflowed, skip the next two \ instructions so we can negate the result CLC \ Otherwise the result is correct, and S contains the \ correct sign of the result as R is the dominant side \ of the subtraction, so clear the C flag RTS \ And return from the subroutine \ If we get here we need to negate both the result and \ the sign in S, as both are the wrong sign PHA \ Store the result of the subtraction on the stack LDA S \ Flip the sign of S EOR #%10000000 STA S PLA \ Restore the subtraction result into A EOR #%11111111 \ Negate the result in A using two's complement, i.e. ADC #1 \ set A = ~A + 1 RTS \ Return from the subroutineName: LL38 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate (S A) = (S R) + (A Q)Context: See this subroutine on its own page References: This subroutine is called as follows: * LL51 calls LL38 * LL9 (Part 5 of 12) calls LL38

Calculate the following between sign-magnitude numbers: (S A) = (S R) + (A Q) where the sign bytes only contain the sign bits, not magnitudes. Returns: C flag Set if the addition overflowed, clear otherwise.LL51 LDX #0 \ Set X = 0, which will contain the offset of the vector \ to use in the calculation, increasing by 6 for each \ new vector LDY #0 \ Set Y = 0, which will contain the offset of the \ result bytes in XX12, increasing by 2 for each new \ result .ll51 LDA XX15 \ Set Q = x_lo STA Q LDA XX16,X \ Set A = |sidev_x| JSR FMLTU \ Set T = A * Q / 256 STA T \ = |sidev_x| * x_lo / 256 LDA XX15+1 \ Set S to the sign of x_sign * sidev_x EOR XX16+1,X STA S LDA XX15+2 \ Set Q = y_lo STA Q LDA XX16+2,X \ Set A = |sidev_y| JSR FMLTU \ Set Q = A * Q / 256 STA Q \ = |sidev_y| * y_lo / 256 LDA T \ Set R = T STA R \ = |sidev_x| * x_lo / 256 LDA XX15+3 \ Set A to the sign of y_sign * sidev_y EOR XX16+3,X JSR LL38 \ Set (S T) = (S R) + (A Q) STA T \ = |sidev_x| * x_lo + |sidev_y| * y_lo LDA XX15+4 \ Set Q = z_lo STA Q LDA XX16+4,X \ Set A = |sidev_z| JSR FMLTU \ Set Q = A * Q / 256 STA Q \ = |sidev_z| * z_lo / 256 LDA T \ Set R = T STA R \ = |sidev_x| * x_lo + |sidev_y| * y_lo LDA XX15+5 \ Set A to the sign of z_sign * sidev_z EOR XX16+5,X JSR LL38 \ Set (S A) = (S R) + (A Q) \ = |sidev_x| * x_lo + |sidev_y| * y_lo \ + |sidev_z| * z_lo STA XX12,Y \ Store the result in XX12+Y(1 0) LDA S STA XX12+1,Y INY \ Set Y = Y + 2 INY TXA \ Set X = X + 6 CLC ADC #6 TAX CMP #17 \ If X < 17, loop back to ll51 for the next vector BCC ll51 RTS \ Return from the subroutineName: LL51 [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Calculate the dot product of XX15 and XX16Context: See this subroutine on its own page References: This subroutine is called as follows: * LL9 (Part 5 of 12) calls LL51 * LL9 (Part 6 of 12) calls LL51

Calculate the following dot products: XX12(1 0) = XX15(5 0) . XX16(5 0) XX12(3 2) = XX15(5 0) . XX16(11 6) XX12(5 4) = XX15(5 0) . XX16(12 17) storing the results as sign-magnitude numbers in XX12 through XX12+5. When called from part 5 of LL9, XX12 contains the vector [x y z] to the ship we're drawing, and XX16 contains the orientation vectors, so it returns: [ x ] [ sidev_x ] [ x ] [ roofv_x ] [ x ] [ nosev_x ] [ y ] . [ sidev_y ] [ y ] . [ roofv_y ] [ y ] . [ nosev_y ] [ z ] [ sidev_z ] [ z ] [ roofv_z ] [ z ] [ nosev_z ] When called from part 6 of LL9, XX12 contains the vector [x y z] of the vertex we're analysing, and XX16 contains the transposed orientation vectors with each of them containing the x, y and z elements of the original vectors, so it returns: [ x ] [ sidev_x ] [ x ] [ sidev_y ] [ x ] [ sidev_z ] [ y ] . [ roofv_x ] [ y ] . [ roofv_y ] [ y ] . [ roofv_z ] [ z ] [ nosev_x ] [ z ] [ nosev_y ] [ z ] [ nosev_z ] Arguments: XX15(1 0) The ship (or vertex)'s x-coordinate as (x_sign x_lo) XX15(3 2) The ship (or vertex)'s y-coordinate as (y_sign y_lo) XX15(5 4) The ship (or vertex)'s z-coordinate as (z_sign z_lo) XX16 to XX16+5 The scaled sidev (or _x) vector, with: * x, y, z magnitudes in XX16, XX16+2, XX16+4 * x, y, z signs in XX16+1, XX16+3, XX16+5 XX16+6 to XX16+11 The scaled roofv (or _y) vector, with: * x, y, z magnitudes in XX16+6, XX16+8, XX16+10 * x, y, z signs in XX16+7, XX16+9, XX16+11 XX16+12 to XX16+17 The scaled nosev (or _z) vector, with: * x, y, z magnitudes in XX16+12, XX16+14, XX16+16 * x, y, z signs in XX16+13, XX16+15, XX16+17 Returns: XX12(1 0) The dot product of [x y z] vector with the sidev (or _x) vector, with the sign in XX12+1 and magnitude in XX12 XX12(3 2) The dot product of [x y z] vector with the roofv (or _y) vector, with the sign in XX12+3 and magnitude in XX12+2 XX12(5 4) The dot product of [x y z] vector with the nosev (or _z) vector, with the sign in XX12+5 and magnitude in XX12+4.LL9 LDA #31 \ Set XX4 = 31 to store the ship's distance for later STA XX4 \ comparison with the visibility distance. We will \ update this value below with the actual ship's \ distance if it turns out to be visible on-screen LDA NEWB \ If bit 7 of the ship's NEWB flags is set, then the BMI EE51 \ ship has been scooped or has docked, so jump down to \ EE51 to redraw its wireframe, to remove it from the \ screen LDA #%00100000 \ If bit 5 of the ship's byte #31 is set, then the ship BIT XX1+31 \ is currently exploding, so jump down to EE28 BNE EE28 BPL EE28 \ If bit 7 of the ship's byte #31 is clear then the ship \ has not just been killed, so jump down to EE28 \ Otherwise bit 5 is clear and bit 7 is set, so the ship \ is not yet exploding but it has been killed, so we \ need to start an explosion ORA XX1+31 \ Clear bits 6 and 7 of the ship's byte #31, to stop the AND #%00111111 \ ship from firing its laser and to mark it as no longer STA XX1+31 \ having just been killed LDA #0 \ Set the ship's acceleration in byte #31 to 0, updating LDY #28 \ the byte in the workspace K% data block so we don't STA (INF),Y \ have to copy it back from INWK later LDY #30 \ Set the ship's pitch counter in byte #30 to 0, to stop STA (INF),Y \ the ship from pitching JSR EE51 \ Call EE51 to remove the ship from the screen \ We now need to set up a new explosion cloud. We \ initialise it with a size of 18 (which gets increased \ by 4 every time the cloud gets redrawn), and the \ explosion count (i.e. the number of particles in the \ explosion), which go into bytes 1 and 2 of the ship \ line heap. See DOEXP for more details of explosion \ clouds LDY #1 \ Set byte #1 of the ship line heap to 18, the initial LDA #18 \ size of the explosion cloud STA (XX19),Y LDY #7 \ Fetch byte #7 from the ship's blueprint, which LDA (XX0),Y \ determines the explosion count (i.e. the number of LDY #2 \ vertices used as origins for explosion clouds), and STA (XX19),Y \ store it in byte #2 of the ship line heap \ The following loop sets bytes 3-6 of the of the ship \ line heap to random numbers .EE55 INY \ Increment Y (so the loop starts at 3) JSR DORND \ Set A and X to random numbers STA (XX19),Y \ Store A in the Y-th byte of the ship line heap CPY #6 \ Loop back until we have randomised the 6th byte BNE EE55 .EE28 LDA XX1+8 \ Set A = z_sign .EE49 BPL LL10 \ If A is positive, i.e. the ship is in front of us, \ jump down to LL10 .LL14 \ The following removes the ship from the screen by \ redrawing it (or, if it is exploding, by redrawing the \ explosion cloud). We call it when the ship is no \ longer on-screen, is too far away to be fully drawn, \ and so on LDA XX1+31 \ If bit 5 of the ship's byte #31 is clear, then the AND #%00100000 \ ship is not currently exploding, so jump down to EE51 BEQ EE51 \ to redraw its wireframe LDA XX1+31 \ The ship is exploding, so clear bit 3 of the ship's AND #%11110111 \ byte #31 to denote that the ship is no longer being STA XX1+31 \ drawn on-screen JMP DOEXP \ Jump to DOEXP to display the explosion cloud, which \ will remove it from the screen, returning from the \ subroutine using a tail call .EE51 LDA #%00001000 \ If bit 3 of the ship's byte #31 is clear, then there BIT XX1+31 \ is already nothing being shown for this ship, so BEQ LL10-1 \ return from the subroutine (as LL10-1 contains an RTS) EOR XX1+31 \ Otherwise flip bit 3 of byte #31 and store it (which STA XX1+31 \ clears bit 3 as we know it was set before the EOR), so \ this sets this ship as no longer being drawn on-screen JMP LL155 \ Jump to LL155 to draw the ship, which removes it from \ the screen, returning from the subroutine using a \ tail call RTS \ Return from the subroutineName: LL9 (Part 1 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Check if ship is exploding, check if ship is in front Deep dive: Drawing shipsContext: See this subroutine on its own page References: This subroutine is called as follows: * BRIEF calls LL9 * HAS1 calls LL9 * LL9_FLIGHT calls LL9 * PAS1 calls LL9 * PAUSE calls LL9 * TITLE calls LL9 * ships_ag calls LL9 * LL9 (Part 1 of 12) calls entry point EE51 * SHPPT calls entry point EE51

This routine draws the current ship on the screen. This part checks to see if the ship is exploding, or if it should start exploding, and if it does it sets things up accordingly. It also does some basic checks to see if we can see the ship, and if not it removes it from the screen. In this code, XX1 is used to point to the current ship's data block at INWK (the two labels are interchangeable). Arguments: XX1 XX1 shares its location with INWK, which contains the zero-page copy of the data block for this ship from the K% workspace INF The address of the data block for this ship in workspace K% XX19(1 0) XX19(1 0) shares its location with INWK(34 33), which contains the ship line heap address pointer XX0 The address of the blueprint for this ship Other entry points: EE51 Remove the current ship from the screen, called from SHPPT before drawing the ship as a point.LL10 LDA XX1+7 \ Set A = z_hi CMP #192 \ If A >= 192 then the ship is a long way away, so jump BCS LL14 \ to LL14 to remove the ship from the screen LDA XX1 \ If x_lo >= z_lo, set the C flag, otherwise clear it CMP XX1+6 LDA XX1+1 \ Set A = x_hi - z_hi using the carry from the low SBC XX1+7 \ bytes, which sets the C flag as if we had done a full \ two-byte subtraction (x_hi x_lo) - (z_hi z_lo) BCS LL14 \ If the C flag is set then x >= z, so the ship is \ further to the side than it is in front of us, so it's \ outside our viewing angle of 45 degrees, and we jump \ to LL14 to remove it from the screen LDA XX1+3 \ If y_lo >= z_lo, set the C flag, otherwise clear it CMP XX1+6 LDA XX1+4 \ Set A = y_hi - z_hi using the carry from the low SBC XX1+7 \ bytes, which sets the C flag as if we had done a full \ two-byte subtraction (y_hi y_lo) - (z_hi z_lo) BCS LL14 \ If the C flag is set then y >= z, so the ship is \ further above us than it is in front of us, so it's \ outside our viewing angle of 45 degrees, and we jump \ to LL14 to remove it from the screen LDY #6 \ Fetch byte #6 from the ship's blueprint into X, which LDA (XX0),Y \ is the number * 4 of the vertex used for the ship's TAX \ laser LDA #255 \ Set bytes X and X+1 of the XX3 heap to 255. We're STA XX3,X \ going to use XX3 to store the screen coordinates of STA XX3+1,X \ all the visible vertices of this ship, so setting the \ laser vertex to 255 means that if we don't update this \ vertex with its screen coordinates in parts 6 and 7, \ this vertex's entry in the XX3 heap will still be 255, \ which we can check in part 9 to see if the laser \ vertex is visible (and therefore whether we should \ draw laser lines if the ship is firing on us) LDA XX1+6 \ Set (A T) = (z_hi z_lo) STA T LDA XX1+7 LSR A \ Set (A T) = (A T) / 8 ROR T LSR A ROR T LSR A ROR T LSR A \ If A >> 4 is non-zero, i.e. z_hi >= 16, jump to LL13 BNE LL13 \ as the ship is possibly far away enough to be shown as \ a dot LDA T \ Otherwise the C flag contains the previous bit 0 of A, ROR A \ which could have been set, so rotate A right four LSR A \ times so it's in the form %000xxxxx, i.e. z_hi reduced LSR A \ to a maximum value of 31 LSR A STA XX4 \ Store A in XX4, which is now the distance of the ship \ we can use for visibility testing BPL LL17 \ Jump down to LL17 (this BPL is effectively a JMP as we \ know bit 7 of A is definitely clear) .LL13 \ If we get here then the ship is possibly far enough \ away to be shown as a dot LDY #13 \ Fetch byte #13 from the ship's blueprint, which gives LDA (XX0),Y \ the ship's visibility distance, beyond which we show \ the ship as a dot CMP XX1+7 \ If z_hi <= the visibility distance, skip to LL17 to BCS LL17 \ draw the ship fully, rather than as a dot, as it is \ closer than the visibility distance LDA #%00100000 \ If bit 5 of the ship's byte #31 is set, then the AND XX1+31 \ ship is currently exploding, so skip to LL17 to draw BNE LL17 \ the ship's explosion cloud JMP SHPPT \ Otherwise jump to SHPPT to draw the ship as a dot, \ returning from the subroutine using a tail callName: LL9 (Part 2 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Check if ship is in field of view, close enough to draw Deep dive: Drawing shipsContext: See this subroutine on its own page References: This subroutine is called as follows: * LL9 (Part 1 of 12) calls entry point LL10-1

This part checks whether the ship is in our field of view, and whether it is close enough to be fully drawn (if not, we jump to SHPPT to draw it as a dot). Other entry points: LL10-1 Contains an RTS.LL17 LDX #5 \ First we copy the three orientation vectors into XX16, \ so set up a counter in X for the 6 bytes in each \ vector .LL15 LDA XX1+21,X \ Copy the X-th byte of sidev to the X-th byte of XX16 STA XX16,X LDA XX1+15,X \ Copy the X-th byte of roofv to XX16+6 to the X-th byte STA XX16+6,X \ of XX16+6 LDA XX1+9,X \ Copy the X-th byte of nosev to XX16+12 to the X-th STA XX16+12,X \ byte of XX16+12 DEX \ Decrement the counter BPL LL15 \ Loop back to copy the next byte of each vector, until \ we have the following: \ \ * XX16(1 0) = sidev_x \ * XX16(3 2) = sidev_y \ * XX16(5 4) = sidev_z \ \ * XX16(7 6) = roofv_x \ * XX16(9 8) = roofv_y \ * XX16(11 10) = roofv_z \ \ * XX16(13 12) = nosev_x \ * XX16(15 14) = nosev_y \ * XX16(17 16) = nosev_z LDA #197 \ Set Q = 197 STA Q LDY #16 \ Set Y to be a counter that counts down by 2 each time, \ starting with 16, then 14, 12 and so on. We use this \ to work through each of the coordinates in each of the \ orientation vectors .LL21 LDA XX16,Y \ Set A = the low byte of the vector coordinate, e.g. \ nosev_z_lo when Y = 16 ASL A \ Shift bit 7 into the C flag LDA XX16+1,Y \ Set A = the high byte of the vector coordinate, e.g. \ nosev_z_hi when Y = 16 ROL A \ Rotate A left, incorporating the C flag, so A now \ contains the original high byte, doubled, and without \ a sign bit, e.g. A = |nosev_z_hi| * 2 JSR LL28 \ Call LL28 to calculate: \ \ R = 256 * A / Q \ \ so, for nosev, this would be: \ \ R = 256 * |nosev_z_hi| * 2 / 197 \ = 2.6 * |nosev_z_hi| LDX R \ Store R in the low byte's location, so we can keep the STX XX16,Y \ old, unscaled high byte intact for the sign DEY \ Decrement the loop counter twice DEY BPL LL21 \ Loop back for the next vector coordinate until we have \ divided them all \ By this point, the vectors have been turned into \ scaled magnitudes, so we have the following: \ \ * XX16 = scaled |sidev_x| \ * XX16+2 = scaled |sidev_y| \ * XX16+4 = scaled |sidev_z| \ \ * XX16+6 = scaled |roofv_x| \ * XX16+8 = scaled |roofv_y| \ * XX16+10 = scaled |roofv_z| \ \ * XX16+12 = scaled |nosev_x| \ * XX16+14 = scaled |nosev_y| \ * XX16+16 = scaled |nosev_z| LDX #8 \ Next we copy the ship's coordinates into XX18, so set \ up a counter in X for 9 bytes .ll91 LDA XX1,X \ Copy the X-th byte from XX1 to XX18 STA XX18,X DEX \ Decrement the loop counter BPL ll91 \ Loop back for the next byte until we have copied all \ three coordinates \ So we now have the following: \ \ * XX18(2 1 0) = (x_sign x_hi x_lo) \ \ * XX18(5 4 3) = (y_sign y_hi y_lo) \ \ * XX18(8 7 6) = (z_sign z_hi z_lo) LDA #255 \ Set the 15th byte of XX2 to 255, so that face 15 is STA XX2+15 \ always visible. No ship definitions actually have this \ number of faces in the cassette version, but this \ allows us to force a vertex to always be visible by \ associating it with face 15 (see the blueprints for \ the Cobra Mk III at SHIP_COBRA_MK_3 and asteroid at \ SHIP_ASTEROID for examples) LDY #12 \ Set Y = 12 to point to the ship blueprint byte #12, LDA XX1+31 \ If bit 5 of the ship's byte #31 is clear, then the AND #%00100000 \ ship is not currently exploding, so jump down to EE29 BEQ EE29 \ to skip the following \ Otherwise we fall through to set up the visibility \ block for an exploding shipName: LL9 (Part 3 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Set up orientation vector, ship coordinate variables Deep dive: Drawing shipsContext: See this subroutine on its own page References: No direct references to this subroutine in this source file

This part sets up the following variable blocks: * XX16 contains the orientation vectors, divided to normalise them * XX18 contains the ship's x, y and z coordinates in spaceLDA (XX0),Y \ Fetch byte #12 of the ship's blueprint, which contains \ the number of faces * 4 LSR A \ Set X = A / 4 LSR A \ = the number of faces TAX LDA #255 \ Set A = 255 .EE30 STA XX2,X \ Set the X-th byte of XX2 to 255 DEX \ Decrement the loop counter BPL EE30 \ Loop back for the next byte until there is one byte \ set to 255 for each face INX \ Set XX4 = 0 for the distance value we use to test STX XX4 \ for visibility, so we always shows everything .LL41 JMP LL42 \ Jump to LL42 to skip the face visibility calculations \ as we don't need to do them now we've set up the XX2 \ block for the explosionName: LL9 (Part 4 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Set visibility for exploding ship (all faces visible) Deep dive: Drawing shipsContext: See this subroutine on its own page References: No direct references to this subroutine in this source file

This part sets up the visibility block in XX2 for a ship that is exploding. The XX2 block consists of one byte for each face in the ship's blueprint, which holds the visibility of that face. Because the ship is exploding, we want to set all the faces to be visible. A value of 255 in the visibility table means the face is visible, so the following code sets each face to 255 and then skips over the face visibility calculations that we would apply to a non-exploding ship..EE29 LDA (XX0),Y \ We set Y to 12 above before jumping down to EE29, so \ this fetches byte #12 of the ship's blueprint, which \ contains the number of faces * 4 BEQ LL41 \ If there are no faces in this ship, jump to LL42 (via \ LL41) to skip the face visibility calculations STA XX20 \ Set A = the number of faces * 4 LDY #18 \ Fetch byte #18 of the ship's blueprint, which contains LDA (XX0),Y \ the factor by which we scale the face normals, into X TAX LDA XX18+7 \ Set A = z_hi .LL90 TAY \ Set Y = z_hi BEQ LL91 \ If z_hi = 0 then jump to LL91 \ The following is a loop that jumps back to LL90+3, \ i.e. here. LL90 is only used for this loop, so it's a \ bit of a strange use of the label here INX \ Increment the scale factor in X LSR XX18+4 \ Divide (y_hi y_lo) by 2 ROR XX18+3 LSR XX18+1 \ Divide (x_hi x_lo) by 2 ROR XX18 LSR A \ Divide (z_hi z_lo) by 2 (as A contains z_hi) ROR XX18+6 TAY \ Set Y = z_hi BNE LL90+3 \ If Y is non-zero, loop back to LL90+3 to divide the \ three coordinates until z_hi is 0 .LL91 \ By this point z_hi is 0 and X contains the number of \ right shifts we had to do, plus the scale factor from \ the blueprint STX XX17 \ Store the updated scale factor in XX17 LDA XX18+8 \ Set XX15+5 = z_sign STA XX15+5 LDA XX18 \ Set XX15(1 0) = (x_sign x_lo) STA XX15 LDA XX18+2 STA XX15+1 LDA XX18+3 \ Set XX15(3 2) = (y_sign y_lo) STA XX15+2 LDA XX18+5 STA XX15+3 LDA XX18+6 \ Set XX15+4 = z_lo, so now XX15(5 4) = (z_sign z_lo) STA XX15+4 JSR LL51 \ Call LL51 to set XX12 to the dot products of XX15 and \ XX16, which we'll call dot_sidev, dot_roofv and \ dot_nosev: \ \ XX12(1 0) = [x y z] . sidev \ = (dot_sidev_sign dot_sidev_lo) \ = dot_sidev \ \ XX12(3 2) = [x y z] . roofv \ = (dot_roofv_sign dot_roofv_lo) \ = dot_roofv \ \ XX12(5 4) = [x y z] . nosev \ = (dot_nosev_sign dot_nosev_lo) \ = dot_nosev LDA XX12 \ Set XX18(2 0) = dot_sidev STA XX18 LDA XX12+1 STA XX18+2 LDA XX12+2 \ Set XX18(5 3) = dot_roofv STA XX18+3 LDA XX12+3 STA XX18+5 LDA XX12+4 \ Set XX18(8 6) = dot_nosev STA XX18+6 LDA XX12+5 STA XX18+8 LDY #4 \ Fetch byte #4 of the ship's blueprint, which contains LDA (XX0),Y \ the low byte of the offset to the faces data CLC \ Set V = low byte faces offset + XX0 ADC XX0 STA V LDY #17 \ Fetch byte #17 of the ship's blueprint, which contains LDA (XX0),Y \ the high byte of the offset to the faces data ADC XX0+1 \ Set V+1 = high byte faces offset + XX0+1 STA V+1 \ \ So V(1 0) now points to the start of the faces data \ for this ship LDY #0 \ We're now going to loop through all the faces for this \ ship, so set a counter in Y, starting from 0, which we \ will increment by 4 each loop to step through the \ four bytes of data for each face .LL86 LDA (V),Y \ Fetch byte #0 for this face into A, so: \ \ A = %xyz vvvvv, where: \ \ * Bits 0-4 = visibility distance, beyond which the \ face is always shown \ \ * Bits 7-5 = the sign bits of normal_x, normal_y \ and normal_z STA XX12+1 \ Store byte #0 in XX12+1, so XX12+1 now has the sign of \ normal_x AND #%00011111 \ Extract bits 0-4 to give the visibility distance CMP XX4 \ If XX4 <= the visibility distance, where XX4 contains BCS LL87 \ the ship's z-distance reduced to 0-31 (which we set in \ part 2), skip to LL87 as this face is close enough \ that we have to test its visibility using the face \ normals \ Otherwise this face is within range and is therefore \ always shown TYA \ Set X = Y / 4 LSR A \ = the number of this face * 4 /4 LSR A \ = the number of this face TAX LDA #255 \ Set the X-th byte of XX2 to 255 to denote that this STA XX2,X \ face is visible TYA \ Set Y = Y + 4 to point to the next face ADC #4 TAY JMP LL88 \ Jump down to LL88 to skip the following, as we don't \ need to test the face normals .LL87 LDA XX12+1 \ Fetch byte #0 for this face into A ASL A \ Shift A left and store it, so XX12+3 now has the sign STA XX12+3 \ of normal_y ASL A \ Shift A left and store it, so XX12+5 now has the sign STA XX12+5 \ of normal_z INY \ Increment Y to point to byte #1 LDA (V),Y \ Fetch byte #1 for this face and store in XX12, so STA XX12 \ XX12 = normal_x INY \ Increment Y to point to byte #2 LDA (V),Y \ Fetch byte #2 for this face and store in XX12+2, so STA XX12+2 \ XX12+2 = normal_y INY \ Increment Y to point to byte #3 LDA (V),Y \ Fetch byte #3 for this face and store in XX12+4, so STA XX12+4 \ XX12+4 = normal_z \ So we now have: \ \ XX12(1 0) = (normal_x_sign normal_x) \ \ XX12(3 2) = (normal_y_sign normal_y) \ \ XX12(5 4) = (normal_z_sign normal_z) LDX XX17 \ If XX17 < 4 then jump to LL92, otherwise we stored a CPX #4 \ larger scale factor above BCC LL92 .LL143 LDA XX18 \ Set XX15(1 0) = XX18(2 0) STA XX15 \ = dot_sidev LDA XX18+2 STA XX15+1 LDA XX18+3 \ Set XX15(3 2) = XX18(5 3) STA XX15+2 \ = dot_roofv LDA XX18+5 STA XX15+3 LDA XX18+6 \ Set XX15(5 4) = XX18(8 6) STA XX15+4 \ = dot_nosev LDA XX18+8 STA XX15+5 JMP LL89 \ Jump down to LL89 .ovflw \ If we get here then the addition below overflowed, so \ we halve the dot products and normal vector LSR XX18 \ Divide dot_sidev_lo by 2, so dot_sidev = dot_sidev / 2 LSR XX18+6 \ Divide dot_nosev_lo by 2, so dot_nosev = dot_nosev / 2 LSR XX18+3 \ Divide dot_roofv_lo by 2, so dot_roofv = dot_roofv / 2 LDX #1 \ Set X = 1 so when we fall through into LL92, we divide \ the normal vector by 2 as well .LL92 \ We jump here from above with the scale factor in X, \ and now we apply it by scaling the normal vector down \ by a factor of 2^X (i.e. divide by 2^X) LDA XX12 \ Set XX15 = normal_x STA XX15 LDA XX12+2 \ Set XX15+2 = normal_y STA XX15+2 LDA XX12+4 \ Set A = normal_z .LL93 DEX \ Decrement the scale factor in X BMI LL94 \ If X was 0 before the decrement, there is no scaling \ to do, so jump to LL94 to exit the loop LSR XX15 \ Set XX15 = XX15 / 2 \ = normal_x / 2 LSR XX15+2 \ Set XX15+2 = XX15+2 / 2 \ = normal_y / 2 LSR A \ Set A = A / 2 \ = normal_z / 2 DEX \ Decrement the scale factor in X BPL LL93+3 \ If we have more scaling to do, loop back up to the \ first LSR above until the normal vector is scaled down .LL94 STA R \ Set R = normal_z LDA XX12+5 \ Set S = normal_z_sign STA S LDA XX18+6 \ Set Q = dot_nosev_lo STA Q LDA XX18+8 \ Set A = dot_nosev_sign JSR LL38 \ Set (S A) = (S R) + (A Q) \ = normal_z + dot_nosev \ \ setting the sign of the result in S BCS ovflw \ If the addition overflowed, jump up to ovflw to divide \ both the normal vector and dot products by 2 and try \ again STA XX15+4 \ Set XX15(5 4) = (S A) LDA S \ = normal_z + dot_nosev STA XX15+5 LDA XX15 \ Set R = normal_x STA R LDA XX12+1 \ Set S = normal_x_sign STA S LDA XX18 \ Set Q = dot_sidev_lo STA Q LDA XX18+2 \ Set A = dot_sidev_sign JSR LL38 \ Set (S A) = (S R) + (A Q) \ = normal_x + dot_sidev \ \ setting the sign of the result in S BCS ovflw \ If the addition overflowed, jump up to ovflw to divide \ both the normal vector and dot products by 2 and try \ again STA XX15 \ Set XX15(1 0) = (S A) LDA S \ = normal_x + dot_sidev STA XX15+1 LDA XX15+2 \ Set R = normal_y STA R LDA XX12+3 \ Set S = normal_y_sign STA S LDA XX18+3 \ Set Q = dot_roofv_lo STA Q LDA XX18+5 \ Set A = dot_roofv_sign JSR LL38 \ Set (S A) = (S R) + (A Q) \ = normal_y + dot_roofv BCS ovflw \ If the addition overflowed, jump up to ovflw to divide \ both the normal vector and dot products by 2 and try \ again STA XX15+2 \ Set XX15(3 2) = (S A) LDA S \ = normal_y + dot_roofv STA XX15+3 .LL89 \ When we get here, we have set up the following: \ \ XX15(1 0) = normal_x + dot_sidev \ = normal_x + [x y z] . sidev \ \ XX15(3 2) = normal_y + dot_roofv \ = normal_y + [x y z] . roofv \ \ XX15(5 4) = normal_z + dot_nosev \ = normal_z + [x y z] . nosev \ \ and: \ \ XX12(1 0) = (normal_x_sign normal_x) \ \ XX12(3 2) = (normal_y_sign normal_y) \ \ XX12(5 4) = (normal_z_sign normal_z) \ \ We now calculate the dot product XX12 . XX15 to tell \ us whether or not this face is visible LDA XX12 \ Set Q = XX12 STA Q LDA XX15 \ Set A = XX15 JSR FMLTU \ Set T = A * Q / 256 STA T \ = XX15 * XX12 / 256 LDA XX12+1 \ Set S = sign of XX15(1 0) * XX12(1 0), so: EOR XX15+1 \ STA S \ (S T) = XX15(1 0) * XX12(1 0) / 256 LDA XX12+2 \ Set Q = XX12+2 STA Q LDA XX15+2 \ Set A = XX15+2 JSR FMLTU \ Set Q = A * Q STA Q \ = XX15+2 * XX12+2 / 256 LDA T \ Set T = R, so now: STA R \ \ (S R) = XX15(1 0) * XX12(1 0) / 256 LDA XX12+3 \ Set A = sign of XX15+3 * XX12+3, so: EOR XX15+3 \ \ (A Q) = XX15(3 2) * XX12(3 2) / 256 JSR LL38 \ Set (S T) = (S R) + (A Q) STA T \ = XX15(1 0) * XX12(1 0) / 256 \ + XX15(3 2) * XX12(3 2) / 256 LDA XX12+4 \ Set Q = XX12+4 STA Q LDA XX15+4 \ Set A = XX15+4 JSR FMLTU \ Set Q = A * Q STA Q \ = XX15+4 * XX12+4 / 256 LDA T \ Set T = R, so now: STA R \ \ (S R) = XX15(1 0) * XX12(1 0) / 256 \ + XX15(3 2) * XX12(3 2) / 256 LDA XX15+5 \ Set A = sign of XX15+5 * XX12+5, so: EOR XX12+5 \ \ (A Q) = XX15(5 4) * XX12(5 4) / 256 JSR LL38 \ Set (S A) = (S R) + (A Q) \ = XX15(1 0) * XX12(1 0) / 256 \ + XX15(3 2) * XX12(3 2) / 256 \ + XX15(5 4) * XX12(5 4) / 256 PHA \ Push the result A onto the stack, so the stack now \ contains the dot product XX12 . XX15 TYA \ Set X = Y / 4 LSR A \ = the number of this face * 4 /4 LSR A \ = the number of this face TAX PLA \ Pull the dot product off the stack into A BIT S \ If bit 7 of S is set, i.e. the dot product is BMI P%+4 \ negative, then this face is visible as its normal is \ pointing towards us, so skip the following instruction LDA #0 \ Otherwise the face is not visible, so set A = 0 so we \ can store this to mean "not visible" STA XX2,X \ Store the face's visibility in the X-th byte of XX2 INY \ Above we incremented Y to point to byte #3, so this \ increments Y to point to byte #4, i.e. byte #0 of the \ next face .LL88 CPY XX20 \ If Y >= XX20, the number of faces * 4, jump down to BCS LL42 \ LL42 to move on to the JMP LL86 \ Otherwise loop back to LL86 to work out the visibility \ of the next faceName: LL9 (Part 5 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Calculate the visibility of each of the ship's faces Deep dive: Drawing ships Back-face cullingContext: See this subroutine on its own page References: No direct references to this subroutine in this source file.LL42 \ The first task is to set up the inverse matrix, ready \ for us to send to the dot product routine at LL51. \ Back up in part 3, we set up the following variables: \ \ * XX16(1 0) = sidev_x \ * XX16(3 2) = sidev_y \ * XX16(5 4) = sidev_z \ \ * XX16(7 6) = roofv_x \ * XX16(9 8) = roofv_y \ * XX16(11 10) = roofv_z \ \ * XX16(13 12) = nosev_x \ * XX16(15 14) = nosev_y \ * XX16(17 16) = nosev_z \ \ and we then scaled the vectors to give the following: \ \ * XX16 = scaled |sidev_x| \ * XX16+2 = scaled |sidev_y| \ * XX16+4 = scaled |sidev_z| \ \ * XX16+6 = scaled |roofv_x| \ * XX16+8 = scaled |roofv_y| \ * XX16+10 = scaled |roofv_z| \ \ * XX16+12 = scaled |nosev_x| \ * XX16+14 = scaled |nosev_y| \ * XX16+16 = scaled |nosev_z| \ \ We now need to rearrange these locations so they \ effectively transpose the matrix into its inverse LDY XX16+2 \ Set XX16+2 = XX16+6 = scaled |roofv_x| LDX XX16+3 \ Set XX16+3 = XX16+7 = roofv_x_hi LDA XX16+6 \ Set XX16+6 = XX16+2 = scaled |sidev_y| STA XX16+2 \ Set XX16+7 = XX16+3 = sidev_y_hi LDA XX16+7 STA XX16+3 STY XX16+6 STX XX16+7 LDY XX16+4 \ Set XX16+4 = XX16+12 = scaled |nosev_x| LDX XX16+5 \ Set XX16+5 = XX16+13 = nosev_x_hi LDA XX16+12 \ Set XX16+12 = XX16+4 = scaled |sidev_z| STA XX16+4 \ Set XX16+13 = XX16+5 = sidev_z_hi LDA XX16+13 STA XX16+5 STY XX16+12 STX XX16+13 LDY XX16+10 \ Set XX16+10 = XX16+14 = scaled |nosev_y| LDX XX16+11 \ Set XX16+11 = XX16+15 = nosev_y_hi LDA XX16+14 \ Set XX16+14 = XX16+10 = scaled |roofv_z| STA XX16+10 \ Set XX16+15 = XX16+11 = roofv_z LDA XX16+15 STA XX16+11 STY XX16+14 STX XX16+15 \ So now we have the following sign-magnitude variables \ containing parts of the scaled orientation vectors: \ \ XX16(1 0) = scaled sidev_x \ XX16(3 2) = scaled roofv_x \ XX16(5 4) = scaled nosev_x \ \ XX16(7 6) = scaled sidev_y \ XX16(9 8) = scaled roofv_y \ XX16(11 10) = scaled nosev_y \ \ XX16(13 12) = scaled sidev_z \ XX16(15 14) = scaled roofv_z \ XX16(17 16) = scaled nosev_z \ \ which is what we want, as the various vectors are now \ arranged so we can use LL51 to multiply by the \ transpose (i.e. the inverse of the matrix) LDY #8 \ Fetch byte #8 of the ship's blueprint, which is the LDA (XX0),Y \ number of vertices * 8, and store it in XX20 STA XX20 \ We now set V(1 0) = XX0(1 0) + 20, so V(1 0) points \ to byte #20 of the ship's blueprint, which is always \ where the vertex data starts (i.e. just after the 20 \ byte block that define the ship's characteristics) LDA XX0 \ We start with the low bytes CLC ADC #20 STA V LDA XX0+1 \ And then do the high bytes ADC #0 STA V+1 LDY #0 \ We are about to step through all the vertices, using \ Y as a counter. There are six data bytes for each \ vertex, so we will increment Y by 6 for each iteration \ so it can act as an offset from V(1 0) to the current \ vertex's data STY CNT \ Set CNT = 0, which we will use as a pointer to the \ heap at XX3, starting it at zero so the heap starts \ out empty .LL48 STY XX17 \ Set XX17 = Y, so XX17 now contains the offset of the \ current vertex's data LDA (V),Y \ Fetch byte #0 for this vertex into XX15, so: STA XX15 \ \ XX15 = magnitude of the vertex's x-coordinate INY \ Increment Y to point to byte #1 LDA (V),Y \ Fetch byte #1 for this vertex into XX15+2, so: STA XX15+2 \ \ XX15+2 = magnitude of the vertex's y-coordinate INY \ Increment Y to point to byte #2 LDA (V),Y \ Fetch byte #2 for this vertex into XX15+4, so: STA XX15+4 \ \ XX15+4 = magnitude of the vertex's z-coordinate INY \ Increment Y to point to byte #3 LDA (V),Y \ Fetch byte #3 for this vertex into T, so: STA T \ \ T = %xyz vvvvv, where: \ \ * Bits 0-4 = visibility distance, beyond which the \ vertex is not shown \ \ * Bits 7-5 = the sign bits of x, y and z AND #%00011111 \ Extract bits 0-4 to get the visibility distance CMP XX4 \ If XX4 > the visibility distance, where XX4 contains BCC LL49-3 \ the ship's z-distance reduced to 0-31 (which we set in \ part 2), then this vertex is too far away to be \ visible, so jump down to LL50 (via the JMP instruction \ in LL49-3) to move on to the next vertex INY \ Increment Y to point to byte #4 LDA (V),Y \ Fetch byte #4 for this vertex into P, so: STA P \ \ P = %ffff ffff, where: \ \ * Bits 0-3 = the number of face 1 \ \ * Bits 4-7 = the number of face 2 AND #%00001111 \ Extract the number of face 1 into X TAX LDA XX2,X \ If XX2+X is non-zero then we decided in part 5 that BNE LL49 \ face 1 is visible, so jump to LL49 LDA P \ Fetch byte #4 for this vertex into A LSR A \ Shift right four times to extract the number of face 2 LSR A \ from bits 4-7 into X LSR A LSR A TAX LDA XX2,X \ If XX2+X is non-zero then we decided in part 5 that BNE LL49 \ face 2 is visible, so jump to LL49 INY \ Increment Y to point to byte #5 LDA (V),Y \ Fetch byte #5 for this vertex into P, so: STA P \ \ P = %ffff ffff, where: \ \ * Bits 0-3 = the number of face 3 \ \ * Bits 4-7 = the number of face 4 AND #%00001111 \ Extract the number of face 1 into X TAX LDA XX2,X \ If XX2+X is non-zero then we decided in part 5 that BNE LL49 \ face 3 is visible, so jump to LL49 LDA P \ Fetch byte #5 for this vertex into A LSR A \ Shift right four times to extract the number of face 4 LSR A \ from bits 4-7 into X LSR A LSR A TAX LDA XX2,X \ If XX2+X is non-zero then we decided in part 5 that BNE LL49 \ face 4 is visible, so jump to LL49 JMP LL50 \ If we get here then none of the four faces associated \ with this vertex are visible, so this vertex is also \ not visible, so jump to LL50 to move on to the next \ vertex .LL49 LDA T \ Fetch byte #5 for this vertex into A and store it, so STA XX15+1 \ XX15+1 now has the sign of the vertex's x-coordinate ASL A \ Shift A left and store it, so XX15+3 now has the sign STA XX15+3 \ of the vertex's y-coordinate ASL A \ Shift A left and store it, so XX15+5 now has the sign STA XX15+5 \ of the vertex's z-coordinate \ By this point we have the following: \ \ XX15(1 0) = vertex x-coordinate \ XX15(3 2) = vertex y-coordinate \ XX15(5 4) = vertex z-coordinate \ \ XX16(1 0) = scaled sidev_x \ XX16(3 2) = scaled roofv_x \ XX16(5 4) = scaled nosev_x \ \ XX16(7 6) = scaled sidev_y \ XX16(9 8) = scaled roofv_y \ XX16(11 10) = scaled nosev_y \ \ XX16(13 12) = scaled sidev_z \ XX16(15 14) = scaled roofv_z \ XX16(17 16) = scaled nosev_z JSR LL51 \ Call LL51 to set XX12 to the dot products of XX15 and \ XX16, as follows: \ \ XX12(1 0) = [ x y z ] . [ sidev_x roofv_x nosev_x ] \ \ XX12(3 2) = [ x y z ] . [ sidev_y roofv_y nosev_y ] \ \ XX12(5 4) = [ x y z ] . [ sidev_z roofv_z nosev_z ] \ \ XX12 contains the vector from the ship's centre to \ the vertex, transformed from the orientation vector \ space to the universe orientated around our ship. So \ we can refer to this vector below, let's call it \ vertv, so: \ \ vertv_x = [ x y z ] . [ sidev_x roofv_x nosev_x ] \ \ vertv_y = [ x y z ] . [ sidev_y roofv_y nosev_y ] \ \ vertv_z = [ x y z ] . [ sidev_z roofv_z nosev_z ] \ \ To finish the calculation, we now want to calculate: \ \ vertv + [ x y z ] \ \ So let's start with the vertv_x + x LDA XX1+2 \ Set A = x_sign of the ship's location STA XX15+2 \ Set XX15+2 = x_sign EOR XX12+1 \ If the sign of x_sign * the sign of vertv_x is BMI LL52 \ negative (i.e. they have different signs), skip to \ LL52 CLC \ Set XX15(2 1 0) = XX1(2 1 0) + XX12(1 0) LDA XX12 \ = (x_sign x_hi x_lo) + vertv_x ADC XX1 \ STA XX15 \ Starting with the low bytes LDA XX1+1 \ And then doing the high bytes (we can add 0 here as ADC #0 \ we know the sign byte of vertv_x is 0) STA XX15+1 JMP LL53 \ We've added the x-coordinates, so jump to LL53 to do \ the y-coordinates .LL52 \ If we get here then x_sign and vertv_x have different \ signs, so we need to subtract them to get the result LDA XX1 \ Set XX15(2 1 0) = XX1(2 1 0) - XX12(1 0) SEC \ = (x_sign x_hi x_lo) - vertv_x SBC XX12 \ STA XX15 \ Starting with the low bytes LDA XX1+1 \ And then doing the high bytes (we can subtract 0 here SBC #0 \ as we know the sign byte of vertv_x is 0) STA XX15+1 BCS LL53 \ If the subtraction didn't underflow, then the sign of \ the result is the same sign as x_sign, and that's what \ we want, so we can jump down to LL53 to do the \ y-coordinates EOR #%11111111 \ Otherwise we need to negate the result using two's STA XX15+1 \ complement, so first we flip the bits of the high byte LDA #1 \ And then subtract the low byte from 1 SBC XX15 STA XX15 BCC P%+4 \ If the above subtraction underflowed then we need to INC XX15+1 \ bump the high byte of the result up by 1 LDA XX15+2 \ And now we flip the sign of the result to get the EOR #%10000000 \ correct result STA XX15+2 .LL53 \ Now for the y-coordinates, vertv_y + y LDA XX1+5 \ Set A = y_sign of the ship's location STA XX15+5 \ Set XX15+5 = y_sign EOR XX12+3 \ If the sign of y_sign * the sign of vertv_y is BMI LL54 \ negative (i.e. they have different signs), skip to \ LL54 CLC \ Set XX15(5 4 3) = XX1(5 4 3) + XX12(3 2) LDA XX12+2 \ = (y_sign y_hi y_lo) + vertv_y ADC XX1+3 \ STA XX15+3 \ Starting with the low bytes LDA XX1+4 \ And then doing the high bytes (we can add 0 here as ADC #0 \ we know the sign byte of vertv_y is 0) STA XX15+4 JMP LL55 \ We've added the y-coordinates, so jump to LL55 to do \ the z-coordinates .LL54 \ If we get here then y_sign and vertv_y have different \ signs, so we need to subtract them to get the result LDA XX1+3 \ Set XX15(5 4 3) = XX1(5 4 3) - XX12(3 2) SEC \ = (y_sign y_hi y_lo) - vertv_y SBC XX12+2 \ STA XX15+3 \ Starting with the low bytes LDA XX1+4 \ And then doing the high bytes (we can subtract 0 here SBC #0 \ as we know the sign byte of vertv_z is 0) STA XX15+4 BCS LL55 \ If the subtraction didn't underflow, then the sign of \ the result is the same sign as y_sign, and that's what \ we want, so we can jump down to LL55 to do the \ z-coordinates EOR #%11111111 \ Otherwise we need to negate the result using two's STA XX15+4 \ complement, so first we flip the bits of the high byte LDA XX15+3 \ And then flip the bits of the low byte and add 1 EOR #%11111111 ADC #1 STA XX15+3 LDA XX15+5 \ And now we flip the sign of the result to get the EOR #%10000000 \ correct result STA XX15+5 BCC LL55 \ If the above subtraction underflowed then we need to INC XX15+4 \ bump the high byte of the result up by 1 .LL55 \ Now for the z-coordinates, vertv_z + z LDA XX12+5 \ If vertv_z_hi is negative, jump down to LL56 BMI LL56 LDA XX12+4 \ Set (U T) = XX1(7 6) + XX12(5 4) CLC \ = (z_hi z_lo) + vertv_z ADC XX1+6 \ STA T \ Starting with the low bytes LDA XX1+7 \ And then doing the high bytes (we can add 0 here as ADC #0 \ we know the sign byte of vertv_y is 0) STA U JMP LL57 \ We've added the z-coordinates, so jump to LL57 \ The adding process is continued in part 7, after a \ couple of subroutines that we don't need quite yetName: LL9 (Part 6 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Calculate the visibility of each of the ship's vertices Deep dive: Drawing ships Calculating vertex coordinates

This section calculates the visibility of each of the ship's vertices, and for those that are visible, it starts the process of calculating the screen coordinates of each vertex.LL61 LDX Q \ If Q = 0, jump down to LL84 to return a division BEQ LL84 \ error \ The LL28 routine returns A / Q, but only if A < Q. In \ our case A >= Q, but we still want to use the LL28 \ routine, so we halve A until it's less than Q, call \ the division routine, and then double A by the same \ number of times LDX #0 \ Set X = 0 to count the number of times we halve A .LL63 LSR A \ Halve A by shifting right INX \ Increment X CMP Q \ If A >= Q, loop back to LL63 to halve it again BCS LL63 STX S \ Otherwise store the number of times we halved A in S JSR LL28 \ Call LL28 to calculate: \ \ R = 256 * A / Q \ \ which we can do now as A < Q LDX S \ Otherwise restore the number of times we halved A \ above into X LDA R \ Set A = our division result .LL64 ASL A \ Double (U A) by shifting left ROL U BMI LL84 \ If bit 7 of U is set, the doubling has overflowed, so \ jump to LL84 to return a division error DEX \ Decrement X BNE LL64 \ If X is not yet zero then we haven't done as many \ doublings as we did halvings earlier, so loop back for \ another doubling STA R \ Store the low byte of the division result in R RTS \ Return from the subroutine .LL84 LDA #50 \ If we get here then either we tried to divide by 0, or STA R \ the result overflowed, so we set U and R to 50 STA U RTS \ Return from the subroutineName: LL61 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate (U R) = 256 * A / QContext: See this subroutine on its own page References: This subroutine is called as follows: * LL9 (Part 8 of 12) calls LL61

Calculate the following, where A >= Q: (U R) = 256 * A / Q This is a sister routine to LL28, which does the division when A < Q..LL62 LDA #128 \ Calculate 128 - (U R), starting with the low bytes SEC SBC R STA XX3,X \ Store the low byte of the result in the X-th byte of \ the heap at XX3 INX \ Increment the heap pointer in X to point to the next \ byte LDA #0 \ And then subtract the high bytes SBC U STA XX3,X \ Store the low byte of the result in the X-th byte of \ the heap at XX3 JMP LL66 \ Jump down to LL66Name: LL62 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate 128 - (U R)Context: See this subroutine on its own page References: This subroutine is called as follows: * LL9 (Part 8 of 12) calls LL62

Calculate the following for a positive sign-magnitude number (U R): 128 - (U R) and then store the result, low byte then high byte, on the end of the heap at XX3, where X points to the first free byte on the heap. Return by jumping down to LL66. Returns: X X is incremented by 1.LL56 LDA XX1+6 \ Set (U T) = XX1(7 6) - XX12(5 4) SEC \ = (z_hi z_lo) - vertv_z SBC XX12+4 \ STA T \ Starting with the low bytes LDA XX1+7 \ And then doing the high bytes (we can subtract 0 here SBC #0 \ as we know the sign byte of vertv_z is 0) STA U BCC LL140 \ If the subtraction just underflowed, skip to LL140 to \ set (U T) to the minimum value of 4 BNE LL57 \ If U is non-zero, jump down to LL57 LDA T \ If T >= 4, jump down to LL57 CMP #4 BCS LL57 .LL140 LDA #0 \ If we get here then either (U T) < 4 or the STA U \ subtraction underflowed, so set (U T) = 4 LDA #4 STA T .LL57 \ By this point we have our results, so now to scale \ the 16-bit results down into 8-bit values LDA U \ If the high bytes of the result are all zero, we are ORA XX15+1 \ done, so jump down to LL60 for the next stage ORA XX15+4 BEQ LL60 LSR XX15+1 \ Shift XX15(1 0) to the right ROR XX15 LSR XX15+4 \ Shift XX15(4 3) to the right ROR XX15+3 LSR U \ Shift (U T) to the right ROR T JMP LL57 \ Jump back to LL57 to see if we can shift the result \ any moreName: LL9 (Part 7 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Calculate the visibility of each of the ship's vertices Deep dive: Drawing ships Calculating vertex coordinates

This section continues the coordinate adding from part 6 by finishing off the calculation that we started above: [ sidev_x roofv_x nosev_x ] [ x ] [ x ] vector to vertex = [ sidev_y roofv_y nosev_y ] . [ y ] + [ y ] [ sidev_z roofv_z nosev_z ] [ z ] [ z ] The gets stored as follows, in sign-magnitude values with the magnitudes fitting into the low bytes: XX15(2 0) [ x y z ] . [ sidev_x roofv_x nosev_x ] + [ x y z ] XX15(5 3) [ x y z ] . [ sidev_y roofv_y nosev_y ] + [ x y z ] (U T) [ x y z ] . [ sidev_z roofv_z nosev_z ] + [ x y z ] Finally, because this vector is from our ship to the vertex, and we are at the origin, this vector is the same as the coordinates of the vertex. In other words, we have just worked out: XX15(2 0) x-coordinate of the current vertex XX15(5 3) y-coordinate of the current vertex (U T) z-coordinate of the current vertex.LL60 LDA T \ Set Q = z_lo STA Q LDA XX15 \ Set A = x_lo CMP Q \ If x_lo < z_lo jump to LL69 BCC LL69 JSR LL61 \ Call LL61 to calculate: \ \ (U R) = 256 * A / Q \ = 256 * x / z \ \ which we can do as x >= z JMP LL65 \ Jump to LL65 to skip the division for x_lo < z_lo .LL69 JSR LL28 \ Call LL28 to calculate: \ \ R = 256 * A / Q \ = 256 * x / z \ \ Because x < z, the result fits into one byte, and we \ also know that U = 0, so (U R) also contains the \ result .LL65 \ At this point we have: \ \ (U R) = x / z \ \ so (U R) contains the vertex's x-coordinate projected \ on screen \ \ The next task is to convert (U R) to a pixel screen \ coordinate and stick it on the XX3 heap. \ \ We start with the x-coordinate. To convert the \ x-coordinate to a screen pixel we add 128, the \ x-coordinate of the centre of the screen, because the \ projected value is relative to an origin at the centre \ of the screen, but the origin of the screen pixels is \ at the top-left of the screen LDX CNT \ Fetch the pointer to the end of the XX3 heap from CNT \ into X LDA XX15+2 \ If x_sign is negative, jump up to LL62, which will BMI LL62 \ store 128 - (U R) on the XX3 heap and return by \ jumping down to LL66 below LDA R \ Calculate 128 + (U R), starting with the low bytes CLC ADC #128 STA XX3,X \ Store the low byte of the result in the X-th byte of \ the heap at XX3 INX \ Increment the heap pointer in X to point to the next \ byte LDA U \ And then add the high bytes ADC #0 STA XX3,X \ Store the high byte of the result in the X-th byte of \ the heap at XX3 .LL66 \ We've just stored the screen x-coordinate of the \ vertex on the XX3 heap, so now for the y-coordinate TXA \ Store the heap pointer in X on the stack (at this PHA \ it points to the last entry on the heap, not the first \ free byte) LDA #0 \ Set U = 0 STA U LDA T \ Set Q = z_lo STA Q LDA XX15+3 \ Set A = y_lo CMP Q \ If y_lo < z_lo jump to LL67 BCC LL67 JSR LL61 \ Call LL61 to calculate: \ \ (U R) = 256 * A / Q \ = 256 * y / z \ \ which we can do as y >= z JMP LL68 \ Jump to LL68 to skip the division for y_lo < z_lo .LL70 \ This gets called from below when y_sign is negative LDA #Y \ Calculate #Y + (U R), starting with the low bytes CLC ADC R STA XX3,X \ Store the low byte of the result in the X-th byte of \ the heap at XX3 INX \ Increment the heap pointer in X to point to the next \ byte LDA #0 \ And then add the high bytes ADC U STA XX3,X \ Store the high byte of the result in the X-th byte of \ the heap at XX3 JMP LL50 \ Jump to LL68 to skip the division for y_lo < z_lo .LL67 JSR LL28 \ Call LL28 to calculate: \ \ R = 256 * A / Q \ = 256 * y / z \ \ Because y < z, the result fits into one byte, and we \ also know that U = 0, so (U R) also contains the \ result .LL68 \ At this point we have: \ \ (U R) = y / z \ \ so (U R) contains the vertex's y-coordinate projected \ on screen \ \ We now want to convert this to a screen y-coordinate \ and stick it on the XX3 heap, much like we did with \ the x-coordinate above. Again, we convert the \ coordinate by adding or subtracting the y-coordinate \ of the centre of the screen, which is in the constant \ #Y, but this time we do the opposite, as a positive \ projected y-coordinate, i.e. up the space y-axis and \ up the screen, converts to a low y-coordinate, which \ is the opposite way round to the x-coordinates PLA \ Restore the heap pointer from the stack into X TAX INX \ When we stored the heap pointer, it pointed to the \ last entry on the heap, not the first free byte, so we \ increment it so it does point to the next free byte LDA XX15+5 \ If y_sign is negative, jump up to LL70, which will BMI LL70 \ store #Y + (U R) on the XX3 heap and return by jumping \ down to LL50 below LDA #Y \ Calculate #Y - (U R), starting with the low bytes SEC SBC R STA XX3,X \ Store the low byte of the result in the X-th byte of \ the heap at XX3 INX \ Increment the heap pointer in X to point to the next \ byte LDA #0 \ And then subtract the high bytes SBC U STA XX3,X \ Store the high byte of the result in the X-th byte of \ the heap at XX3 .LL50 \ By the time we get here, the XX3 heap contains four \ bytes containing the screen coordinates of the current \ vertex, in the order: x_lo, x_hi, y_lo, y_hi CLC \ Set CNT = CNT + 4, so the heap pointer points to the LDA CNT \ next free byte on the heap ADC #4 STA CNT LDA XX17 \ Set A to the offset of the current vertex's data, \ which we set in part 6 ADC #6 \ Set Y = A + 6, so Y now points to the data for the TAY \ next vertex BCS LL72 \ If the addition just overflowed, meaning we just tried \ to access vertex #43, jump to LL72, as the maximum \ number of vertices allowed is 42 CMP XX20 \ If Y >= number of vertices * 6 (which we stored in BCS LL72 \ XX20 in part 6), jump to LL72, as we have processed \ all the vertices for this ship JMP LL48 \ Loop back to LL48 in part 6 to calculate visibility \ and screen coordinates for the next vertexName: LL9 (Part 8 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Calculate the screen coordinates of visible vertices Deep dive: Drawing ships

This section projects the coordinate of the vertex into screen coordinates and stores them on the XX3 heap. By the end of this part, the XX3 heap contains four bytes containing the 16-bit screen coordinates of the current vertex, in the order: x_lo, x_hi, y_lo, y_hi. When we reach here, we are looping through the vertices, and we've just worked out the coordinates of the vertex in our normal coordinate system, as follows XX15(2 0) (x_sign x_lo) = x-coordinate of the current vertex XX15(5 3) (y_sign y_lo) = y-coordinate of the current vertex (U T) (z_sign z_lo) = z-coordinate of the current vertex Note that U is always zero when we get to this point, as the vertex is always in front of us (so it has a positive z-coordinate, into the screen). Other entry points: LL70+1 Contains an RTS (as the first byte of an LDA instruction).LL72 LDA XX1+31 \ If bit 5 of the ship's byte #31 is clear, then the AND #%00100000 \ ship is not currently exploding, so jump down to EE31 BEQ EE31 LDA XX1+31 \ The ship is exploding, so set bit 3 of the ship's byte ORA #8 \ #31 to denote that we are drawing something on-screen STA XX1+31 \ for this ship JMP DOEXP \ Jump to DOEXP to display the explosion cloud, \ returning from the subroutine using a tail call .EE31 LDA #%00001000 \ If bit 3 of the ship's byte #31 is clear, then there BIT XX1+31 \ is nothing already being shown for this ship, so skip BEQ LL74 \ to LL74 as we don't need to erase anything from the \ screen JSR LL155 \ Otherwise call LL155 to draw the existing ship, which \ removes it from the screen LDA #%00001000 \ Set bit 3 of A so the next instruction sets bit 3 of \ the ship's byte #31 to denote that we are drawing \ something on-screen for this ship .LL74 ORA XX1+31 \ Apply bit 3 of A to the ship's byte #31, so if there STA XX1+31 \ was no ship already on screen, the bit is clear, \ otherwise it is set LDY #9 \ Fetch byte #9 of the ship's blueprint, which is the LDA (XX0),Y \ number of edges, and store it in XX20 STA XX20 LDY #0 \ We are about to step through all the edges, using Y \ as a counter STY U \ Set U = 0 (though we increment it to 1 below) STY XX17 \ Set XX17 = 0, which we are going to use as a counter \ for stepping through the ship's edges INC U \ We are going to start calculating the lines we need to \ draw for this ship, and will store them in the ship \ line heap, using U to point to the end of the heap, so \ we start by setting U = 1 BIT XX1+31 \ If bit 6 of the ship's byte #31 is clear, then the BVC LL170 \ ship is not firing its lasers, so jump to LL170 to \ skip the drawing of laser lines \ The ship is firing its laser at us, so we need to draw \ the laser lines LDA XX1+31 \ Clear bit 6 of the ship's byte #31 so the ship doesn't AND #%10111111 \ keep firing endlessly STA XX1+31 LDY #6 \ Fetch byte #6 of the ship's blueprint, which is the LDA (XX0),Y \ number * 4 of the vertex where the ship has its lasers TAY \ Put the vertex number into Y, where it can act as an \ index into list of vertex screen coordinates we added \ to the XX3 heap LDX XX3,Y \ Fetch the x_lo coordinate of the laser vertex from the STX XX15 \ XX3 heap into XX15 INX \ If X = 255 then the laser vertex is not visible, as BEQ LL170 \ the value we stored in part 2 wasn't overwritten by \ the vertex calculation in part 6 and 7, so jump to \ LL170 to skip drawing the laser lines \ We now build a laser beam from the ship's laser vertex \ towards our ship, as follows: \ \ XX15(1 0) = laser vertex x-coordinate \ \ XX15(3 2) = laser vertex y-coordinate \ \ XX15(5 4) = x-coordinate of the end of the beam \ \ XX12(1 0) = y-coordinate of the end of the beam \ \ The end of the laser beam will be set positioned to \ look good, rather than being directly aimed at us, as \ otherwise we would only see a flashing point of light \ as they unleashed their attack LDX XX3+1,Y \ Fetch the x_hi coordinate of the laser vertex from the STX XX15+1 \ XX3 heap into XX15+1 INX \ If X = 255 then the laser vertex is not visible, as BEQ LL170 \ the value we stored in part 2 wasn't overwritten by \ a vertex calculation in part 6 and 7, so jump to LL170 \ to skip drawing the laser beam LDX XX3+2,Y \ Fetch the y_lo coordinate of the laser vertex from the STX XX15+2 \ XX3 heap into XX15+2 LDX XX3+3,Y \ Fetch the y_hi coordinate of the laser vertex from the STX XX15+3 \ XX3 heap into XX15+3 LDA #0 \ Set XX15(5 4) = 0, so their laser beam fires to the STA XX15+4 \ left edge of the screen STA XX15+5 STA XX12+1 \ Set XX12(1 0) = the ship's z_lo coordinate, which will LDA XX1+6 \ effectively make the vertical position of the end of STA XX12 \ the laser beam move around as the ship moves in space LDA XX1+2 \ If the ship's x_sign is positive, skip the next BPL P%+4 \ instruction DEC XX15+4 \ The ship's x_sign is negative (i.e. it's on the left \ side of the screen), so switch the laser beam so it \ goes to the right edge of the screen by decrementing \ XX15(5 4) to 255 JSR LL145 \ Call LL145 to see if the laser beam needs to be \ clipped to fit on-screen, returning the clipped line's \ end-points in (X1, Y1) and (X2, Y2) BCS LL170 \ If the C flag is set then the line is not visible on \ screen, so jump to LL170 so we don't store this line \ in the ship line heap LDY U \ Fetch the ship line heap pointer, which points to the \ next free byte on the heap, into Y LDA XX15 \ Add X1 to the end of the heap STA (XX19),Y INY \ Increment the heap pointer LDA XX15+1 \ Add Y1 to the end of the heap STA (XX19),Y INY \ Increment the heap pointer LDA XX15+2 \ Add X2 to the end of the heap STA (XX19),Y INY \ Increment the heap pointer LDA XX15+3 \ Add Y2 to the end of the heap STA (XX19),Y INY \ Increment the heap pointer STY U \ Store the updated ship line heap pointer in UName: LL9 (Part 9 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Draw laser beams if the ship is firing its laser at us Deep dive: Drawing ships

This part sets things up so we can loop through the edges in the next part. It also adds a line to the ship line heap, if the ship is firing at us. When we get here, the heap at XX3 contains all the visible vertex screen coordinates..LL170 LDY #3 \ Fetch byte #3 of the ship's blueprint, which contains CLC \ the low byte of the offset to the edges data LDA (XX0),Y ADC XX0 \ Set V = low byte edges offset + XX0 STA V LDY #16 \ Fetch byte #16 of the ship's blueprint, which contains LDA (XX0),Y \ the high byte of the offset to the edges data ADC XX0+1 \ Set V+1 = high byte edges offset + XX0+1 STA V+1 \ \ So V(1 0) now points to the start of the edges data \ for this ship LDY #5 \ Fetch byte #5 of the ship's blueprint, which contains LDA (XX0),Y \ the maximum heap size for plotting the ship (which is STA T1 \ 1 + 4 * the maximum number of visible edges) and store \ it in T1 LDY XX17 \ Set Y to the edge counter in XX17 .LL75 LDA (V),Y \ Fetch byte #0 for this edge, which contains the \ visibility distance for this edge, beyond which the \ edge is not shown CMP XX4 \ If XX4 > the visibility distance, where XX4 contains BCC LL79-3 \ the ship's z-distance reduced to 0-31 (which we set in \ part 2), then this edge is too far away to be visible, \ so jump down to LL78 (via LL79-3) to move on to the \ next edge INY \ Increment Y to point to byte #1 LDA (V),Y \ Fetch byte #1 for this edge into A, so: \ \ A = %ffff ffff, where: \ \ * Bits 0-3 = the number of face 1 \ \ * Bits 4-7 = the number of face 2 INY \ Increment Y to point to byte #2 STA P \ Store byte #1 into P AND #%00001111 \ Extract the number of face 1 into X TAX LDA XX2,X \ If XX2+X is non-zero then we decided in part 5 that BNE LL79 \ face 1 is visible, so jump to LL79 LDA P \ Fetch byte #1 for this edge into A LSR A \ Shift right four times to extract the number of face 2 LSR A \ from bits 4-7 into X LSR A LSR A TAX LDA XX2,X \ If XX2+X is non-zero then we decided in part 5 that BNE LL79 \ face 2 is visible, so skip the following instruction JMP LL78 \ Face 2 is hidden, so jump to LL78 .LL79 \ We now build the screen line for this edge, as \ follows: \ \ XX15(1 0) = start x-coordinate \ \ XX15(3 2) = start y-coordinate \ \ XX15(5 4) = end x-coordinate \ \ XX12(1 0) = end y-coordinate \ \ We can then pass this to the line clipping routine \ before storing the resulting line in the ship line \ heap LDA (V),Y \ Fetch byte #2 for this edge into X, which contains TAX \ the number of the vertex at the start of the edge INY \ Increment Y to point to byte #3 LDA (V),Y \ Fetch byte #3 for this edge into Q, which contains STA Q \ the number of the vertex at the end of the edge LDA XX3+1,X \ Fetch the x_hi coordinate of the edge's start vertex STA XX15+1 \ from the XX3 heap into XX15+1 LDA XX3,X \ Fetch the x_lo coordinate of the edge's start vertex STA XX15 \ from the XX3 heap into XX15 LDA XX3+2,X \ Fetch the y_lo coordinate of the edge's start vertex STA XX15+2 \ from the XX3 heap into XX15+2 LDA XX3+3,X \ Fetch the y_hi coordinate of the edge's start vertex STA XX15+3 \ from the XX3 heap into XX15+3 LDX Q \ Set X to the number of the vertex at the end of the \ edge, which we stored in Q LDA XX3,X \ Fetch the x_lo coordinate of the edge's end vertex STA XX15+4 \ from the XX3 heap into XX15+4 LDA XX3+3,X \ Fetch the y_hi coordinate of the edge's end vertex STA XX12+1 \ from the XX3 heap into XX11+1 LDA XX3+2,X \ Fetch the y_lo coordinate of the edge's end vertex STA XX12 \ from the XX3 heap into XX12 LDA XX3+1,X \ Fetch the x_hi coordinate of the edge's end vertex STA XX15+5 \ from the XX3 heap into XX15+5 JSR LL147 \ Call LL147 to see if the new line segment needs to be \ clipped to fit on-screen, returning the clipped line's \ end-points in (X1, Y1) and (X2, Y2) BCS LL79-3 \ If the C flag is set then the line is not visible on \ screen, so jump to LL78 (via LL79-3) so we don't store \ this line in the ship line heap JMP LL80 \ Jump down to part 11 to draw this edgeName: LL9 (Part 10 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Calculate the visibility of each of the ship's edges Deep dive: Drawing ships

This part calculates which edges are visible - in other words, which lines we should draw - and clips them to fit on the screen. When we get here, the heap at XX3 contains all the visible vertex screen coordinates..LL145 LDA #0 \ Set SWAP = 0 STA SWAP LDA XX15+5 \ Set A = x2_hi .LL147 LDX #Y*2-1 \ Set Y2 = #Y * 2 - 1. The constant #Y is 96, the \ y-coordinate of the mid-point of the space view, so \ this sets Y2 to 191, the y-coordinate of the bottom \ pixel row of the space view ORA XX12+1 \ If one or both of x2_hi and y2_hi are non-zero, jump BNE LL107 \ to LL107 to skip the following CPX XX12 \ If y2_lo > the y-coordinate of the bottom of screen BCC LL107 \ then (x2, y2) is off the bottom of the screen, so skip \ the following instruction, leaving X at 191 LDX #0 \ Set X = 0 .LL107 STX XX13 \ Set XX13 = X, so we have: \ \ * XX13 = 0 if x2_hi = y2_hi = 0, y2_lo is on-screen \ \ * XX13 = 191 if x2_hi or y2_hi are non-zero or y2_lo \ is off the bottom of the screen \ \ In other words, XX13 is 191 if (x2, y2) is off-screen, \ otherwise it is 0 LDA XX15+1 \ If one or both of x1_hi and y1_hi are non-zero, jump ORA XX15+3 \ jump to LL83 BNE LL83 LDA #Y*2-1 \ If y1_lo > the y-coordinate of the bottom of screen CMP XX15+2 \ then (x1, y1) is off the bottom of the screen, so jump BCC LL83 \ to LL83 \ If we get here, (x1, y1) is on-screen LDA XX13 \ If XX13 is non-zero, i.e. (x2, y2) is off-screen, jump BNE LL108 \ to LL108 to halve it before continuing at LL83 \ If we get here, the high bytes are all zero, which \ means the x-coordinates are < 256 and therefore fit on \ screen, and neither coordinate is off the bottom of \ the screen. That means both coordinates are already on \ screen, so we don't need to do any clipping, all we \ need to do is move the low bytes into (X1, Y1) and \ X2, Y2) and return .LL146 \ If we get here then we have clipped our line to the \ (if we had to clip it at all), so we move the low \ bytes from (x1, y1) and (x2, y2) into (X1, Y1) and \ (X2, Y2), remembering that they share locations with \ XX15: \ \ X1 = XX15 \ Y1 = XX15+1 \ X2 = XX15+2 \ Y2 = XX15+3 \ \ X1 already contains x1_lo, so now we do the rest LDA XX15+2 \ Set Y1 (aka XX15+1) = y1_lo STA XX15+1 LDA XX15+4 \ Set X2 (aka XX15+2) = x2_lo STA XX15+2 LDA XX12 \ Set Y2 (aka XX15+3) = y2_lo STA XX15+3 CLC \ Clear the C flag as the clipped line fits on-screen RTS \ Return from the subroutine .LL109 SEC \ Set the C flag to indicate the clipped line does not \ fit on-screen RTS \ Return from the subroutine .LL108 LSR XX13 \ If we get here then (x2, y2) is off-screen and XX13 is \ 191, so shift XX13 right to halve it to 95Name: LL145 (Part 1 of 4) [Show more] Type: Subroutine Category: Drawing lines Summary: Clip line: Work out which end-points are on-screen, if any Deep dive: Line-clipping Extended screen coordinatesContext: See this subroutine on its own page References: This subroutine is called as follows: * BLINE calls LL145 * LL9 (Part 9 of 12) calls LL145 * LL9 (Part 10 of 12) calls entry point LL147

This routine clips the line from (x1, y1) to (x2, y2) so it fits on-screen, or returns an error if it can't be clipped to fit. The arguments are 16-bit coordinates, and the clipped line is returned using 8-bit screen coordinates. This part sets XX13 to reflect which of the two points are on-screen and off-screen. Arguments: XX15(1 0) x1 as a 16-bit coordinate (x1_hi x1_lo) XX15(3 2) y1 as a 16-bit coordinate (y1_hi y1_lo) XX15(5 4) x2 as a 16-bit coordinate (x2_hi x2_lo) XX12(1 0) y2 as a 16-bit coordinate (y2_hi y2_lo) Returns: (X1, Y1) Screen coordinate of the start of the clipped line (X2, Y2) Screen coordinate of the end of the clipped line C flag Clear if the clipped line fits on-screen, set if it doesn't XX13 The state of the original coordinates on-screen: * 0 = (x2, y2) on-screen * 95 = (x1, y1) on-screen, (x2, y2) off-screen * 191 = (x1, y1) off-screen, (x2, y2) off-screen So XX13 is non-zero if the end of the line was clipped, meaning the next line sent to BLINE can't join onto the end but has to start a new segment SWAP The swap status of the returned coordinates: * &FF if we swapped the values of (x1, y1) and (x2, y2) as part of the clipping process * 0 if the coordinates are still in the same order Y Y is preserved Other entry points: LL147 Don't initialise the values in SWAP or A.LL83 LDA XX13 \ If XX13 < 128 then only one of the points is on-screen BPL LL115 \ so jump down to LL115 to skip the checks of whether \ both points are in the strips to the right or bottom \ of the screen \ If we get here, both points are off-screen LDA XX15+1 \ If both x1_hi and x2_hi have bit 7 set, jump to LL109 AND XX15+5 \ to return from the subroutine with the C flag set, as BMI LL109 \ the entire line is above the top of the screen LDA XX15+3 \ If both y1_hi and y2_hi have bit 7 set, jump to LL109 AND XX12+1 \ to return from the subroutine with the C flag set, as BMI LL109 \ the entire line is to the left of the screen LDX XX15+1 \ Set A = X = x1_hi - 1 DEX TXA LDX XX15+5 \ Set XX12+2 = x2_hi - 1 DEX STX XX12+2 ORA XX12+2 \ If neither (x1_hi - 1) or (x2_hi - 1) have bit 7 set, BPL LL109 \ jump to LL109 to return from the subroutine with the C \ flag set, as the line doesn't fit on-screen LDA XX15+2 \ If y1_lo < y-coordinate of screen bottom, clear the C CMP #Y*2 \ flag, otherwise set it LDA XX15+3 \ Set XX12+2 = y1_hi - (1 - C), so: SBC #0 \ STA XX12+2 \ * Set XX12+2 = y1_hi - 1 if y1_lo is on-screen \ * Set XX12+2 = y1_hi otherwise \ \ We do this subtraction because we are only interested \ in trying to move the points up by a screen if that \ might move the point into the space view portion of \ the screen, i.e. if y1_lo is on-screen LDA XX12 \ If y2_lo < y-coordinate of screen bottom, clear the C CMP #Y*2 \ flag, otherwise set it LDA XX12+1 \ Set XX12+2 = y2_hi - (1 - C), so: SBC #0 \ \ * Set XX12+1 = y2_hi - 1 if y2_lo is on-screen \ * Set XX12+1 = y2_hi otherwise \ \ We do this subtraction because we are only interested \ in trying to move the points up by a screen if that \ might move the point into the space view portion of \ the screen, i.e. if y1_lo is on-screen ORA XX12+2 \ If neither XX12+1 or XX12+2 have bit 7 set, jump to BPL LL109 \ LL109 to return from the subroutine with the C flag \ set, as the line doesn't fit on-screenName: LL145 (Part 2 of 4) [Show more] Type: Subroutine Category: Drawing lines Summary: Clip line: Work out if any part of the line is on-screen Deep dive: Line-clipping Extended screen coordinates

This part does a number of tests to see if the line is on or off the screen. If we get here then at least one of (x1, y1) and (x2, y2) is off-screen, with XX13 set as follows: * 0 = (x1, y1) off-screen, (x2, y2) on-screen * 95 = (x1, y1) on-screen, (x2, y2) off-screen * 191 = (x1, y1) off-screen, (x2, y2) off-screen where "off-screen" is defined as having a non-zero high byte in one of the coordinates, or in the case of y-coordinates, having a low byte > 191, the y-coordinate of the bottom of the space view..LL115 TYA \ Store Y on the stack so we can preserve it through the PHA \ call to this subroutine LDA XX15+4 \ Set XX12+2 = x2_lo - x1_lo SEC SBC XX15 STA XX12+2 LDA XX15+5 \ Set XX12+3 = x2_hi - x1_hi SBC XX15+1 STA XX12+3 LDA XX12 \ Set XX12+4 = y2_lo - y1_lo SEC SBC XX15+2 STA XX12+4 LDA XX12+1 \ Set XX12+5 = y2_hi - y1_hi SBC XX15+3 STA XX12+5 \ So we now have: \ \ delta_x in XX12(3 2) \ delta_y in XX12(5 4) \ \ where the delta is (x1, y1) - (x2, y2)) EOR XX12+3 \ Set S = the sign of delta_x * the sign of delta_y, so STA S \ if bit 7 of S is set, the deltas have different signs LDA XX12+5 \ If delta_y_hi is positive, jump down to LL110 to skip BPL LL110 \ the following LDA #0 \ Otherwise flip the sign of delta_y to make it SEC \ positive, starting with the low bytes SBC XX12+4 STA XX12+4 LDA #0 \ And then doing the high bytes, so now: SBC XX12+5 \ STA XX12+5 \ XX12(5 4) = |delta_y| .LL110 LDA XX12+3 \ If delta_x_hi is positive, jump down to LL111 to skip BPL LL111 \ the following SEC \ Otherwise flip the sign of delta_x to make it LDA #0 \ positive, starting with the low bytes SBC XX12+2 STA XX12+2 LDA #0 \ And then doing the high bytes, so now: SBC XX12+3 \ \ (A XX12+2) = |delta_x| .LL111 \ We now keep halving |delta_x| and |delta_y| until \ both of them have zero in their high bytes TAX \ IF |delta_x_hi| is non-zero, skip the following BNE LL112 LDX XX12+5 \ If |delta_y_hi| = 0, jump down to LL113 (as both BEQ LL113 \ |delta_x_hi| and |delta_y_hi| are 0) .LL112 LSR A \ Halve the value of delta_x in (A XX12+2) ROR XX12+2 LSR XX12+5 \ Halve the value of delta_y XX12(5 4) ROR XX12+4 JMP LL111 \ Loop back to LL111 .LL113 \ By now, the high bytes of both |delta_x| and |delta_y| \ are zero STX T \ We know that X = 0 as that's what we tested with a BEQ \ above, so this sets T = 0 LDA XX12+2 \ If delta_x_lo < delta_y_lo, so our line is more CMP XX12+4 \ vertical than horizontal, jump to LL114 BCC LL114 STA Q \ Set Q = delta_x_lo LDA XX12+4 \ Set A = delta_y_lo JSR LL28 \ Call LL28 to calculate: \ \ R = 256 * A / Q \ = 256 * delta_y_lo / delta_x_lo JMP LL116 \ Jump to LL116, as we now have the line's gradient in R .LL114 LDA XX12+4 \ Set Q = delta_y_lo STA Q LDA XX12+2 \ Set A = delta_x_lo JSR LL28 \ Call LL28 to calculate: \ \ R = 256 * A / Q \ = 256 * delta_x_lo / delta_y_lo DEC T \ T was set to 0 above, so this sets T = &FFName: LL145 (Part 3 of 4) [Show more] Type: Subroutine Category: Drawing lines Summary: Clip line: Calculate the line's gradient Deep dive: Line-clipping Extended screen coordinates.LL116 LDA R \ Store the gradient in XX12+2 STA XX12+2 LDA S \ Store the type of slope in XX12+3, bit 7 clear means STA XX12+3 \ top left to bottom right, bit 7 set means top right to \ bottom left LDA XX13 \ If XX13 = 0, skip the following instruction BEQ LL138 BPL LLX117 \ If XX13 is positive, it must be 95. This means \ (x1, y1) is on-screen but (x2, y2) isn't, so we jump \ to LLX117 to swap the (x1, y1) and (x2, y2) \ coordinates around before doing the actual clipping, \ because we need to clip (x2, y2) but the clipping \ routine at LL118 only clips (x1, y1) .LL138 \ If we get here, XX13 = 0 or 191, so (x1, y1) is \ off-screen and needs clipping JSR LL118 \ Call LL118 to move (x1, y1) along the line onto the \ screen, i.e. clip the line at the (x1, y1) end LDA XX13 \ If XX13 = 0, i.e. (x2, y2) is on-screen, jump down to BPL LL124 \ LL124 to return with a successfully clipped line .LL117 \ If we get here, XX13 = 191 (both coordinates are \ off-screen) LDA XX15+1 \ If either of x1_hi or y1_hi are non-zero, jump to ORA XX15+3 \ LL137 to return from the subroutine with the C flag BNE LL137 \ set, as the line doesn't fit on-screen LDA XX15+2 \ If y1_lo > y-coordinate of the bottom of the screen CMP #Y*2 \ jump to LL137 to return from the subroutine with the BCS LL137 \ C flag set, as the line doesn't fit on-screen .LLX117 \ If we get here, XX13 = 95 or 191, and in both cases \ (x2, y2) is off-screen, so we now need to swap the \ (x1, y1) and (x2, y2) coordinates around before doing \ the actual clipping, because we need to clip (x2, y2) \ but the clipping routine at LL118 only clips (x1, y1) LDX XX15 \ Swap x1_lo = x2_lo LDA XX15+4 STA XX15 STX XX15+4 LDA XX15+5 \ Swap x2_lo = x1_lo LDX XX15+1 STX XX15+5 STA XX15+1 LDX XX15+2 \ Swap y1_lo = y2_lo LDA XX12 STA XX15+2 STX XX12 LDA XX12+1 \ Swap y2_lo = y1_lo LDX XX15+3 STX XX12+1 STA XX15+3 JSR LL118 \ Call LL118 to move (x1, y1) along the line onto the \ screen, i.e. clip the line at the (x1, y1) end DEC SWAP \ Set SWAP = &FF to indicate that we just clipped the \ line at the (x2, y2) end by swapping the coordinates \ (the DEC does this as we set SWAP to 0 at the start of \ this subroutine) .LL124 PLA \ Restore Y from the stack so it gets preserved through TAY \ the call to this subroutine JMP LL146 \ Jump up to LL146 to move the low bytes of (x1, y1) and \ (x2, y2) into (X1, Y1) and (X2, Y2), and return from \ the subroutine with a successfully clipped line .LL137 PLA \ Restore Y from the stack so it gets preserved through TAY \ the call to this subroutine SEC \ Set the C flag to indicate the clipped line does not \ fit on-screen RTS \ Return from the subroutineName: LL145 (Part 4 of 4) [Show more] Type: Subroutine Category: Drawing lines Summary: Clip line: Call the routine in LL188 to do the actual clipping Deep dive: Line-clipping Extended screen coordinates

This part sets things up to call the routine in LL188, which does the actual clipping. If we get here, then R has been set to the gradient of the line (x1, y1) to (x2, y2), with T indicating the type of slope: * 0 = it's more vertical than horizontal * &FF = it's more horizontal than vertical and XX13 has been set as follows: * 0 = (x1, y1) off-screen, (x2, y2) on-screen * 95 = (x1, y1) on-screen, (x2, y2) off-screen * 191 = (x1, y1) off-screen, (x2, y2) off-screen.LL80 LDY U \ Fetch the ship line heap pointer, which points to the \ next free byte on the heap, into Y LDA XX15 \ Add X1 to the end of the heap STA (XX19),Y INY \ Increment the heap pointer LDA XX15+1 \ Add Y1 to the end of the heap STA (XX19),Y INY \ Increment the heap pointer LDA XX15+2 \ Add X2 to the end of the heap STA (XX19),Y INY \ Increment the heap pointer LDA XX15+3 \ Add Y2 to the end of the heap STA (XX19),Y INY \ Increment the heap pointer STY U \ Store the updated ship line heap pointer in U CPY T1 \ If Y >= T1 then we have reached the maximum number of BCS LL81 \ edge lines that we can store in the ship line heap, so \ skip to LL81 so we don't loop back for the next edge .LL78 INC XX17 \ Increment the edge counter to point to the next edge LDY XX17 \ If Y >= XX20, which contains the number of edges in CPY XX20 \ the blueprint, jump to LL81 as we have processed all BCS LL81 \ the edges and don't need to loop back for the next one LDY #0 \ Set Y to point to byte #0 again, ready for the next \ edge LDA V \ Increment V by 4 so V(1 0) points to the data for the ADC #4 \ next edge STA V BCC ll81 \ If the above addition didn't overflow, jump to ll81 INC V+1 \ Otherwise increment the high byte of V(1 0), as we \ just moved the V(1 0) pointer past a page boundary .ll81 JMP LL75 \ Loop back to LL75 to process the next edge .LL81 \ We have finished adding lines to the ship line heap, \ so now we need to set the first byte of the heap to \ the number of bytes stored there LDA U \ Fetch the ship line heap pointer from U into A, which \ points to the end of the heap, and therefore contains \ the heap size LDY #0 \ Store A as the first byte of the ship line heap, so STA (XX19),Y \ the heap is now correctly set upName: LL9 (Part 11 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Add all visible edges to the ship line heap Deep dive: Drawing shipsContext: See this subroutine on its own page References: This subroutine is called as follows: * SHPPT calls entry point LL81+2

This part adds all the visible edges to the ship line heap, so we can draw them in part 12. Other entry points: LL81+2 Draw the contents of the ship line heap, used to draw the ship as a dot from SHPPT.LL155 LDY #0 \ Fetch the first byte from the ship line heap into A, LDA (XX19),Y \ which contains the number of bytes in the heap STA XX20 \ Store the heap size in XX20 CMP #4 \ If the heap size is less than 4, there is nothing to BCC LL118-1 \ draw, so return from the subroutine (as LL118-1 \ contains an RTS) INY \ Set Y = 1, which we will use as an index into the ship \ line heap, starting at byte #1 (as byte #0 contains \ the heap size) .LL27 LDA (XX19),Y \ Fetch the X1 line coordinate from the heap and store STA XX15 \ it in XX15 INY \ Increment the heap pointer LDA (XX19),Y \ Fetch the Y1 line coordinate from the heap and store STA XX15+1 \ it in XX15+1 INY \ Increment the heap pointer LDA (XX19),Y \ Fetch the X2 line coordinate from the heap and store STA XX15+2 \ it in XX15+2 INY \ Increment the heap pointer LDA (XX19),Y \ Fetch the Y2 line coordinate from the heap and store STA XX15+3 \ it in XX15+3 JSR LL30 \ Draw a line from (X1, Y1) to (X2, Y2) INY \ Increment the heap pointer CPY XX20 \ If the heap counter is less than the size of the heap, BCC LL27 \ loop back to LL27 to draw the next line from the heap RTS \ Return from the subroutineName: LL9 (Part 12 of 12) [Show more] Type: Subroutine Category: Drawing ships Summary: Draw ship: Draw all the visible edges from the ship line heap Deep dive: Drawing ships

This part draws the lines in the ship line heap, which is used both to draw the ship, and to remove it from the screen..LL118 LDA XX15+1 \ If x1_hi is positive, jump down to LL119 to skip BPL LL119 \ the following STA S \ Otherwise x1_hi is negative, i.e. off the left of the \ screen, so set S = x1_hi JSR LL120 \ Call LL120 to calculate: \ \ (Y X) = (S x1_lo) * XX12+2 if T = 0 \ = x1 * gradient \ \ (Y X) = (S x1_lo) / XX12+2 if T <> 0 \ = x1 / gradient \ \ with the sign of (Y X) set to the opposite of the \ line's direction of slope TXA \ Set y1 = y1 + (Y X) CLC \ ADC XX15+2 \ starting with the low bytes STA XX15+2 TYA \ And then adding the high bytes ADC XX15+3 STA XX15+3 LDA #0 \ Set x1 = 0 STA XX15 STA XX15+1 TAX \ Set X = 0 so the next instruction becomes a JMP .LL119 BEQ LL134 \ If x1_hi = 0 then jump down to LL134 to skip the \ following, as the x-coordinate is already on-screen \ (as 0 <= (x_hi x_lo) <= 255) STA S \ Otherwise x1_hi is positive, i.e. x1 >= 256 and off DEC S \ the right side of the screen, so set S = x1_hi - 1 JSR LL120 \ Call LL120 to calculate: \ \ (Y X) = (S x1_lo) * XX12+2 if T = 0 \ = (x1 - 256) * gradient \ \ (Y X) = (S x1_lo) / XX12+2 if T <> 0 \ = (x1 - 256) / gradient \ \ with the sign of (Y X) set to the opposite of the \ line's direction of slope TXA \ Set y1 = y1 + (Y X) CLC \ ADC XX15+2 \ starting with the low bytes STA XX15+2 TYA \ And then adding the high bytes ADC XX15+3 STA XX15+3 LDX #255 \ Set x1 = 255 STX XX15 INX STX XX15+1 .LL134 \ We have moved the point so the x-coordinate is on \ screen (i.e. in the range 0-255), so now for the \ y-coordinate LDA XX15+3 \ If y1_hi is positive, jump down to LL119 to skip BPL LL135 \ the following STA S \ Otherwise y1_hi is negative, i.e. off the top of the \ screen, so set S = y1_hi LDA XX15+2 \ Set R = y1_lo STA R JSR LL123 \ Call LL123 to calculate: \ \ (Y X) = (S R) / XX12+2 if T = 0 \ = y1 / gradient \ \ (Y X) = (S R) * XX12+2 if T <> 0 \ = y1 * gradient \ \ with the sign of (Y X) set to the opposite of the \ line's direction of slope TXA \ Set x1 = x1 + (Y X) CLC \ ADC XX15 \ starting with the low bytes STA XX15 TYA \ And then adding the high bytes ADC XX15+1 STA XX15+1 LDA #0 \ Set y1 = 0 STA XX15+2 STA XX15+3 .LL135 LDA XX15+2 \ Set (S R) = (y1_hi y1_lo) - 192 SEC \ SBC #Y*2 \ starting with the low bytes STA R LDA XX15+3 \ And then subtracting the high bytes SBC #0 STA S BCC LL136 \ If the subtraction underflowed, i.e. if y1 < 192, then \ y1 is already on-screen, so jump to LL136 to return \ from the subroutine, as we are done .LL139 \ If we get here then y1 >= 192, i.e. off the bottom of \ the screen JSR LL123 \ Call LL123 to calculate: \ \ (Y X) = (S R) / XX12+2 if T = 0 \ = (y1 - 192) / gradient \ \ (Y X) = (S R) * XX12+2 if T <> 0 \ = (y1 - 192) * gradient \ \ with the sign of (Y X) set to the opposite of the \ line's direction of slope TXA \ Set x1 = x1 + (Y X) CLC \ ADC XX15 \ starting with the low bytes STA XX15 TYA \ And then adding the high bytes ADC XX15+1 STA XX15+1 LDA #Y*2-1 \ Set y1 = 2 * #Y - 1. The constant #Y is 96, the STA XX15+2 \ y-coordinate of the mid-point of the space view, so LDA #0 \ this sets Y2 to 191, the y-coordinate of the bottom STA XX15+3 \ pixel row of the space view .LL136 RTS \ Return from the subroutineName: LL118 [Show more] Type: Subroutine Category: Drawing lines Summary: Move a point along a line until it is on-screen Deep dive: Line-clippingContext: See this subroutine on its own page References: This subroutine is called as follows: * LL145 (Part 4 of 4) calls LL118 * LL9 (Part 12 of 12) calls entry point LL118-1

Given a point (x1, y1), a gradient and a direction of slope, move the point along the line until it is on-screen, so this effectively clips the (x1, y1) end of a line to be on the screen. See the deep dive on "Line-clipping" for more details. Arguments: XX15(1 0) x1 as a 16-bit coordinate (x1_hi x1_lo) XX15(3 2) y1 as a 16-bit coordinate (y1_hi y1_lo) XX12+2 The line's gradient * 256 (so 1.0 = 256) XX12+3 The direction of slope: * Positive (bit 7 clear) = top left to bottom right * Negative (bit 7 set) = top right to bottom left T The type of slope: * 0 if it's more vertical than horizontal * &FF if it's more horizontal than vertical Returns: XX15 x1 as an 8-bit coordinate XX15+2 y1 as an 8-bit coordinate Other entry points: LL118-1 Contains an RTS.LL120 LDA XX15 \ Set R = x1_lo STA R JSR LL129 \ Call LL129 to do the following: \ \ Q = XX12+2 \ = line gradient \ \ A = S EOR XX12+3 \ = S EOR slope direction \ \ (S R) = |S R| \ \ So A contains the sign of S * slope direction PHA \ Store A on the stack so we can use it later LDX T \ If T is non-zero, so it's more horizontal than BNE LL121 \ vertical, jump down to LL121 to calculate this \ instead: \ \ (Y X) = (S R) / Q .LL122 \ The following calculates: \ \ (Y X) = (S R) * Q \ \ using the same shift-and-add algorithm that's \ documented in MULT1 LDA #0 \ Set A = 0 TAX \ Set (Y X) = 0 so we can start building the answer here TAY LSR S \ Shift (S R) to the right, so we extract bit 0 of (S R) ROR R \ into the C flag ASL Q \ Shift Q to the left, catching bit 7 in the C flag BCC LL126 \ If C (i.e. the next bit from Q) is clear, do not do \ the addition for this bit of Q, and instead skip to \ LL126 to just do the shifts .LL125 TXA \ Set (Y X) = (Y X) + (S R) CLC \ ADC R \ starting with the low bytes TAX TYA \ And then doing the high bytes ADC S TAY .LL126 LSR S \ Shift (S R) to the right ROR R ASL Q \ Shift Q to the left, catching bit 7 in the C flag BCS LL125 \ If C (i.e. the next bit from Q) is set, loop back to \ LL125 to do the addition for this bit of Q BNE LL126 \ If Q has not yet run out of set bits, loop back to \ LL126 to do the "shift" part of shift-and-add until \ we have done additions for all the set bits in Q, to \ give us our multiplication result PLA \ Restore A, which we calculated above, from the stack BPL LL133 \ If A is positive jump to LL133 to negate (Y X) and \ return from the subroutine using a tail call RTS \ Return from the subroutineName: LL120 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate (Y X) = (S x1_lo) * XX12+2 or (S x1_lo) / XX12+2Context: See this subroutine on its own page References: This subroutine is called as follows: * LL118 calls LL120 * LL123 calls entry point LL122

Calculate the following: * If T = 0 (more vertical than horizontal), (Y X) = (S x1_lo) * XX12+2 * If T <> 0 (more horizontal than vertical), (Y X) = (S x1_lo) / XX12+2 giving (Y X) the opposite sign to the slope direction in XX12+3. Other entry points: LL122 Calculate (Y X) = (S R) * Q and set the sign to the opposite of the top byte on the stack.LL123 JSR LL129 \ Call LL129 to do the following: \ \ Q = XX12+2 \ = line gradient \ \ A = S EOR XX12+3 \ = S EOR slope direction \ \ (S R) = |S R| \ \ So A contains the sign of S * slope direction PHA \ Store A on the stack so we can use it later LDX T \ If T is non-zero, so it's more horizontal than BNE LL122 \ vertical, jump up to LL122 to calculate this instead: \ \ (Y X) = (S R) * Q .LL121 \ The following calculates: \ \ (Y X) = (S R) / Q \ \ using the same shift-and-subtract algorithm that's \ documented in TIS2 LDA #%11111111 \ Set Y = %11111111 TAY ASL A \ Set X = %11111110 TAX \ This sets (Y X) = %1111111111111110, so we can rotate \ through 15 loop iterations, getting a 1 each time, and \ then getting a 0 on the 16th iteration... and we can \ also use it to catch our result bits into bit 0 each \ time .LL130 ASL R \ Shift (S R) to the left ROL S LDA S \ Set A = S BCS LL131 \ If bit 7 of S was set, then jump straight to the \ subtraction CMP Q \ If A < Q (i.e. S < Q), skip the following subtractions BCC LL132 .LL131 SBC Q \ A >= Q (i.e. S >= Q) so set: STA S \ \ S = (A R) - Q \ = (S R) - Q \ \ starting with the low bytes (we know the C flag is \ set so the subtraction will be correct) LDA R \ And then doing the high bytes SBC #0 STA R SEC \ Set the C flag to rotate into the result in (Y X) .LL132 TXA \ Rotate the counter in (Y X) to the left, and catch the ROL A \ result bit into bit 0 (which will be a 0 if we didn't TAX \ do the subtraction, or 1 if we did) TYA ROL A TAY BCS LL130 \ If we still have set bits in (Y X), loop back to LL130 \ to do the next iteration of 15, until we have done the \ whole division PLA \ Restore A, which we calculated above, from the stack BMI LL128 \ If A is negative jump to LL128 to return from the \ subroutine with (Y X) as is .LL133 TXA \ Otherwise negate (Y X) using two's complement by first EOR #%11111111 \ setting the low byte to ~X + 1 ADC #1 \ TAX \ The addition works as we know the C flag is clear from \ when we passed through the BCS above TYA \ Then set the high byte to ~Y + C EOR #%11111111 ADC #0 TAY .LL128 RTS \ Return from the subroutineName: LL123 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate (Y X) = (S R) / XX12+2 or (S R) * XX12+2Context: See this subroutine on its own page References: This subroutine is called as follows: * LL118 calls LL123 * LL120 calls entry point LL121 * LL120 calls entry point LL133

Calculate the following: * If T = 0, calculate (Y X) = (S R) / XX12+2 * If T <> 0, calculate (Y X) = (S R) * XX12+2 giving (Y X) the opposite sign to the slope direction in XX12+3. Arguments: XX12+2 The line's gradient * 256 (so 1.0 = 256) XX12+3 The direction of slope: * Bit 7 clear means top left to bottom right * Bit 7 set means top right to bottom left Other entry points: LL121 Calculate (Y X) = (S R) / Q and set the sign to the opposite of the top byte on the stack LL133 Negate (Y X) and return from the subroutine LL128 Contains an RTS.LL129 LDX XX12+2 \ Set Q = XX12+2 STX Q LDA S \ If S is positive, jump to LL127 BPL LL127 LDA #0 \ Otherwise set R = -R SEC SBC R STA R LDA S \ Push S onto the stack PHA EOR #%11111111 \ Set S = ~S + 1 + C ADC #0 STA S PLA \ Pull the original, negative S from the stack into A .LL127 EOR XX12+3 \ Set A = original argument S EOR'd with XX12+3 RTS \ Return from the subroutineName: LL129 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate Q = XX12+2, A = S EOR XX12+3 and (S R) = |S R|Context: See this subroutine on its own page References: This subroutine is called as follows: * LL120 calls LL129 * LL123 calls LL129

Do the following, in this order: Q = XX12+2 A = S EOR XX12+3 (S R) = |S R| This sets up the variables required above to calculate (S R) / XX12+2 and give the result the opposite sign to XX13+3..n_buyship LDX #0 \ Set a counter in X so we can work our way through the \ available ships, starting with X = 0, and working our \ way through the types in the new_ships table (where \ the ships are in order of increasing price) SEC \ Set QQ25 = 15 - 2 * QQ28 LDA #15 \ SBC QQ28 \ QQ25 contains the number of ship types that we offer SBC QQ28 \ for sale, so the number is smaller in less advanced STA QQ25 \ economies, and ranges from 15 ship types for rich \ industrial economies, down to 1 for poor agricultural \ economies .n_bloop STX XX13 \ Store the loop counter X in XX13 so we can retrieve it \ after the call to TT67, and throughout the following JSR TT67 \ Print a newline LDX XX13 \ Set X = XX13 + 1, so X contains 1 for the first ship INX \ type, 2 for the second ship type, and so on CLC \ Clear the C flag so the call to pr2 doesn't show a \ decimal point JSR pr2 \ Call pr2 to print the number in X to a width of 3 \ 3 figures, so this prints the item number at the start \ of the menu item, starting with item 1 at the top JSR TT162 \ Print a space LDY XX13 \ Print the name of the ship type given in XX13 JSR n_name LDY XX13 \ Set K(3 2 1 0) to the price of the ship given in XX13 JSR n_price LDA #22 \ Move the text cursor to column 22 STA XC LDA #9 \ We want to print the ship price using up to 9 digits STA U \ (including the decimal point), so store this in U \ for BRPNT to take as an argument SEC \ We want to print the price with a decimal point, \ so set the C flag for BRPNT to take as an argument JSR BPRNT \ Print the amount of cash to 9 digits with a decimal \ point LDX XX13 \ Fetch the loop counter from XX13 INX \ Increment the loop counter CPX QQ25 \ Loop back to n_bloop until we have shown the first BCC n_bloop \ QQ25 ship types (ordered by price) JSR CLYNS \ Clear the bottom three text rows of the upper screen, \ and move the text cursor to column 1 on row 21, i.e. \ the start of the top row of the three bottom rows LDA #185 \ Print recursive token 25 ("SHIP") followed by a JSR prq \ question mark JSR gnum \ Call gnum to get a number from the keyboard, which \ will be the menu item number of the ship we want to \ buy, returning the number entered in A and R, and \ setting the C flag if the number is bigger than the \ highest menu item number in QQ25 BEQ jmp_start3 \ If no number was entered, jump to jmp_start3 to make a \ beep and show the cargo bay BCS jmp_start3 \ If the number entered was too big, jump to jmp_start3 \ to make a beep and show the cargo bay SBC #0 \ Set A = A - 1 (as we know the C flag is clear) CMP QQ25 \ If A >= QQ25 then the number entered is bigger than BCS jmp_start3 \ the number of entries in the menu, so jump to \ jmp_start3 to make a beep and show the cargo bay LDX #2 \ Move the text cursor to column 2 STX XC INC YC \ Move the text cursor down one line STA Q \ Set INWK to the number of the ship type we want to buy LDY cmdr_type \ Set K(0 1 2 3) to the price of our current ship, whose JSR n_price \ type is in new_type \ We now want to do the following 32-bit addition: \ \ XX16(0 1 2 3) = CASH(0 1 2 3) + K(0 1 2 3) \ \ so XX16 contains the cash pot after we get a refund \ for the price of our existing ship CLC \ Clear the C flag for the addition below LDX #3 \ Set a counter in X to loop through the four bytes in \ the addition .n_addl LDA CASH,X \ Add the X-th bytes of CASH and K and store the result ADC K,X \ in the X-th byte of XX16 STA XX16,X DEX \ Decrement the loop counter BPL n_addl \ Loop back until we have added all four bytes LDY Q \ Fetch the number of the ship type that we want to buy \ into Y JSR n_price \ Set K(0 1 2 3) to the price of the ship we want to buy \ We now want to do the following 32-bit subtraction: \ \ K(0 1 2 3) = XX16(0 1 2 3) - K(0 1 2 3) \ \ so K(0 1 2 3) contains the cash we have left after we \ buy our new ship SEC \ Set the C flag for the subtraction below LDX #3 \ Set a counter in X to loop through the four bytes in \ the subtraction .n_subl LDA XX16,X \ Subtract the X-th byte of K from the X-th byte of XX16 SBC K,X \ and store the result in the X-th byte of K STA K,X DEX \ Decrement the loop counter BPL n_subl \ Loop back until we have subtracted all four bytes LDA Q \ Fetch the number of the ship type that we just bought \ into A BCS n_buy \ If the subtraction didn't underflow, then we have \ enough cash after the refund to buy the ship, so jump \ to n_buy to skip the following .cash_query LDA #197 \ We don't have enough cash to buy this ship, so print JSR prq \ recursive token 37 ("CASH") followed by a question \ mark .jmp_start3 JSR dn2 \ Call dn2 to make a short, high beep and delay for 1 \ second JMP BAY \ Jump to BAY to go to the docking bay (i.e. show the \ Status Mode screen) .n_buy TAX \ Store the number of the ship type that we just bought \ in X LDY #3 \ As the transaction has gone through, we now update our \ cash levels in CASH(0 1 2 3) to the amount we have \ left after buying our new ship, which is in K(0 1 2 3) .n_cpyl LDA K,Y \ Copy the Y-th byte of K(0 1 2 3) to the Y-th byte of STA CASH,Y \ CASH(0 1 2 3) DEY \ Decrement the loop counter BPL n_cpyl \ Loop back until we have copied all four bytes \ Next we want to reset the current ship's equipment, so \ we start with nothing and don't carry anything over \ from our previous ship, and we also want to reset \ any special cargo missions, as well as our legal \ status (so buying a new ship is a good way to get the \ law off our backs) LDA #0 \ Set A = 0 so we can use it to zero the settings LDY #36 \ We want to zero everything from LASER (the start of \ our current ship's equipment table) to LASER+36 (our \ legal status in FIST), so set Y as an index, starting \ at 36 .n_wipe STA LASER,Y \ Zero the Y-th byte of the block starting with LASER DEY \ Decrement the index BPL n_wipe \ Loop back until we have zeroed from LASER+36 down to \ LASER+0 STX cmdr_type \ Store the type of ship we just bought in cmdr_type, to \ set our current ship type to our new purchase JSR n_load \ Call n_load to load the flight characteristics and set \ the name token for our new ship LDA new_range \ Set our fuel level in QQ14 to the hyperspace range of STA QQ14 \ of our new ship, so our new ship comes with a full \ tank JSR msblob \ Reset the dashboard's missile indicators so they show \ the correct number of missiles fitted to our new ship \ (which will be zero) JSR update_pod \ Update the dashboard colours to reflect whether we \ have an escape pod fitted to our new ship (which we \ don't) JMP BAY \ Jump to BAY to go to the docking bay (i.e. show the \ Status Mode screen)Name: n_buyship [Show more] Type: Subroutine Category: Buying ships Summary: Show the Buy Ship screen (CTRL-f3) Deep dive: Buying and flying ships in Elite-AContext: See this subroutine on its own page References: This subroutine is called as follows: * EQSHP calls n_buyship * cour_buy calls entry point jmp_start3 * cour_buy calls entry point cash_query

Other entry points: cash_query Print "CASH?", make a short, high beep, delay for 1 second and go to the docking bay (i.e. show the Status Mode screen) jmp_start3 Make a short, high beep, and delay for 1 second and go to the docking bay (i.e. show the Status Mode screen).n_load LDY cmdr_type \ Set Y to the type of our current ship, which is stored \ in new_type LDX new_offsets,Y \ Set X to the offset, measured from new_ships, for this \ ship's details block, so X now points to the offset of \ the first character of the ship's type in the \ new_ships table, as well as the first byte of flight \ characteristics data in new_details LDY #0 \ We now want to do two things: \ \ * Update extended text token 132 in the QQ18 table \ with the name of the ship type, so that printing \ token 132 always shows the current ship type \ \ * Copy the flight characteristics of the specified \ ship type from the new_details table to our \ current ship data block, which is stored between \ new_pulse and new_max \ \ We can do these two at the same time in one loop, so \ set a counter in Y to count through the above .n_lname CPY #9 \ If Y >= 9, jump to n_linfo to skip copying the name, BCS n_linfo \ as the ship type contains a maximum of 9 characters or \ tokens, and there are more than 9 bytes of flight \ characteristics data LDA new_ships,X \ Set A to the character/token we want to fetch from \ the new_ships table EOR #35 \ Tokens in the new_ships table are stored as token \ numbers that are not EOR'd with 35, but the extended \ text token table at QQ18 expects all tokens to be \ obfuscated, so we add the obfuscation here STA new_name,Y \ Store the obfuscated character/token into extended \ text token 132 at the Y-th character of new_name .n_linfo \ We now want to copy the flight characteristics data \ for this ship type LDA new_details,X \ Set A to the flight characteristic byte we want to \ fetch from the new_details table STA new_pulse,Y \ And store it in the Y-th byte of the new_pulse block \ to set our current ship accordingly INX \ Increment the offset so we can fetch the next \ character (for the name) and the next byte (for the \ flight characteristics) INY \ Increment the loop counter CPY #13 \ If Y < 13 then we still have data to copy, so loop BNE n_lname \ back to n_lname until we have copied 9 characters from \ the name and 13 bytes of flight characteristics LDA new_max \ Set the minimum roll/pitch rate in new_min to 255 - EOR #%11111110 \ the maximum roll/pitch rate, which we can achieve STA new_min \ by EOR'ing with %11111110 LDY #11 \ We now work our way through the equipment that takes \ up space in the hold, and reduce the amount of free \ space for each item on the list that is fitted. The \ items that take up space are defined in the count_offs \ table, so set a counter in Y so we can work our way \ through the table, checking each of the items in turn .count_lasers LDX count_offs,Y \ Set X to the Y-th entry in the count_offs table, which \ contains offsets from LASER for each of the equipment \ items that take up space in the hold LDA LASER,X \ Check whether we have this item fitted, by testing BEQ count_sys \ whether LASER+X is zero, and if it is, then this item \ is not fitted, so skip the following instruction DEC new_hold \ The item at offset X is fitted, so decrement the free \ space in new_hold .count_sys DEY \ Decrement the loop counter in Y BPL count_lasers \ Loop back to process the next item of equipment until \ we have checked them all and reduced the free space \ accordingly RTS \ Return from the subroutineName: n_load [Show more] Type: Subroutine Category: Buying ships Summary: Load the name and flight characteristics for the current ship type Deep dive: Buying and flying ships in Elite-AContext: See this subroutine on its own page References: This subroutine is called as follows: * DFAULT calls n_load * n_buyship calls n_load.count_offs EQUB 0 \ LASER+0 = Front laser EQUB 1 \ LASER+1 = Rear laser EQUB 2 \ LASER+2 = Left laser EQUB 3 \ LASER+3 = Right laser EQUB 6 \ LASER+6 = CRGO = I.F.F. system EQUB 24 \ LASER+24 = ECM = E.C.M. system EQUB 25 \ LASER+25 = BST = Fuel scoops EQUB 26 \ LASER+26 = BOMB = Hyperspace unit EQUB 27 \ LASER+27 = ENGY = Energy unit EQUB 28 \ LASER+28 = DKCMP = Docking computer EQUB 29 \ LASER+29 = GHYP = Galactic hyperdrive EQUB 30 \ LASER+30 = ESCP = Escape podName: count_offs [Show more] Type: Variable Category: Buying ships Summary: Offsets from LASER for equipment that takes up space in the holdContext: See this variable on its own page References: This variable is used as follows: * n_load calls count_offs.n_name LDX new_offsets,Y \ Set X to the offset, measured from new_ships, for this \ ship's details block, so X now points to the offset of \ the first character of the ship's type in the \ new_ships table LDA #9 \ Each ship type consists of exactly 9 characters STA K+1 \ (including spaces), so set K+1 = 9 as a character \ counter in the following loop .n_lprint LDA new_ships,X \ Set A to the character we want to print from the \ new_ships table STX K \ Store the offset in K so we can retrieve it after the \ call to TT27 JSR TT27 \ Call TT27 to print the text token in A LDX K \ Restore the offset from K back into X INX \ Increment X to point to the next character DEC K+1 \ Decrement the character counter in K+1 BNE n_lprint \ Loop back to print the next character until we have \ printed all 9 of them RTS \ Return from the subroutineName: n_name [Show more] Type: Subroutine Category: Text Summary: Print the type of a given ship Deep dive: Buying and flying ships in Elite-AContext: See this subroutine on its own page References: This subroutine is called as follows: * n_buyship calls n_name

Arguments: Y The ship type number, in the range 0 to 14, as defined in the new_ships table.n_price LDX new_offsets,Y \ Set X to the offset, measured from new_price, for this \ ship's details block, so X now points to the offset of \ the ship's price in the new_ships table LDY #3 \ Each ship price consists of exactly four bytes (as it \ is a 32-bit number), so set Y = 3 to act as a byte \ counter in the following loop .n_lprice LDA new_price,X \ Set A to X-th byte of the ship's price from the \ new_ships table STA K,Y \ Store it in the X-th byte of K(0 1 2 3) INX \ Increment X to point to the next price byte DEY \ Decrement the byte counter BPL n_lprice \ Loop back to copy the next byte until we have copied \ all 4 of them RTS \ Return from the subroutineName: n_price [Show more] Type: Subroutine Category: Buying ships Summary: Set K(0 1 2 3) to the price of a given ship Deep dive: Buying and flying ships in Elite-AContext: See this subroutine on its own page References: This subroutine is called as follows: * n_buyship calls n_price

This routine fetches the ship price from the new_price table, where prices are stored in the standard little-endian manner of 6502 assembly (i.e. using an EQUD), and copies it in to K(0 1 2 3), which is a big-endian number like the CASH variable. Arguments: Y The ship type number, in the range 0 to 14, as defined in the new_ships table.cour_buy LDA cmdr_cour \ If there is no special cargo delivery mission in ORA cmdr_cour+1 \ progress, then the mission reward in cmdr_cour(1 0) BEQ cour_start \ will be zero, so jump to cour_start to skip the next \ instruction JMP jmp_start3 \ There is already a special cargo delivery mission in \ progress, so jump to jmp_start3 to make a beep and \ show the cargo bay .cour_start LDA #10 \ Move the text cursor to column 10 STA XC LDA #111 \ Print extended recursive token 111 ("{all caps}SPECIAL JSR DETOK \ CARGO") JSR NLIN4 \ Draw a horizontal line at pixel row 19 to box in the \ title LDA #%10000000 \ Set bit 7 of QQ17 to switch standard tokens to STA QQ17 \ Sentence Case LDA QQ26 \ Set INWK = the random market seed for this system in EOR QQ0 \ QQ26, EOR'd with the current system's galactic EOR QQ1 \ x-coordinate in QQ0, the current system's galactic EOR FIST \ y-coordinate in QQ1, our legal status in FIST, and EOR TALLY \ the low byte of our combat rank, which should give us STA INWK \ a pretty random number that will stay the same until \ we leave the station \ \ We use this to determine the number of systems to skip \ when generating the first delivery mission in the menu SEC \ Set INWK+1 = 1 + our legal status in FIST + the LDA FIST \ current galaxy number in GCNT + the type of our ADC GCNT \ current ship in cmdr_type, which again will give us ADC cmdr_type \ a random number that will stay the same until we STA INWK+1 \ leave the station, as well as randomising the C flag \ \ We use this to determine the number of systems to skip \ when generating subsequent delivery missions in the \ menu ADC INWK \ Set QQ25 = INWK+1 + INWK + C - cmdr_courx - cmdr_coury SBC cmdr_courx \ SBC cmdr_coury \ where (cmdr_courx, cmdr_coury) are the coordinates of AND #15 \ the previous special cargo delivery destination (which STA QQ25 \ will be (0, 0) if this is the first) and reduce the \ result to be in the range 0 to 15 \ \ We use this to determine the maximum number of \ delivery missions in the menu BEQ cour_pres \ If the value of QQ25 = 0, jump to cour_pres to make a \ beep and show the cargo bay (as QQ25 contains the \ number of missions in the menu, so if it's zero we \ have nothing more to do) LDA #0 \ Set INWK+3 = 0 to act as a counter of the number of STA INWK+3 \ delivery missions we have displayed in the menu so far STA INWK+6 \ Set INWK+6 = 0 to act as a system counter that runs \ from 0 to 255 as we work our way through all the \ systems in the galaxy 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 iterate around the cour_loop loop, working our \ way through systems in the galaxy and picking suitable \ destinations for display in the Special Cargo menu. We \ use the following counters as we go: \ \ * QQ25 contains the maximum number of delivery \ missions to display in the menu \ \ * INWK is the number of systems we skip past for the \ very first menu item, when generating destinations \ in cour_count \ \ * INWK+1 is the number of systems we skip past for \ subsequent menu items, when generating \ destinations in cour_count \ \ * INWK+3 counts the number of delivery missions we \ have already displayed in the menu, starting at 0 \ \ * INWK+6 contains the system number we are currently \ considering, starting at 0 and working through to \ 255, at which point we are done (even if we \ haven't managed to find QQ25 delivery missions) .cour_loop LDA INWK+3 \ If INWK+3 < QQ25 then call cour_count to add another CMP QQ25 \ destination to the menu, as we have not yet shown QQ25 BCC cour_count \ delivery missions in the menu (cour_count ends with a \ jump back to cour_loop) .cour_menu \ If we get here then we have either got QQ25 items in \ the menu, or we have worked our way through the whole \ galaxy, so in either case we have finished displaying \ the menu of destinations, and we want to process the \ choice JSR CLYNS \ Clear the bottom three text rows of the upper screen, \ and move the text cursor to column 1 on row 21, i.e. \ the start of the top row of the three bottom rows LDA #206 \ Print recursive token 46 (" CARGO{sentence case}") JSR prq \ followed by a question mark JSR gnum \ Call gnum to get a number from the keyboard, which \ will be the menu item number of the mission we want to \ take, returning the number entered in A and R, and \ setting the C flag if the number is bigger than the \ highest menu item number in QQ25 BEQ cour_pres \ If no number was entered, jump to cour_pres to make a \ beep and show the cargo bay BCS cour_pres \ If the number entered was too big, jump to cour_pres \ to make a beep and show the cargo bay TAX \ Set X = A - 1, so X is now 0 if we picked the first DEX \ destination, 1 if we picked the second, and so on CPX INWK+3 \ If X >= INWK+3 then the number entered is bigger than BCS cour_pres \ the number of entries in the menu, so jump to \ cour_pres to make a beep and show the cargo bay LDA #2 \ Move the text cursor to column 2 STA XC INC YC \ Move the text cursor down one line STX INWK \ Set INWK to the number of the chosen mission LDY &0C50,X \ Set (Y X) to the cost of this mission in LDA &0C40,X \ (&0C50+X &0C40+X) TAX JSR LCASH \ Subtract (Y X) cash from the cash pot, but only if \ we have enough cash BCS cour_cash \ If the transaction was successful, we have just bought \ ourselves a delivery mission, so jump to cour_cash JMP cash_query \ Otherwise we didn't have enough cash, so jump to \ cash_query to print "CASH?", make a short, high beep, \ delay for 1 second and go to the docking bay (i.e. \ show the Status Mode screen) .cour_cash \ We have now taken on the delivery mission, so we need \ to set variables that govern the mission progress, \ i.e. the destination and the mission reward LDX INWK \ Set X to the number of the chosen mission which we \ stored in INWK above LDA &0C00,X \ Set cmdr_courx to the galactic x-coordinate of the STA cmdr_courx \ destination of the chosen mission, which we stored in \ &0C00+X when setting up the menu LDA &0C10,X \ Set cmdr_coury to the galactic y-coordinate of the STA cmdr_coury \ destination of the chosen mission, which we stored in \ &0C10+X when setting up the menu CLC \ When setting up the menu, we set &0C20+X to the legal LDA &0C20,X \ status of taking this mission, so we add this value to ADC FIST \ our legal status in FIST, so taking on dodgy delivery STA FIST \ missions adversely affects our legal status LDA &0C30,X \ Set the mission reward in cmdr_cour(1 0) to the value STA cmdr_cour+1 \ we set in (&0C30+X &0C40+X) when setting up the menu LDA &0C40,X STA cmdr_cour .cour_pres JMP jmp_start3 \ Jump to jmp_start3 to make a beep and show the cargo \ bayName: cour_buy [Show more] Type: Subroutine Category: Missions Summary: Show the Special Cargo screen (CTRL-f1) Deep dive: Special cargo missionsContext: See this subroutine on its own page References: This subroutine is called as follows: * TT219 calls cour_buy.cour_count \ If we get here then we want to display another item \ in the menu, so first we need to skip our way through \ the number of systems given in INWK JSR TT20 \ We want to move on to the next system, so call TT20 \ to twist the three 16-bit seeds in QQ15 INC INWK+6 \ We also increment the counter in INWK+6 to point to \ the next system BEQ cour_menu \ If INWK+6 has wrapped around back to 0, then we have \ worked our way through the entire galaxy, so jump to \ cour_menu to display the menu DEC INWK \ Loop back to keep twisting the seeds until we have BNE cour_count \ stepped through the number of systems in INWK \ We now have a system that we can consider for \ inclusion in the destination menu LDX INWK+3 \ Set X = INWK+3, which counts the number of delivery \ missions we have already displayed in the menu, and \ which we can use as an index when populating the menu \ data in &0C00 below LDA QQ15+3 \ Fetch the s1_hi seed of the system we are considering \ adding to the menu into A, which gives us the galactic \ x-coordinate of the system we are considering CMP QQ0 \ If the x-coordinate of the system we are considering BNE cour_star \ is different to the current system's galactic \ x-coordinate in QQ0, then jump to cour_star to keep \ going LDA QQ15+1 \ Fetch the s0_hi seed of the system we are considering \ adding to the menu into A, which gives us the galactic \ y-coordinate of the system we are considering CMP QQ1 \ If the y-coordinate of the system we are considering BNE cour_star \ is different to the current system's galactic \ y-coordinate in QQ1, then jump to cour_star to keep \ going JMP cour_next \ If we get here then the system we are considering has \ the same coordinates as the current system, and we \ can't offer a cargo mission to the system we are \ already in, so jump to cour_next to move onto the next \ system .cour_star \ If we get here then this destination is a suitable \ system for a delivery mission, so we now want to add \ the destination's data to the block at &0C00, which is \ where we build up the menu data \ \ We build up the data as follows, where X is the number \ of the menu item (0-15): \ \ * &0C00+X = x-coordinate of the delivery destination \ * &0C10+X = y-coordinate of the delivery destination \ * &0C20+X = legal status of the delivery mission \ * &0C30+X = high byte of the mission reward \ * &0C40+X = low byte of the mission reward \ low byte of the mission cost \ * &0C50+X = high byte of the mission cost \ \ In other words, when we take on a mission, the reward \ in cmdr_cour(1 0) is set to (&0C30+X &0C40+X), we pay \ the mission cost of (&0C50+X &0C40+X), and our legal \ status goes up by the amount in &0C20+X LDA QQ15+3 \ Set A = s1_hi EOR s2_hi EOR INWK+1 EOR QQ15+5 \ EOR INWK+1 \ which is a pretty random number based on the seeds for \ the destination system, plus the random INWK+1 that we \ generated above CMP FIST \ If A < FIST then jump to cour_legal, so we will only BCC cour_legal \ jump if FIST is non-zero, with a bigger chance of \ jumping if we've been bad LDA #0 \ We have either been very good or very lucky, so set \ A = 0 to indicate that this delivery mission is legit .cour_legal STA &0C20,X \ Store A in the X-th byte of &0C20, which is the legal \ status of this delivery mission (A = 0 means it's \ legit, while higher numbers are increasingly bad) LDA QQ15+3 \ Set the X-th byte of &0C00 to s1_hi, the galactic STA &0C00,X \ x-coordinate of the delivery destination \ We need to calculate the distance from the current \ system to the delivery destination, as the mission \ reward is based on the distance of the delivery (as \ well as the legality of the mission) \ \ We do this using Pythagoras, so let's denote the \ current system's coordinates as (current_x, current_y) \ and the delivery destination's coordinates as \ (destination_x, destination_y) SEC \ Set A = A - QQ0 SBC QQ0 \ = destination_x - current_x BCS cour_negx \ If the subtraction didn't underflow, jump to cour_negx EOR #&FF \ The subtraction underflowed, so negate the result ADC #1 \ using two's complement, so we know A is positive, i.e. \ \ A = |destination_x - current_x| .cour_negx JSR SQUA2 \ Set K(1 0) = A * A STA K+1 \ = |destination_x - current_x| ^ 2 LDA P STA K LDX INWK+3 \ Set X = INWK+3 again, so we can use as an index when \ populating the menu data in &0C00 LDA QQ15+1 \ Set the X-th byte of &0C10 to s0_hi, the galactic STA &0C10,X \ y-coordinate of the delivery destination SEC \ Set A = A - QQ1 SBC QQ1 \ = destination_y - current_y BCS cour_negy \ If the subtraction didn't underflow, jump to cour_negy EOR #&FF \ The subtraction underflowed, so negate the result ADC #1 \ using two's complement, so we know A is positive, i.e. \ \ A = |destination_y - current_y| .cour_negy 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 \ 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 JSR SQUA2 \ Set (A P) = A * A \ = (|destination_y - current_y| / 2) ^ 2 \ We now want to add the two so we can then apply \ Pythagoras, so first we do this: \ \ (R Q) = K(1 0) + (A P)) \ = |destination_x - current_x| ^ 2 \ + (|destination_y - current_y| / 2) ^ 2 \ \ and then the distance will be the square root: \ \ Q = SQRT(R Q) PHA \ Store the high byte of the result on the stack LDA P \ Set Q = P + K CLC \ ADC K \ which adds the low bytes STA Q PLA \ Set R = A + K+1 ADC K+1 \ STA R \ which adds the high bytes JSR LL5 \ Set Q = SQRT(R Q), so Q now contains the distance \ between the two systems, in terms of coordinates, \ which we can use to determine the reward for this \ delivery mission LDX INWK+3 \ Set X = INWK+3 again, so we can use as an index when \ populating the menu data in &0C00 LDA QQ15+1 \ Set A = (s0_hi EOR s2_hi EOR INWK+1) / 8 EOR QQ15+5 \ EOR INWK+1 \ which is another pretty random number based on the LSR A \ seeds for the destination system, plus the random LSR A \ INWK+1 that we generated above LSR A CMP Q \ If A >= Q then skip the following BCS cour_dist LDA Q \ A < Q, so set A = Q, so A has a minimum value of Q, \ i.e. our mission reward is always at least the \ distance we have to travel .cour_dist ORA &0C20,X \ We now OR this value with the legal status of this \ delivery mission, so a legit mission (which has a \ status of 0) will not change the value in A, but more \ dangerous missions will bump the value up, with a \ higher premium paid for more illegal missions STA &0C30,X \ Set the X-th byte of &0C30 to A, which we use as the \ high byte of the mission reward STA INWK+4 \ Set INWK(5 4) = (A A) / 8 LSR A \ ROR INWK+4 \ which we use as the mission cost (i.e. the amount of LSR A \ cash we have to part with in order to take on the ROR INWK+4 \ delivery mission) LSR A ROR INWK+4 STA INWK+5 STA &0C50,X \ Store INWK+5 in the X-th byte of &0C50, so it contains \ the high byte of the mission cost LDA INWK+4 \ Store INWK+4 in the X-th byte of &0C40, so it contains STA &0C40,X \ the low byte of the mission cost (and the low byte of \ the mission reward, as they share the same value) LDA #1 \ Move the text cursor to column 1 STA XC CLC \ Move the text cursor to row INWK+3 plus 3, where LDA INWK+3 \ INWK+3 is the menu item number, starting from 0 (so ADC #3 \ the first menu item is on row 3, the next is on row 4 STA YC \ and so on) LDX INWK+3 \ Set X to INWK+3 + 1, which we can use as the menu item INX \ number on-screen (so the first menu item with is shown \ as item 1 on screen, the next is shown as item 2, and \ so on) CLC \ Clear the C flag so the call to pr2 doesn't show a \ decimal point JSR pr2 \ Call pr2 to print the number in X to a width of 3 \ 3 figures, so this prints the item number at the start \ of the menu item JSR TT162 \ Print a space JSR cpl \ Call cpl to print the name of the selected system \ (i.e. the destination system) LDX INWK+4 \ Set (Y X) = INWK(5 4) LDY INWK+5 \ \ so (Y X) contains the mission cost, as we set up \ INWK(5 4) with this value above SEC \ Set the C flag so the call to TT11 below includes a \ decimal point LDA #25 \ Move the text cursor to column 25, so we can print the STA XC \ mission cost LDA #6 \ Set A = 6, for the call to TT11 below, so we pad out \ the number to 6 digits JSR TT11 \ Call TT11 to print the mission cost in (Y X), padded \ to six digits and with a decimal point INC INWK+3 \ We have just printed a menu item, so increment the \ counter in INWK+3, as it contains a count of menu \ items we have printed .cour_next LDA INWK+1 \ Reset INWK to the value in INWK+1, so the next time we STA INWK \ iterate round the loop, we skip over INWK+1 systems \ before adding to the menu JMP cour_loop \ Loop back to cour_loop to add the next menu itemName: cour_count [Show more] Type: Subroutine Category: Missions Summary: Generate a single special cargo mission and display its menu item Deep dive: Special cargo missionsContext: See this subroutine on its own page References: This subroutine is called as follows: * cour_buy calls cour_count.cour_dock LDA cmdr_cour \ If there is no special cargo delivery mission in ORA cmdr_cour+1 \ progress, then the mission reward in cmdr_cour(1 0) BEQ cour_quit \ will be zero, so jump to cour_quit to return from the \ subroutine LDA QQ0 \ Set A = the current system's galactic x-coordinate CMP cmdr_courx \ If A does not match the x-coordinate of the cargo BNE cour_half \ mission's destination in cmdr_courx then we aren't at \ the destination station, so jump to cour_half to \ halve the mission reward LDA QQ1 \ Set A = the current system's galactic y-coordinate CMP cmdr_coury \ If A does not match the y-coordinate of the cargo BNE cour_half \ mission's destination in cmdr_coury then we aren't at \ the destination station, so jump to cour_half to \ halve the mission reward LDA #2 \ We have arrived at the destination for the special JSR TT66 \ cargo mission, so clear the top part of the screen, \ draw a white border, and set the current view type \ in QQ11 to 2 (for the Buy Cargo screen) LDA #6 \ Move the text cursor to column 6 STA XC LDA #10 \ Move the text cursor to row 10 STA YC LDA #113 \ Print extended token 113 ("CARGO VALUE:") JSR DETOK LDX cmdr_cour \ Set (Y X) to the mission reward in cmdr_cour(1 0) LDY cmdr_cour+1 SEC \ Set the C flag so the call to TT11 includes a decimal \ point LDA #6 \ Set A = 6, for the call to TT11 below, so we pad out \ the number to 6 digits JSR TT11 \ Call TT11 to print the mission reward in (Y X), padded \ to six digits and with a decimal point LDA #226 \ Print recursive text token 66 (" CR") JSR TT27 LDX cmdr_cour \ Set (Y X) to the mission reward in cmdr_cour(1 0) LDY cmdr_cour+1 JSR MCASH \ Call MCASH to add (Y X) to the cash pot LDA #0 \ Reset the mission reward by doing cmdr_cour(1 0) = 0 STA cmdr_cour STA cmdr_cour+1 LDY #96 \ Wait for 96 vertical syncs (96/50 = 1.92 seconds) JSR DELAY .cour_half LSR cmdr_cour+1 \ Halve the value of the mission reward in ROR cmdr_cour \ cmdr_cour(1 0) .cour_quit RTS \ Return from the subroutineName: cour_dock [Show more] Type: Subroutine Category: Missions Summary: Update the current special cargo delivery mission on docking Deep dive: Special cargo missionsContext: See this subroutine on its own page References: This subroutine is called as follows: * DOENTRY calls cour_dock * stay_here calls cour_dock.stay_here LDX #&F4 \ It costs 50.0 Cr to refresh the station's market LDY #&01 \ prices, which is represented as a value of 500, so \ this sets (Y X) = &1F4 = 500 JSR LCASH \ Subtract (Y X) cash from the cash pot, but only if \ we have enough cash BCC stay_quit \ If the C flag is clear then we did not have enough \ cash for the transaction, so jump to stay_quit to \ return from the subroutine without refreshing the \ market prices JSR cour_dock \ Update the current special cargo delivery mission JSR DORND \ Set A and X to random numbers STA QQ26 \ Set QQ26 to the random byte that's used in the market \ calculations JSR GVL \ Calculate the availability for each market item in the \ new system .stay_quit JMP BAY \ Go to the docking bay (i.e. show the Status Mode \ screen)Name: stay_here [Show more] Type: Subroutine Category: Market Summary: Pay a docking fee and refresh the system's market pricesContext: See this subroutine on its own page References: This subroutine is called as follows: * TT102 calls stay_here.GVL 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 subroutineName: GVL [Show more] Type: Subroutine Category: Universe Summary: Calculate the availability of market items Deep dive: Market item prices and availability Galaxy and system seedsContext: See this subroutine on its own page References: This subroutine is called as follows: * hyp1_FLIGHT calls GVL * stay_here calls GVL

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.new_offsets FOR I%, 0, 14 EQUB I% * 13 \ Offset of the 13-byte details block for ship I% NEXTName: new_offsets [Show more] Type: Variable Category: Buying ships Summary: Table of offsets for each ship type Deep dive: Buying and flying ships in Elite-AContext: See this variable on its own page References: This variable is used as follows: * n_load calls new_offsets * n_name calls new_offsets * n_price calls new_offsets

There are 13 bytes in of flight characteristics for each ship type in the new_details table. There are also 13 bytes of name and price data for each ship type in the new_ships table (9 characters in the name plus 4 bytes in the 32-bit price). As a result, the offset in this table at position X can be used for any of the following: * An offset into the new_details to fetch the flight characteristics for ship type X * An offset into the new_ships table to fetch the type name of ship type X * An offset into the new_price table to fetch the price of ship type X.new_ships IF _SOURCE_DISC OR _BUG_FIX EQUS "ADDER " \ #0 = Adder = 27,000.0 Cr .new_price EQUD 270000 EQUS "GECKO " \ #1 = Gecko = 32,500.0 Cr EQUD 325000 EQUS "MORAY " \ #2 = Moray = 36,000.0 Cr EQUD 360000 EQUS "COBRA MK1" \ #3 = Cobra Mk I = 39,500.0 Cr EQUD 395000 EQUS "IGUANA " \ #4 = Iguana = 64,000.0 Cr EQUD 640000 EQUS "OPHIDIAN " \ #5 = Ophidian = 64,500.0 Cr EQUD 645000 EQUS "CHAMELEON" \ #6 = Chameleon = 97,500.0 Cr EQUD 975000 EQUS "COBRA MK3" \ #7 = Cobra Mk III = 100,000.0 Cr EQUD 1000000 EQUS "GHAVIAL " \ #8 = Ghavial = 136,500.0 Cr EQUD 1365000 EQUS "F" \ #9 = Fer-de-Lance = 143,500.0 Cr EQUB 144 \ EQUS "-DE-L" \ 144 = Two-letter token 'ER' EQUB 155 \ 155 = Two-letter token 'AN' EQUB 133 \ 133 = Two-letter token 'CE' EQUD 1435000 EQUS "MONITOR " \ #10 = Monitor = 175,000.0 Cr EQUD 1750000 EQUS "PYTHON " \ #11 = Python = 205,000.0 Cr EQUD 2050000 EQUS "BOA " \ #12 = Boa = 240,000.0 Cr EQUD 2400000 EQUS "ANACONDA " \ #13 = Anaconda = 400,000.0 Cr EQUD 4000000 EQUS "ASP MK2 " \ #14 = Asp Mk II = 895,000.0 Cr EQUD 8950000 ELIF _RELEASED EQUS "ADDER " \ #0 = Adder = 31,000.0 Cr .new_price EQUD 310000 EQUS "GECKO " \ #1 = Gecko = 40,000.0 Cr EQUD 400000 EQUS "MORAY " \ #2 = Moray = 56,500.0 Cr EQUD 565000 EQUS "COBRA MK1" \ #3 = Cobra Mk I = 75,000.0 Cr EQUD 750000 EQUS "IGUANA " \ #4 = Iguana = 131,500.0 Cr EQUD 1315000 EQUS "OPHIDIAN " \ #5 = Ophidian = 147,000.0 Cr EQUD 1470000 EQUS "CHAMELEON" \ #6 = Chameleon = 225,000.0 Cr EQUD 2250000 EQUS "COBRA MK3" \ #7 = Cobra Mk III = 287,000.0 Cr EQUD 2870000 EQUS "F" \ #8 = Fer-de-Lance = 359,500.0 Cr EQUB 144 \ EQUS "-DE-L" \ 144 = Two-letter token 'ER' EQUB 155 \ 155 = Two-letter token 'AN' EQUB 133 \ 133 = Two-letter token 'CE' EQUD 3595000 EQUS "GHAVIAL " \ #9 = Ghavial = 379,500.0 Cr EQUD 3795000 EQUS "MONITOR " \ #10 = Monitor = 585,500.0 Cr EQUD 5855000 EQUS "PYTHON " \ #11 = Python = 762,000.0 Cr EQUD 7620000 EQUS "BOA " \ #12 = Boa = 960,000.0 Cr EQUD 9600000 EQUS "ASP MK2 " \ #13 = Asp Mk II = 1012,000.0 Cr EQUD 10120000 EQUS "ANACONDA " \ #14 = Anaconda = 1869,500.0 Cr EQUD 18695000 ENDIFName: new_ships [Show more] Type: Variable Category: Buying ships Summary: Ship names and prices for the different ship types we can buy Deep dive: Buying and flying ships in Elite-AContext: See this variable on its own page References: This variable is used as follows: * n_load calls new_ships * n_name calls new_ships.new_details \ Adder EQUB 14 \ Pulse laser power = 14 EQUB 142 \ Beam laser power = 142 EQUB 146 \ Military laser power = 146 EQUB 25 \ Mining laser power = 25 EQUB 2 \ Laser mounts = Front, rear EQUB 2 \ Maximum missile count = 2 - 1 = 1 EQUB 4 \ Shields = 4 EQUB 1 \ Energy recharge rate = 1 EQUB 36 \ Maximum speed = 36 EQUB 9 \ Cargo hold capacity = 9 - 1 = 8 EQUB 60 \ Hyperspace range = 6.0 LY EQUB 1 * 26 \ Equipment prices offset from PRXS = 1 EQUB 223 \ Maximum roll/pitch rate = 223 \EQUB 33 \ Not used (minimum roll/pitch rate) = 33 \EQUB 5 \ Not used (new_space) = 5 \EQUB 0 \ Not used \ Gecko EQUB 14 \ Pulse laser power = 14 EQUB 143 \ Beam laser power = 143 EQUB 147 \ Military laser power = 147 EQUB 25 \ Mining laser power = 25 EQUB 4 \ Laser mounts = All four EQUB 3 \ Maximum missile count = 3 - 1 = 2 EQUB 5 \ Shields = 5 EQUB 1 \ Energy recharge rate = 1 EQUB 45 \ Maximum speed = 45 EQUB 10 \ Cargo hold capacity = 10 - 1 = 9 EQUB 70 \ Hyperspace range = 7.0 LY EQUB 1 * 26 \ Equipment prices offset from PRXS = 1 EQUB 239 \ Maximum roll/pitch rate = 239 \EQUB 17 \ Not used (minimum roll/pitch rate) = 17 \EQUB 6 \ Not used (new_space) = 6 \EQUB 0 \ Not used \ Moray EQUB 16 \ Pulse laser power = 16 EQUB 143 \ Beam laser power = 143 EQUB 150 \ Military laser power = 150 EQUB 25 \ Mining laser power = 25 EQUB 4 \ Laser mounts = All four EQUB 3 \ Maximum missile count = 3 - 1 = 2 EQUB 6 \ Shields = 6 EQUB 1 \ Energy recharge rate = 1 EQUB 38 \ Maximum speed = 38 EQUB 12 \ Cargo hold capacity = 12 - 1 = 11 EQUB 80 \ Hyperspace range = 8.0 LY EQUB 4 * 26 \ Equipment prices offset from PRXS = 4 EQUB 239 \ Maximum roll/pitch rate = 239 \EQUB 17 \ Not used (minimum roll/pitch rate) = 17 \EQUB 7 \ Not used (new_space) = 7 \EQUB 0 \ Not used \ Cobra Mk I EQUB 14 \ Pulse laser power = 14 EQUB 142 \ Beam laser power = 142 EQUB 148 \ Military laser power = 148 EQUB 25 \ Mining laser power = 25 EQUB 4 \ Laser mounts = All four EQUB 4 \ Maximum missile count = 4 - 1 = 3 EQUB 5 \ Shields = 5 EQUB 1 \ Energy recharge rate = 1 EQUB 39 \ Maximum speed = 39 EQUB 15 \ Cargo hold capacity = 15 - 1 = 14 EQUB 60 \ Hyperspace range = 6.0 LY EQUB 1 * 26 \ Equipment prices offset from PRXS = 1 EQUB 207 \ Maximum roll/pitch rate = 207 \EQUB 49 \ Not used (minimum roll/pitch rate) = 49 \EQUB 8 \ Not used (new_space) = 8 \EQUB 0 \ Not used \ Iguana EQUB 14 \ Pulse laser power = 14 EQUB 142 \ Beam laser power = 142 EQUB 148 \ Military laser power = 148 EQUB 25 \ Mining laser power = 25 EQUB 4 \ Laser mounts = All four EQUB 4 \ Maximum missile count = 4 - 1 = 3 EQUB 7 \ Shields = 7 EQUB 1 \ Energy recharge rate = 1 EQUB 50 \ Maximum speed = 50 EQUB 22 \ Cargo hold capacity = 22 - 1 = 21 EQUB 75 \ Hyperspace range = 7.5 LY EQUB 0 * 26 \ Equipment prices offset from PRXS = 0 EQUB 223 \ Maximum roll/pitch rate = 223 \EQUB 33 \ Not used (minimum roll/pitch rate) = 33 \EQUB 8 \ Not used (new_space) = 8 \EQUB 0 \ Not used \ Ophidian EQUB 13 \ Pulse laser power = 13 EQUB 141 \ Beam laser power = 141 EQUB 144 \ Military laser power = 144 EQUB 12 \ Mining laser power = 12 EQUB 1 \ Laser mounts = Front EQUB 3 \ Maximum missile count = 3 - 1 = 2 EQUB 4 \ Shields = 4 EQUB 1 \ Energy recharge rate = 1 EQUB 51 \ Maximum speed = 51 EQUB 25 \ Cargo hold capacity = 25 - 1 = 24 EQUB 70 \ Hyperspace range = 7.0 LY EQUB 4 * 26 \ Equipment prices offset from PRXS = 4 EQUB 255 \ Maximum roll/pitch rate = 255 \EQUB 1 \ Not used (minimum roll/pitch rate) = 1 \EQUB 6 \ Not used (new_space) = 6 \EQUB 0 \ Not used \ Chameleon EQUB 16 \ Pulse laser power = 16 EQUB 143 \ Beam laser power = 143 EQUB 151 \ Military laser power = 151 EQUB 50 \ Mining laser power = 50 EQUB 2 \ Laser mounts = Front, rear EQUB 4 \ Maximum missile count = 4 - 1 = 3 EQUB 8 \ Shields = 8 EQUB 1 \ Energy recharge rate = 1 EQUB 43 \ Maximum speed = 43 EQUB 36 \ Cargo hold capacity = 36 - 1 = 35 EQUB 80 \ Hyperspace range = 8.0 LY EQUB 4 * 26 \ Equipment prices offset from PRXS = 4 EQUB 223 \ Maximum roll/pitch rate = 223 \EQUB 33 \ Not used (minimum roll/pitch rate) = 33 \EQUB 5 \ Not used (new_space) = 5 \EQUB 0 \ Not used \ Cobra Mk III EQUB 18 \ Pulse laser power = 18 EQUB 143 \ Beam laser power = 143 EQUB 152 \ Military laser power = 152 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 5 \ Maximum missile count = 5 - 1 = 4 EQUB 7 \ Shields = 7 EQUB 1 \ Energy recharge rate = 1 EQUB 42 \ Maximum speed = 42 EQUB 43 \ Cargo hold capacity = 43 - 1 = 42 EQUB 70 \ Hyperspace range = 7.0 LY EQUB 0 * 26 \ Equipment prices offset from PRXS = 0 EQUB 239 \ Maximum roll/pitch rate = 239 \EQUB 17 \ Not used (minimum roll/pitch rate) = 17 \EQUB 10 \ Not used (new_space) = 10 \EQUB 0 \ Not used IF _SOURCE_DISC \ Ghavial EQUB 17 \ Pulse laser power = 17 EQUB 144 \ Beam laser power = 144 EQUB 153 \ Military laser power = 153 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 4 \ Maximum missile count = 4 - 1 = 3 EQUB 9 \ Shields = 9 EQUB 1 \ Energy recharge rate = 1 EQUB 37 \ Maximum speed = 37 EQUB 56 \ Cargo hold capacity = 56 - 1 = 55 EQUB 80 \ Hyperspace range = 8.0 LY EQUB 0 * 26 \ Equipment prices offset from PRXS = 0 EQUB 207 \ Maximum roll/pitch rate = 207 \EQUB 49 \ Not used (minimum roll/pitch rate) = 49 \EQUB 9 \ Not used (new_space) = 9 \EQUB 0 \ Not used \ Fer-de-lance EQUB 18 \ Pulse laser power = 18 EQUB 146 \ Beam laser power = 146 EQUB 156 \ Military laser power = 156 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 4 \ Maximum missile count = 4 - 1 = 3 EQUB 8 \ Shields = 8 EQUB 2 \ Energy recharge rate = 2 EQUB 45 \ Maximum speed = 45 EQUB 10 \ Cargo hold capacity = 10 - 1 = 9 EQUB 85 \ Hyperspace range = 8.5 LY EQUB 2 * 26 \ Equipment prices offset from PRXS = 2 EQUB 223 \ Maximum roll/pitch rate = 223 \EQUB 33 \ Not used (minimum roll/pitch rate) = 33 \EQUB 9 \ Not used (new_space) = 9 \EQUB 0 \ Not used ELIF _RELEASED \ Fer-de-lance EQUB 18 \ Pulse laser power = 18 EQUB 146 \ Beam laser power = 146 EQUB 156 \ Military laser power = 156 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 4 \ Maximum missile count = 4 - 1 = 3 EQUB 8 \ Shields = 8 EQUB 2 \ Energy recharge rate = 2 EQUB 45 \ Maximum speed = 45 EQUB 10 \ Cargo hold capacity = 10 - 1 = 9 EQUB 85 \ Hyperspace range = 8.5 LY EQUB 2 * 26 \ Equipment prices offset from PRXS = 2 EQUB 223 \ Maximum roll/pitch rate = 223 \EQUB 33 \ Not used (minimum roll/pitch rate) = 33 \EQUB 9 \ Not used (new_space) = 9 \EQUB 0 \ Not used \ Ghavial EQUB 17 \ Pulse laser power = 17 EQUB 144 \ Beam laser power = 144 EQUB 153 \ Military laser power = 153 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 4 \ Maximum missile count = 4 - 1 = 3 EQUB 9 \ Shields = 9 EQUB 1 \ Energy recharge rate = 1 EQUB 37 \ Maximum speed = 37 EQUB 56 \ Cargo hold capacity = 56 - 1 = 55 EQUB 80 \ Hyperspace range = 8.0 LY EQUB 0 * 26 \ Equipment prices offset from PRXS = 0 EQUB 207 \ Maximum roll/pitch rate = 207 \EQUB 49 \ Not used (minimum roll/pitch rate) = 49 \EQUB 9 \ Not used (new_space) = 9 \EQUB 0 \ Not used ENDIF \ Monitor EQUB 24 \ Pulse laser power = 24 EQUB 147 \ Beam laser power = 147 EQUB 156 \ Military laser power = 156 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 9 \ Maximum missile count = 9 - 1 = 8 EQUB 10 \ Shields = 10 EQUB 1 \ Energy recharge rate = 1 EQUB 24 \ Maximum speed = 24 EQUB 82 \ Cargo hold capacity = 82 - 1 = 81 EQUB 110 \ Hyperspace range = 11.0 LY EQUB 3 * 26 \ Equipment prices offset from PRXS = 3 EQUB 191 \ Maximum roll/pitch rate = 191 \EQUB 65 \ Not used (minimum roll/pitch rate) = 65 \EQUB 12 \ Not used (new_space) = 12 \EQUB 0 \ Not used \ Python EQUB 24 \ Pulse laser power = 24 EQUB 146 \ Beam laser power = 146 EQUB 155 \ Military laser power = 155 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 5 \ Maximum missile count = 5 - 1 = 4 EQUB 11 \ Shields = 11 EQUB 1 \ Energy recharge rate = 1 EQUB 30 \ Maximum speed = 30 EQUB 107 \ Cargo hold capacity = 107 - 1 = 106 EQUB 80 \ Hyperspace range = 8.0 LY EQUB 1 * 26 \ Equipment prices offset from PRXS = 1 EQUB 175 \ Maximum roll/pitch rate = 175 \EQUB 81 \ Not used (minimum roll/pitch rate) = 81 \EQUB 9 \ Not used (new_space) = 9 \EQUB 0 \ Not used \ Boa EQUB 20 \ Pulse laser power = 20 EQUB 142 \ Beam laser power = 142 EQUB 152 \ Military laser power = 152 EQUB 50 \ Mining laser power = 50 EQUB 2 \ Laser mounts = Front, rear EQUB 7 \ Maximum missile count = 7 - 1 = 6 EQUB 10 \ Shields = 10 EQUB 1 \ Energy recharge rate = 1 EQUB 36 \ Maximum speed = 36 EQUB 133 \ Cargo hold capacity = 133 - 1 = 132 EQUB 90 \ Hyperspace range = 9.0 LY EQUB 0 * 26 \ Equipment prices offset from PRXS = 0 EQUB 191 \ Maximum roll/pitch rate = 191 \EQUB 65 \ Not used (minimum roll/pitch rate) = 65 \EQUB 10 \ Not used (new_space) = 10 \EQUB 0 \ Not used IF _SOURCE_DISC \ Anaconda EQUB 28 \ Pulse laser power = 28 EQUB 144 \ Beam laser power = 144 EQUB 127 \ Military laser power = 127 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 17 \ Maximum missile count = 17 - 1 = 16 EQUB 13 \ Shields = 13 EQUB 1 \ Energy recharge rate = 1 EQUB 21 \ Maximum speed = 21 EQUB 254 \ Cargo hold capacity = 254 - 1 = 253 EQUB 100 \ Hyperspace range = 10.0 LY EQUB 3 * 26 \ Equipment prices offset from PRXS = 3 EQUB 175 \ Maximum roll/pitch rate = 175 \EQUB 81 \ Not used (minimum roll/pitch rate) = 81 \EQUB 12 \ Not used (new_space) = 12 \EQUB 0 \ Not used \ Asp Mk II EQUB 16 \ Pulse laser power = 16 EQUB 145 \ Beam laser power = 145 EQUB 159 \ Military laser power = 159 EQUB 12 \ Mining laser power = 12 EQUB 1 \ Laser mounts = Front EQUB 2 \ Maximum missile count = 2 - 1 = 1 EQUB 10 \ Shields = 10 EQUB 1 \ Energy recharge rate = 1 EQUB 60 \ Maximum speed = 60 EQUB 7 \ Cargo hold capacity = 7 - 1 = 6 EQUB 125 \ Hyperspace range = 12.5 LY EQUB 2 * 26 \ Equipment prices offset from PRXS = 2 EQUB 223 \ Maximum roll/pitch rate = 223 \EQUB 33 \ Not used (minimum roll/pitch rate) = 33 \EQUB 7 \ Not used (new_space) = 7 \EQUB 0 \ Not used ELIF _RELEASED \ Asp Mk II EQUB 16 \ Pulse laser power = 16 EQUB 145 \ Beam laser power = 145 EQUB 159 \ Military laser power = 159 EQUB 12 \ Mining laser power = 12 EQUB 1 \ Laser mounts = Front EQUB 2 \ Maximum missile count = 2 - 1 = 1 EQUB 10 \ Shields = 10 EQUB 1 \ Energy recharge rate = 1 EQUB 60 \ Maximum speed = 60 EQUB 7 \ Cargo hold capacity = 7 - 1 = 6 EQUB 125 \ Hyperspace range = 12.5 LY EQUB 2 * 26 \ Equipment prices offset from PRXS = 2 EQUB 223 \ Maximum roll/pitch rate = 223 \EQUB 33 \ Not used (minimum roll/pitch rate) = 33 \EQUB 7 \ Not used (new_space) = 7 \EQUB 0 \ Not used \ Anaconda EQUB 28 \ Pulse laser power = 28 EQUB 144 \ Beam laser power = 144 EQUB 127 \ Military laser power = 127 EQUB 50 \ Mining laser power = 50 EQUB 4 \ Laser mounts = All four EQUB 17 \ Maximum missile count = 17 - 1 = 16 EQUB 13 \ Shields = 13 EQUB 1 \ Energy recharge rate = 1 EQUB 21 \ Maximum speed = 21 EQUB 254 \ Cargo hold capacity = 254 - 1 = 253 EQUB 100 \ Hyperspace range = 10.0 LY EQUB 3 * 26 \ Equipment prices offset from PRXS = 3 EQUB 175 \ Maximum roll/pitch rate = 175 \EQUB 81 \ Not used (minimum roll/pitch rate) = 81 \EQUB 12 \ Not used (new_space) = 12 \EQUB 0 \ Not used ENDIFName: new_details [Show more] Type: Variable Category: Buying ships Summary: The flight characteristics for each of the different ship types Deep dive: Buying and flying ships in Elite-AContext: See this variable on its own page References: This variable is used as follows: * n_load calls new_detailsPRINT "ELITE G" PRINT "Assembled at ", ~CODE_G% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_G%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_G% PRINT "S.2.ELTG ", ~CODE_G%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_G% SAVE "3-assembled-output/2.ELTG.bin", CODE_G%, P%, LOAD%Save ELTG.bin

[X]

Subroutine BAY (category: Status)

Go to the docking bay (i.e. show the Status Mode screen)

[X]

Subroutine BPRNT (category: Text)

Print a 32-bit number, left-padded to a specific number of digits, with an optional decimal point

[X]

Subroutine CLYNS (category: Utility routines)

Clear the bottom three text rows of the mode 4 screen by sending a clr_line command to the I/O processor

[X]

Subroutine DELAY (category: Utility routines)

Wait for a specified time, in 1/50s of a second

[X]

Subroutine DETOK (category: Text)

Print an extended recursive token from the TKN1 token table

[X]

Subroutine DOEXP (category: Drawing ships)

Draw an exploding ship

[X]

Subroutine DORND (category: Utility routines)

Generate random numbers

[X]

Label EE28 in subroutine LL9 (Part 1 of 12)

[X]

Label EE29 in subroutine LL9 (Part 5 of 12)

[X]

Label EE30 in subroutine LL9 (Part 4 of 12)

[X]

Label EE31 in subroutine LL9 (Part 9 of 12)

[X]

Entry point EE51 in subroutine LL9 (Part 1 of 12) (category: Drawing ships)

Remove the current ship from the screen, called from SHPPT before drawing the ship as a point

[X]

Label EE55 in subroutine LL9 (Part 1 of 12)

[X]

Subroutine FMLTU (category: Maths (Arithmetic))

Calculate A = A * Q / 256

[X]

Subroutine GVL (category: Universe)

Calculate the availability of market items

[X]

Subroutine LCASH (category: Maths (Arithmetic))

Subtract an amount of cash from the cash pot

[X]

Label LL10 in subroutine LL9 (Part 2 of 12)

[X]

Entry point LL10-1 in subroutine LL9 (Part 2 of 12) (category: Drawing ships)

Contains an RTS

[X]

Label LL107 in subroutine LL145 (Part 1 of 4)

[X]

Label LL108 in subroutine LL145 (Part 1 of 4)

[X]

Label LL109 in subroutine LL145 (Part 1 of 4)

[X]

Label LL110 in subroutine LL145 (Part 3 of 4)

[X]

Label LL111 in subroutine LL145 (Part 3 of 4)

[X]

Label LL112 in subroutine LL145 (Part 3 of 4)

[X]

Label LL113 in subroutine LL145 (Part 3 of 4)

[X]

Label LL114 in subroutine LL145 (Part 3 of 4)

[X]

Label LL115 in subroutine LL145 (Part 3 of 4)

[X]

Label LL116 in subroutine LL145 (Part 4 of 4)

[X]

Subroutine LL118 (category: Drawing lines)

Move a point along a line until it is on-screen

[X]

Entry point LL118-1 in subroutine LL118 (category: Drawing lines)

Contains an RTS

[X]

Subroutine LL120 (category: Maths (Arithmetic))

Calculate (Y X) = (S x1_lo) * XX12+2 or (S x1_lo) / XX12+2

[X]

Entry point LL121 in subroutine LL123 (category: Maths (Arithmetic))

Calculate (Y X) = (S R) / Q and set the sign to the opposite of the top byte on the stack

[X]

Entry point LL122 in subroutine LL120 (category: Maths (Arithmetic))

Calculate (Y X) = (S R) * Q and set the sign to the opposite of the top byte on the stack

[X]

Subroutine LL123 (category: Maths (Arithmetic))

Calculate (Y X) = (S R) / XX12+2 or (S R) * XX12+2

[X]

Label LL124 in subroutine LL145 (Part 4 of 4)

[X]

Entry point LL128 in subroutine LL123 (category: Maths (Arithmetic))

Contains an RTS

[X]

Subroutine LL129 (category: Maths (Arithmetic))

Calculate Q = XX12+2, A = S EOR XX12+3 and (S R) = |S R|

[X]

Label LL13 in subroutine LL9 (Part 2 of 12)

[X]

Entry point LL133 in subroutine LL123 (category: Maths (Arithmetic))

Negate (Y X) and return from the subroutine LL128 Contains an RTS

[X]

Label LL137 in subroutine LL145 (Part 4 of 4)

[X]

Label LL138 in subroutine LL145 (Part 4 of 4)

[X]

Label LL14 in subroutine LL9 (Part 1 of 12)

[X]

Label LL140 in subroutine LL9 (Part 7 of 12)

[X]

Subroutine LL145 (Part 1 of 4) (category: Drawing lines)

Clip line: Work out which end-points are on-screen, if any

[X]

Label LL146 in subroutine LL145 (Part 1 of 4)

[X]

Entry point LL147 in subroutine LL145 (Part 1 of 4) (category: Drawing lines)

Don't initialise the values in SWAP or A

[X]

Label LL15 in subroutine LL9 (Part 3 of 12)

[X]

Label LL155 in subroutine LL9 (Part 12 of 12)

[X]

Label LL17 in subroutine LL9 (Part 3 of 12)

[X]

Label LL170 in subroutine LL9 (Part 10 of 12)

[X]

Label LL21 in subroutine LL9 (Part 3 of 12)

[X]

Label LL27 in subroutine LL9 (Part 12 of 12)

[X]

Subroutine LL28 (category: Maths (Arithmetic))

Calculate R = 256 * A / Q

[X]

Subroutine LL30 (category: Drawing lines)

Draw a one-segment line by sending a draw_line command to the I/O processor

[X]

Entry point LL31 in subroutine LL28 (category: Maths (Arithmetic))

Skips the A >= Q check and does not set the R counter, so this can be used for jumping straight into the division loop if R is already set to 254 and we know the division will work

[X]

Subroutine LL38 (category: Maths (Arithmetic))

Calculate (S A) = (S R) + (A Q)

[X]

Label LL41 in subroutine LL9 (Part 4 of 12)

[X]

Label LL42 in subroutine LL9 (Part 6 of 12)

[X]

Label LL48 in subroutine LL9 (Part 6 of 12)

[X]

Label LL49 in subroutine LL9 (Part 6 of 12)

[X]

[X]

Subroutine LL5 (category: Maths (Arithmetic))

Calculate Q = SQRT(R Q)

[X]

Label LL50 in subroutine LL9 (Part 8 of 12)

[X]

Subroutine LL51 (category: Maths (Geometry))

Calculate the dot product of XX15 and XX16

[X]

Label LL52 in subroutine LL9 (Part 6 of 12)

[X]

Label LL53 in subroutine LL9 (Part 6 of 12)

[X]

Label LL54 in subroutine LL9 (Part 6 of 12)

[X]

Label LL55 in subroutine LL9 (Part 6 of 12)

[X]

Label LL56 in subroutine LL9 (Part 7 of 12)

[X]

Label LL57 in subroutine LL9 (Part 7 of 12)

[X]

Label LL60 in subroutine LL9 (Part 8 of 12)

[X]

Subroutine LL61 (category: Maths (Arithmetic))

Calculate (U R) = 256 * A / Q

[X]

Subroutine LL62 (category: Maths (Arithmetic))

Calculate 128 - (U R)

[X]

Label LL65 in subroutine LL9 (Part 8 of 12)

[X]

Label LL66 in subroutine LL9 (Part 8 of 12)

[X]

Label LL67 in subroutine LL9 (Part 8 of 12)

[X]

Label LL68 in subroutine LL9 (Part 8 of 12)

[X]

Label LL69 in subroutine LL9 (Part 8 of 12)

[X]

Label LL70 in subroutine LL9 (Part 8 of 12)

[X]

Label LL72 in subroutine LL9 (Part 9 of 12)

[X]

Label LL74 in subroutine LL9 (Part 9 of 12)

[X]

Label LL75 in subroutine LL9 (Part 10 of 12)

[X]

Label LL78 in subroutine LL9 (Part 11 of 12)

[X]

Label LL79 in subroutine LL9 (Part 10 of 12)

[X]

[X]

Label LL80 in subroutine LL9 (Part 11 of 12)

[X]

Label LL81 in subroutine LL9 (Part 11 of 12)

[X]

Entry point LL81+2 in subroutine LL9 (Part 11 of 12) (category: Drawing ships)

Draw the contents of the ship line heap, used to draw the ship as a dot from SHPPT

[X]

Label LL83 in subroutine LL145 (Part 2 of 4)

[X]

Label LL86 in subroutine LL9 (Part 5 of 12)

[X]

Label LL87 in subroutine LL9 (Part 5 of 12)

[X]

Label LL88 in subroutine LL9 (Part 5 of 12)

[X]

Label LL89 in subroutine LL9 (Part 5 of 12)

[X]

Label LL90 in subroutine LL9 (Part 5 of 12)

[X]

[X]

Label LL91 in subroutine LL9 (Part 5 of 12)

[X]

Label LL92 in subroutine LL9 (Part 5 of 12)

[X]

Label LL93 in subroutine LL9 (Part 5 of 12)

[X]

[X]

Label LL94 in subroutine LL9 (Part 5 of 12)

[X]

Label LLX117 in subroutine LL145 (Part 4 of 4)

[X]

Subroutine MCASH (category: Maths (Arithmetic))

Add an amount of cash to the cash pot

[X]

Subroutine NLIN4 (category: Drawing lines)

Draw a horizontal line at pixel row 19 to box in a title

[X]

Subroutine PROJ (category: Drawing ships)

Project the current ship onto the screen

[X]

Variable QQ23 (category: Market)

Market prices table

[X]

Subroutine SHPPT (category: Drawing ships)

Draw a distant ship as a point rather than a full wireframe

[X]

Subroutine SQUA2 (category: Maths (Arithmetic))

Calculate (A P) = A * A

[X]

Subroutine TT11 (category: Text)

Print a 16-bit number, left-padded to n digits, and optional point

[X]

Subroutine TT162 (category: Text)

Print a space

[X]

Subroutine TT20 (category: Universe)

Twist the selected system's seeds four times

[X]

Subroutine TT27 (category: Text)

Print a text token

[X]

Subroutine TT66 (category: Utility routines)

Clear the screen and set the current view type

[X]

Subroutine TT67 (category: Text)

Print a newline

[X]

Subroutine TT81 (category: Universe)

Set the selected system's seeds to those of system 0

[X]

Temporary storage, used to store the address of a ship blueprint. For example, it is used when we add a new ship to the local bubble in routine NWSHP, and it contains the address of the current ship's blueprint as we loop through all the nearby ships in the main flight loop

[X]

Workspace XX3 (category: Workspaces)

Temporary storage space for complex calculations

[X]

Configuration variable: Y = 96

The centre y-coordinate of the 256 x 192 space view

[X]

Entry point cash_query in subroutine n_buyship (category: Buying ships)

Print "CASH?", make a short, high beep, delay for 1 second and go to the docking bay (i.e. show the Status Mode screen)

[X]

Variable cmdr_courx in workspace UP

The galactic x-coordinate for the current special cargo delivery destination

[X]

Variable cmdr_coury in workspace UP

The galactic y-coordinate for the current special cargo delivery destination

[X]

Label count_lasers in subroutine n_load

[X]

Variable count_offs (category: Buying ships)

Offsets from LASER for equipment that takes up space in the hold

[X]

Subroutine cour_count (category: Missions)

Generate a single special cargo mission and display its menu item

[X]

Label cour_dist in subroutine cour_count

[X]

Subroutine cour_dock (category: Missions)

Update the current special cargo delivery mission on docking

[X]

Label cour_legal in subroutine cour_count

[X]

Label cour_negx in subroutine cour_count

[X]

Label cour_negy in subroutine cour_count

[X]

Label cour_next in subroutine cour_count

[X]

Label cour_star in subroutine cour_count

[X]

Label cour_start in subroutine cour_buy

[X]

Subroutine cpl (category: Text)

Print the selected system name

[X]

Subroutine dn2 (category: Text)

Make a short, high beep and delay for 1 second

[X]

Subroutine gnum (category: Market)

Get a number from the keyboard

[X]

Entry point jmp_start3 in subroutine n_buyship (category: Buying ships)

Make a short, high beep, and delay for 1 second and go to the docking bay (i.e. show the Status Mode screen)

[X]

Label ll81 in subroutine LL9 (Part 11 of 12)

[X]

Label ll91 in subroutine LL9 (Part 3 of 12)

[X]

Subroutine msblob (category: Dashboard)

Display the dashboard's missile indicators in green

[X]

Subroutine n_load (category: Buying ships)

Load the name and flight characteristics for the current ship type

[X]

Subroutine n_name (category: Text)

Print the type of a given ship

[X]

Subroutine n_price (category: Buying ships)

Set K(0 1 2 3) to the price of a given ship

[X]

Variable new_details (category: Buying ships)

The flight characteristics for each of the different ship types

[X]

Entry point new_name in variable QQ18 (category: Text)

This part of token 132 is updated with our current ship's type by routine n_load, so printing token 132 will always show the correct type of our ship

[X]

Variable new_offsets (category: Buying ships)

Table of offsets for each ship type

[X]

Variable new_ships (category: Buying ships)

Ship names and prices for the different ship types we can buy

[X]

[X]

Label ovflw in subroutine LL9 (Part 5 of 12)

[X]

Subroutine pr2 (category: Text)

Print an 8-bit number, left-padded to 3 digits, and optional point

[X]

Subroutine prq (category: Text)

Print a text token followed by a question mark

[X]

Subroutine update_pod (category: Dashboard)

Ensure the correct palette is shown for the dashboard/hyperspace tunnel, by sending a write_pod command to the I/O processor

[X]

Subroutine var (category: Market)

Calculate QQ19+3 = economy * |economic_factor|