ORG CODE% LOAD_A% = LOAD%ELITE A FILE.S1% EQUS ":0.E."Name: S1% [Show more] Type: Variable Category: Save and load Summary: The drive and directory number used when saving or loading a commander file Deep dive: Commander save filesContext: See this variable on its own page References: No direct references to this variable in this source file
The drive part of this string (the "0") is updated with the chosen drive in the GTNMEW routine, but the directory part (the "E") is fixed. The variable is followed directly by the commander file at NA%, which starts with the commander name, so the full string at S1% is in the format ":0.E.JAMESON", which gives the full filename of the commander file..NA% EQUS "NEWCOME" \ The current commander name, which defaults to NEWCOME EQUB 13 \ \ The commander name can be up to 7 characters (the DFS \ limit for filenames), and is terminated by a carriage \ return \ NA%+8 is the start of the commander data block \ \ This block contains the last saved commander data \ block. As the game is played it uses an identical \ block at location TP to store the current commander \ state, and that block is copied here when the game is \ saved. Conversely, when the game starts up, the block \ here is copied to TP, which restores the last saved \ commander when we die \ \ The initial state of this block defines the default \ commander. Q% can be set to TRUE to give the default \ commander lots of credits and equipment EQUB 0 \ TP = Mission status, #0 EQUB 20 \ QQ0 = Current system X-coordinate (Lave), #1 EQUB 173 \ QQ1 = Current system Y-coordinate (Lave), #2 EQUW &5A4A \ QQ21 = Seed s0 for system 0, galaxy 0 (Tibedied), #3-4 EQUW &0248 \ QQ21 = Seed s1 for system 0, galaxy 0 (Tibedied), #5-6 EQUW &B753 \ QQ21 = Seed s2 for system 0, galaxy 0 (Tibedied), #7-8 IF Q% EQUD &00CA9A3B \ CASH = Amount of cash (100,000,000 Cr), #9-12 ELSE EQUD &88130000 \ CASH = Amount of cash (500 Cr), #9-12 ENDIF EQUB 60 + (15 AND Q%) \ QQ14 = Fuel level, #13 EQUB 0 \ COK = Competition flags, #14 EQUB 0 \ GCNT = Galaxy number, 0-7, #15 EQUB &9C AND Q% \ LASER = Front laser, #16 EQUB &9C AND Q% \ LASER+1 = Rear laser, #17 EQUB 0 \ LASER+2 = Left laser, #18 EQUB 0 \ LASER+3 = Right laser, #19 EQUB 0 \ This byte appears to be unused, #20 EQUB 8 AND Q% \ cmdr_type = Type of our current ship, #21 EQUB Q% \ CRGO = I.F.F. system, #22 EQUB 0 \ QQ20+0 = Amount of food in cargo hold, #23 EQUB 0 \ QQ20+1 = Amount of textiles in cargo hold, #24 EQUB 0 \ QQ20+2 = Amount of radioactives in cargo hold, #25 EQUB 0 \ QQ20+3 = Amount of slaves in cargo hold, #26 EQUB 0 \ QQ20+4 = Amount of liquor/Wines in cargo hold, #27 EQUB 0 \ QQ20+5 = Amount of luxuries in cargo hold, #28 EQUB 0 \ QQ20+6 = Amount of narcotics in cargo hold, #29 EQUB 0 \ QQ20+7 = Amount of computers in cargo hold, #30 EQUB 0 \ QQ20+8 = Amount of machinery in cargo hold, #31 EQUB 0 \ QQ20+9 = Amount of alloys in cargo hold, #32 EQUB 0 \ QQ20+10 = Amount of firearms in cargo hold, #33 EQUB 0 \ QQ20+11 = Amount of furs in cargo hold, #34 EQUB 0 \ QQ20+12 = Amount of minerals in cargo hold, #35 EQUB 0 \ QQ20+13 = Amount of gold in cargo hold, #36 EQUB 0 \ QQ20+14 = Amount of platinum in cargo hold, #37 EQUB 0 \ QQ20+15 = Amount of gem-stones in cargo hold, #38 EQUB 0 \ QQ20+16 = Amount of alien items in cargo hold, #39 EQUB Q% \ ECM = E.C.M. system, #40 EQUB Q% \ BST = Fuel scoops ("barrel status"), #41 EQUB Q% \ BOMB = Hyperspace unit, #42 EQUB Q% AND 1 \ ENGY = Energy/shield level, #43 EQUB Q% \ DKCMP = Docking computer, #44 EQUB Q% \ GHYP = Galactic hyperdrive, #45 EQUB Q% \ ESCP = Escape pod, #46 EQUW 0 \ cmdr_cour = Special cargo mission timer, #47 EQUB 0 \ cmdr_courx = Special cargo destination x-coord, #49 EQUB 0 \ cmdr_coury = Special cargo destination y-coord, #50 EQUB 0 \ NOMSL = Number of missiles, #51 EQUB 0 \ FIST = Legal status ("fugitive/innocent status"), #52 EQUB 0 \ AVL+0 = Market availability of food, #53 EQUB 15 \ AVL+1 = Market availability of textiles, #54 EQUB 17 \ AVL+2 = Market availability of radioactives, #55 EQUB 0 \ AVL+3 = Market availability of slaves, #56 EQUB 3 \ AVL+4 = Market availability of liquor/Wines, #57 EQUB 28 \ AVL+5 = Market availability of luxuries, #58 EQUB 14 \ AVL+6 = Market availability of narcotics, #59 EQUB 0 \ AVL+7 = Market availability of computers, #60 EQUB 0 \ AVL+8 = Market availability of machinery, #61 EQUB 10 \ AVL+9 = Market availability of alloys, #62 EQUB 0 \ AVL+10 = Market availability of firearms, #63 EQUB 17 \ AVL+11 = Market availability of furs, #64 EQUB 58 \ AVL+12 = Market availability of minerals, #65 EQUB 7 \ AVL+13 = Market availability of gold, #66 EQUB 9 \ AVL+14 = Market availability of platinum, #67 EQUB 8 \ AVL+15 = Market availability of gem-stones, #68 EQUB 0 \ AVL+16 = Market availability of alien items, #69 EQUB 0 \ QQ26 = Random byte that changes for each visit to a \ system, for randomising market prices, #70 EQUW 0 \ TALLY = Number of kills, #71-72 EQUB 32 \ SVC = Save count, #73Name: NA% [Show more] Type: Variable Category: Save and load Summary: The data block for the last saved commander Deep dive: Commander save files The competition codeContext: See this variable on its own page References: This variable is used as follows: * CHECK uses NA% * cmn uses NA% * DFAULT uses NA% * GTNMEW uses NA% * LOD uses NA% * SVE uses NA% * TR1 uses NA% * TRNME uses NA%
Contains the last saved commander data, with the name at NA% and the data at NA%+8 onwards. The size of the data block is given in NT% (which also includes the two checksum bytes that follow this block). This block is initially set up with the default commander, which can be maxed out for testing purposes by setting Q% to TRUE. The commander's name is stored at NA%, and can be up to 7 characters long (the DFS filename limit). It is terminated with a carriage return character, ASCII 13. The offset of each byte within a saved commander file is also shown as #0, #1 and so on, so the kill tally, for example, is in bytes #71 and #72 of the saved file. The related variable name from the current commander block is also shown..CHK2 EQUB &58 EOR &A9 \ The checksum value for the default commander, EOR'd \ with &A9 to make it harder to tamper with the checksum \ byte, #74Name: CHK2 [Show more] Type: Variable Category: Save and load Summary: Second checksum byte for the saved commander data file Deep dive: Commander save files The competition codeContext: See this variable on its own page References: This variable is used as follows: * SVE uses CHK2
Second commander checksum byte. If the default commander is changed, a new checksum will be calculated and inserted by the elite-checksum.py script. The offset of this byte within a saved commander file is also shown (it's at byte #74)..CHK EQUB &58 \ The checksum value for the default commander, #75Name: CHK [Show more] Type: Variable Category: Save and load Summary: First checksum byte for the saved commander data file Deep dive: Commander save files The competition codeContext: See this variable on its own page References: This variable is used as follows: * DFAULT uses CHK * SVE uses CHK
Commander checksum byte. If the default commander is changed, a new checksum will be calculated and inserted by the elite-checksum.py script. The offset of this byte within a saved commander file is also shown (it's at byte #75)..tube_write BIT tube_r1s \ Check whether FIFO 1 is available for use, so we can \ use it to transmit a byte to the I/O processor. We do \ this by checking bit 6 of the FIFO 1 status register NOP \ Pause while the register is checked BVC tube_write \ If FIFO 1 is available for use then bit 6 of the \ status register will be set, so this loops back to \ tube_write until FIFO 1 is available for us to use STA tube_r1d \ FIFO 1 is available for use, so store the value we \ want to transmit in the FIFO 1 data register, so it \ gets sent to the I/O processor RTS \ Return from the subroutineName: tube_write [Show more] Type: Subroutine Category: Tube Summary: As the parasite, send a byte across the Tube to the I/O processor Deep dive: Tube communication in Elite-AContext: See this subroutine on its own page References: This subroutine is called as follows: * boot_in calls tube_write * CATS calls tube_write * CHPR calls tube_write * CLYNS calls tube_write * CPIX2 calls tube_write * DET1 calls tube_write * DIL2 calls tube_write * DILX calls tube_write * DKS1 calls tube_write * DKS4 calls tube_write * ECBLB calls tube_write * HANGER calls tube_write * HLOIN calls tube_write * LL30 calls tube_write * MSBAR calls tube_write * MT26 calls tube_write * PIXEL calls tube_write * RDKEY calls tube_write * read_0346 calls tube_write * SCAN calls tube_write * scan_fire calls tube_write * SPBLB calls tube_write * TT217 calls tube_write * TTX66 calls tube_write * UNWISE calls tube_write * update_pod calls tube_write * write_0346 calls tube_write * WSCAN calls tube_write
Tube communication in Elite-A uses the following protocol: Parasite -> I/O processor * Uses the FIFO 1 status and data registers to transmit the data * The parasite calls tube_write to send a byte to the I/O processor * The I/O processor calls tube_get to receive that byte from the parasite I/O processor -> Parasite * Uses the FIFO 2 status and data registers to transmit the data * The I/O processor calls tube_put to send a byte to the parasite * The parasite calls tube_read to receive that byte from the I/O processor This routine is called by the parasite to send a byte to the I/O processor. The code is identical to Acorn's MOS routine that runs on the parasite to implement OSWRCH across the Tube..tube_read BIT tube_r2s \ Check whether FIFO 2 has received a byte from the I/O \ processor (which it will have sent by calling its own \ tube_put routine). We do this by checking bit 7 of the \ FIFO 2 status register NOP \ Pause while the register is checked BPL tube_read \ If FIFO 2 has received a byte then bit 7 of the status \ register will be set, so this loops back to tube_read \ until FIFO 2 contains the byte transmitted from the \ I/O processor LDA tube_r2d \ Fetch the transmitted byte by reading the FIFO 2 data \ register into A RTS \ Return from the subroutineName: tube_read [Show more] Type: Subroutine Category: Tube Summary: As the parasite, fetch a byte that's been sent over the Tube from the I/O processor Deep dive: Tube communication in Elite-AContext: See this subroutine on its own page References: This subroutine is called as follows: * DKS1 calls tube_read * DKS4 calls tube_read * MT26 calls tube_read * RDKEY calls tube_read * read_0346 calls tube_read * scan_fire calls tube_read * TT217 calls tube_read * WSCAN calls tube_read
Tube communication in Elite-A uses the following protocol: Parasite -> I/O processor * Uses the FIFO 1 status and data registers to transmit the data * The parasite calls tube_write to send a byte to the I/O processor * The I/O processor calls tube_get to receive that byte from the parasite I/O processor -> Parasite * Uses the FIFO 2 status and data registers to transmit the data * The I/O processor calls tube_put to send a byte to the parasite * The parasite calls tube_read to receive that byte from the I/O processor This routine is called by the parasite to receive a byte from the I/O processor. The code is identical to Acorn's MOS routine that runs on the parasite to implement OSWRCH across the Tube (except this uses FIFO 2 instead of FIFO 1)..DOENTRY LDA #0 \ Set dockedp = 0 to indicate we are docked STA dockedp LDA #&FF \ Call SCRAM to set save_lock to &FF (i.e. we have just JSR SCRAM \ docked and have unsaved changes) and set the break \ handler JSR RES2 \ Reset a number of flight variables and workspaces JSR HFS1 \ Show the space station docking tunnel JSR HALL \ Show the ship hangar LDY #44 \ Wait for 44/50 of a second (0.88 seconds) JSR DELAY JSR cour_dock \ Update the current special cargo delivery mission LDA TP \ Fetch bits 0 and 1 of TP, and if they are non-zero AND #%00000011 \ (i.e. mission 1 is either in progress or has been BNE EN1 \ completed), skip to EN1 LDA TALLY+1 \ If the high byte of TALLY is zero (so we have a combat BEQ EN4 \ rank below Competent), jump to EN4 as we are not yet \ good enough to qualify for a mission LDA GCNT \ Fetch the galaxy number into A, and if any of bits 1-7 LSR A \ are set (i.e. A > 1), jump to EN4 as mission 1 can BNE EN4 \ only be triggered in the first two galaxies JMP BRIEF \ If we get here, mission 1 hasn't started, we have \ reached a combat rank of Competent, and we are in \ galaxy 0 or 1 (shown in-game as galaxy 1 or 2), so \ it's time to start mission 1 by calling BRIEF .EN1 \ If we get here then mission 1 is either in progress or \ has been completed CMP #%00000011 \ If bits 0 and 1 are not both set, then jump to EN2 BNE EN2 JMP DEBRIEF \ Bits 0 and 1 are both set, so mission 1 is both in \ progress and has been completed, which means we have \ only just completed it, so jump to DEBRIEF to end the \ mission get our reward .EN2 \ Mission 1 has been completed, so now to check for \ mission 2 LDA TP \ Extract bits 0-3 of TP into A AND #%00001111 CMP #%00000010 \ If mission 1 is complete and no longer in progress, BNE EN3 \ and mission 2 is not yet started, then bits 0-3 of TP \ will be %0010, so this jumps to EN3 if this is not the \ case LDA TALLY+1 \ If the high byte of TALLY is < 5 (so we have a combat CMP #5 \ rank that is less than 3/8 of the way from Dangerous BCC EN4 \ to Deadly), jump to EN4 as our rank isn't high enough \ for mission 2 LDA GCNT \ Fetch the galaxy number into A CMP #2 \ If this is not galaxy 2 (shown in-game as galaxy 3), BNE EN4 \ jump to EN4 as we can only start mission 2 in the \ third galaxy JMP BRIEF2 \ If we get here, mission 1 is complete and no longer in \ progress, mission 2 hasn't started, we have reached a \ combat rank of 3/8 of the way from Dangerous to \ Deadly, and we are in galaxy 2 (shown in-game as \ galaxy 3), so it's time to start mission 2 by calling \ BRIEF2 .EN3 CMP #%00000110 \ If mission 1 is complete and no longer in progress, BNE EN5 \ and mission 2 has started but we have not yet been \ briefed and picked up the plans, then bits 0-3 of TP \ will be %0110, so this jumps to EN5 if this is not the \ case LDA GCNT \ Fetch the galaxy number into A CMP #2 \ If this is not galaxy 2 (shown in-game as galaxy 3), BNE EN4 \ jump to EN4 as we can only start mission 2 in the \ third galaxy LDA QQ0 \ Set A = the current system's galactic x-coordinate CMP #215 \ If A <> 215 then jump to EN4 BNE EN4 LDA QQ1 \ Set A = the current system's galactic y-coordinate CMP #84 \ If A <> 84 then jump to EN4 BNE EN4 JMP BRIEF3 \ If we get here, mission 1 is complete and no longer in \ progress, mission 2 has started but we have not yet \ picked up the plans, and we have just arrived at \ Ceerdi at galactic coordinates (215, 84), so we jump \ to BRIEF3 to get a mission brief and pick up the plans \ that we need to carry to Birera .EN5 CMP #%00001010 \ If mission 1 is complete and no longer in progress, BNE EN4 \ and mission 2 has started and we have picked up the \ plans, then bits 0-3 of TP will be %1010, so this \ jumps to EN5 if this is not the case LDA GCNT \ Fetch the galaxy number into A CMP #2 \ If this is not galaxy 2 (shown in-game as galaxy 3), BNE EN4 \ jump to EN4 as we can only start mission 2 in the \ third galaxy LDA QQ0 \ Set A = the current system's galactic x-coordinate CMP #63 \ If A <> 63 then jump to EN4 BNE EN4 LDA QQ1 \ Set A = the current system's galactic y-coordinate CMP #72 \ If A <> 72 then jump to EN4 BNE EN4 JMP DEBRIEF2 \ If we get here, mission 1 is complete and no longer in \ progress, mission 2 has started and we have picked up \ the plans, and we have just arrived at Birera at \ galactic coordinates (63, 72), so we jump to DEBRIEF2 \ to end the mission and get our reward .EN4 JMP BAY \ If we get here them we didn't start or any missions, \ so jump to BAY to go to the docking bay (i.e. show the \ Status Mode screen)Name: DOENTRY [Show more] Type: Subroutine Category: Flight Summary: Dock at the space station, show the ship hangar and work out any mission progression Deep dive: The Constrictor mission The Thargoid Plans missionContext: See this subroutine on its own page References: This subroutine is called as follows: * DOENTRYS calls DOENTRY.SCRAM STA save_lock \ Set the save_lock variable to the value in A (which \ will be either 0 or &FF) \ Fall through into BRKBK to set the standard BRKV \ handler for the game and return from the subroutineName: SCRAM [Show more] Type: Subroutine Category: Loader Summary: Set the save_lock variable and break handlerContext: See this subroutine on its own page References: This subroutine is called as follows: * DOENTRY calls SCRAM
Arguments: A Set the save_lock flag as follows: * 0 = this is a new game, so there are no unsaved changes in the commander file * &FF = we just docked, so there are unsaved changes in the commander file.BRKBK LDA #LO(BRBR) \ Set BRKV to point to the BRBR routine STA BRKV LDA #HI(BRBR) STA BRKV+1 RTS \ Return from the subroutine.write_msg3 PHA \ Store A on the stack, so we can retrieve it later TAX \ Copy the token number from A into X TYA \ Store Y on the stack PHA LDA V \ Store V(1 0) on the stack PHA LDA V+1 PHA LDA #LO(msg_3) \ Set V to the low byte of msg_3 STA V LDA #HI(msg_3) \ Set A to the high byte of msg_3 BNE DTEN \ Call DTEN to print token number X from the msg_3 \ table and restore the values of A, Y and V(1 0) from \ the stack, returning from the subroutine using a tail \ call (this BNE is effectively a JMP as A is never \ zero)Name: write_msg3 [Show more] Type: Subroutine Category: Text Summary: Print an extended recursive token from the msg_3 token table Deep dive: The Encyclopedia GalacticaContext: See this subroutine on its own page References: This subroutine is called as follows: * controls calls write_msg3 * equip_data calls write_msg3 * menu calls write_msg3 * ships_ag calls write_msg3 * write_card calls write_msg3
Arguments: A The recursive token to be printed, in the range 0-255
Returns: A A is preserved Y Y is preserved V(1 0) V(1 0) is preserved.DETOK3 PHA \ Store A on the stack, so we can retrieve it later TAX \ Copy the token number from A into X TYA \ Store Y on the stack PHA LDA V \ Store V(1 0) on the stack PHA LDA V+1 PHA LDA #LO(RUTOK) \ Set V to the low byte of RUTOK STA V LDA #HI(RUTOK) \ Set A to the high byte of RUTOK BNE DTEN \ Call DTEN to print token number X from the RUTOK \ table and restore the values of A, Y and V(1 0) from \ the stack, returning from the subroutine using a tail \ call (this BNE is effectively a JMP as A is never \ zero)Name: DETOK3 [Show more] Type: Subroutine Category: Text Summary: Print an extended recursive token from the RUTOK token table Deep dive: Extended system descriptions Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * PDESC calls DETOK3
Arguments: A The recursive token to be printed, in the range 0-255
Returns: A A is preserved Y Y is preserved V(1 0) V(1 0) is preserved.MT27 LDA #217 \ Set A = 217, so when we fall through into MT28, the \ 217 gets added to the current galaxy number, so the \ extended token that is printed is 217-219 (as this is \ only called in galaxies 0 through 2) EQUB &2C \ Skip the next instruction by turning it into \ &2C &A9 &DC, or BIT &DCA9, which does nothing apart \ from affect the flagsName: MT27 [Show more] Type: Subroutine Category: Text Summary: Print the captain's name during mission briefings Deep dive: Extended text tokens The Constrictor missionContext: See this subroutine on its own page References: This subroutine is called as follows: * JMTB calls MT27
This routine prints the following tokens, depending on the galaxy number: * Token 217 ("CURRUTHERS") in galaxy 0 * Token 218 ("FOSDYKE SMYTHE") in galaxy 1 * Token 219 ("FORTESQUE") in galaxy 2 This is used when printing extended token 213 as part of the mission briefings, which looks like this when printed: Commander {commander name}, I am Captain {mission captain's name} of Her Majesty's Space Navy where {mission captain's name} is replaced by one of the names above..MT28 LDA #220 \ Set A = galaxy number in GCNT + 220, which is in the CLC \ range 220-221, as this is only called in galaxies 0 ADC GCNT \ and 1 \ Fall through into DETOK to print extended token \ 220-221Name: MT28 [Show more] Type: Subroutine Category: Text Summary: Print the location hint during the mission 1 briefing Deep dive: Extended text tokens The Constrictor missionContext: See this subroutine on its own page References: This subroutine is called as follows: * JMTB calls MT28
This routine prints the following tokens, depending on the galaxy number: * Token 220 ("WAS LAST SEEN AT {single cap}REESDICE") in galaxy 0 * Token 221 ("IS BELIEVED TO HAVE JUMPED TO THIS GALAXY") in galaxy 1 This is used when printing extended token 10 as part of the mission 1 briefing, which looks like this when printed: It went missing from our ship yard on Xeer five months ago and {mission 1 location hint} where {mission 1 location hint} is replaced by one of the names above..DETOK PHA \ Store A on the stack, so we can retrieve it later TAX \ Copy the token number from A into X TYA \ Store Y on the stack PHA LDA V \ Store V(1 0) on the stack PHA LDA V+1 PHA LDA #LO(TKN1) \ Set V to the low byte of TKN1 STA V LDA #HI(TKN1) \ Set A to the high byte of TKN1, so when we fall \ through into DTEN, V(1 0) gets set to the address of \ the TKN1 token table .DTEN STA V+1 \ Set the high byte of V(1 0) to A, so V(1 0) now points \ to the start of the token table to use LDY #0 \ First, we need to work our way through the table until \ we get to the token that we want to print. Tokens are \ delimited by #VE, and VE EOR VE = 0, so we work our \ way through the table in, counting #VE delimiters \ until we have passed X of them, at which point we jump \ down to DTL2 to do the actual printing. So first, we \ set a counter Y to point to the character offset as we \ scan through the table .DTL1 LDA (V),Y \ Load the character at offset Y in the token table, \ which is the next character from the token table BNE DT1 \ If the result is non-zero, then this is a character \ in a token rather than the delimiter (which is #VE), \ so jump to DT1 DEX \ We have just scanned the end of a token, so decrement \ X, which contains the token number we are looking for BEQ DTL2 \ If X has now reached zero then we have found the token \ we are looking for, so jump down to DTL2 to print it .DT1 INY \ Otherwise this isn't the token we are looking for, so \ increment the character pointer BNE DTL1 \ If Y hasn't just wrapped around to 0, loop back to \ DTL1 to process the next character INC V+1 \ We have just crossed into a new page, so increment \ V+1 so that V points to the start of the new page BNE DTL1 \ Jump back to DTL1 to process the next character (this \ BNE is effectively a JMP as V+1 won't reach zero \ before we reach the end of the token table) .DTL2 INY \ We just detected the delimiter byte before the token \ that we want to print, so increment the character \ pointer to point to the first character of the token, \ rather than the delimiter BNE P%+4 \ If Y hasn't just wrapped around to 0, skip the next \ instruction INC V+1 \ We have just crossed into a new page, so increment \ V+1 so that V points to the start of the new page LDA (V),Y \ Load the character at offset Y in the token table, \ which is the next character from the token we want to \ print BEQ DTEX \ If the result is zero, then this is the delimiter at \ the end of the token to print (which is #VE), so jump \ to DTEX to return from the subroutine, as we are done \ printing JSR DETOK2 \ Otherwise call DETOK2 to print this part of the token JMP DTL2 \ Jump back to DTL2 to process the next character .DTEX PLA \ Restore V(1 0) from the stack, so it is preserved STA V+1 \ through calls to this routine PLA STA V PLA \ Restore Y from the stack, so it is preserved through TAY \ calls to this routine PLA \ Restore A from the stack, so it is preserved through \ calls to this routine RTS \ Return from the subroutineName: DETOK [Show more] Type: Subroutine Category: Text Summary: Print an extended recursive token from the TKN1 token table Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * BRIS calls DETOK * BRP calls DETOK * CATS calls DETOK * confirm calls DETOK * cour_buy calls DETOK * cour_dock calls DETOK * DELT calls DETOK * DETOK2 calls DETOK * GTDRV calls DETOK * GTNMEW calls DETOK * HME2 calls DETOK * MT17 calls DETOK * PDESC calls DETOK * sell_yn calls DETOK * STATUS calls DETOK * SVE calls DETOK * TITLE calls DETOK * TT102 calls DETOK * DETOK3 calls via DTEN * write_msg3 calls via DTEN
Arguments: A The recursive token to be printed, in the range 1-255
Returns: A A is preserved Y Y is preserved V(1 0) V(1 0) is preserved
Other entry points: DTEN Print recursive token number X from the token table pointed to by (A V), used to print tokens from the RUTOK table via calls to DETOK3.DETOK2 CMP #32 \ If A < 32 then this is a jump token, so skip to DT3 to BCC DT3 \ process it BIT DTW3 \ If bit 7 of DTW3 is clear, then extended tokens are BPL DT8 \ enabled, so jump to DT8 to process them \ If we get there then this is not a jump token and \ extended tokens are not enabled, so we can call the \ standard text token routine at TT27 to print the token TAX \ Copy the token number from A into X TYA \ Store Y on the stack PHA LDA V \ Store V(1 0) on the stack PHA LDA V+1 PHA TXA \ Copy the token number from X back into A JSR TT27 \ Call TT27 to print the text token JMP DT7 \ Jump to DT7 to restore V(1 0) and Y from the stack and \ return from the subroutine .DT8 \ If we get here then this is not a jump token and \ extended tokens are enabled CMP #'[' \ If A < ASCII "[" (i.e. A <= ASCII "Z", or 90) then BCC DTS \ this is a printable ASCII character, so jump down to \ DTS to print it CMP #129 \ If A < 129, so A is in the range 91-128, jump down to BCC DT6 \ DT6 to print a randomised token from the MTIN table CMP #215 \ If A < 215, so A is in the range 129-214, jump to BCC DETOK \ DETOK as this is a recursive token, returning from the \ subroutine using a tail call \ If we get here then A >= 215, so this is a two-letter \ token from the extended TKN2/QQ16 table .msg_pairs SBC #215 \ Subtract 215 to get a token number in the range 0-12 \ (the C flag is set as we passed through the BCC above, \ so this subtraction is correct) ASL A \ Set A = A * 2, so it can be used as a pointer into the \ two-letter token tables at TKN2 and QQ16 PHA \ Store A on the stack, so we can restore it for the \ second letter below TAX \ Fetch the first letter of the two-letter token from LDA TKN2,X \ TKN2, which is at TKN2 + X JSR DTS \ Call DTS to print it PLA \ Restore A from the stack and transfer it into X TAX LDA TKN2+1,X \ Fetch the second letter of the two-letter token from \ TKN2, which is at TKN2 + X + 1, and fall through into \ DTS to print it .DTS CMP #'A' \ If A < ASCII "A", jump to DT9 to print this as ASCII BCC DT9 BIT DTW6 \ If bit 7 of DTW6 is set, then lower case has been BMI DT10 \ enabled by jump token 13, {lower case}, so jump to \ DT10 to apply the lower case and single cap masks BIT DTW2 \ If bit 7 of DTW2 is set, then we are not currently BMI DT5 \ printing a word, so jump to DT5 so we skip the setting \ of lower case in Sentence Case (which we only want to \ do when we are already printing a word) .DT10 ORA DTW1 \ Convert the character to lower case if DTW1 is \ %00100000 (i.e. if we are in {sentence case} mode) .DT5 AND DTW8 \ Convert the character to upper case if DTW8 is \ %11011111 (i.e. after a {single cap} token) .DT9 JMP DASC \ Jump to DASC to print the ASCII character in A, \ returning from the routine using a tail call .DT3 \ If we get here then the token number in A is in the \ range 1 to 32, so this is a jump token that should \ call the corresponding address in the jump table at \ JMTB TAX \ Copy the token number from A into X TYA \ Store Y on the stack PHA LDA V \ Store V(1 0) on the stack PHA LDA V+1 PHA TXA \ Copy the token number from X back into A ASL A \ Set A = A * 2, so it can be used as a pointer into the \ jump table at JMTB, though because the original range \ of values is 1-32, so the doubled range is 2-64, we \ need to take the offset into the jump table from \ JMTB-2 rather than JMTB TAX \ Copy the doubled token number from A into X LDA JMTB-2,X \ Set DTM(2 1) to the X-th address from the table at STA DTM+1 \ JTM-2, which modifies the JSR DASC instruction at LDA JMTB-1,X \ label DTM below so that it calls the subroutine at the STA DTM+2 \ relevant address from the JMTB table TXA \ Copy the doubled token number from X back into A LSR A \ Halve A to get the original token number .DTM JSR DASC \ Call the relevant JMTB subroutine, as this instruction \ will have been modified by the above to point to the \ relevant address .DT7 PLA \ Restore V(1 0) from the stack, so it is preserved STA V+1 \ through calls to this routine PLA STA V PLA \ Restore Y from the stack, so it is preserved through TAY \ calls to this routine RTS \ Return from the subroutine .DT6 \ If we get here then the token number in A is in the \ range 91-128, which means we print a randomly picked \ token from the token range given in the corresponding \ entry in the MTIN table STA SC \ Store the token number in SC TYA \ Store Y on the stack PHA LDA V \ Store V(1 0) on the stack PHA LDA V+1 PHA JSR DORND \ Set X to a random number TAX LDA #0 \ Set A to 0, so we can build a random number from 0 to \ 4 in A plus the C flag, with each number being equally \ likely CPX #51 \ Add 1 to A if X >= 51 ADC #0 CPX #102 \ Add 1 to A if X >= 102 ADC #0 CPX #153 \ Add 1 to A if X >= 153 ADC #0 CPX #204 \ Set the C flag if X >= 204 LDX SC \ Fetch the token number from SC into X, so X is now in \ the range 91-128 ADC MTIN-91,X \ Set A = MTIN-91 + token number (91-128) + random (0-4) \ = MTIN + token number (0-37) + random (0-4) JSR DETOK \ Call DETOK to print the extended recursive token in A JMP DT7 \ Jump to DT7 to restore V(1 0) and Y from the stack and \ return from the subroutine using a tail callName: DETOK2 [Show more] Type: Subroutine Category: Text Summary: Print an extended text token (1-255) Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * DETOK calls DETOK2 * PDESC calls DETOK2 * MT18 calls via DTS * write_card calls via DTS * write_card calls via DT3 * write_card calls via msg_pairs
Arguments: A The token to be printed (1-255)
Returns: A A is preserved Y Y is preserved V(1 0) V(1 0) is preserved
Other entry points: DTS Print a single letter in the correct case DT3 Print the jump token given in A (where A is in the range 0 to 31) msg_pairs Print the extended two-letter token in A (where A is in the range 215 to 255).MT1 LDA #%00000000 \ Set A = %00000000, so when we fall through into MT2, \ both DTW1 and DTW6 get set to %00000000 EQUB &2C \ Skip the next instruction by turning it into \ &2C &A9 &20, or BIT &20A9, which does nothing apart \ from affect the flagsName: MT1 [Show more] Type: Subroutine Category: Text Summary: Switch to ALL CAPS when printing extended tokens Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * controls calls MT1 * equip_data calls MT1 * JMTB calls MT1 * menu calls MT1 * ships_ag calls MT1 * write_card calls MT1
This routine sets the following: * DTW1 = %00000000 (do not change case to lower case) * DTW6 = %00000000 (lower case is not enabled).MT2 LDA #%00100000 \ Set DTW1 = %00100000 STA DTW1 LDA #00000000 \ Set DTW6 = %00000000 STA DTW6 RTS \ Return from the subroutineName: MT2 [Show more] Type: Subroutine Category: Text Summary: Switch to Sentence Case when printing extended tokens Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * controls calls MT2 * equip_data calls MT2 * JMTB calls MT2 * menu calls MT2 * TTX66 calls MT2 * write_card calls MT2
This routine sets the following: * DTW1 = %00100000 (apply lower case to the second letter of a word onwards) * DTW6 = %00000000 (lower case is not enabled).MT8 LDA #6 \ Move the text cursor to column 6 STA XC LDA #%11111111 \ Set all the bits in DTW2 STA DTW2 RTS \ Return from the subroutineName: MT8 [Show more] Type: Subroutine Category: Text Summary: Tab to column 6 and start a new word when printing extended tokens Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * JMTB calls MT8
This routine sets the following: * XC = 6 (tab to column 6) * DTW2 = %11111111 (we are not currently printing a word).MT9 LDA #1 \ Move the text cursor to column 1 STA XC JMP TT66 \ Jump to TT66 to clear the screen and set the current \ view type to 1, returning from the subroutine using a \ tail callName: MT9 [Show more] Type: Subroutine Category: Text Summary: Clear the screen and set the current view type to 1 Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * JMTB calls MT9
This routine sets the following: * XC = 1 (tab to column 1) before calling TT66 to clear the screen and set the view type to 1..MT13 LDA #%10000000 \ Set DTW6 = %10000000 STA DTW6 LDA #%00100000 \ Set DTW1 = %00100000 STA DTW1 RTS \ Return from the subroutineName: MT13 [Show more] Type: Subroutine Category: Text Summary: Switch to lower case when printing extended tokens Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * equip_data calls MT13 * JMTB calls MT13 * MT29 calls MT13
This routine sets the following: * DTW1 = %00100000 (apply lower case to the second letter of a word onwards) * DTW6 = %10000000 (lower case is enabled).MT6 LDA #%10000000 \ Set bit 7 of QQ17 to switch standard tokens to STA QQ17 \ Sentence Case .set_token LDA #%11111111 \ Set A = %11111111, so when we fall through into MT5, \ DTW3 gets set to %11111111 and calls to DETOK print \ standard tokens EQUB &2C \ Skip the next instruction by turning it into \ &2C &A9 &00, or BIT &00A9, which does nothing apart \ from affect the flagsName: MT6 [Show more] Type: Subroutine Category: Text Summary: Switch to standard tokens in Sentence Case Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * JMTB calls MT6
This routine sets the following: * QQ17 = %10000000 (set Sentence Case for standard tokens) * DTW3 = %11111111 (print standard tokens)
Other entry points: set_token Switch to standard tokens, keeping the current case.MT5 LDA #%00000000 \ Set DTW3 = %00000000, so that calls to DETOK print STA DTW3 \ extended tokens RTS \ Return from the subroutineName: MT5 [Show more] Type: Subroutine Category: Text Summary: Switch to extended tokens Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * JMTB calls MT5
This routine sets the following: * DTW3 = %00000000 (print extended tokens).MT14 LDA #%10000000 \ Set A = %10000000, so when we fall through into MT15, \ DTW4 gets set to %10000000 EQUB &2C \ Skip the next instruction by turning it into \ &2C &A9 &00, or BIT &00A9, which does nothing apart \ from affect the flagsName: MT14 [Show more] Type: Subroutine Category: Text Summary: Switch to justified text when printing extended tokens Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * HME2 calls MT14 * JMTB calls MT14 * PDESC calls MT14
This routine sets the following: * DTW4 = %10000000 (justify text, print buffer on carriage return) * DTW5 = 0 (reset line buffer size).MT15 LDA #0 \ Set DTW4 = %00000000 STA DTW4 ASL A \ Set DTW5 = 0 (even when we fall through from MT14 with STA DTW5 \ A set to %10000000) RTS \ Return from the subroutineName: MT15 [Show more] Type: Subroutine Category: Text Summary: Switch to left-aligned text when printing extended tokens Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * HME2 calls MT15 * JMTB calls MT15
This routine sets the following: * DTW4 = %00000000 (do not justify text, print buffer on carriage return) * DTW5 = 0 (reset line buffer size).MT17 LDA QQ17 \ Set QQ17 = %10111111 to switch to Sentence Case AND #%10111111 STA QQ17 LDA #3 \ Print control code 3 (selected system name) into the JSR TT27 \ line buffer LDX DTW5 \ Load the last character of the line buffer BUF into A LDA BUF-1,X \ (as DTW5 contains the buffer size, so character DTW5-1 \ is the last character in the buffer BUF) JSR VOWEL \ Test whether the character is a vowel, in which case \ this will set the C flag BCC MT171 \ If the character is not a vowel, skip the following \ instruction DEC DTW5 \ The character is a vowel, so decrement DTW5, which \ removes the last character from the line buffer (i.e. \ it removes the trailing vowel from the system name) .MT171 LDA #153 \ Print extended token 153 ("IAN"), returning from the JMP DETOK \ subroutine using a tail callName: MT17 [Show more] Type: Subroutine Category: Text Summary: Print the selected system's adjective, e.g. Lavian for Lave Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * JMTB calls MT17
The adjective for the current system is generated by taking the system name, removing the last character if it is a vowel, and adding "-ian" to the end, so: * Lave gives Lavian (as in "Lavian tree grub") * Leesti gives Leestian (as in "Leestian Evil Juice") This routine is called by jump token 17, {system name adjective}, and it can only be used when justified text is being printed - i.e. following jump token 14, {justify} - because the routine needs to use the line buffer to work..MT18 JSR MT19 \ Call MT19 to capitalise the next letter (i.e. set \ Sentence Case for this word only) JSR DORND \ Set A and X to random numbers and reduce A to a AND #3 \ random number in the range 0-3 TAY \ Copy the random number into Y, so we can use Y as a \ loop counter to print 1-4 words (i.e. Y+1 words) .MT18L JSR DORND \ Set A and X to random numbers and reduce A to an even AND #62 \ random number in the range 0-62 (as bit 0 of 62 is 0) TAX \ Copy the random number into X, so X contains the table \ offset of a random extended two-letter token from 0-31 \ which we can now use to pick a token from the combined \ tables at TKN2+2 and QQ16 (we intentionally exclude \ the first token in TKN2, which contains a newline) LDA TKN2+2,X \ Print the first letter of the token at TKN2+2 + X JSR DTS LDA TKN2+3,X \ Print the second letter of the token at TKN2+2 + X JSR DTS DEY \ Decrement the loop counter BPL MT18L \ Loop back to MT18L to print another two-letter token \ until we have printed Y+1 of them RTS \ Return from the subroutineName: MT18 [Show more] Type: Subroutine Category: Text Summary: Print a random 1-8 letter word in Sentence Case Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * JMTB calls MT18.MT19 LDA #%11011111 \ Set DTW8 = %11011111 STA DTW8 RTS \ Return from the subroutineName: MT19 [Show more] Type: Subroutine Category: Text Summary: Capitalise the next letter Deep dive: Extended text tokensContext: See this subroutine on its own page References: This subroutine is called as follows: * cmn calls MT19 * JMTB calls MT19 * MT18 calls MT19
This routine sets the following: * DTW8 = %11011111 (capitalise the next letter).VOWEL ORA #%00100000 \ Set bit 5 of the character to make it lower case CMP #'a' \ If the letter is a vowel, jump to VRTS to return from BEQ VRTS \ the subroutine with the C flag set (as the CMP will CMP #'e' \ set the C flag if the comparison is equal) BEQ VRTS CMP #'i' BEQ VRTS CMP #'o' BEQ VRTS CMP #'u' BEQ VRTS CLC \ The character is not a vowel, so clear the C flag .VRTS RTS \ Return from the subroutineName: VOWEL [Show more] Type: Subroutine Category: Text Summary: Test whether a character is a vowelContext: See this subroutine on its own page References: This subroutine is called as follows: * MT17 calls VOWEL
Arguments: A The character to be tested
Returns: C flag The C flag is set if the character is a vowel, otherwise it is clear.JMTB EQUW MT1 \ Token 1: Switch to ALL CAPS EQUW MT2 \ Token 2: Switch to Sentence Case EQUW TT27 \ Token 3: Print the selected system name EQUW TT27 \ Token 4: Print the commander's name EQUW MT5 \ Token 5: Switch to extended tokens EQUW MT6 \ Token 6: Switch to standard tokens, in Sentence Case EQUW DASC \ Token 7: Beep EQUW MT8 \ Token 8: Tab to column 6 EQUW MT9 \ Token 9: Clear screen, tab to column 1, view type = 1 EQUW DASC \ Token 10: Line feed EQUW NLIN4 \ Token 11: Draw box around title (line at pixel row 19) EQUW DASC \ Token 12: Carriage return EQUW MT13 \ Token 13: Switch to lower case EQUW MT14 \ Token 14: Switch to justified text EQUW MT15 \ Token 15: Switch to left-aligned text EQUW MT16 \ Token 16: Print the character in DTW7 (drive number) EQUW MT17 \ Token 17: Print system name adjective in Sentence Case EQUW MT18 \ Token 18: Randomly print 1 to 4 two-letter tokens EQUW MT19 \ Token 19: Capitalise first letter of next word only EQUW DASC \ Token 20: Unused EQUW CLYNS \ Token 21: Clear the bottom few lines of the space view EQUW PAUSE \ Token 22: Display ship and wait for key press EQUW MT23 \ Token 23: Move to row 10, white text, set lower case EQUW PAUSE2 \ Token 24: Wait for a key press EQUW BRIS \ Token 25: Show incoming message screen, wait 2 seconds EQUW MT26 \ Token 26: Fetch line input from keyboard (filename) EQUW MT27 \ Token 27: Print mission captain's name (217-219) EQUW MT28 \ Token 28: Print mission 1 location hint (220-221) EQUW MT29 \ Token 29: Column 6, white text, lower case in words EQUW DASC \ Token 30: Unused EQUW DASC \ Token 31: Unused EQUW DASC \ Token 32: UnusedName: JMTB [Show more] Type: Variable Category: Text Summary: The extended token table for jump tokens 1-32 (DETOK) Deep dive: Extended text tokensContext: See this variable on its own page References: This variable is used as follows: * DETOK2 uses JMTB.TKN2 EQUB 12, 10 \ Token 215 = {crlf} EQUS "AB" \ Token 216 EQUS "OU" \ Token 217 EQUS "SE" \ Token 218 EQUS "IT" \ Token 219 EQUS "IL" \ Token 220 EQUS "ET" \ Token 221 EQUS "ST" \ Token 222 EQUS "ON" \ Token 223 EQUS "LO" \ Token 224 EQUS "NU" \ Token 225 EQUS "TH" \ Token 226 EQUS "NO" \ Token 227Name: TKN2 [Show more] Type: Variable Category: Text Summary: The extended two-letter token lookup table Deep dive: Extended text tokensContext: See this variable on its own page References: This variable is used as follows: * DETOK2 uses TKN2 * MT18 uses TKN2
Two-letter token lookup table for extended tokens 215-227..QQ16 EQUS "AL" \ Token 128 EQUS "LE" \ Token 129 EQUS "XE" \ Token 130 EQUS "GE" \ Token 131 EQUS "ZA" \ Token 132 EQUS "CE" \ Token 133 EQUS "BI" \ Token 134 EQUS "SO" \ Token 135 EQUS "US" \ Token 136 EQUS "ES" \ Token 137 EQUS "AR" \ Token 138 EQUS "MA" \ Token 139 EQUS "IN" \ Token 140 EQUS "DI" \ Token 141 EQUS "RE" \ Token 142 EQUS "A?" \ Token 143 EQUS "ER" \ Token 144 EQUS "AT" \ Token 145 EQUS "EN" \ Token 146 EQUS "BE" \ Token 147 EQUS "RA" \ Token 148 EQUS "LA" \ Token 149 EQUS "VE" \ Token 150 EQUS "TI" \ Token 151 EQUS "ED" \ Token 152 EQUS "OR" \ Token 153 EQUS "QU" \ Token 154 EQUS "AN" \ Token 155 EQUS "TE" \ Token 156 EQUS "IS" \ Token 157 EQUS "RI" \ Token 158 EQUS "ON" \ Token 159Name: QQ16 [Show more] Type: Variable Category: Text Summary: The two-letter token lookup table Deep dive: Printing text tokensContext: See this variable on its own page References: This variable is used as follows: * TT43 uses QQ16
Two-letter token lookup table for tokens 128-159..MVEIT LDA INWK+31 \ If bit 5 of ship byte #31 is set, jump to MV3 as the AND #%00100000 \ ship is exploding, so we don't need to tidy its BNE MV3 \ orientation vectors LDA MCNT \ Fetch the main loop counter EOR XSAV \ Fetch the slot number of the ship we are moving, EOR AND #15 \ with the loop counter and apply mod 15 to the result. BNE MV3 \ The result will be zero when "counter mod 15" matches \ the slot number, so this makes sure we call TIDY 12 \ times every 16 main loop iterations, like this: \ \ Iteration 0, tidy the ship in slot 0 \ Iteration 1, tidy the ship in slot 1 \ Iteration 2, tidy the ship in slot 2 \ ... \ Iteration 11, tidy the ship in slot 11 \ Iteration 12, do nothing \ Iteration 13, do nothing \ Iteration 14, do nothing \ Iteration 15, do nothing \ Iteration 16, tidy the ship in slot 0 \ ... \ \ and so on JSR TIDY \ Call TIDY to tidy up the orientation vectors, to \ prevent the ship from getting elongated and out of \ shape due to the imprecise nature of trigonometry \ in assembly language .MV3 \ Fall through into part 7 (parts 2-6 are not required \ when we are docked)Name: MVEIT (Part 1 of 9) [Show more] Type: Subroutine Category: Moving Summary: Move current ship: Tidy the orientation vectors Deep dive: Program flow of the ship-moving routine Scheduling tasks with the main loop counterContext: See this subroutine on its own page References: This subroutine is called as follows: * BRIEF calls MVEIT * PAS1 calls MVEIT * ships_ag calls MVEIT * TITLE calls MVEIT * MVEIT_FLIGHT (Part 6 of 6) calls via MV3
This routine has multiple stages. This stage does the following: * Tidy the orientation vectors for one of the ship slots
Arguments: INWK The current ship/planet/sun's data block XSAV The slot number of the current ship/planet/sun TYPE The type of the current ship/planet/sun
Other entry points: MV3 Fall through into part 7 of MVEITLDY #9 \ Apply our pitch and roll rotations to the current JSR MVS4 \ ship's nosev vector LDY #15 \ Apply our pitch and roll rotations to the current JSR MVS4 \ ship's roofv vector LDY #21 \ Apply our pitch and roll rotations to the current JSR MVS4 \ ship's sidev vectorName: MVEIT (Part 7 of 9) [Show more] Type: Subroutine Category: Moving Summary: Move current ship: Rotate ship's orientation vectors by pitch/roll Deep dive: Orientation vectors Pitching and rollingContext: See this subroutine on its own page References: No direct references to this subroutine in this source file
This routine has multiple stages. This stage does the following: * Rotate the ship's orientation vectors according to our pitch and roll As with the previous step, this is all about moving the other ships rather than us (even though we are the one doing the moving). So we rotate the current ship's orientation vectors (which defines its orientation in space), by the angles we are "moving" the rest of the sky through (alpha and beta, our roll and pitch), so the ship appears to us to be stationary while we rotate.LDA INWK+30 \ Fetch the ship's pitch counter and extract the sign AND #%10000000 \ into RAT2 STA RAT2 LDA INWK+30 \ Fetch the ship's pitch counter and extract the value AND #%01111111 \ without the sign bit into A BEQ MV8 \ If the pitch counter is 0, then jump to MV8 to skip \ the following, as the ship is not pitching CMP #%01111111 \ If bits 0-6 are set in the pitch counter (i.e. the \ ship's pitch is not damping down), then the C flag \ will be set by this instruction SBC #0 \ Set A = A - 0 - (1 - C), so if we are damping then we \ reduce A by 1, otherwise it is unchanged ORA RAT2 \ Change bit 7 of A to the sign we saved in RAT2, so \ the updated pitch counter in A retains its sign STA INWK+30 \ Store the updated pitch counter in byte #30 LDX #15 \ Rotate (roofv_x, nosev_x) by a small angle (pitch) LDY #9 JSR MVS5 LDX #17 \ Rotate (roofv_y, nosev_y) by a small angle (pitch) LDY #11 JSR MVS5 LDX #19 \ Rotate (roofv_z, nosev_z) by a small angle (pitch) LDY #13 JSR MVS5 .MV8 LDA INWK+29 \ Fetch the ship's roll counter and extract the sign AND #%10000000 \ into RAT2 STA RAT2 LDA INWK+29 \ Fetch the ship's roll counter and extract the value AND #%01111111 \ without the sign bit into A BEQ MV5 \ If the roll counter is 0, then jump to MV5 to skip the \ following, as the ship is not rolling CMP #%01111111 \ If bits 0-6 are set in the roll counter (i.e. the \ ship's roll is not damping down), then the C flag \ will be set by this instruction SBC #0 \ Set A = A - 0 - (1 - C), so if we are damping then we \ reduce A by 1, otherwise it is unchanged ORA RAT2 \ Change bit 7 of A to the sign we saved in RAT2, so \ the updated roll counter in A retains its sign STA INWK+29 \ Store the updated pitch counter in byte #29 LDX #15 \ Rotate (roofv_x, sidev_x) by a small angle (roll) LDY #21 JSR MVS5 LDX #17 \ Rotate (roofv_y, sidev_y) by a small angle (roll) LDY #23 JSR MVS5 LDX #19 \ Rotate (roofv_z, sidev_z) by a small angle (roll) LDY #25 JSR MVS5Name: MVEIT (Part 8 of 9) [Show more] Type: Subroutine Category: Moving Summary: Move current ship: Rotate ship about itself by its own pitch/roll Deep dive: Orientation vectors Pitching and rolling by a fixed angleContext: See this subroutine on its own page References: No direct references to this subroutine in this source file
This routine has multiple stages. This stage does the following: * If the ship we are processing is rolling or pitching itself, rotate it and apply damping if required.MV5 BIT dockedp \ If bit 7 of dockedp is clear, then we are docked, so BPL l_noradar \ jump to l_noradar to return from the subroutine as the \ scanner is not being used LDA INWK+31 \ Fetch the ship's exploding/killed state from byte #31 AND #%10100000 \ If we are exploding or removing this ship then jump to BNE MVD1 \ MVD1 to remove it from the scanner permanently LDA INWK+31 \ Set bit 4 to keep the ship visible on the scanner ORA #%00010000 STA INWK+31 JMP SCAN \ Display the ship on the scanner, returning from the \ subroutine using a tail call .MVD1 LDA INWK+31 \ Clear bit 4 to hide the ship on the scanner AND #%11101111 STA INWK+31 .l_noradar RTS \ Return from the subroutineName: MVEIT (Part 9 of 9) [Show more] Type: Subroutine Category: Moving Summary: Move current ship: Redraw on scanner, if it hasn't been destroyedContext: See this subroutine on its own page References: No direct references to this subroutine in this source file
This routine has multiple stages. This stage does the following: * If the ship is exploding or being removed, hide it on the scanner * Otherwise redraw the ship on the scanner, now that it's been moved.MVS4 LDA ALPHA \ Set Q = alpha (the roll angle to rotate through) STA Q LDX INWK+2,Y \ Set (S R) = nosev_y STX R LDX INWK+3,Y STX S LDX INWK,Y \ These instructions have no effect as MAD overwrites STX P \ X and P when called, but they set X = P = nosev_x_lo LDA INWK+1,Y \ Set A = -nosev_x_hi EOR #%10000000 JSR MAD \ Set (A X) = Q * A + (S R) STA INWK+3,Y \ = alpha * -nosev_x_hi + nosev_y STX INWK+2,Y \ \ and store (A X) in nosev_y, so this does: \ \ nosev_y = nosev_y - alpha * nosev_x_hi STX P \ This instruction has no effect as MAD overwrites P, \ but it sets P = nosev_y_lo LDX INWK,Y \ Set (S R) = nosev_x STX R LDX INWK+1,Y STX S LDA INWK+3,Y \ Set A = nosev_y_hi JSR MAD \ Set (A X) = Q * A + (S R) STA INWK+1,Y \ = alpha * nosev_y_hi + nosev_x STX INWK,Y \ \ and store (A X) in nosev_x, so this does: \ \ nosev_x = nosev_x + alpha * nosev_y_hi STX P \ This instruction has no effect as MAD overwrites P, \ but it sets P = nosev_x_lo LDA BETA \ Set Q = beta (the pitch angle to rotate through) STA Q LDX INWK+2,Y \ Set (S R) = nosev_y STX R LDX INWK+3,Y STX S LDX INWK+4,Y STX P \ This instruction has no effect as MAD overwrites P, \ but it sets P = nosev_y LDA INWK+5,Y \ Set A = -nosev_z_hi EOR #%10000000 JSR MAD \ Set (A X) = Q * A + (S R) STA INWK+3,Y \ = beta * -nosev_z_hi + nosev_y STX INWK+2,Y \ \ and store (A X) in nosev_y, so this does: \ \ nosev_y = nosev_y - beta * nosev_z_hi STX P \ This instruction has no effect as MAD overwrites P, \ but it sets P = nosev_y_lo LDX INWK+4,Y \ Set (S R) = nosev_z STX R LDX INWK+5,Y STX S LDA INWK+3,Y \ Set A = nosev_y_hi JSR MAD \ Set (A X) = Q * A + (S R) STA INWK+5,Y \ = beta * nosev_y_hi + nosev_z STX INWK+4,Y \ \ and store (A X) in nosev_z, so this does: \ \ nosev_z = nosev_z + beta * nosev_y_hi RTS \ Return from the subroutineName: MVS4 [Show more] Type: Subroutine Category: Moving Summary: Apply pitch and roll to an orientation vector Deep dive: Orientation vectors Pitching and rollingContext: See this subroutine on its own page References: This subroutine is called as follows: * MVEIT (Part 7 of 9) calls MVS4
Apply pitch and roll angles alpha and beta to the orientation vector in Y. Specifically, this routine rotates a point (x, y, z) around the origin by pitch alpha and roll beta, using the small angle approximation to make the maths easier, and incorporating the Minsky circle algorithm to make the rotation more stable (though more elliptic). If that paragraph makes sense to you, then you should probably be writing this commentary! For the rest of us, see the associated deep dives.
Arguments: Y Determines which of the INWK orientation vectors to transform: * Y = 9 rotates nosev: (nosev_x, nosev_y, nosev_z) * Y = 15 rotates roofv: (roofv_x, roofv_y, roofv_z) * Y = 21 rotates sidev: (sidev_x, sidev_y, sidev_z).MVS5 LDA INWK+1,X \ Fetch roofv_x_hi, clear the sign bit, divide by 2 and AND #%01111111 \ store in T, so: LSR A \ STA T \ T = |roofv_x_hi| / 2 \ = |roofv_x| / 512 \ \ The above is true because: \ \ |roofv_x| = |roofv_x_hi| * 256 + roofv_x_lo \ \ so: \ \ |roofv_x| / 512 = |roofv_x_hi| * 256 / 512 \ + roofv_x_lo / 512 \ = |roofv_x_hi| / 2 LDA INWK,X \ Now we do the following subtraction: SEC \ SBC T \ (S R) = (roofv_x_hi roofv_x_lo) - |roofv_x| / 512 STA R \ = (1 - 1/512) * roofv_x \ \ by doing the low bytes first LDA INWK+1,X \ And then the high bytes (the high byte of the right SBC #0 \ side of the subtraction being 0) STA S LDA INWK,Y \ Set P = nosev_x_lo STA P LDA INWK+1,Y \ Fetch the sign of nosev_x_hi (bit 7) and store in T AND #%10000000 STA T LDA INWK+1,Y \ Fetch nosev_x_hi into A and clear the sign bit, so AND #%01111111 \ A = |nosev_x_hi| LSR A \ Set (A P) = (A P) / 16 ROR P \ = |nosev_x_hi nosev_x_lo| / 16 LSR A \ = |nosev_x| / 16 ROR P LSR A ROR P LSR A ROR P ORA T \ Set the sign of A to the sign in T (i.e. the sign of \ the original nosev_x), so now: \ \ (A P) = nosev_x / 16 EOR RAT2 \ Give it the sign as if we multiplied by the direction \ by the pitch or roll direction STX Q \ Store the value of X so it can be restored after the \ call to ADD JSR ADD \ (A X) = (A P) + (S R) \ = +/-nosev_x / 16 + (1 - 1/512) * roofv_x STA K+1 \ Set K(1 0) = (1 - 1/512) * roofv_x +/- nosev_x / 16 STX K LDX Q \ Restore the value of X from before the call to ADD LDA INWK+1,Y \ Fetch nosev_x_hi, clear the sign bit, divide by 2 and AND #%01111111 \ store in T, so: LSR A \ STA T \ T = |nosev_x_hi| / 2 \ = |nosev_x| / 512 LDA INWK,Y \ Now we do the following subtraction: SEC \ SBC T \ (S R) = (nosev_x_hi nosev_x_lo) - |nosev_x| / 512 STA R \ = (1 - 1/512) * nosev_x \ \ by doing the low bytes first LDA INWK+1,Y \ And then the high bytes (the high byte of the right SBC #0 \ side of the subtraction being 0) STA S LDA INWK,X \ Set P = roofv_x_lo STA P LDA INWK+1,X \ Fetch the sign of roofv_x_hi (bit 7) and store in T AND #%10000000 STA T LDA INWK+1,X \ Fetch roofv_x_hi into A and clear the sign bit, so AND #%01111111 \ A = |roofv_x_hi| LSR A \ Set (A P) = (A P) / 16 ROR P \ = |roofv_x_hi roofv_x_lo| / 16 LSR A \ = |roofv_x| / 16 ROR P LSR A ROR P LSR A ROR P ORA T \ Set the sign of A to the opposite sign to T (i.e. the EOR #%10000000 \ sign of the original -roofv_x), so now: \ \ (A P) = -roofv_x / 16 EOR RAT2 \ Give it the sign as if we multiplied by the direction \ by the pitch or roll direction STX Q \ Store the value of X so it can be restored after the \ call to ADD JSR ADD \ (A X) = (A P) + (S R) \ = -/+roofv_x / 16 + (1 - 1/512) * nosev_x STA INWK+1,Y \ Set nosev_x = (1-1/512) * nosev_x -/+ roofv_x / 16 STX INWK,Y LDX Q \ Restore the value of X from before the call to ADD LDA K \ Set roofv_x = K(1 0) STA INWK,X \ = (1-1/512) * roofv_x +/- nosev_x / 16 LDA K+1 STA INWK+1,X RTS \ Return from the subroutineName: MVS5 [Show more] Type: Subroutine Category: Moving Summary: Apply a 3.6 degree pitch or roll to an orientation vector Deep dive: Orientation vectors Pitching and rolling by a fixed angleContext: See this subroutine on its own page References: This subroutine is called as follows: * HAS1 calls MVS5 * MVEIT (Part 8 of 9) calls MVS5
Pitch or roll a ship by a small, fixed amount (1/16 radians, or 3.6 degrees), in a specified direction, by rotating the orientation vectors. The vectors to rotate are given in X and Y, and the direction of the rotation is given in RAT2. The calculation is as follows: * If the direction is positive: X = X * (1 - 1/512) + Y / 16 Y = Y * (1 - 1/512) - X / 16 * If the direction is negative: X = X * (1 - 1/512) - Y / 16 Y = Y * (1 - 1/512) + X / 16 So if X = 15 (roofv_x), Y = 21 (sidev_x) and RAT2 is positive, it does this: roofv_x = roofv_x * (1 - 1/512) + sidev_x / 16 sidev_x = sidev_x * (1 - 1/512) - roofv_x / 16
Arguments: X The first vector to rotate: * If X = 15, rotate roofv_x * If X = 17, rotate roofv_y * If X = 19, rotate roofv_z * If X = 21, rotate sidev_x * If X = 23, rotate sidev_y * If X = 25, rotate sidev_z Y The second vector to rotate: * If Y = 9, rotate nosev_x * If Y = 11, rotate nosev_y * If Y = 13, rotate nosev_z * If Y = 21, rotate sidev_x * If Y = 23, rotate sidev_y * If Y = 25, rotate sidev_z RAT2 The direction of the pitch or roll to perform, positive or negative (i.e. the sign of the roll or pitch counter in bit 7)PRINT "ELITE A" PRINT "Assembled at ", ~CODE% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_A% PRINT "S.2.ELTA ", ~CODE%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_A% \SAVE "3-assembled-output/2.ELTA.bin", CODE%, P%, LOAD%Save ELTA.bin
[X]
Subroutine ADD (category: Maths (Arithmetic))
Calculate (A X) = (A P) + (S R)
[X]
Subroutine BAY (category: Status)
Go to the docking bay (i.e. show the Status Mode screen)
[X]
Subroutine BRBR (category: Utility routines)
The standard BRKV handler for the game
[X]
Subroutine BRIEF (category: Missions)
Start mission 1 and show the mission briefing
[X]
Subroutine BRIEF2 (category: Missions)
Start mission 2
[X]
Subroutine BRIEF3 (category: Missions)
Receive the briefing and plans for mission 2
[X]
Subroutine BRIS (category: Missions)
Clear the screen, display "INCOMING MESSAGE" and wait for 2 seconds
[X]
Configuration variable BRKV
The address of the break vector
[X]
Subroutine CLYNS (category: Drawing the screen)
Clear the bottom three text rows of the mode 4 screen by sending a clr_line command to the I/O processor
[X]
Subroutine DEBRIEF (category: Missions)
Finish mission 1
[X]
Subroutine DEBRIEF2 (category: Missions)
Finish mission 2
[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 DETOK2 (category: Text)
Print an extended text token (1-255)
[X]
Subroutine DORND (category: Maths (Arithmetic))
Generate random numbers
[X]
Variable DTW1 (category: Text)
A mask for applying the lower case part of Sentence Case to extended text tokens
[X]
Variable DTW2 (category: Text)
A flag that indicates whether we are currently printing a word
[X]
Variable DTW3 (category: Text)
A flag for switching between standard and extended text tokens
[X]
Variable DTW4 (category: Text)
Flags that govern how justified extended text tokens are printed
[X]
Variable DTW5 (category: Text)
The size of the justified text buffer at BUF
[X]
Variable DTW6 (category: Text)
A flag to denote whether printing in lower case is enabled for extended text tokens
[X]
Variable DTW8 (category: Text)
A mask for capitalising the next letter in an extended text token
[X]
Subroutine HALL (category: Ship hangar)
Draw the ships in the ship hangar, then draw the hangar
[X]
Subroutine HFS1 (category: Drawing circles)
Draw the launch or hyperspace tunnel
[X]
Variable JMTB (category: Text)
The extended token table for jump tokens 1-32 (DETOK)
[X]
Subroutine MAD (category: Maths (Arithmetic))
Calculate (A X) = Q * A + (S R)
[X]
Subroutine MT1 (category: Text)
Switch to ALL CAPS when printing extended tokens
[X]
Subroutine MT13 (category: Text)
Switch to lower case when printing extended tokens
[X]
Subroutine MT14 (category: Text)
Switch to justified text when printing extended tokens
[X]
Subroutine MT15 (category: Text)
Switch to left-aligned text when printing extended tokens
[X]
Subroutine MT16 (category: Text)
Print the character in variable DTW7
[X]
Subroutine MT17 (category: Text)
Print the selected system's adjective, e.g. Lavian for Lave
[X]
Subroutine MT18 (category: Text)
Print a random 1-8 letter word in Sentence Case
[X]
Subroutine MT19 (category: Text)
Capitalise the next letter
[X]
Subroutine MT2 (category: Text)
Switch to Sentence Case when printing extended tokens
[X]
Subroutine MT23 (category: Text)
Move to row 10, switch to white text, and switch to lower case when printing extended tokens
[X]
Subroutine MT26 (category: Text)
Fetch a line of text from the keyboard
[X]
Subroutine MT27 (category: Text)
Print the captain's name during mission briefings
[X]
Subroutine MT28 (category: Text)
Print the location hint during the mission 1 briefing
[X]
Subroutine MT29 (category: Text)
Move to row 6, switch to white text, and switch to lower case when printing extended tokens
[X]
Subroutine MT5 (category: Text)
Switch to extended tokens
[X]
Subroutine MT6 (category: Text)
Switch to standard tokens in Sentence Case
[X]
Subroutine MT8 (category: Text)
Tab to column 6 and start a new word when printing extended tokens
[X]
Subroutine MT9 (category: Text)
Clear the screen and set the current view type to 1
[X]
Variable MTIN (category: Text)
Lookup table for random tokens in the extended token table (0-37)
[X]
Entry point MV3 in subroutine MVEIT (Part 1 of 9) (category: Moving)
Fall through into part 7 of MVEIT
[X]
Label MV5 in subroutine MVEIT (Part 9 of 9)
[X]
Label MV8 in subroutine MVEIT (Part 8 of 9)
[X]
Label MVD1 in subroutine MVEIT (Part 9 of 9)
[X]
Subroutine MVS4 (category: Moving)
Apply pitch and roll to an orientation vector
[X]
Subroutine MVS5 (category: Moving)
Apply a 3.6 degree pitch or roll to an orientation vector
[X]
Subroutine NLIN4 (category: Drawing lines)
Draw a horizontal line at pixel row 19 to box in a title
[X]
Subroutine PAUSE (category: Missions)
Display a rotating ship, waiting until a key is pressed, then remove the ship from the screen
[X]
Subroutine PAUSE2 (category: Keyboard)
Wait until a key is pressed, ignoring any existing key press
[X]
Configuration variable Q%
Set Q% to TRUE to max out the default commander, FALSE for the standard default commander
[X]
Subroutine RES2 (category: Start and end)
Reset a number of flight variables and workspaces
[X]
Variable RUTOK (category: Text)
The second extended token table for recursive tokens 0-26 (DETOK3)
[X]
Subroutine SCAN (category: Dashboard)
Display the current ship on the scanner by sending a draw_tail command to the I/O processor
[X]
Subroutine SCRAM (category: Loader)
Set the save_lock variable and break handler
[X]
Subroutine TIDY (category: Maths (Geometry))
Orthonormalise the orientation vectors for a ship
[X]
Variable TKN1 (category: Text)
The first extended token table for recursive tokens 0-255 (DETOK)
[X]
Variable TKN2 (category: Text)
The extended two-letter token lookup table
[X]
Subroutine TT27 (category: Text)
Print a text token
[X]
Subroutine TT66 (category: Drawing the screen)
Clear the screen and set the current view type
[X]
Subroutine VOWEL (category: Text)
Test whether a character is a vowel
[X]
Subroutine cour_dock (category: Missions)
Update the current special cargo delivery mission on docking
[X]
Label l_noradar in subroutine MVEIT (Part 9 of 9)
[X]
Variable msg_3 (category: Text)
The second extended token table for recursive tokens 0-255 (write_msg3)
[X]
Configuration variable save_lock
This flag indicates whether we should be asking for confirmation before saving or loading a commander file
[X]
Configuration variable tube_r1d
The Tube's memory-mapped FIFO 1 data register
[X]
Configuration variable tube_r1s
The Tube's memory-mapped FIFO 1 status register
[X]
Configuration variable tube_r2d
The Tube's memory-mapped FIFO 2 data register
[X]
Configuration variable tube_r2s
The Tube's memory-mapped FIFO 2 status register
[X]
Subroutine tube_read (category: Tube)
As the parasite, fetch a byte that's been sent over the Tube from the I/O processor
[X]
Subroutine tube_write (category: Tube)
As the parasite, send a byte across the Tube to the I/O processor