Repository: markmoxon/elite-beebasm Branch: main Commit: a8bc28d22ed9 Files: 91 Total size: 2.3 MB Directory structure: gitextract_xn5smrlz/ ├── .gitattributes ├── .gitignore ├── 1-source-files/ │ ├── README.md │ ├── basic-programs/ │ │ └── README.md │ ├── boot-files/ │ │ └── README.md │ ├── images/ │ │ └── README.md │ ├── main-sources/ │ │ ├── README.md │ │ ├── elite-bcfs.asm │ │ ├── elite-build-options.asm │ │ ├── elite-disc.asm │ │ ├── elite-loader.asm │ │ ├── elite-readme.asm │ │ └── elite-source.asm │ └── original-sources/ │ ├── $.DEFEDIT.inf │ ├── $.DEFEDIT.txt │ ├── $.DEFGEN.inf │ ├── $.DEFGEN.txt │ ├── $.DEFTRAN.inf │ ├── $.DEFTRAN.txt │ ├── $.DIALGEN.inf │ ├── $.DIALGEN.txt │ ├── $.ELITEA.inf │ ├── $.ELITEA.txt │ ├── $.ELITEB.inf │ ├── $.ELITEB.txt │ ├── $.ELITEC.inf │ ├── $.ELITEC.txt │ ├── $.ELITED.inf │ ├── $.ELITED.txt │ ├── $.ELITEE.inf │ ├── $.ELITEE.txt │ ├── $.ELITEF.inf │ ├── $.ELITEF.txt │ ├── $.ELITEG.inf │ ├── $.ELITEG.txt │ ├── $.ELITES.inf │ ├── $.ELITES.txt │ ├── $.FINDSC2.inf │ ├── $.FINDSC2.txt │ ├── $.GENTOK.inf │ ├── $.GENTOK.txt │ ├── $.GETBIT.inf │ ├── $.GETBIT.txt │ ├── $.MAKER.inf │ ├── $.MAKER.txt │ ├── $.SBLOCK.inf │ ├── $.SBLOCK.txt │ ├── $.SFTPROT.inf │ ├── $.SFTPROT.txt │ ├── $.SHPPRTE.inf │ ├── $.SHPPRTE.txt │ ├── $.TOKPRI.inf │ ├── $.TOKPRI.txt │ ├── $.UNPACK.inf │ ├── $.UNPACK.txt │ ├── A.GENTOK.inf │ ├── A.GENTOK.txt │ ├── O.ELITED.inf │ ├── O.ELITED.txt │ ├── README.md │ ├── S.BCFS.inf │ ├── S.BCFS.txt │ ├── S.GENTOK.inf │ ├── S.GENTOK.txt │ ├── S.STEST.inf │ ├── S.STEST.txt │ └── text-sources/ │ ├── ELITEA.txt │ ├── ELITEB.txt │ ├── ELITEC.txt │ ├── ELITED.txt │ ├── ELITEE.txt │ ├── ELITEF.txt │ └── ELITEG.txt ├── 2-build-files/ │ ├── README.md │ ├── crc32.py │ ├── elite-checksum.py │ ├── elite-decrypt.py │ ├── mktibet-0.3.php │ └── tibetuef-0.8.php ├── 3-assembled-output/ │ ├── README.md │ ├── README.txt │ └── compile.txt ├── 4-reference-binaries/ │ └── README.md ├── 5-compiled-game-discs/ │ ├── README.md │ ├── elite-cassette-from-source-disc.ssd │ ├── elite-cassette-from-text-sources.ssd │ ├── elite-cassette-sth.ssd │ └── elite-cassette-sth.uef ├── Makefile ├── README.md └── make.bat ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization * text=auto # Custom for Visual Studio *.cs diff=csharp # Standard to msysgit *.doc diff=astextplain *.DOC diff=astextplain *.docx diff=astextplain *.DOCX diff=astextplain *.dot diff=astextplain *.DOT diff=astextplain *.pdf diff=astextplain *.PDF diff=astextplain *.rtf diff=astextplain *.RTF diff=astextplain ================================================ FILE: .gitignore ================================================ # Windows thumbnail cache files Thumbs.db ehthumbs.db ehthumbs_vista.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp # Windows shortcuts *.lnk # IDE files .vscode/ *.code-workspace run.bat ================================================ FILE: 1-source-files/README.md ================================================ # Source files for the BBC Micro cassette version of Elite This folder contains the source files for the BBC Micro cassette version of Elite. * [basic-programs](basic-programs) contains any BASIC programs to be included on the final game disc * [boot-files](boot-files) contains any !BOOT files to be included on the final game disc * [images](images) contains the image binaries for the title screen and dashboard * [main-sources](main-sources) contains the annotated source code * [original-sources](original-sources) contains the original source code from Ian Bell's personal website --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 1-source-files/basic-programs/README.md ================================================ # BASIC programs for the BBC Micro cassette version of Elite This folder contains the BASIC programs from the original sources for the BBC Micro cassette version of Elite on Ian Bell's personal website. * [$.ELITE.bin]($.ELITE.bin) is the mode 7 loader program for the version that loads from disc, with an added command to insert a key into the keyboard buffer, so the Elite loader doesn't wait for a key press * [$.ELITE-cassette.bin]($.ELITE-cassette.bin) is the mode 7 loader program for the original cassette version * [$.ELITE-disc.bin]($.ELITE-disc.bin) is the mode 7 loader program for the version that loads from disc --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 1-source-files/boot-files/README.md ================================================ # Boot files for the BBC Micro cassette version of Elite This folder contains the boot file from the original sources for the BBC Micro cassette version of Elite on Ian Bell's personal website. * [$.!BOOT.bin]($.!BOOT.bin) is the original boot file from the game disc --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 1-source-files/images/README.md ================================================ # Image binaries for the BBC Micro cassette version of Elite This folder contains the image binaries from the original sources for the BBC Micro cassette version of Elite on Ian Bell's personal website. * [P.(C)ASFT.bin](P.(C)ASFT.bin) is the "(c) ACORNSOFT 1984" image for the bottom of the title screen * [P.A-SOFT.bin](P.A-SOFT.bin) is the "ACORNSOFT" image for the very top of the title screen * [P.DIALS.bin](P.DIALS2P.bin) is the dashboard image * [P.ELITE.bin](P.ELITE.bin) is the "ELITE" image for the title screen --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 1-source-files/main-sources/README.md ================================================ # Annotated source code for the BBC Micro cassette version of Elite This folder contains the annotated source code for the BBC Micro cassette version of Elite. * Main source files: * [elite-source.asm](elite-source.asm) contains the main source for the game * [elite-bcfs.asm](elite-bcfs.asm) contains the Big Code File source, which concatenates individually assembled binaries into the final game binary * Other source files: * [elite-loader.asm](elite-loader.asm) contains the source for the loader * [elite-disc.asm](elite-disc.asm) builds the SSD disc image from the assembled binaries and other source files * [elite-readme.asm](elite-readme.asm) generates a README file for inclusion on the SSD disc image * Files that are generated during the build process: * [elite-build-options.asm](elite-build-options.asm) stores the make options in BeebAsm format so they can be included in the assembly process --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 1-source-files/main-sources/elite-bcfs.asm ================================================ \ ****************************************************************************** \ \ BBC MICRO CASSETTE ELITE BIG CODE FILE SOURCE \ \ BBC Micro cassette Elite was written by Ian Bell and David Braben and is \ copyright Acornsoft 1984 \ \ The code in this file is identical to the source discs released on Ian Bell's \ personal website at http://www.elitehomepage.org/ (it's just been reformatted \ to be more readable) \ \ The commentary is copyright Mark Moxon, and any misunderstandings or mistakes \ in the documentation are entirely my fault \ \ The terminology and notations used in this commentary are explained at \ https://elite.bbcelite.com/terminology \ \ The deep dive articles referred to in this commentary can be found at \ https://elite.bbcelite.com/deep_dives \ \ ------------------------------------------------------------------------------ \ \ This source file contains code to produce the Big Code File for BBC Micro \ cassette Elite. The Big Code File comprises the game code and the ship \ blueprints. \ \ ------------------------------------------------------------------------------ \ \ This source file produces the following binary files: \ \ * ELTcode.unprot.bin \ * ELThead.bin \ \ after reading in the following files: \ \ * ELTA.bin \ * ELTB.bin \ * ELTC.bin \ * ELTD.bin \ * ELTE.bin \ * ELTF.bin \ * ELTG.bin \ * SHIPS.bin \ \ ****************************************************************************** INCLUDE "1-source-files/main-sources/elite-build-options.asm" _SOURCE_DISC = (_VARIANT = 1) _TEXT_SOURCES = (_VARIANT = 2) _STH_CASSETTE = (_VARIANT = 3) GUARD &8000 \ Guard against assembling over MOS memory \ ****************************************************************************** \ \ Configuration variables \ \ ****************************************************************************** CODE% = &0F40 \ CODE% is set to the location that the main game code \ gets moved to after it is loaded LOAD% = &1128 \ LOAD% points to the start of the actual game code, \ after the &28 bytes of header code that are inserted \ below \ ****************************************************************************** \ \ Name: ZP \ Type: Workspace \ Address: &0070 to &0071 \ Category: Workspaces \ Summary: Important variables used by the loader \ \ ****************************************************************************** ORG &0070 \ Set the assembly address to &0070 .ZP SKIP 2 \ Stores addresses used for moving content around \ ****************************************************************************** \ \ Load the compiled binaries to create the Big Code File \ \ ****************************************************************************** ORG &1100 \ The load address of the main game code file ("ELTcode" \ for loading from disc, "ELITEcode" for loading from \ tape) \ ****************************************************************************** \ \ Name: LBL \ Type: Subroutine \ Category: Copy protection \ Summary: Checksum the two pages of code that were copied from UU% to LE% \ \ ------------------------------------------------------------------------------ \ \ This routine is called at LBL+1 from the CHECKER routine in the loader code in \ elite-loader.asm. It calculates the checksum of the first two pages of the \ loader code that was copied from UU% to LE% by part 3 of the loader, and \ checks the result against the result in the first byte of the LE% block, \ CHECKbyt, at address &0B00. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ LBL+2 Contains an RTS \ \ ****************************************************************************** .LBL EQUB &6C \ This value is decremented by the tape loading routine \ in the loader, in IRQ1. During loading this value gets \ decremented down to &6C, and this new value is then \ included in the checksum calculation for the MAINSUM \ checksum in the CHECKER routine (the value is set to \ &6C here as the tape protection is disabled) LDX #&60 \ Set X = &60. This value of X isn't used, it's just a \ set up for the RTS call below, where we jump to LBL+2 \ to perform an RTS, as the opcode for RTS is &60 \ We now run a checksum on the block of memory from \ &0B01 to &0CFF, which is the UU% routine from the \ loader LDA #&B \ Set ZP(1 0) = &0B00, to point to the start of the code STA ZP+1 \ we want to checksum LDY #0 \ Set Y = 0 to count through each byte within each page STY ZP TYA \ Set A = 0 for building the checksum INY \ Increment Y to 1 .CHK3 CLC \ Add the Y-th byte of the game code to A ADC (ZP),Y INY \ Increment the counter to point to the next byte BNE CHK3 \ Loop back for the next byte until we have finished \ adding up this page INC ZP+1 \ Increment the high byte of ZP(1 0) to point to the \ next page .CHK4 CLC \ Add the Y-th byte of this page to the checksum in A ADC (ZP),Y INY \ Increment the counter for this page BPL CHK4 \ Loop back for the next byte until we have finished \ adding up this second page CMP &0B00 \ Compare the result to the contents of CHECKbyt in the \ loader code at elite-loader.asm. This value gets set \ by elite-checksum.py BEQ LBL+2 \ If the checksums match, jump to LBL+2, which contains \ an RTS \ Otherwise the checksum just failed, so we reset the \ machine LDA #%01111111 \ Set 6522 System VIA interrupt enable register IER STA &FE4E \ (SHEILA &4E) bits 0-6 (i.e. disable all hardware \ interrupts from the System VIA) JMP (&FFFC) \ Jump to the address in &FFFC to reset the machine .elitea PRINT "elitea = ", ~P% INCBIN "3-assembled-output/ELTA.bin" .eliteb PRINT "eliteb = ", ~P% INCBIN "3-assembled-output/ELTB.bin" .elitec PRINT "elitec = ", ~P% INCBIN "3-assembled-output/ELTC.bin" .elited PRINT "elited = ", ~P% INCBIN "3-assembled-output/ELTD.bin" .elitee PRINT "elitee = ", ~P% INCBIN "3-assembled-output/ELTE.bin" .elitef PRINT "elitef = ", ~P% INCBIN "3-assembled-output/ELTF.bin" .eliteg PRINT "eliteg = ", ~P% INCBIN "3-assembled-output/ELTG.bin" .checksum0 PRINT "checksum0 = ", ~P% IF _SOURCE_DISC OR _TEXT_SOURCES SKIP 1 \ We skip this byte so we can insert the checksum later \ in elite-checksum.py ELIF _STH_CASSETTE EQUB &20 \ We skip this byte so we can insert the checksum later \ in elite-checksum.py; it contains workspace noise in \ the Stairway to Hell variant ENDIF .ships PRINT "ships = ", ~P% INCBIN "3-assembled-output/SHIPS.bin" .end \ ****************************************************************************** \ \ Save ELTcode.unprot.bin and ELThead.bin \ \ ****************************************************************************** PRINT "P% = ", ~P% PRINT "S.ELTcode 1100 ", ~(LOAD% + &6000 - CODE%), " ", ~LOAD%, " ", ~LOAD% SAVE "3-assembled-output/ELTcode.unprot.bin", &1100, (LOAD% + &6000 - CODE%), LOAD% SAVE "3-assembled-output/ELThead.bin", &1100, elitea, &1100 ================================================ FILE: 1-source-files/main-sources/elite-build-options.asm ================================================ _VERSION=1 _VARIANT=3 _REMOVE_CHECKSUMS=FALSE _MAX_COMMANDER=FALSE _DISC=TRUE _PROT=FALSE ================================================ FILE: 1-source-files/main-sources/elite-disc.asm ================================================ \ ****************************************************************************** \ \ BBC MICRO CASSETTE ELITE DISC IMAGE SCRIPT \ \ BBC Micro cassette Elite was written by Ian Bell and David Braben and is \ copyright Acornsoft 1984 \ \ The code in this file is identical to the source discs released on Ian Bell's \ personal website at http://www.elitehomepage.org/ (it's just been reformatted \ to be more readable) \ \ The commentary is copyright Mark Moxon, and any misunderstandings or mistakes \ in the documentation are entirely my fault \ \ The terminology and notations used in this commentary are explained at \ https://elite.bbcelite.com/terminology \ \ The deep dive articles referred to in this commentary can be found at \ https://elite.bbcelite.com/deep_dives \ \ ------------------------------------------------------------------------------ \ \ This source file produces an SSD disc image for BBC Micro cassette Elite. \ \ ------------------------------------------------------------------------------ \ \ This source file produces one of the following SSD disc images, depending on \ which release is being built: \ \ * elite-cassette-sth.ssd \ * elite-cassette-from-source-disc.ssd \ * elite-cassette-from-text-sources.ssd \ \ This can be loaded into an emulator or a real BBC Micro. \ \ ****************************************************************************** INCLUDE "1-source-files/main-sources/elite-build-options.asm" _SOURCE_DISC = (_VARIANT = 1) _TEXT_SOURCES = (_VARIANT = 2) _STH_CASSETTE = (_VARIANT = 3) IF _DISC PUTFILE "1-source-files/boot-files/$.!BOOT.bin", "!BOOT", &FFFFFF, &FFFFFF PUTFILE "1-source-files/basic-programs/$.ELITE.bin", "ELITE", &FF1900, &FF8023 PUTFILE "3-assembled-output/ELITE.bin", "ELTdata", &FF1100, &FF2000 PUTFILE "3-assembled-output/ELTcode.bin", "ELTcode", &FF1128, &FF1128 ELSE PUTFILE "1-source-files/boot-files/$.!BOOT.bin", "!BOOT", &FFFFFF, &FFFFFF PUTFILE "1-source-files/basic-programs/$.ELITE-cassette.bin", "ELITE", &FF1900, &FF8023 \PUTFILE "3-assembled-output/ELITE.bin", "ELITEdata", &FF0E00, &FF1D00 \PUTFILE "3-assembled-output/ELTcode.bin", "ELITEcode", &000E00, &000132 PUTFILE "3-assembled-output/ELITE.bin", "ELITEda", &FF0E00, &FF1D00 PUTFILE "3-assembled-output/ELTcode.bin", "ELITEco", &000E00, &000132 ENDIF PUTFILE "3-assembled-output/README.txt", "README", &FFFFFF, &FFFFFF ================================================ FILE: 1-source-files/main-sources/elite-loader.asm ================================================ \ ****************************************************************************** \ \ BBC MICRO CASSETTE ELITE GAME LOADER SOURCE \ \ BBC Micro cassette Elite was written by Ian Bell and David Braben and is \ copyright Acornsoft 1984 \ \ The code in this file is identical to the source discs released on Ian Bell's \ personal website at http://www.elitehomepage.org/ (it's just been reformatted \ to be more readable) \ \ The commentary is copyright Mark Moxon, and any misunderstandings or mistakes \ in the documentation are entirely my fault \ \ The terminology and notations used in this commentary are explained at \ https://elite.bbcelite.com/terminology \ \ The deep dive articles referred to in this commentary can be found at \ https://elite.bbcelite.com/deep_dives \ \ ------------------------------------------------------------------------------ \ \ This source file contains the game loader for BBC Micro cassette Elite. \ \ ------------------------------------------------------------------------------ \ \ This source file produces the following binary file: \ \ * ELITE.unprot.bin \ \ after reading in the following files: \ \ * P.A-SOFT.bin \ * P.(C)ASFT.bin \ * DIALS.bin \ * P.ELITE.bin \ * PYTHON.bin \ * WORDS9.bin \ \ ****************************************************************************** INCLUDE "1-source-files/main-sources/elite-build-options.asm" _SOURCE_DISC = (_VARIANT = 1) _TEXT_SOURCES = (_VARIANT = 2) _STH_CASSETTE = (_VARIANT = 3) GUARD &6000 \ Guard against assembling over screen memory \ ****************************************************************************** \ \ Configuration variables \ \ ****************************************************************************** DISC = _DISC \ Set to TRUE to load the code above DFS and relocate \ down, so we can load the cassette version from disc, \ or set to FALSE to load the code as if it were from a \ cassette PROT = _PROT \ Set to TRUE to enable the tape protection code, or set \ to FALSE to disable the code (for TRUE, the file must \ be saved to tape with the block data corrupted, so you \ probably want to leave this as FALSE) IF DISC CODE% = &1100 \ CODE% is set to the assembly address of the loader \ code file that we assemble in this file ("ELITE"), \ which is at the lowest DFS page value of &1100 for the \ version that loads from disc LOAD% = &1100 \ LOAD% is the load address of the main game code file \ ("ELTcode" for loading from disc, "ELITEcode" for \ loading from tape) L% = &1128 \ L% points to the start of the actual game code from \ elite-source.asm, after the &28 bytes of header code \ that are inserted by elite-bcfs.asm ELSE CODE% = &0E00 \ CODE% is set to the assembly address of the loader \ code file that we assemble in this file ("ELITE"), \ which is at the standard &0E00 address for the version \ that loads from cassette LOAD% = &0F1F \ LOAD% is the load address of the main game code file \ ("ELTcode" for loading from disc, "ELITEcode" for \ loading from tape) L% = &0F47 \ L% points to the start of the actual game code from \ elite-source.asm, after the &28 bytes of header code \ that are inserted by elite-bcfs.asm ENDIF LEN1 = 15 \ Size of the BEGIN% routine that gets pushed onto the \ stack and executed there LEN2 = 18 \ Size of the MVDL routine that gets pushed onto the \ stack and executed there LEN = LEN1 + LEN2 \ Total number of bytes that get pushed on the stack for \ execution there (33) VSCAN = 57-1 \ Defines the split position in the split-screen mode LE% = &0B00 \ LE% is the address to which the code from UU% onwards \ is copied in part 3. It contains: \ \ * ENTRY2, the entry point for the second block of \ loader code \ \ * IRQ1, the interrupt routine for the split-screen \ mode \ \ * BLOCK, which by this point has already been put \ on the stack by this point \ \ * The variables used by the above NETV = &0224 \ The NETV vector that we intercept as part of the copy \ protection IRQ1V = &0204 \ The IRQ1V vector that we intercept to implement the \ split-screen mode OSPRNT = &0234 \ The address for the OSPRNT vector C% = &0F40 \ C% is set to the location that the main game code gets \ moved to after it is loaded S% = C% \ S% points to the entry point for the main game code IF _SOURCE_DISC D% = &563A \ D% is set to the address of the byte after the end of \ the code, i.e. the byte after checksum0 at XX21 ELIF _TEXT_SOURCES D% = &5638 \ D% is set to the address of the byte after the end of \ the code, i.e. the byte after checksum0 at XX21 ELIF _STH_CASSETTE D% = &563A \ D% is set to the address of the byte after the end of \ the code, i.e. the byte after checksum0 at XX21 ENDIF LC% = &6000 - C% \ LC% is set to the maximum size of the main game code \ (as the code starts at C% and screen memory starts \ at &6000) N% = 67 \ N% is set to the number of bytes in the VDU table, so \ we can loop through them in part 2 below SVN = &7FFD \ SVN is where we store the "saving in progress" flag, \ and it matches the location in elite-source.asm VEC = &7FFE \ VEC is where we store the original value of the IRQ1 \ vector, and it matches the value in elite-source.asm VIA = &FE00 \ Memory-mapped space for accessing internal hardware, \ such as the video ULA, 6845 CRTC and 6522 VIAs (also \ known as SHEILA) OSWRCH = &FFEE \ The address for the OSWRCH routine OSBYTE = &FFF4 \ The address for the OSBYTE routine OSWORD = &FFF1 \ The address for the OSWORD routine \ ****************************************************************************** \ \ Name: ZP \ Type: Workspace \ Address: &0004 to &0005 and &0070 to &0086 \ Category: Workspaces \ Summary: Important variables used by the loader \ \ ****************************************************************************** ORG &0004 \ Set the assembly address to &0004 .TRTB% SKIP 2 \ Contains the address of the keyboard translation \ table, which is used to translate internal key \ numbers to ASCII ORG &0070 \ Set the assembly address to &0070 .ZP SKIP 2 \ Stores addresses used for moving content around .P SKIP 1 \ Temporary storage, used in a number of places .Q SKIP 1 \ Temporary storage, used in a number of places .YY SKIP 1 \ Temporary storage, used in a number of places .T SKIP 1 \ Temporary storage, used in a number of places .SC SKIP 1 \ Screen address (low byte) \ \ Elite draws on-screen by poking bytes directly into \ screen memory, and SC(1 0) is typically set to the \ address of the character block containing the pixel \ we want to draw .SCH SKIP 1 \ Screen address (high byte) .BLPTR SKIP 2 \ Gets set to &03CA as part of the obfuscation code .V219 SKIP 2 \ Gets set to &0218 as part of the obfuscation code SKIP 4 \ These bytes appear to be unused .K3 SKIP 1 \ Temporary storage, used in a number of places .BLCNT SKIP 2 \ Stores the tape loader block count as part of the copy \ protection code in IRQ1 .BLN SKIP 2 \ Gets set to &03C6 as part of the obfuscation code .EXCN SKIP 2 \ Gets set to &03C2 as part of the obfuscation code \ ****************************************************************************** \ \ ELITE LOADER \ \ ****************************************************************************** ORG CODE% \ Set the assembly address to CODE% \ ****************************************************************************** \ \ Name: Elite loader (Part 1 of 6) \ Type: Subroutine \ Category: Loader \ Summary: Include binaries for recursive tokens, Python blueprint and images \ \ ------------------------------------------------------------------------------ \ \ The loader bundles a number of binary files in with the loader code, and moves \ them to their correct memory locations in part 3 below. \ \ There are two files containing code: \ \ * WORDS9.bin contains the recursive token table, which is moved to &0400 \ before the main game is loaded \ \ * PYTHON.bin contains the Python ship blueprint, which gets moved to &7F00 \ before the main game is loaded \ \ and four files containing images, which are all moved into screen memory by \ the loader: \ \ * P.A-SOFT.bin contains the "ACORNSOFT" title across the top of the loading \ screen, which gets moved to screen address &6100, on the second character \ row of the monochrome mode 4 screen \ \ * P.ELITE.bin contains the "ELITE" title across the top of the loading \ screen, which gets moved to screen address &6300, on the fourth character \ row of the monochrome mode 4 screen \ \ * P.(C)ASFT.bin contains the "(C) Acornsoft 1984" title across the bottom \ of the loading screen, which gets moved to screen address &7600, the \ penultimate character row of the monochrome mode 4 screen, just above the \ dashboard \ \ * P.DIALS.bin contains the dashboard, which gets moved to screen address \ &7800, which is the starting point of the four-colour mode 5 portion at \ the bottom of the split screen \ \ The routine ends with a jump to the start of the loader code at ENTRY. \ \ ****************************************************************************** PRINT "WORDS9 = ", ~P% INCBIN "3-assembled-output/WORDS9.bin" ALIGN 256 PRINT "P.DIALS = ", ~P% INCBIN "1-source-files/images/P.DIALS.bin" PRINT "PYTHON = ", ~P% INCBIN "3-assembled-output/PYTHON.bin" PRINT "P.ELITE = ", ~P% INCBIN "1-source-files/images/P.ELITE.bin" PRINT "P.A-SOFT = ", ~P% INCBIN "1-source-files/images/P.A-SOFT.bin" PRINT "P.(C)ASFT = ", ~P% INCBIN "1-source-files/images/P.(C)ASFT.bin" .run JMP ENTRY \ Jump to ENTRY to start the loading process \ ****************************************************************************** \ \ Name: B% \ Type: Variable \ Category: Drawing the screen \ Summary: VDU commands for setting the square mode 4 screen \ Deep dive: The split-screen mode in BBC Micro Elite \ Drawing monochrome pixels on the BBC Micro \ \ ------------------------------------------------------------------------------ \ \ This block contains the bytes that get written by OSWRCH to set up the screen \ mode (this is equivalent to using the VDU statement in BASIC). \ \ It defines the whole screen using a square, monochrome mode 4 configuration; \ the mode 5 part for the dashboard is implemented in the IRQ1 routine. \ \ The top part of Elite's screen mode is based on mode 4 but with the following \ differences: \ \ * 32 columns, 31 rows (256 x 248 pixels) rather than 40, 32 \ \ * The horizontal sync position is at character 45 rather than 49, which \ pushes the screen to the right (which centres it as it's not as wide as \ the normal screen modes) \ \ * Screen memory goes from &6000 to &7EFF, which leaves another whole page \ for code (i.e. 256 bytes) after the end of the screen. This is where the \ Python ship blueprint slots in \ \ * The text window is 1 row high and 13 columns wide, and is at (2, 16) \ \ * The cursor is disabled \ \ This almost-square mode 4 variant makes life a lot easier when drawing to the \ screen, as there are 256 pixels on each row (or, to put it in screen memory \ terms, there's one page of memory per row of pixels). \ \ There is also an interrupt-driven routine that switches the bytes-per-pixel \ setting from that of mode 4 to that of mode 5, when the raster reaches the \ split between the space view and the dashboard. \ \ ****************************************************************************** .B% EQUB 22, 4 \ Switch to screen mode 4 EQUB 28 \ Define a text window as follows: EQUB 2, 17, 15, 16 \ \ * Left = 2 \ * Right = 15 \ * Top = 16 \ * Bottom = 17 \ \ i.e. 1 row high, 13 columns wide at (2, 16) EQUB 23, 0, 6, 31 \ Set 6845 register R6 = 31 EQUB 0, 0, 0 \ EQUB 0, 0, 0 \ This is the "vertical displayed" register, and sets \ the number of displayed character rows to 31. For \ comparison, this value is 32 for standard modes 4 and \ 5, but we claw back the last row for storing code just \ above the end of screen memory EQUB 23, 0, 12, &0C \ Set 6845 register R12 = &0C and R13 = &00 EQUB 0, 0, 0 \ EQUB 0, 0, 0 \ This sets 6845 registers (R12 R13) = &0C00 to point EQUB 23, 0, 13, &00 \ to the start of screen memory in terms of character EQUB 0, 0, 0 \ rows. There are 8 pixel lines in each character row, EQUB 0, 0, 0 \ so to get the actual address of the start of screen \ memory, we multiply by 8: \ \ &0C00 * 8 = &6000 \ \ So this sets the start of screen memory to &6000 EQUB 23, 0, 1, 32 \ Set 6845 register R1 = 32 EQUB 0, 0, 0 \ EQUB 0, 0, 0 \ This is the "horizontal displayed" register, which \ defines the number of character blocks per horizontal \ character row. For comparison, this value is 40 for \ modes 4 and 5, but our custom screen is not as wide at \ only 32 character blocks across EQUB 23, 0, 2, 45 \ Set 6845 register R2 = 45 EQUB 0, 0, 0 \ EQUB 0, 0, 0 \ This is the "horizontal sync position" register, which \ defines the position of the horizontal sync pulse on \ the horizontal line in terms of character widths from \ the left-hand side of the screen. For comparison this \ is 49 for modes 4 and 5, but needs to be adjusted for \ our custom screen's width EQUB 23, 0, 10, 32 \ Set 6845 register R10 = %00100000 = 32 EQUB 0, 0, 0 \ EQUB 0, 0, 0 \ This is the "cursor start" register, and bits 5 and 6 \ define the "cursor display mode", as follows: \ \ * %00 = steady, non-blinking cursor \ \ * %01 = do not display a cursor \ \ * %10 = fast blinking cursor (blink at 1/16 of the \ field rate) \ \ * %11 = slow blinking cursor (blink at 1/32 of the \ field rate) \ \ We can therefore turn off the cursor completely by \ setting cursor display mode %01, with bit 6 of R10 \ clear and bit 5 of R10 set \ ****************************************************************************** \ \ Name: E% \ Type: Variable \ Category: Sound \ Summary: Sound envelope definitions \ \ ------------------------------------------------------------------------------ \ \ This table contains the sound envelope data, which is passed to OSWORD by the \ FNE macro to create the four sound envelopes used in-game. Refer to chapter 30 \ of the "BBC Microcomputer User Guide" by John Coll for details of sound \ envelopes and what all the parameters mean. \ \ The envelopes are as follows: \ \ * Envelope 1 is the sound of our own laser firing \ \ * Envelope 2 is the sound of lasers hitting us, or hyperspace \ \ * Envelope 3 is the first sound in the two-part sound of us dying, or the \ second sound in the two-part sound of us hitting or killing an enemy ship \ \ * Envelope 4 is the sound of E.C.M. firing \ \ ****************************************************************************** .E% EQUB 1, 1, 0, 111, -8, 4, 1, 8, 8, -2, 0, -1, 112, 44 EQUB 2, 1, 14, -18, -1, 44, 32, 50, 6, 1, 0, -2, 120, 126 EQUB 3, 1, 1, -1, -3, 17, 32, 128, 1, 0, 0, -1, 1, 1 EQUB 4, 1, 4, -8, 44, 4, 6, 8, 22, 0, 0, -127, 126, 0 \ ****************************************************************************** \ \ Name: swine \ Type: Subroutine \ Category: Copy protection \ Summary: Resets the machine if the copy protection detects a problem \ \ ****************************************************************************** .swine LDA #%01111111 \ Set 6522 System VIA interrupt enable register IER STA &FE4E \ (SHEILA &4E) bits 0-6 (i.e. disable all hardware \ interrupts from the System VIA) JMP (&FFFC) \ Jump to the address in &FFFC to reset the machine \ ****************************************************************************** \ \ Name: OSB \ Type: Subroutine \ Category: Utility routines \ Summary: A convenience routine for calling OSBYTE with Y = 0 \ \ ****************************************************************************** .OSB LDY #0 \ Call OSBYTE with Y = 0, returning from the subroutine JMP OSBYTE \ using a tail call (so we can call OSB to call OSBYTE \ for when we know we want Y set to 0) \ ****************************************************************************** \ \ Name: Authors' names \ Type: Variable \ Category: Copy protection \ Summary: The authors' names, buried in the code \ \ ------------------------------------------------------------------------------ \ \ Contains the authors' names, plus an unused OS command string that would \ *RUN the main game code, which isn't what actually happens (so presumably \ this is to throw the crackers off the scent). \ \ ****************************************************************************** EQUS "R.ELITEcode" \ This is short for "*RUN ELITEcode" EQUB 13 EQUS "By D.Braben/I.Bell" EQUB 13 EQUB &B0 \ ****************************************************************************** \ \ Name: oscliv \ Type: Variable \ Category: Utility routines \ Summary: Contains the address of OSCLIV, for executing OS commands \ \ ****************************************************************************** .oscliv EQUW &FFF7 \ Address of OSCLIV, for executing OS commands \ (specifically the *LOAD that loads the main game code) \ ****************************************************************************** \ \ Name: David9 \ Type: Variable \ Category: Copy protection \ Summary: Address used as part of the stack-based decryption loop \ \ ------------------------------------------------------------------------------ \ \ This address is used in the decryption loop starting at David2 in part 4, and \ is used to jump back into the loop at David5. \ \ ****************************************************************************** .David9 EQUW David5 \ The address of David5 CLD \ This instruction is not used \ ****************************************************************************** \ \ Name: David23 \ Type: Variable \ Category: Copy protection \ Summary: Address pointer to the start of the 6502 stack \ \ ------------------------------------------------------------------------------ \ \ This two-byte address points to the start of the 6502 stack, which descends \ from the end of page 2, less LEN bytes, which comes out as &01DF. So when we \ push 33 bytes onto the stack (LEN being 33), this address will point to the \ start of those bytes, which means we can push executable code onto the stack \ and run it by calling this address with a JMP (David23) instruction. Sneaky \ stuff! \ \ ****************************************************************************** .David23 EQUW (512-LEN) \ The address of LEN bytes before the start of the stack \ ****************************************************************************** \ \ Name: doPROT1 \ Type: Subroutine \ Category: Copy protection \ Summary: Routine to self-modify the loader code \ \ ------------------------------------------------------------------------------ \ \ This routine modifies various bits of code in-place as part of the copy \ protection mechanism. It is called with A = &48 and X = 255. \ \ ****************************************************************************** .doPROT1 LDY #&DB \ Store &EFDB in TRTB%(1 0) to point to the keyboard STY TRTB% \ translation table for OS 0.1 (which we will overwrite LDY #&EF \ with a call to OSBYTE later) STY TRTB%+1 LDY #2 \ Set the high byte of V219(1 0) to 2 STY V219+1 STA PROT1-255,X \ Poke &48 into PROT1, which changes the instruction \ there to a PHA LDY #&18 \ Set the low byte of V219(1 0) to &18 (as X = 255), so STY V219+1,X \ V219(1 0) now contains &0218 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MHCA \ Type: Variable \ Category: Copy protection \ Summary: Used to set one of the vectors in the copy protection code \ \ ------------------------------------------------------------------------------ \ \ This value is used to set the low byte of BLPTR(1 0), when it's set in PLL1 \ as part of the copy protection. \ \ ****************************************************************************** .MHCA EQUB &CA \ The low byte of BLPTR(1 0) \ ****************************************************************************** \ \ Name: David7 \ Type: Subroutine \ Category: Copy protection \ Summary: Part of the multi-jump obfuscation code in PROT1 \ \ ------------------------------------------------------------------------------ \ \ This instruction is part of the multi-jump obfuscation in PROT1 (see part 2 of \ the loader), which does the following jumps: \ \ David8 -> FRED1 -> David7 -> Ian1 -> David3 \ \ ****************************************************************************** .David7 BCC Ian1 \ This instruction is part of the multi-jump obfuscation \ in PROT1 \ ****************************************************************************** \ \ Name: FNE \ Type: Macro \ Category: Sound \ Summary: Macro definition for defining a sound envelope \ \ ------------------------------------------------------------------------------ \ \ The following macro is used to define the four sound envelopes used in the \ game. It uses OSWORD 8 to create an envelope using the 14 parameters in the \ I%-th block of 14 bytes at location E%. This OSWORD call is the same as BBC \ BASIC's ENVELOPE command. \ \ See variable E% for more details of the envelopes themselves. \ \ ****************************************************************************** MACRO FNE I% LDX #LO(E%+I%*14) \ Set (Y X) to point to the I%-th set of envelope data LDY #HI(E%+I%*14) \ in E% LDA #8 \ Call OSWORD with A = 8 to set up sound envelope I% JSR OSWORD ENDMACRO \ ****************************************************************************** \ \ Name: Elite loader (Part 2 of 6) \ Type: Subroutine \ Category: Loader \ Summary: Perform a number of OS calls, set up sound, push routines on stack \ \ ------------------------------------------------------------------------------ \ \ This part of the loader does a number of calls to OS routines, sets up the \ sound envelopes, pushes 33 bytes onto the stack that will be used later, and \ sends us on a wild goose chase, just for kicks. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ Ian1 Re-entry point following the wild goose chase \ obfuscation \ \ ****************************************************************************** .ENTRY SEI \ Disable all interrupts CLD \ Clear the decimal flag, so we're not in decimal mode IF NOT(DISC) LDA #0 \ Call OSBYTE with A = 0 and X = 255 to fetch the LDX #255 \ operating system version into X JSR OSBYTE TXA \ If X = 0 then this is OS 1.00, so jump down to OS100 BEQ OS100 \ to skip the following LDY &FFB6 \ Otherwise this is OS 1.20, so set Y to the contents of \ &FFB6, which contains the length of the default vector \ table LDA &FFB7 \ Set ZP(1 0) to the location stored in &FFB7-&FFB8, STA ZP \ which contains the address of the default vector table LDA &FFB8 STA ZP+1 DEY \ Decrement Y so we can use it as an index for setting \ all the vectors to their default states .ABCDEFG LDA (ZP),Y \ Copy the Y-th byte from the default vector table into STA &0200,Y \ the vector table in &0200 DEY \ Decrement the loop counter BPL ABCDEFG \ Loop back for the next vector until we have done them \ all .OS100 ENDIF LDA #%01111111 \ Set 6522 System VIA interrupt enable register IER STA &FE4E \ (SHEILA &4E) bits 0-6 (i.e. disable all hardware \ interrupts from the System VIA) STA &FE6E \ Set 6522 User VIA interrupt enable register IER \ (SHEILA &6E) bits 0-6 (i.e. disable all hardware \ interrupts from the User VIA) LDA &FFFC \ Fetch the low byte of the reset address in &FFFC, \ which will reset the machine if called STA &0200 \ Set the low bytes of USERV, BRKV, IRQ2V and EVENTV STA &0202 STA &0206 STA &0220 LDA &FFFD \ Fetch the high byte of the reset address in &FFFD, \ which will reset the machine if called STA &0201 \ Set the high bytes of USERV, BRKV, IRQ2V and EVENTV STA &0203 STA &0207 STA &0221 LDX #&2F-2 \ We now step through all the vectors from &0204 to \ &022F and OR their high bytes with &C0, so they all \ point into the MOS ROM space (which is from &C000 and \ upwards), so we set a counter in X to count through \ them .purge LDA &0202,X \ Set the high byte of the vector in &0202+X so it ORA #&C0 \ points to the MOS ROM STA &0202,X DEX \ Increment the counter to point to the next high byte DEX BPL purge \ Loop back until we have done all the vectors LDA #&60 \ Store an RTS instruction in location &0232 STA &0232 LDA #&2 \ Point the NETV vector to &0232, which we just filled STA NETV+1 \ with an RTS LDA #&32 STA NETV LDA #&20 \ Set A to the op code for a JSR call with absolute \ addressing EQUB &2C \ Skip the next instruction by turning it into \ &2C &D0 &66, or BIT &66D0, which does nothing apart \ from affect the flags .Ian1 BNE David3 \ This instruction is skipped if we came from above, \ otherwise this is part of the multi-jump obfuscation \ in PROT1 STA David2 \ Store &20 in location David2, which modifies the \ instruction there (see David2 for details) LSR A \ Set A = 16 LDX #3 \ Set the high bytes of BLPTR(1 0), BLN(1 0) and STX BLPTR+1 \ EXCN(1 0) to &3. We will fill in the high bytes in STX BLN+1 \ the PLL1 routine, and will then use these values in STX EXCN+1 \ the IRQ1 handler DEX \ Set X = 2 JSR OSBYTE \ Call OSBYTE with A = 16 and X = 2 to set the ADC to \ sample 2 channels from the joystick EQUB &2C \ Skip the next instruction by turning it into \ &2C &D0 &A1, or BIT &A1D0, which does nothing apart \ from affect the flags .FRED1 BNE David7 \ This instruction is skipped if we came from above, \ otherwise this is part of the multi-jump obfuscation \ in PROT1 LDX #255 \ Call doPROT1 to change an instruction in the PROT1 LDA #&48 \ routine and set up another couple of variables JSR doPROT1 LDA #144 \ Call OSBYTE with A = 144, X = 255 and Y = 0 to move JSR OSB \ the screen down one line and turn screen interlace on LDA #247 \ Call OSBYTE with A = 247 and X = Y = 0 to disable the LDX #0 \ BREAK intercept code by poking 0 into the first value JSR OSB \LDA #129 \ These instructions are commented out in the original \LDY #255 \ source, along with the comment "Damn 0.1", so \LDX #1 \ presumably MOS version 0.1 was a bit of a pain to \JSR OSBYTE \ support - which is probably why Elite doesn't bother \ \ and only supports 1.0 and 1.2 \TXA \ \BPL OS01 \ \Damn 0.1 LDA #190 \ Call OSBYTE with A = 190, X = 8 and Y = 0 to set the LDX #8 \ ADC conversion type to 8 bits, for the joystick JSR OSB EQUB &2C \ Skip the next instruction by turning it into \ &2C &D0 &E1, or BIT &E1D0, which does nothing apart \ from affect the flags .David8 BNE FRED1 \ This instruction is skipped if we came from above, \ otherwise this is part of the multi-jump obfuscation \ in PROT1 LDA #143 \ Call OSBYTE 143 to issue a paged ROM service call of LDX #&C \ type &C with argument &FF, which is the "NMI claim" LDY #&FF \ service call that asks the current user of the NMI JSR OSBYTE \ space to clear it out LDA #13 \ Set A = 13 for the next OSBYTE call .abrk LDX #0 \ Call OSBYTE with A = 13, X = 0 and Y = 0 to disable JSR OSB \ the "output buffer empty" event LDA #225 \ Call OSBYTE with A = 225, X = 128 and Y = 0 to set LDX #128 \ the function keys to return ASCII codes for SHIFT-fn JSR OSB \ keys (i.e. add 128) LDA #172 \ Call OSBYTE 172 to read the address of the MOS LDX #0 \ keyboard translation table into (Y X) LDY #255 JSR OSBYTE STX TRTB% \ Store the address of the keyboard translation table in STY TRTB%+1 \ TRTB%(1 0) LDA #200 \ Call OSBYTE with A = 200, X = 3 and Y = 0 to disable LDX #3 \ the ESCAPE key and clear memory if the BREAK key is JSR OSB \ pressed IF PROT AND NOT(DISC) CPX #3 \ If the previous value of X from the call to OSBYTE 200 BNE abrk+1 \ was not 3 (ESCAPE disabled, clear memory), jump to \ abrk+1, which contains a BRK instruction which will \ reset the computer (as we set BRKV to point to the \ reset address above) ENDIF LDA #13 \ Call OSBYTE with A = 13, X = 2 and Y = 0 to disable LDX #2 \ the "character entering keyboard buffer" event JSR OSB .OS01 LDX #&FF \ Set the stack pointer to &01FF, which is the standard TXS \ location for the 6502 stack, so this instruction \ effectively resets the stack INX \ Set X = 0, to use as a counter in the following loop .David3 LDA BEGIN%,X \ This routine pushes 33 bytes from BEGIN% onto the \ stack, so fetch the X-th byte from BEGIN% .PROT1 INY \ This instruction gets changed to a PHA instruction by \ the doPROT1 routine that's called above, so by the \ time we get here, this instruction actually pushes the \ X-th byte from BEGIN% onto the stack INX \ Increment the loop counter CPX #LEN \ If X < #LEN (which is 33), loop back for the next one. BNE David8 \ This branch actually takes us on a wild goose chase \ through the following locations, where each BNE is \ prefaced by an EQUB &2C that disables the branch \ instruction during the normal instruction flow: \ \ David8 -> FRED1 -> David7 -> Ian1 -> David3 \ \ so in the end this just loops back to push the next \ byte onto the stack, but in a really sneaky way LDA #LO(B%) \ Set the low byte of ZP(1 0) to point to the VDU code STA ZP \ table at B% LDA #&C8 \ Poke &C8 into PROT1 to change the instruction that we STA PROT1 \ modified back to an INY instruction, rather than a PHA LDA #HI(B%) \ Set the high byte of ZP(1 0) to point to the VDU code STA ZP+1 \ table at B% LDY #0 \ We are now going to send the N% VDU bytes in the table \ at B% to OSWRCH to set up the special mode 4 screen \ that forms the basis for the split-screen mode .LOOP LDA (ZP),Y \ Pass the Y-th byte of the B% table to OSWRCH JSR OSWRCH INY \ Increment the loop counter CPY #N% \ Loop back for the next byte until we have done them BNE LOOP \ all (the number of bytes was set in N% above) LDA #1 \ In doPROT1 above we set V219(1 0) = &0218, so this TAX \ code sets the contents of &0219 (the high byte of TAY \ BPUTV) to 1. We will see why this later, at the start STA (V219),Y \ of part 4 LDA #4 \ Call OSBYTE with A = 4, X = 1 and Y = 0 to disable JSR OSB \ cursor editing, so the cursor keys return ASCII values \ and can therefore be used in-game LDA #9 \ Call OSBYTE with A = 9, X = 0 and Y = 0 to disable LDX #0 \ flashing colours JSR OSB LDA #&6C \ Poke &6C into crunchit after EOR'ing it first (which EOR crunchit \ has no effect as crunchit contains a BRK instruction STA crunchit \ with opcode 0), to change crunchit to an indirect JMP FNE 0 \ Set up sound envelopes 0-3 using the FNE macro FNE 1 FNE 2 FNE 3 \ ****************************************************************************** \ \ Name: Elite loader (Part 3 of 6) \ Type: Subroutine \ Category: Loader \ Summary: Move and decrypt recursive tokens, Python blueprint and images \ \ ------------------------------------------------------------------------------ \ \ Move and decrypt the following memory blocks: \ \ * WORDS9: move 4 pages (1024 bytes) from CODE% to &0400 \ \ * P.ELITE: move 1 page (256 bytes) from CODE% + &0C00 to &6300 \ \ * P.A-SOFT: move 1 page (256 bytes) from CODE% + &0D00 to &6100 \ \ * P.(C)ASFT: move 1 page (256 bytes) from CODE% + &0E00 to &7600 \ \ * P.DIALS and PYTHON: move 8 pages (2048 bytes) from CODE% + &0400 to &7800 \ \ * Move 2 pages (512 bytes) from UU% to &0B00-&0CFF \ \ and call the routine to draw Saturn between P.(C)ASFT and P.DIALS. \ \ See part 1 above for more details on the above files and the locations that \ they are moved to. \ \ The code at UU% (see below) forms part of the loader code and is moved before \ being run, so it's tucked away safely while the main game code is loaded and \ decrypted. \ \ ****************************************************************************** LDX #4 \ Set the following: STX P+1 \ LDA #HI(CODE%) \ P(1 0) = &0400 STA ZP+1 \ ZP(1 0) = CODE% LDY #0 \ (X Y) = &400 = 1024 LDA #256-LEN1 \ STA (V219-4,X) \ In doPROT1 above we set V219(1 0) = &0218, so this STY ZP \ also sets the contents of &0218 (the low byte of STY P \ BPUTV) to 256 - LEN1, or &F1. We set the low byte to \ 1 above, so BPUTV now contains &01F1, which we will \ use at the start of part 4 JSR crunchit \ Call crunchit, which has now been modified to call the \ MVDL routine on the stack, to move and decrypt &400 \ bytes from CODE% to &0400. We loaded WORDS9.bin to \ CODE% in part 1, so this moves WORDS9 LDX #1 \ Set the following: LDA #(HI(CODE%)+&C) \ STA ZP+1 \ P(1 0) = &6300 LDA #&63 \ ZP(1 0) = CODE% + &C STA P+1 \ (X Y) = &100 = 256 LDY #0 JSR crunchit \ Call crunchit to move and decrypt &100 bytes from \ CODE% + &C to &6300, so this moves P.ELITE LDX #1 \ Set the following: LDA #(HI(CODE%)+&D) \ STA ZP+1 \ P(1 0) = &6100 LDA #&61 \ ZP(1 0) = CODE% + &D STA P+1 \ (X Y) = &100 = 256 LDY #0 JSR crunchit \ Call crunchit to move and decrypt &100 bytes from \ CODE% + &D to &6100, so this moves P.A-SOFT LDX #1 \ Set the following: LDA #(HI(CODE%)+&E) \ STA ZP+1 \ P(1 0) = &7600 LDA #&76 \ ZP(1 0) = CODE% + &E STA P+1 \ (X Y) = &100 = 256 LDY #0 JSR crunchit \ Call crunchit to move and decrypt &100 bytes from \ CODE% + &E to &7600, so this moves P.(C)ASFT JSR PLL1 \ Call PLL1 to draw Saturn LDX #8 \ Set the following: LDA #(HI(CODE%)+4) \ STA ZP+1 \ P(1 0) = &7800 LDA #&78 \ ZP(1 0) = CODE% + &4 STA P+1 \ (X Y) = &800 = 2048 LDY #0 \ STY ZP \ Also set BLCNT = 0 STY BLCNT STY P JSR crunchit \ Call crunchit to move and decrypt &800 bytes from \ CODE% + &4 to &7800, so this moves P.DIALS and PYTHON IF DISC LDX #2 \ Set the following: LDA #HI(UU%) \ STA ZP+1 \ P(1 0) = LE% LDA #LO(UU%) \ ZP(1 0) = UU% STA ZP \ (X Y) = &200 = 512 (as we are building for disc) LDA #HI(LE%) STA P+1 LDY #0 STY P ELSE LDX #3 \ Set the following: LDA #HI(UU%) \ STA ZP+1 \ P(1 0) = LE% LDA #LO(UU%) \ ZP(1 0) = UU% STA ZP \ (X Y) = &300 = 768 (as we are building for tape) LDA #HI(LE%) STA P+1 LDY #0 STY P ENDIF JSR crunchit \ Call crunchit to move and decrypt either &200 or &300 \ bytes from UU% to LE%, leaving X = 0 \ ****************************************************************************** \ \ Name: Elite loader (Part 4 of 6) \ Type: Subroutine \ Category: Loader \ Summary: Copy more code onto stack, decrypt TUT block, set up IRQ1 handler \ \ ------------------------------------------------------------------------------ \ \ This part copies more code onto the stack (from BLOCK to ENDBLOCK), decrypts \ the code from TUT onwards, and sets up the IRQ1 handler for the split-screen \ mode. \ \ ****************************************************************************** STY David3-2 \ Y was set to 0 above, so this modifies the OS01 \ routine above by changing the TXS instruction to BRK, \ so calls to OS01 will now do this: \ \ LDX #&FF \ BRK \ \ This is presumably just to confuse any cracker, as we \ don't call OS01 again \ We now enter a loop that starts with the counter in Y \ (initially set to 0). It calls JSR &01F1 on the stack, \ which pushes the Y-th byte of BLOCK on the stack \ before encrypting the Y-th byte of BLOCK in-place. It \ then jumps back to David5 below, where we increment Y \ until it reaches a value of ENDBLOCK - BLOCK. So this \ loop basically decrypts the code from TUT onwards, and \ at the same time it pushes the code between BLOCK and \ ENDBLOCK onto the stack, so it's there ready to be run \ (at address &0163) .David2 EQUB &AC \ This byte was changed to &20 by part 2, so by the time EQUW &FFD4 \ we get here, these three bytes together become JSR \ &FFD4, or JSR OSBPUT. Amongst all the code above, \ we've also managed to set BPUTV to &01F1, and as BPUTV \ is the vector that OSBPUT goes through, these three \ bytes are actually doing JSR &01F1 \ \ That address is in the stack, and is the address of \ the BEGIN% routine, which we pushed onto the stack in \ the modified PROT1 routine. That routine doesn't \ return with an RTS, but instead it removes the return \ address from the stack and jumps to David5 below after \ pushing the Y-th byte of BLOCK onto the stack and \ EOR'ing the Y-th byte of TUT with the Y-th byte of \ BLOCK \ \ This obfuscation probably kept the crackers busy for a \ while - it's difficult enough to work out when you \ have the source code in front of you! .LBLa \ If, for some reason, the above JSR doesn't call the \ routine on the stack and returns normally, which might \ happen if crackers manage to unpick the BPUTV \ redirection, then we end up here. We now obfuscate the \ first 255 bytes of the location where the main game \ gets loaded (which is set in C%), just to make things \ hard, and then we reset the machine... all in a \ completely twisted manner, of course LDA C%,X \ Obfuscate the X-th byte of C% by EOR'ing with &A5 EOR #&A5 STA C%,X DEX \ Decrement the loop counter BNE LBLa \ Loop back until X wraps around, after EOR'ing a whole \ page JMP (C%+&CF) \ C%+&CF is &100F, which in the main game code contains \ an LDA KY17 instruction (it's in the main loader in \ the MA76 section). This has opcode &A5 &4E, and the \ EOR above changes the first of these to &00, so this \ jump goes to a BRK instruction, which in turn goes to \ BRKV, which in turn resets the computer (as we set \ BRKV to point to the reset address in part 2) .swine2 JMP swine \ Jump to swine to reset the machine EQUW &4CFF \ This data doesn't appear to be used .crunchit BRK \ This instruction gets changed to an indirect JMP at EQUW David23 \ the end of part 2, so this does JMP (David23). David23 \ contains &01DF, so these bytes are actually doing JMP \ &01DF. That address is in the stack, and is the \ address of the MVDL routine, which we pushed onto the \ stack in the modified PROT1 routine... so this \ actually does the following: \ \ JMP MVDL \ \ meaning that this instruction: \ \ JSR crunchit \ \ actually does this, because it's a tail call: \ \ JSR MVDL \ \ It's yet another impressive bit of obfuscation and \ misdirection .RAND EQUD &6C785349 \ The random number seed used for drawing Saturn .David5 INY \ Increment the loop counter CPY #(ENDBLOCK-BLOCK) \ Loop back to copy the next byte until we have copied BNE David2 \ all the bytes between BLOCK and ENDBLOCK SEI \ Disable interrupts while we set up our interrupt \ handler to support the split-screen mode LDA #%11000010 \ Clear 6522 System VIA interrupt enable register IER STA VIA+&4E \ (SHEILA &4E) bits 1 and 7 (i.e. enable CA1 and TIMER1 \ interrupts from the System VIA, which enable vertical \ sync and the 1 MHz timer, which we need enabled for \ the split-screen interrupt code to work) LDA #%01111111 \ Set 6522 User VIA interrupt enable register IER STA &FE6E \ (SHEILA &6E) bits 0-7 (i.e. disable all hardware \ interrupts from the User VIA) LDA IRQ1V \ Store the low byte of the current IRQ1V vector in VEC STA VEC LDA IRQ1V+1 \ If the current high byte of the IRQ1V vector is less BPL swine2 \ than &80, which means it points to user RAM rather \ the MOS ROM, then something is probably afoot, so jump \ to swine2 to reset the machine STA VEC+1 \ Otherwise all is well, so store the high byte of the \ current IRQ1V vector in VEC+1, so VEC(1 0) now \ contains the original address of the IRQ1 handler LDA #HI(IRQ1) \ Set the IRQ1V vector to IRQ1, so IRQ1 is now the STA IRQ1V+1 \ interrupt handler LDA #LO(IRQ1) STA IRQ1V LDA #VSCAN \ Set 6522 System VIA T1C-L timer 1 high-order counter STA VIA+&45 \ (SHEILA &45) to VSCAN (56) to start the T1 counter \ counting down from 14080 at a rate of 1 MHz (this is \ a different value to the main game code) CLI \ Re-enable interrupts IF DISC LDA #%10000001 \ Clear 6522 System VIA interrupt enable register IER STA &FE4E \ (SHEILA &4E) bit 1 (i.e. enable the CA2 interrupt, \ which comes from the keyboard) LDY #20 \ Set Y = 20 for the following OSBYTE call IF _REMOVE_CHECKSUMS NOP \ If we have disabled checksums, skip the OSBYTE call NOP NOP ELSE JSR OSBYTE \ A was set to 129 above, so this calls OSBYTE with \ A = 129 and Y = 20, as well as a value of X = 0, \ which was set by the call to crunchit at the end of \ part 3 \ \ This reads the keyboard with a time limit of (Y X) \ centiseconds, or 20 * 256 = 5120 centiseconds, or \ 51.2 seconds ENDIF LDA #%00000001 \ Set 6522 System VIA interrupt enable register IER STA &FE4E \ (SHEILA &4E) bit 1 (i.e. disable the CA2 interrupt, \ which comes from the keyboard) ENDIF RTS \ This RTS actually does a jump to ENTRY2, to the next \ step of the loader in part 5. See the documentation \ for the stack routine at BEGIN% for more details \ ****************************************************************************** \ \ Name: PLL1 (Part 1 of 3) \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw Saturn on the loading screen (draw the planet) \ Deep dive: Drawing Saturn on the loading screen \ \ ****************************************************************************** .PLL1 \ The following loop iterates CNT(1 0) times, i.e. &500 \ or 1280 times, and draws the planet part of the \ loading screen's Saturn LDA VIA+&44 \ Read the 6522 System VIA T1C-L timer 1 low-order STA RAND+1 \ counter (SHEILA &44), which decrements one million \ times a second and will therefore be pretty random, \ and store it in location RAND+1, which is among the \ main game code's random seeds in RAND (so this seeds \ the random number generator) JSR DORND \ Set A and X to signed random numbers between -128 and \ 127, so let's say A = r1 JSR SQUA2 \ Set (A P) = A * A \ = r1^2 STA ZP+1 \ Set ZP(1 0) = (A P) LDA P \ = r1^2 STA ZP JSR DORND \ Set A and X to signed random numbers between -128 and \ 127, so let's say A = r2 STA YY \ Set YY = A \ = r2 JSR SQUA2 \ Set (A P) = A * A \ = r2^2 TAX \ Set (X P) = (A P) \ = r2^2 LDA P \ Set (A ZP) = (X P) + ZP(1 0) ADC ZP \ STA ZP \ first adding the low bytes TXA \ And then adding the high bytes ADC ZP+1 BCS PLC1 \ If the addition overflowed, jump down to PLC1 to skip \ to the next pixel STA ZP+1 \ Set ZP(1 0) = (A ZP) \ = r1^2 + r2^2 LDA #1 \ Set ZP(1 0) = &4001 - ZP(1 0) - (1 - C) SBC ZP \ = 128^2 - ZP(1 0) STA ZP \ \ (as the C flag is clear), first subtracting the low \ bytes LDA #&40 \ And then subtracting the high bytes SBC ZP+1 STA ZP+1 BCC PLC1 \ If the subtraction underflowed, jump down to PLC1 to \ skip to the next pixel \ If we get here, then both calculations fitted into \ 16 bits, and we have: \ \ ZP(1 0) = 128^2 - (r1^2 + r2^2) \ \ where ZP(1 0) >= 0 JSR ROOT \ Set ZP = SQRT(ZP(1 0)) LDA ZP \ Set X = ZP >> 1 LSR A \ = SQRT(128^2 - (a^2 + b^2)) / 2 TAX LDA YY \ Set A = YY \ = r2 CMP #128 \ If YY >= 128, set the C flag (so the C flag is now set \ to bit 7 of A) ROR A \ Rotate A and set the sign bit to the C flag, so A is \ halved while retaining its sign \ \ A is still a signed number from -128 to 127 JSR PIX \ Draw a pixel at screen coordinate (X + 128, A + 128), \ where: \ \ X = ZP / 2 \ A = r2 / 2 \ ZP = SQRT(128^2 - (r1^2 + r2^2)) \ \ So this is the same as plotting at (x, y) where: \ \ r1 = random number from -128 to 127 \ r2 = random number from -128 to 127 \ \ (r1^2 + r2^2) < 128^2 \ \ x = (SQRT(128^2 - (r1^2 + r2^2)) / 2) + 128 \ y = (r2 / 2) + 128 \ \ which is what we want .PLC1 DEC CNT \ Decrement the counter in CNT (the low byte) BNE PLL1 \ Loop back to PLL1 until CNT = 0 DEC CNT+1 \ Decrement the counter in CNT+1 (the high byte) BNE PLL1 \ Loop back to PLL1 until CNT+1 = 0 LDX #&C2 \ Set the low byte of EXCN(1 0) to &C2, so we now have STX EXCN \ EXCN(1 0) = &03C2, which we will use in the IRQ1 \ handler (this has nothing to do with drawing Saturn, \ it's all part of the copy protection) \ ****************************************************************************** \ \ Name: PLL1 (Part 2 of 3) \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw Saturn on the loading screen (draw the stars) \ Deep dive: Drawing Saturn on the loading screen \ \ ****************************************************************************** \ The following loop iterates CNT2(1 0) times, i.e. &1DD \ or 477 times, and draws the background stars on the \ loading screen .PLL2 JSR DORND \ Set A and X to signed random numbers between -128 and \ 127, so let's say A = r3 TAX \ Set X = A \ = r3 JSR SQUA2 \ Set (A P) = A * A \ = r3^2 STA ZP+1 \ Set ZP+1 = A \ = r3^2 / 256 JSR DORND \ Set A and X to signed random numbers between -128 and \ 127, so let's say A = r4 STA YY \ Set YY = r4 JSR SQUA2 \ Set (A P) = A * A \ = r4^2 ADC ZP+1 \ Set A = A + r3^2 / 256 \ = r4^2 / 256 + r3^2 / 256 \ = (r3^2 + r4^2) / 256 CMP #&11 \ If A < 17, jump down to PLC2 to skip to the next pixel BCC PLC2 LDA YY \ Set A = r4 JSR PIX \ Draw a pixel at screen coordinate (X + 128, A + 128), \ where: \ \ X = r3 \ A = r4 \ \ So this is the same as plotting at (x, y) where: \ \ r3 = random number from -128 to 127 \ r4 = random number from -128 to 127 \ \ (r3^2 + r4^2) / 256 >= 17 \ \ x = r3 \ y = r4 \ \ which is what we want .PLC2 DEC CNT2 \ Decrement the counter in CNT2 (the low byte) BNE PLL2 \ Loop back to PLL2 until CNT2 = 0 DEC CNT2+1 \ Decrement the counter in CNT2+1 (the high byte) BNE PLL2 \ Loop back to PLL2 until CNT2+1 = 0 LDX MHCA \ Set the low byte of BLPTR(1 0) to the contents of MHCA STX BLPTR \ (which is &CA), so we now have BLPTR(1 0) = &03CA, \ which we will use in the IRQ1 handler (this has \ nothing to do with drawing Saturn, it's all part of \ the copy protection) LDX #&C6 \ Set the low byte of BLN(1 0) to &C6, so we now have STX BLN \ BLN(1 0) = &03C6, which we will use in the IRQ1 \ handler (this has nothing to do with drawing Saturn, \ it's all part of the copy protection) \ ****************************************************************************** \ \ Name: PLL1 (Part 3 of 3) \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw Saturn on the loading screen (draw the rings) \ Deep dive: Drawing Saturn on the loading screen \ \ ****************************************************************************** \ The following loop iterates CNT3(1 0) times, i.e. &500 \ or 1280 times, and draws the rings around the loading \ screen's Saturn .PLL3 JSR DORND \ Set A and X to signed random numbers between -128 and \ 127, so let's say A = r5 STA ZP \ Set ZP = r5 JSR SQUA2 \ Set (A P) = A * A \ = r5^2 STA ZP+1 \ Set ZP+1 = A \ = r5^2 / 256 JSR DORND \ Set A and X to signed random numbers between -128 and \ 127, so let's say A = r6 STA YY \ Set YY = r6 JSR SQUA2 \ Set (A P) = A * A \ = r6^2 STA T \ Set T = A \ = r6^2 / 256 ADC ZP+1 \ Set ZP+1 = A + r5^2 / 256 STA ZP+1 \ = r6^2 / 256 + r5^2 / 256 \ = (r5^2 + r6^2) / 256 LDA ZP \ Set A = ZP \ = r5 CMP #128 \ If A >= 128, set the C flag (so the C flag is now set \ to bit 7 of ZP, i.e. bit 7 of A) ROR A \ Rotate A and set the sign bit to the C flag, so bits \ 6 and 7 are now the same CMP #128 \ If A >= 128, set the C flag (so again, the C flag is \ set to bit 7 of A) ROR A \ Rotate A and set the sign bit to the C flag, so bits \ 5-7 are now the same, i.e. A is a random number in one \ of these ranges: \ \ %00000000 - %00011111 = 0-31 \ %11100000 - %11111111 = 224-255 \ \ In terms of signed 8-bit integers, this is a random \ number from -32 to 31. Let's call it r7 ADC YY \ Set A = A + YY \ = r7 + r6 TAX \ Set X = A \ = r6 + r7 JSR SQUA2 \ Set (A P) = A * A \ = (r6 + r7)^2 TAY \ Set Y = A \ = (r6 + r7)^2 / 256 ADC ZP+1 \ Set A = A + ZP+1 \ = (r6 + r7)^2 / 256 + (r5^2 + r6^2) / 256 \ = ((r6 + r7)^2 + r5^2 + r6^2) / 256 BCS PLC3 \ If the addition overflowed, jump down to PLC3 to skip \ to the next pixel CMP #80 \ If A >= 80, jump down to PLC3 to skip to the next BCS PLC3 \ pixel CMP #32 \ If A < 32, jump down to PLC3 to skip to the next pixel BCC PLC3 TYA \ Set A = Y + T ADC T \ = (r6 + r7)^2 / 256 + r6^2 / 256 \ = ((r6 + r7)^2 + r6^2) / 256 CMP #16 \ If A >= 16, skip to PL1 to plot the pixel BCS PL1 LDA ZP \ If ZP is positive (i.e. r5 < 128), jump down to PLC3 BPL PLC3 \ to skip to the next pixel .PL1 \ If we get here then the following is true: \ \ 32 <= ((r6 + r7)^2 + r5^2 + r6^2) / 256 < 80 \ \ and either this is true: \ \ ((r6 + r7)^2 + r6^2) / 256 >= 16 \ \ or both these are true: \ \ ((r6 + r7)^2 + r6^2) / 256 < 16 \ r5 >= 128 LDA YY \ Set A = YY \ = r6 JSR PIX \ Draw a pixel at screen coordinate (X + 128, A + 128), \ where: \ \ X = (random -32 to 31) + r6 \ A = r6 \ \ So this is the same as plotting at (x, y) where: \ \ r5 = random number from -128 to 127 \ r6 = random number from -128 to 127 \ r7 = r5, squashed into -32 to 31 \ \ 32 <= ((r6 + r7)^2 + r5^2 + r6^2) / 256 < 80 \ \ Either: ((r6 + r7)^2 + r6^2) / 256 >= 16 \ \ Or: ((r6 + r7)^2 + r6^2) / 256 < 16 \ r5 >= 128 \ \ x = r6 + r7 + 128 \ y = r6 + 128 \ \ which is what we want .PLC3 DEC CNT3 \ Decrement the counter in CNT3 (the low byte) BNE PLL3 \ Loop back to PLL3 until CNT3 = 0 DEC CNT3+1 \ Decrement the counter in CNT3+1 (the high byte) BNE PLL3 \ Loop back to PLL3 until CNT3+1 = 0 \ ****************************************************************************** \ \ Name: DORND \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Generate random numbers \ Deep dive: Generating random numbers \ Fixing ship positions \ \ ------------------------------------------------------------------------------ \ \ Set A and X to random numbers (though note that X is set to the random number \ that was returned in A the last time DORND was called). \ \ The C and V flags are also set randomly. \ \ This is a simplified version of the DORND routine in the main game code. It \ swaps the two calculations around and omits the ROL A instruction, but is \ otherwise very similar. See the DORND routine in the main game code for more \ details. \ \ ****************************************************************************** .DORND LDA RAND+1 \ r1´ = r1 + r3 + C TAX \ r3´ = r1 ADC RAND+3 STA RAND+1 STX RAND+3 LDA RAND \ X = r2´ = r0 TAX \ A = r0´ = r0 + r2 ADC RAND+2 STA RAND STX RAND+2 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SQUA2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A P) = A * A \ Deep dive: Shift-and-add multiplication \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of signed 8-bit numbers: \ \ (A P) = A * A \ \ This uses a similar approach to routine SQUA2 in the main game code, which \ itself uses the MU11 routine to do the multiplication. However, this version \ first ensures that A is positive, so it can support signed numbers. \ \ ****************************************************************************** .SQUA2 BPL SQUA \ If A > 0, jump to SQUA EOR #&FF \ Otherwise we need to negate A for the SQUA algorithm CLC \ to work, so we do this using two's complement, by ADC #1 \ setting A = ~A + 1 .SQUA STA Q \ Set Q = A and P = A STA P \ Set P = A LDA #0 \ Set A = 0 so we can start building the answer in A LDY #8 \ Set up a counter in Y to count the 8 bits in P LSR P \ Set P = P >> 1 \ and C flag = bit 0 of P .SQL1 BCC SQ1 \ If C (i.e. the next bit from P) is set, do the CLC \ addition for this bit of P: ADC Q \ \ A = A + Q .SQ1 ROR A \ Shift A right to catch the next digit of our result, \ which the next ROR sticks into the left end of P while \ also extracting the next bit of P ROR P \ Add the overspill from shifting A to the right onto \ the start of P, and shift P right to fetch the next \ bit for the calculation into the C flag DEY \ Decrement the loop counter BNE SQL1 \ Loop back for the next bit until P has been rotated \ all the way RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PIX \ Type: Subroutine \ Category: Drawing pixels \ Summary: Draw a single pixel at a specific coordinate \ \ ------------------------------------------------------------------------------ \ \ Draw a pixel at screen coordinate (X + 128, A + 128). The routine uses the \ same approach as the PIXEL routine in the main game code, except it plots a \ single pixel from TWOS instead of a two pixel dash from TWOS2. This applies \ to the top part of the screen (the monochrome mode 4 space view). \ \ See the PIXEL routine in the main game code for more details. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The signed screen x-coordinate of the pixel to draw, \ from -128 to 127, to be plotted relative to the origin \ at (128, 128) \ \ A The signed screen y-coordinate of the pixel to draw, \ from -128 to 127, to be plotted relative to the origin \ at (128, 128) \ \ ****************************************************************************** .PIX TAY \ Copy A into Y, for use later EOR #%10000000 \ Add 128 to A and treat this as an unsigned number from \ now on LSR A \ Set ZP+1 = &60 + A >> 3 LSR A LSR A ORA #&60 STA ZP+1 TXA \ Set A = X + 128 and treat this as an unsigned number EOR #%10000000 \ from now on AND #%11111000 \ Set ZP = (A >> 3) * 8 STA ZP TYA \ Set Y = Y mod 8, which is the pixel row within the AND #7 \ character block at which we want to draw our pixel TAY \ (as each character block has 8 rows) TXA \ Set X = X mod 8, which is the horizontal pixel number AND #7 \ within the character block where the pixel lies (as TAX \ each pixel line in the character block is 8 pixels \ wide) LDA TWOS,X \ Fetch a pixel from TWOS and OR it into ZP+Y ORA (ZP),Y STA (ZP),Y RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TWOS \ Type: Variable \ Category: Drawing pixels \ Summary: Ready-made single-pixel character row bytes for mode 4 \ \ ------------------------------------------------------------------------------ \ \ Ready-made bytes for plotting one-pixel points in mode 4 (the top part of the \ split screen). See the PIX routine for details. \ \ ****************************************************************************** .TWOS EQUB %10000000 EQUB %01000000 EQUB %00100000 EQUB %00010000 EQUB %00001000 EQUB %00000100 EQUB %00000010 EQUB %00000001 \ ****************************************************************************** \ \ Name: CNT \ Type: Variable \ Category: Drawing planets \ Summary: A counter for use in drawing Saturn's planetary body \ \ ------------------------------------------------------------------------------ \ \ Defines the number of iterations of the PLL1 loop, which draws the planet part \ of the loading screen's Saturn. \ \ ****************************************************************************** .CNT EQUW &0500 \ The number of iterations of the PLL1 loop (1280) \ ****************************************************************************** \ \ Name: CNT2 \ Type: Variable \ Category: Drawing planets \ Summary: A counter for use in drawing Saturn's background stars \ \ ------------------------------------------------------------------------------ \ \ Defines the number of iterations of the PLL2 loop, which draws the background \ stars on the loading screen. \ \ ****************************************************************************** .CNT2 EQUW &01DD \ The number of iterations of the PLL2 loop (477) \ ****************************************************************************** \ \ Name: CNT3 \ Type: Variable \ Category: Drawing planets \ Summary: A counter for use in drawing Saturn's rings \ \ ------------------------------------------------------------------------------ \ \ Defines the number of iterations of the PLL3 loop, which draws the rings \ around the loading screen's Saturn. \ \ ****************************************************************************** .CNT3 EQUW &0500 \ The number of iterations of the PLL3 loop (1280) \ ****************************************************************************** \ \ Name: ROOT \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate ZP = SQRT(ZP(1 0)) \ \ ------------------------------------------------------------------------------ \ \ Calculate the following square root: \ \ ZP = SQRT(ZP(1 0)) \ \ This routine is identical to LL5 in the main game code - it even has the same \ label names. The only difference is that LL5 calculates Q = SQRT(R Q), but \ apart from the variables used, the instructions are identical, so see the LL5 \ routine in the main game code for more details on the algorithm used here. \ \ ****************************************************************************** .ROOT LDY ZP+1 \ Set (Y Q) = ZP(1 0) LDA ZP STA Q \ So now to calculate ZP = SQRT(Y Q) LDX #0 \ Set X = 0, to hold the remainder STX ZP \ Set ZP = 0, to hold the result LDA #8 \ Set P = 8, to use as a loop counter STA P .LL6 CPX ZP \ If X < ZP, jump to LL7 BCC LL7 BNE LL8 \ If X > ZP, 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 - ZP SBC ZP TAX .LL7 ROL ZP \ Shift the result in Q to the left, shifting the C flag \ into bit 0 and bit 7 into the C flag ASL Q \ 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 Q \ 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 P \ Decrement the loop counter BNE LL6 \ Loop back to LL6 until we have done 8 loops RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: BEGIN% \ Type: Subroutine \ Category: Copy protection \ Summary: Single-byte decryption and copying routine, run on the stack \ \ ------------------------------------------------------------------------------ \ \ This routine is copied to the stack at &01F1. It pushes BLOCK to ENDBLOCK onto \ the stack, and decrypts the code from TUT onwards. \ \ The 15 instructions for this routine are pushed onto the stack and executed \ there. The instructions are pushed onto the stack in reverse (as the stack \ grows downwards in memory), so first the JMP gets pushed, then the STA, and \ so on. \ \ This is the code that is pushed onto the stack. It gets run by a JMP call to \ David2, which then calls the routine on the stack with JSR &01F1. \ \ 01F1 : PLA \ Remove the return address from the stack that was \ 01F2 : PLA \ put here by the JSR that called this routine \ \ 01F3 : LDA BLOCK,Y \ Set A = the Y-th byte of BLOCK \ \ 01F6 : PHA \ Push A onto the stack \ \ 01F7 : EOR TUT,Y \ EOR the Y-th byte of TUT with A \ 01FA : STA TUT,Y \ \ 01FD : JMP (David9) \ Jump to the address in David9 \ \ The routine is called inside a loop with Y as the counter. It counts from 0 to \ ENDBLOCK - BLOCK, so the routine eventually pushes every byte between BLOCK \ and ENDBLOCK onto the stack, as well as EOR'ing each byte from TUT onwards to \ decrypt that section. \ \ The elite-checksums.py script reverses the order of the bytes between BLOCK \ and ENDBLOCK in the final file, so pushing them onto the stack (which is a \ descending stack) realigns them in memory as assembled below. Not only that, \ but the last two bytes pushed on the stack are the ones that are at the start \ of the block at BLOCK, and these contain the address of ENTRY2. This is why \ the RTS at the end of part 4 above actually jumps to ENTRY2 in part 5. \ \ ****************************************************************************** .BEGIN% EQUB HI(David9) \ JMP (David9) EQUB LO(David9) EQUB &6C EQUB HI(TUT) \ STA TUT,Y EQUB LO(TUT) EQUB &99 IF _REMOVE_CHECKSUMS EQUB HI(TUT) \ If we have disabled checksums, then just load the Y-th EQUB LO(TUT) \ byte of TUT with LDA TUT,Y EQUB &B9 ELSE EQUB HI(TUT) \ EOR TUT,Y EQUB LO(TUT) EQUB &59 ENDIF PHA \ PHA EQUB HI(BLOCK) \ LDA BLOCK,Y EQUB LO(BLOCK) EQUB &B9 PLA \ PLA PLA \ PLA \ ****************************************************************************** \ \ Name: DOMOVE \ Type: Subroutine \ Category: Copy protection \ Summary: Multi-byte decryption and copying routine, run on the stack \ \ ------------------------------------------------------------------------------ \ \ This routine is copied to the stack at &01DF. It moves and decrypts a block of \ memory. The original source refers to the stack routine as MVDL. \ \ The 18 instructions for this routine are pushed onto the stack and executed \ there. The instructions are pushed onto the stack in reverse (as the stack \ grows downwards in memory), so first the RTS gets pushed, then the BNE, and \ so on. \ \ This is the code that is pushed onto the stack. It gets run by a JMP call to \ crunchit, which then calls the routine on the stack at MVDL, or &01DF. The \ label MVDL comes from a comment in the original source file ELITES. \ \ 01DF : .MVDL \ \ 01DF : LDA (ZP),Y \ Set A = the Y-th byte from the block whose address \ \ is in ZP(1 0) \ \ 01E1 : EOR OSB,Y \ EOR A with the Y-th byte on from OSB \ \ 01E4 : STA (P),Y \ Store A in the Y-th byte of the block whose \ \ address is in P(1 0) \ \ 01E6 : DEY \ Decrement the loop counter \ \ 01E7 : BNE MVDL \ Loop back to copy and EOR the next byte until we \ \ have copied an entire page (256 bytes) \ \ 01E9 : INC P+1 \ Increment the high byte of P(1 0) so it points to \ \ the next page of 256 bytes \ \ 01EB : INC ZP+1 \ Increment ZP(1 0) so it points to the next page of \ \ 256 bytes \ \ 01ED : DEX \ Decrement X \ \ 01EE : BNE MVDL \ Loop back to copy the next page \ \ 01F0 : RTS \ Return from the subroutine, which takes us back \ \ to the caller of the crunchit routine using a \ \ tail call, as we called this with JMP crunchit \ \ We call MVDL with the following arguments: \ \ (X Y) The number of bytes to copy \ \ ZP(1 0) The source address \ \ P(1 0) The destination address \ \ The routine moves and decrypts a block of memory, and is used in part 3 to \ move blocks of code and images that are embedded within the loader binary, \ either into low memory locations below PAGE (for the recursive token table and \ page at UU%), or into screen memory (for the loading screen and dashboard \ images). \ \ If checksums are disabled in the build, we don't do the EOR instruction, so \ the routine just moves and doesn't decrypt. \ \ ****************************************************************************** .DOMOVE RTS \ RTS EQUW &D0EF \ BNE MVDL DEX \ DEX EQUB ZP+1 \ INC ZP+1 INC P+1 \ INC P+1 EQUB &E6 EQUW &D0F6 \ BNE MVDL DEY \ DEY EQUB P \ STA(P),Y EQUB &91 IF _REMOVE_CHECKSUMS NOP \ If we have disabled checksums, skip the EOR so the NOP \ routine just does the copying part NOP ELSE EQUB HI(OSB) \ EOR OSB,Y EQUB LO(OSB) EQUB &59 ENDIF EQUB ZP \ LDA(ZP),Y EQUB &B1 \ ****************************************************************************** \ \ Name: UU% \ Type: Workspace \ Address: &0B00 \ Category: Workspaces \ Summary: Marker for a block that is moved as part of the obfuscation \ \ ------------------------------------------------------------------------------ \ \ The code from here to the end of the file gets copied to &0B00 (LE%) by part \ 3. It is called from the end of part 4, via ENTRY2 in part 5 below. \ \ ****************************************************************************** .UU% Q% = P% - LE% ORG LE% \ Set the assembly address to LE% \ ****************************************************************************** \ \ Name: CHECKbyt \ Type: Variable \ Category: Copy protection \ Summary: Checksum for the validity of the UU% workspace \ \ ------------------------------------------------------------------------------ \ \ We calculate the value of the CHECKbyt checksum in elite-checksum.py, so this \ just reserves a byte. It checks the validity of the first two pages of the UU% \ workspace, which gets copied to LE%. \ \ ****************************************************************************** .CHECKbyt BRK \ This could be an EQUB 0 directive instead of a BRK, \ but this is what's in the source code \ ****************************************************************************** \ \ Name: MAINSUM \ Type: Variable \ Category: Copy protection \ Summary: Two checksums for the decryption header and text token table \ \ ------------------------------------------------------------------------------ \ \ Contains two checksum values, one for the header code at LBL, and the other \ for the recursive token table from &0400 to &07FF. \ \ ****************************************************************************** .MAINSUM EQUB &CB \ This is the checksum value of the decryption header \ code (from LBL to elitea) that gets prepended to the \ main game code by elite-bcfs.asm and saved as \ ELThead.bin EQUB 0 \ This is the checksum value for the recursive token \ table from &0400 to &07FF. We calculate the value in \ elite-checksum.py, so this just reserves a byte \ ****************************************************************************** \ \ Name: FOOLV \ Type: Variable \ Category: Copy protection \ Summary: Part of the AFOOL roundabout obfuscation routine \ \ ------------------------------------------------------------------------------ \ \ FOOLV contains the address of FOOL. This is part of the JSR AFOOL obfuscation \ routine, which calls AFOOL, which then jumps to the address in FOOLV, which \ contains the address of FOOL, which contains an RTS instruction... so overall \ it does nothing, but in a rather roundabout fashion. \ \ ****************************************************************************** .FOOLV EQUW FOOL \ The address of FOOL, which contains an RTS \ ****************************************************************************** \ \ Name: CHECKV \ Type: Variable \ Category: Copy protection \ Summary: The address of the LBL routine in the decryption header \ \ ------------------------------------------------------------------------------ \ \ CHECKV contains the address of the LBL routine at the very start of the main \ game code file, in the decryption header code that gets prepended to the main \ game code by elite-bcfs.asm and saved as ELThead.bin \ \ ****************************************************************************** .CHECKV EQUW LOAD%+1 \ The address of the LBL routine \ ****************************************************************************** \ \ Name: block1 \ Type: Variable \ Category: Drawing the screen \ Summary: Palette data for the two dashboard colour scheme \ \ ------------------------------------------------------------------------------ \ \ Palette bytes for use with the split-screen mode 5. See TVT1 in the main game \ code for an explanation. \ \ ****************************************************************************** .block1 EQUB &F5, &E5 EQUB &B5, &A5 EQUB &76, &66 EQUB &36, &26 EQUB &D4, &C4 EQUB &94, &84 \ ****************************************************************************** \ \ Name: block2 \ Type: Variable \ Category: Drawing the screen \ Summary: Palette data for the space part of the screen \ \ ------------------------------------------------------------------------------ \ \ Palette bytes for use with the split-screen mode 4. See TVT1 in the main game \ code for an explanation. \ \ ****************************************************************************** .block2 EQUB &D0, &C0 EQUB &B0, &A0 EQUB &F0, &E0 EQUB &90, &80 EQUB &77, &67 EQUB &37, &27 \ ****************************************************************************** \ \ Name: TT26 \ Type: Subroutine \ Category: Text \ Summary: Print a character at the text cursor (WRCHV points here) \ \ ------------------------------------------------------------------------------ \ \ This routine prints a character at the text cursor (XC, YC). It is very \ similar to the routine of the same name in the main game code, so refer to \ that routine for a more detailed description. \ \ This routine, however, only works within a small 14x14 character text window, \ which we use for the tape loading messages, so there is extra code for fitting \ the text into the window (and it also reverses the effect of line feeds and \ carriage returns). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The character to be printed \ \ XC Contains the text column to print at (the x-coordinate) \ \ YC Contains the line number to print on (the y-coordinate) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A is preserved \ \ X X is preserved \ \ Y Y is preserved \ \ ****************************************************************************** .TT26 STA K3 \ Store the A, X and Y registers (in K3 for A, and on TYA \ the stack for the others), so we can restore them at PHA \ the end (so they don't get changed by this routine) TXA PHA .rr LDA K3 \ Set A = the character to be printed CMP #7 \ If this is a beep character (A = 7), jump to R5, BEQ R5 \ which will emit the beep, restore the registers and \ return from the subroutine CMP #32 \ If this is an ASCII character (A >= 32), jump to RR1 BCS RR1 \ below, which will print the character, restore the \ registers and return from the subroutine CMP #13 \ If this is control code 13 (carriage return) then jump BEQ RRX1 \ to RRX1, which will move along on character, restore \ the registers and return from the subroutine (as we \ don't have room in the text window for new lines) INC YC \ If we get here, then this is control code 10, a line \ feed, so move down one line and fall through into RRX1 \ to move the cursor to the start of the line .RRX1 LDX #7 \ Set the column number (x-coordinate) of the text STX XC \ to 7 BNE RR4 \ Jump to RR4 to restore the registers and return from \ the subroutine (this BNE is effectively a JMP as Y \ will never be zero) .RR1 LDX #&BF \ Set X to point to the first font page in ROM minus 1, \ which is &C0 - 1, or &BF ASL A \ If bit 6 of the character is clear (A is 32-63) ASL A \ then skip the following instruction BCC P%+4 LDX #&C1 \ A is 64-126, so set X to point to page &C1 ASL A \ If bit 5 of the character is clear (A is 64-95) BCC P%+3 \ then skip the following instruction INX \ Increment X, so X now contains the high byte \ (the page) of the address of the definition that we \ want, while A contains the low byte (the offset into \ the page) of the address STA P \ Store the address of this character's definition in STX P+1 \ P(1 0) LDA XC \ If the column number (x-coordinate) of the text is CMP #20 \ less than 20, skip to NOLF BCC NOLF LDA #7 \ Otherwise we just reached the end of the line, so STA XC \ move the text cursor to column 7, and down onto the INC YC \ next line .NOLF ASL A \ Multiply the x-coordinate (column) of the text by 8 ASL A \ and store in ZP, to get the low byte of the screen ASL A \ address for the character we want to print STA ZP INC XC \ Once we print the character, we want to move the text \ cursor to the right, so we do this by incrementing XC LDA YC \ If the row number (y-coordinate) of the text is less CMP #19 \ than 19, skip to RR3 BCC RR3 \ Otherwise we just reached the bottom of the screen, \ which is a small 14x14 character text window we use \ for showing the tape loading messages, so now we need \ to clear that window and move the cursor to the top LDA #7 \ Move the text cursor to column 7 STA XC LDA #&65 \ Set the high byte of the SC(1 0) to &65, for character STA SC+1 \ row 5 of the screen LDY #7*8 \ Set Y = 7 * 8, for column 7 (as there are 8 bytes per \ character block) LDX #14 \ Set X = 14, to count the number of character rows we \ need to clear STY SC \ Set the low byte of SC(1 0) to 7*8, so SC(1 0) now \ points to the character block at row 5, column 7, at \ the top-left corner of the small text window LDA #0 \ Set A = 0 for use in clearing the screen (which we do \ by setting the screen memory to 0) TAY \ Set Y = 0 .David1 STA (SC),Y \ Clear the Y-th byte of the block pointed to by SC(1 0) INY \ Increment the counter in Y CPY #14*8 \ Loop back to clear the next byte until we have done 14 BCC David1 \ lots of 8 bytes (i.e. 14 characters, the width of the \ small text window) TAY \ Set Y = 0, ready for the next row INC SC+1 \ Point SC(1 0) to the next page in memory, i.e. the \ next character row DEX \ Decrement the counter in X BPL David1 \ Loop back to David1 until we have done 14 character \ rows (the height of the small text window) LDA #5 \ Move the text cursor to row 5 STA YC BNE rr \ Jump to rr to print the character we were about to \ print when we ran out of space (this BNE is \ effectively a JMP as A will never be zero) .RR3 ORA #&60 \ Add &60 to YC, giving us the page number that we want STA ZP+1 \ Store the page number of the destination screen \ location in ZP+1, so ZP now points to the full screen \ location where this character should go LDY #7 \ We want to print the 8 bytes of character data to the \ screen (one byte per row), so set up a counter in Y \ to count these bytes .RRL1 LDA (P),Y \ The character definition is at P(1 0) - we set this up \ above - so load the Y-th byte from P(1 0) STA (ZP),Y \ Store the Y-th byte at the screen address for this \ character location DEY \ Decrement the loop counter BPL RRL1 \ Loop back for the next byte to print to the screen .RR4 PLA \ We're done printing, so restore the values of the TAX \ A, X and Y registers that we saved above, loading them PLA \ from K3 (for A) and the stack (for X and Y) TAY LDA K3 .FOOL RTS \ Return from the subroutine .R5 LDA #7 \ Control code 7 makes a beep, so load this into A JSR osprint \ Call OSPRINT to "print" the beep character JMP RR4 \ Jump to RR4 to restore the registers and return from \ the subroutine using a tail call \ ****************************************************************************** \ \ Name: osprint \ Type: Subroutine \ Category: Utility routines \ Summary: Print a character \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The character to print \ \ ****************************************************************************** .TUT .osprint JMP (OSPRNT) \ Jump to the address in OSPRNT and return using a \ tail call EQUB &6C \ This byte appears to be unused \ ****************************************************************************** \ \ Name: command \ Type: Subroutine \ Category: Utility routines \ Summary: Execute an OS command \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ (Y X) The address of the OS command string to execute \ \ ****************************************************************************** .command JMP (oscliv) \ Jump to &FFF7 to execute the OS command pointed to \ by (Y X) and return using a tail call \ ****************************************************************************** \ \ Name: MESS1 \ Type: Variable \ Category: Utility routines \ Summary: Contains an OS command string for loading the main game code \ \ ****************************************************************************** .MESS1 IF DISC EQUS "L.ELTcode 1100" \ This is short for "*LOAD ELTcode 1100" ELSE EQUS "L.ELITEcode F1F" \ This is short for "*LOAD ELITEcode F1F" ENDIF EQUB 13 \ ****************************************************************************** \ \ Name: Elite loader (Part 5 of 6) \ Type: Subroutine \ Category: Loader \ Summary: Load main game code, decrypt it, move it to the correct location \ \ ------------------------------------------------------------------------------ \ \ This part loads the main game code, decrypts it and moves it to the correct \ location for it to run. \ \ The code in this part is encrypted by elite-checksum.py and is decrypted in \ part 4 by the same routine that moves part 6 onto the stack. \ \ ****************************************************************************** .ENTRY2 \ We start this part of the loader by setting the \ following: \ \ OSPRNT(1 0) = WRCHV \ WRCHV(1 0) = TT26 \ (Y X) = MESS1(1 0) \ \ so any character printing will use the TT26 routine LDA &020E \ Copy the low byte of WRCHV to the low byte of OSPRNT STA OSPRNT LDA #LO(TT26) \ Set the low byte of WRCHV to the low byte of TT26 STA &020E LDX #LO(MESS1) \ Set X to the low byte of MESS1 LDA &020F \ Copy the high byte of WRCHV to the high byte of OSPRNT STA OSPRNT+1 LDA #HI(TT26) \ Set the high byte of WRCHV to the high byte of TT26 LDY #HI(MESS1) \ and set Y to the high byte of MESS1 STA &020F JSR AFOOL \ This calls AFOOL, which jumps to the address in FOOLV, \ which contains the address of FOOL, which contains an \ RTS instruction... so overall this does nothing, but \ in a rather roundabout fashion JSR command \ Call command to execute the OSCLI command pointed to \ by (Y X) in MESS1, which starts loading the main game \ code JSR 512-LEN+CHECKER-ENDBLOCK \ Call the CHECKER routine in its new location on \ the stack, to run a number of checksums on the \ code (this routine, along with the whole of part \ 6, was pushed onto the stack in part 4) JSR AFOOL \ Another call to the round-the-houses routine to try \ and distract the crackers, presumably IF DISC LDA #140 \ Call OSBYTE with A = 140 and X = 12 to select the LDX #12 \ tape filing system (i.e. do a *TAPE command) JSR OSBYTE ENDIF LDA #0 \ Set SVN to 0, as the main game code checks the value STA SVN \ of this location in its IRQ1 routine, so it needs to \ be set to 0 so it can work properly once it takes over \ when the game itself runs \ We now decrypt and move the main game code from &1128 \ to &0F40 LDX #HI(LC%) \ Set X = high byte of LC%, the maximum size of the main \ game code, so if we move this number of pages, we will \ have definitely moved all the game code down LDA #LO(L%) \ Set ZP(1 0) = L% (the start of the game code) STA ZP LDA #HI(L%) STA ZP+1 LDA #LO(C%) \ Set P(1 0) = C% = &0F40 STA P LDA #HI(C%) STA P+1 LDY #0 \ Set Y as a counter for working our way through every \ byte of the game code. We EOR the counter with the \ current byte to decrypt it .ML1 TYA \ Copy the counter into A IF _REMOVE_CHECKSUMS LDA (ZP),Y \ If we have disabled checksums, just fetch the byte to \ copy from the Y-th block pointed to by ZP(1 0) ELSE EOR (ZP),Y \ Fetch the byte and EOR it with the counter ENDIF STA (P),Y \ Store the copied (and decrypted) byte in the Y-th byte \ of the block pointed to by P(1 0) INY \ Increment the loop counter BNE ML1 \ Loop back for the next byte until we have finished the \ first 256 bytes INC ZP+1 \ Increment the high bytes of both ZP(1 0) and P(1 0) to INC P+1 \ point to the next 256 bytes DEX \ Decrement the number of pages we need to copy in X BPL ML1 \ Loop back to copy and decrypt the next page of bytes \ until we have done them all \ S% points to the entry point for the main game code, \ so the following copies the addresses from the start \ of the main code (see the S% label in the main game \ code for the vector values) LDA S%+6 \ Set BRKV to point to the BR1 routine in the main game STA &0202 \ code LDA S%+7 STA &0203 LDA S%+2 \ Set WRCHV to point to the TT26 routine in the main STA &020E \ game code LDA S%+3 STA &020F RTS \ This RTS actually does a jump to the first instruction \ in BLOCK, after the two EQUW operatives, which is now \ on the stack. This takes us to the next and final \ step of the loader in part 6. See the documentation \ for the stack routine at BEGIN% for more details .AFOOL JMP (FOOLV) \ This jumps to the address in FOOLV as part of the \ JSR AFOOL instruction above, which does nothing except \ take us on wild goose chase \ ****************************************************************************** \ \ Name: M2 \ Type: Variable \ Category: Utility routines \ Summary: Used for testing the 6522 System VIA status byte in IRQ1 \ \ ------------------------------------------------------------------------------ \ \ Used for testing bit 1 of the 6522 System VIA status byte in the IRQ1 routine, \ as well as bit 1 of the block flag. \ \ ****************************************************************************** .M2 EQUB %00000010 \ Bit 1 is set \ ****************************************************************************** \ \ Name: IRQ1 \ Type: Subroutine \ Category: Drawing the screen \ Summary: The loader's screen-mode interrupt handler (IRQ1V points here) \ Deep dive: The split-screen mode in BBC Micro Elite \ \ ------------------------------------------------------------------------------ \ \ The main interrupt handler, which implements Elite's split-screen mode. \ \ This routine is similar to the main IRQ1 routine in the main game code, except \ it's a bit simpler (it doesn't need to support the mode-flashing effect of \ hyperspace, for example). \ \ It also sets Timer 1 to a different value, 14386 instead of 14622. The split \ in the split-screen mode does overlap more in the loader than in the game, so \ it's interesting that they didn't fine-tune this version as much. \ \ For more details on how the following works, see the IRQ1 routine in the main \ game code. \ \ ****************************************************************************** .VIA2 LDA #%00000100 \ Set the Video ULA control register (SHEILA &20) to STA &FE20 \ %00000100, which is the same as switching to mode 5, \ (i.e. the bottom part of the screen) but with no \ cursor LDY #11 \ We now apply the palette bytes from block1 to the \ mode 5 screen, so set a counter in Y for 12 bytes .inlp1 LDA block1,Y \ Copy the Y-th palette byte from block1 to SHEILA &21 STA &FE21 \ to map logical to actual colours for the bottom part \ of the screen (i.e. the dashboard) DEY \ Decrement the palette byte counter BPL inlp1 \ Loop back to the inlp1 until we have copied all the \ palette bytes PLA \ Restore Y from the stack TAY JMP (VEC) \ Jump to the address in VEC, which was set to the \ original IRQ1V vector in part 4, so this instruction \ passes control to the next interrupt handler .IRQ1 TYA \ Store Y on the stack PHA IF PROT AND NOT(DISC) \ By this point, we have set up the following in \ various places throughout the loader code (such as \ part 2 and PLL1): \ \ BLPTR(1 0) = &03CA \ BLN(1 0) = &03C6 \ EXCN(1 0) = &03C2 \ \ BLPTR (&03CA) is a byte in the MOS workspace that \ stores the block flag of the most recent block loaded \ from tape \ \ BLN (&03C6) is the low byte of the number of the last \ block loaded from tape \ \ EXCN (&03C2) is the low byte of the execution address \ of the file being loaded LDY #0 \ Set A to the block flag of the most recent block LDA (BLPTR),Y \ loaded from tape BIT M2 \ If bit 1 of the block flag is set, jump to itdone BNE itdone EOR #%10000011 \ Otherwise flip bits 0, 1 and 7 of A. This has two \ main effects: \ \ * Bit 0 of the block flag gets cleared. Most \ cassette versions of Acornsoft games are saved to \ tape with locked blocks, so you can't just load \ the game into memory (you'll get a "Locked" error \ for each block). Locked blocks have bit 0 set, so \ this clears the locked status, so when the MOS \ gets round to checking whether the block is \ locked, we've already cleared it and updated it in \ memory (which we do below), so the block loads \ without throwing an error \ \ * Bit 1 of the block flag gets set, so we won't \ increment BLCNT again until the next block starts \ loading (so in this way we count the number of \ blocks loaded in BLCNT) INC BLCNT \ Increment BLCNT, which was initialised to 0 in part 3 BNE ZQK \ If BLCNT is non-zero, skip the next instruction DEC BLCNT \ If incrementing BLCNT set it to zero, decrement it, so \ this sets a maximum of 255 on BLCNT .ZQK STA (BLPTR),Y \ Store the updated value of A in the block flag, so the \ block gets unlocked LDA #35 \ If the block number in BLN is 35, skip the next CMP (BLN),Y \ instruction, leaving A = 32 = &23 BEQ P%+4 EOR #17 \ Set A = 35 EOR 17 = 50 = &32 CMP (EXCN),Y \ If the low byte of the execution address of the file BEQ itdone \ we are loading is equal to A (which is either &23 or \ &32), skip to itdone DEC LOAD% \ Otherwise decrement LOAD%, which is the address of the \ first byte of the main game code file (i.e. the load \ address of "ELTcode"), so this decrements the first \ byte of the file we are loading, i.e. the LBL variable \ added by the Big Code File source .itdone ENDIF LDA VIA+&4D \ Read the 6522 System VIA status byte bit 1 (SHEILA BIT M2 \ &4D), which is set if vertical sync has occurred on \ the video system BNE LINSCN \ If we are on the vertical sync pulse, jump to LINSCN \ to set up the timers to enable us to switch the \ screen mode between the space view and dashboard AND #%01000000 \ If the 6522 System VIA status byte bit 6 is set, which BNE VIA2 \ means timer 1 has timed out, jump to VIA2 PLA \ Restore Y from the stack TAY JMP (VEC) \ Jump to the address in VEC, which was set to the \ original IRQ1V vector in part 4, so this instruction \ passes control to the next interrupt handler .LINSCN LDA #50 \ Set 6522 System VIA T1C-L timer 1 low-order counter STA VIA+&44 \ (SHEILA &44) to 50 LDA #VSCAN \ Set 6522 System VIA T1C-L timer 1 high-order counter STA VIA+&45 \ (SHEILA &45) to VSCAN (56) to start the T1 counter \ counting down from 14386 at a rate of 1 MHz LDA #8 \ Set the Video ULA control register (SHEILA &20) to STA &FE20 \ %00001000, which is the same as switching to mode 4 \ (i.e. the top part of the screen) but with no cursor LDY #11 \ We now apply the palette bytes from block2 to the \ mode 4 screen, so set a counter in Y for 12 bytes .inlp2 LDA block2,Y \ Copy the Y-th palette byte from block2 to SHEILA &21 STA &FE21 \ to map logical to actual colours for the top part of \ the screen (i.e. the space view) DEY \ Decrement the palette byte counter BPL inlp2 \ Loop back to the inlp1 until we have copied all the \ palette bytes PLA \ Restore Y from the stack TAY JMP (VEC) \ Jump to the address in VEC, which was set to the \ original IRQ1V vector in part 4, so this instruction \ passes control to the next interrupt handler \ ****************************************************************************** \ \ Name: BLOCK \ Type: Variable \ Category: Copy protection \ Summary: Addresses for the obfuscated jumps that use RTS not JMP \ \ ------------------------------------------------------------------------------ \ \ These two addresses get pushed onto the stack in part 4. The first EQUW is the \ address of ENTRY2, while the second is the address of the first instruction in \ part 6, after it is pushed onto the stack. \ \ This entire section from BLOCK to ENDBLOCK gets copied into the stack at \ location &015E by part 4, so by the time we call the routine at the second \ EQUW address at the start, the entry point is on the stack at &0163. \ \ This means that the RTS instructions at the end of parts 4 and 5 jump to \ ENTRY2 and the start of part 6 respectively. See part 4 for details. \ \ ****************************************************************************** .BLOCK EQUW ENTRY2-1 EQUW 512-LEN+BLOCK-ENDBLOCK+3 \ ****************************************************************************** \ \ Name: Elite loader (Part 6 of 6) \ Type: Subroutine \ Category: Loader \ Summary: Set up interrupt vectors, calculate checksums, run main game code \ \ ------------------------------------------------------------------------------ \ \ This is the final part of the loader. It sets up some of the main game's \ interrupt vectors and calculates various checksums, before finally handing \ over to the main game. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ nononono Reset the machine \ \ ****************************************************************************** LDA VIA+&44 \ Read the 6522 System VIA T1C-L timer 1 low-order STA &0001 \ counter (SHEILA &44), which decrements one million \ times a second and will therefore be pretty random, \ and store it in location &0001, which is among the \ main game code's random seeds (so this seeds the \ random number generator for the main game) SEI \ Disable all interrupts LDA #%00111001 \ Set 6522 System VIA interrupt enable register IER STA VIA+&4E \ (SHEILA &4E) bits 0 and 3-5 (i.e. disable the Timer1, \ CB1, CB2 and CA2 interrupts from the System VIA) \LDA #&7F \ These instructions are commented out in the original \STA &FE6E \ source with the comment "already done", which they \LDA IRQ1V \ were, in part 4 \STA VEC \LDA IRQ1V+1 \STA VEC+1 LDA S%+4 \ S% points to the entry point for the main game code, STA IRQ1V \ so this copies the address of the main game's IRQ1 LDA S%+5 \ routine from the start of the main code into IRQ1V STA IRQ1V+1 LDA #VSCAN \ Set 6522 System VIA T1C-L timer 1 high-order counter STA VIA+&45 \ (SHEILA &45) to VSCAN (56) to start the T1 counter \ counting down from 14080 at a rate of 1 MHz (this is \ a different value to the main game code) CLI \ Re-enable interrupts \LDA #129 \ These instructions are commented out in the original \LDY #&FF \ source. They call OSBYTE with A = 129, X = 1 and \LDX #1 \ Y = &FF, which returns the machine type in X, so \JSR OSBYTE \ this code would detect the MOS version \ \TXA \EOR #&FF \STA MOS \ \BMI BLAST LDY #0 \ Call OSBYTE with A = 200, X = 3 and Y = 0 to disable LDA #200 \ the ESCAPE key and clear memory if the BREAK key is LDX #3 \ pressed JSR OSBYTE \ The rest of the routine calculates various checksums \ and makes sure they are correct before proceeding, to \ prevent code tampering. We start by calculating the \ checksum for the main game code from &0F40 to &5540, \ which just adds up every byte and checks it against \ the checksum stored at the end of the main game code .BLAST LDA #HI(S%) \ Set ZP(1 0) = S% STA ZP+1 \ LDA #LO(S%) \ so ZP(1 0) points to the start of the main game code STA ZP LDX #&45 \ We are going to checksum &45 pages from &0F40 to &5540 \ so set a page counter in X LDY #0 \ Set Y to count through each byte within each page TYA \ Set A = 0 for building the checksum .CHK CLC \ Add the Y-th byte of this page of the game code to A ADC (ZP),Y INY \ Increment the counter for this page BNE CHK \ Loop back for the next byte until we have finished \ adding up this page INC ZP+1 \ Increment the high byte of ZP(1 0) to point to the \ next page DEX \ Decrement the page counter we set in X BPL CHK \ Loop back to add up the next page until we have done \ them all IF _REMOVE_CHECKSUMS LDA #0 \ If we have disabled checksums, just set A to 0 so the NOP \ BEQ below jumps to itsOK ELSE CMP D%-1 \ D% is set to the address of the byte after the end of \ the code, so this compares the result to the last byte \ in the main game code at location checksum0 ENDIF BEQ itsOK \ If the checksum we just calculated matches the value \ in location checksum0, jump to itsOK .nononono STA S%+1 \ If we get here then the checksum was wrong, so first \ we store the incorrect checksum value in the low byte \ of the address stored at the start of the main game \ code, which contains the address of TT170, the entry \ point for the main game (so this hides this address \ from prying eyes) LDA #%01111111 \ Set 6522 System VIA interrupt enable register IER STA &FE4E \ (SHEILA &4E) bits 0-6 (i.e. disable all hardware \ interrupts from the System VIA) JMP (&FFFC) \ Jump to the address in &FFFC to reset the machine .itsOK JMP (S%) \ The checksum was correct, so we call the address held \ in the first two bytes of the main game code, which \ point to TT170, the entry point for the main game \ code, so this, finally, is where we hand over to the \ game itself \ ****************************************************************************** \ \ Name: CHECKER \ Type: Subroutine \ Category: Copy protection \ Summary: Run checksum checks on tokens, loader and tape block count \ \ ------------------------------------------------------------------------------ \ \ This routine runs checksum checks on the recursive token table and the loader \ code at the start of the main game code file, to prevent tampering with these \ areas of memory. It also runs a check on the tape loading block count. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ ENDBLOCK Denotes the end of the encrypted code that starts at \ BLOCK \ \ ****************************************************************************** .CHECKER \ First we check the MAINSUM+1 checksum for the \ recursive token table from &0400 to &07FF LDY #0 \ Set Y = 0 to count through each byte within each page LDX #4 \ We are going to checksum 4 pages from &0400 to &07FF \ so set a page counter in X STX ZP+1 \ Set ZP(1 0) = &0400, to point to the start of the code STY ZP \ we want to checksum TYA \ Set A = 0 for building the checksum .CHKq CLC \ Add the Y-th byte of this page of the token table to A ADC (ZP),Y INY \ Increment the counter for this page BNE CHKq \ Loop back for the next byte until we have finished \ adding up this page INC ZP+1 \ Increment the high byte of ZP(1 0) to point to the \ next page DEX \ Decrement the page counter we set in X BNE CHKq \ Loop back to add up the next page until we have done \ them all CMP MAINSUM+1 \ Compare the result to the contents of MAINSUM+1, which \ contains the checksum for the table (this gets set by \ elite-checksum.py) IF _REMOVE_CHECKSUMS NOP \ If we have disabled checksums, do nothing NOP ELSE BNE nononono \ If the checksum we just calculated does not match the \ contents of MAINSUM+1, jump to nononono to reset the \ machine ENDIF \ Next, we check the LBL routine in the header that's \ appended to the main game code in elite-bcfs.asm, and \ which is currently loaded at LOAD% (which contains the \ load address of the main game code file) TYA \ Set A = 0 for building the checksum (as Y is still 0 \ from the above checksum loop) .CHKb CLC \ Add the Y-th byte of LOAD% to A ADC LOAD%,Y INY \ Increment the counter CPY #40 \ There are 40 bytes in the loader, so loop back until BNE CHKb \ we have added them all CMP MAINSUM \ Compare the result to the contents of MAINSUM, which \ contains the checksum for loader code IF _REMOVE_CHECKSUMS NOP \ If we have disabled checksums, do nothing NOP ELSE BNE nononono \ If the checksum we just calculated does not match the \ contents of MAINSUM, jump to nononono to reset the \ machine ENDIF \ Finally, we check the block count from the tape \ loading code in the IRQ1 routine, which counts the \ number of blocks in the main game code IF PROT AND NOT(DISC) LDA BLCNT \ If the tape protection is enabled and we are loading CMP #&4F \ from tape (as opposed to disc), check that the block BCC nononono \ count in BLCNT is &4F, and if it isn't, jump to \ nononono to reset the machine ENDIF IF _REMOVE_CHECKSUMS RTS \ If we have disabled checksums, return from the NOP \ subroutine NOP ELSE JMP (CHECKV) \ Call the LBL routine in the header (whose address is \ in CHECKV). This routine is inserted before the main \ game code by elite-bcfs.asm, and it checks the \ validity of the first two pages of the UU% routine, \ which was copied to LE% above, and which contains a \ checksum byte in CHECKbyt. We then return from the \ subroutine using a tail call ENDIF .ENDBLOCK \ ****************************************************************************** \ \ Name: XC \ Type: Variable \ Category: Text \ Summary: The x-coordinate of the text cursor \ \ ------------------------------------------------------------------------------ \ \ Contains the x-coordinate of the text cursor (i.e. the text column) with an \ initial value of column 7, at the top-left corner of the 14x14 text window \ where we show the tape loading messages (see TT26 for details). \ \ ****************************************************************************** .XC EQUB 7 \ ****************************************************************************** \ \ Name: YC \ Type: Variable \ Category: Text \ Summary: The y-coordinate of the text cursor \ \ ------------------------------------------------------------------------------ \ \ Contains the y-coordinate of the text cursor (i.e. the text row) with an \ initial value of row 6, at the top-left corner of the 14x14 text window where \ we show the tape loading messages (see TT26 for details). \ \ ****************************************************************************** .YC EQUB 6 \ ****************************************************************************** \ \ Save ELITE.unprot.bin \ \ ****************************************************************************** COPYBLOCK LE%, P%, UU% \ Copy the block that we assembled at LE% to \ UU%, which is where it will actually run PRINT "Addresses for the scramble routines in elite-checksum.py" PRINT "BLOCK_offset = ", ~(BLOCK - LE%) + (UU% - CODE%) PRINT "ENDBLOCK_offset = ", ~(ENDBLOCK - LE%) + (UU% - CODE%) PRINT "MAINSUM_offset = ", ~(MAINSUM - LE%) + (UU% - CODE%) PRINT "TUT_offset = ", ~(TUT - LE%) + (UU% - CODE%) PRINT "CHECKbyt_offset = ", ~(CHECKbyt - LE%) + (UU% - CODE%) PRINT "CODE_offset = ", ~(OSB - CODE%) PRINT "UU% = ", ~UU% PRINT "Q% = ", ~Q% PRINT "OSB = ", ~OSB PRINT "Memory usage: ", ~LE%, " - ", ~P% PRINT "Stack: ",LEN + ENDBLOCK - BLOCK PRINT "S. ELITE ", ~CODE%, " ", ~UU% + (P% - LE%), " ", ~run, " ", ~CODE% SAVE "3-assembled-output/ELITE.unprot.bin", CODE%, UU% + (P% - LE%), run, CODE% ================================================ FILE: 1-source-files/main-sources/elite-readme.asm ================================================ \ ****************************************************************************** \ \ BBC MICRO CASSETTE ELITE README SOURCE \ \ BBC Micro cassette Elite was written by Ian Bell and David Braben and is \ copyright Acornsoft 1984 \ \ The code in this file is identical to the source discs released on Ian Bell's \ personal website at http://www.elitehomepage.org/ (it's just been reformatted \ to be more readable) \ \ The commentary is copyright Mark Moxon, and any misunderstandings or mistakes \ in the documentation are entirely my fault \ \ The terminology and notations used in this commentary are explained at \ https://elite.bbcelite.com/terminology \ \ The deep dive articles referred to in this commentary can be found at \ https://elite.bbcelite.com/deep_dives \ \ ------------------------------------------------------------------------------ \ \ This source file produces a README file for BBC Micro cassette Elite. \ \ ------------------------------------------------------------------------------ \ \ This source file produces the following binary file: \ \ * README.txt \ \ ****************************************************************************** INCLUDE "1-source-files/main-sources/elite-build-options.asm" _SOURCE_DISC = (_VARIANT = 1) _TEXT_SOURCES = (_VARIANT = 2) _STH_CASSETTE = (_VARIANT = 3) .readme EQUB 10, 13 EQUS "---------------------------------------" EQUB 10, 13 EQUS "Acornsoft Elite" EQUB 10, 13 EQUB 10, 13 EQUS "Version: BBC Micro cassette" EQUB 10, 13 IF _SOURCE_DISC EQUS "Variant: Ian Bell's source disc" EQUB 10, 13 ELIF _TEXT_SOURCES EQUS "Variant: Ian Bell's text sources" EQUB 10, 13 ELIF _STH_CASSETTE EQUS "Variant: Stairway to Hell cassette" EQUB 10, 13 EQUS "Product: Acornsoft SBG38" EQUB 10, 13 ENDIF EQUB 10, 13 EQUS "See www.bbcelite.com for details" EQUB 10, 13 EQUS "---------------------------------------" EQUB 10, 13 SAVE "3-assembled-output/README.txt", readme, P% ================================================ FILE: 1-source-files/main-sources/elite-source.asm ================================================ \ ****************************************************************************** \ \ BBC MICRO CASSETTE ELITE MAIN GAME SOURCE \ \ BBC Micro cassette Elite was written by Ian Bell and David Braben and is \ copyright Acornsoft 1984 \ \ The code in this file is identical to the source discs released on Ian Bell's \ personal website at http://www.elitehomepage.org/ (it's just been reformatted \ to be more readable) \ \ The commentary is copyright Mark Moxon, and any misunderstandings or mistakes \ in the documentation are entirely my fault \ \ The terminology and notations used in this commentary are explained at \ https://elite.bbcelite.com/terminology \ \ The deep dive articles referred to in this commentary can be found at \ https://elite.bbcelite.com/deep_dives \ \ ------------------------------------------------------------------------------ \ \ This source file contains the main game code for BBC Micro cassette Elite. It \ also contains the ship blueprints and game text. \ \ ------------------------------------------------------------------------------ \ \ This source file produces the following binary files: \ \ * ELTA.bin \ * ELTB.bin \ * ELTC.bin \ * ELTD.bin \ * ELTE.bin \ * ELTF.bin \ * ELTG.bin \ * PYTHON.bin \ * SHIPS.bin \ * WORDS9.bin \ \ ****************************************************************************** INCLUDE "1-source-files/main-sources/elite-build-options.asm" _SOURCE_DISC = (_VARIANT = 1) _TEXT_SOURCES = (_VARIANT = 2) _STH_CASSETTE = (_VARIANT = 3) GUARD &6000 \ Guard against assembling over screen memory \ ****************************************************************************** \ \ Configuration variables \ \ ****************************************************************************** CODE% = &0F40 \ The address where the code will be run LOAD% = &1128 \ The address where the code will be loaded CODE_WORDS% = &0400 \ The address where the text data will be run LOAD_WORDS% = &1100 \ The address where the text data will be loaded Q% = _MAX_COMMANDER \ Set Q% to TRUE to max out the default commander, FALSE \ for the standard default commander NOST = 18 \ The number of stardust particles in normal space (this \ goes down to 3 in witchspace) NOSH = 12 \ The maximum number of ships in our local bubble of \ universe NTY = 13 \ The number of different ship types COPS = 2 \ Ship type for a Viper THG = 6 \ Ship type for a Thargoid CYL = 7 \ Ship type for a Cobra Mk III (trader) SST = 8 \ Ship type for the space station MSL = 9 \ Ship type for a missile AST = 10 \ Ship type for an asteroid OIL = 11 \ Ship type for a cargo canister TGL = 12 \ Ship type for a Thargon ESC = 13 \ Ship type for an escape pod POW = 15 \ Pulse laser power NI% = 36 \ The number of bytes in each ship's data block (as \ stored in INWK and K%) VSCAN = 57 \ Defines the split position in the split-screen mode X = 128 \ The centre x-coordinate of the 256 x 192 space view Y = 96 \ The centre y-coordinate of the 256 x 192 space view f0 = &20 \ Internal key number for red key f0 (Launch, Front) f1 = &71 \ Internal key number for red key f1 (Buy Cargo, Rear) f2 = &72 \ Internal key number for red key f2 (Sell Cargo, Left) f3 = &73 \ Internal key number for red key f3 (Equip Ship, Right) f4 = &14 \ Internal key number for red key f4 (Long-range Chart) f5 = &74 \ Internal key number for red key f5 (Short-range Chart) f6 = &75 \ Internal key number for red key f6 (Data on System) f7 = &16 \ Internal key number for red key f7 (Market Price) f8 = &76 \ Internal key number for red key f8 (Status Mode) f9 = &77 \ Internal key number for red key f9 (Inventory) RE = &23 \ The obfuscation byte used to hide the recursive tokens \ table from crackers viewing the binary code VIA = &FE00 \ Memory-mapped space for accessing internal hardware, \ such as the video ULA, 6845 CRTC and 6522 VIAs (also \ known as SHEILA) OSBYTE = &FFF4 \ The address for the OSBYTE routine, which is used \ three times in the main game code OSWORD = &FFF1 \ The address for the OSWORD routine, which is used \ twice in the main game code OSFILE = &FFDD \ The address for the OSFILE routine, which is used \ once in the main game code \ ****************************************************************************** \ \ Name: ZP \ Type: Workspace \ Address: &0000 to &00E1 \ Category: Workspaces \ Summary: Lots of important variables are stored in the zero page workspace \ as it is quicker and more space-efficient to access memory here \ \ ****************************************************************************** ORG &0000 \ Set the assembly address to &0000 .ZP SKIP 0 \ The start of the zero page workspace .RAND SKIP 4 \ Four 8-bit seeds for the random number generation \ system implemented in the DORND routine .TRTB% SKIP 2 \ Contains the address of the keyboard translation \ table, which is used to translate internal key \ numbers to ASCII .T1 SKIP 1 \ Temporary storage, used in a number of places .SC SKIP 1 \ Screen address (low byte) \ \ Elite draws on-screen by poking bytes directly into \ screen memory, and SC(1 0) is typically set to the \ address of the character block containing the pixel \ we want to draw .SCH SKIP 1 \ Screen address (high byte) .XX16 SKIP 18 \ Temporary storage for a block of values, used in a \ number of places .P SKIP 3 \ Temporary storage, used in a number of places .XX0 SKIP 2 \ 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 .INF SKIP 2 \ Temporary storage, typically used for storing the \ address of a ship's data block, so it can be copied \ to and from the internal workspace at INWK .V SKIP 2 \ Temporary storage, typically used for storing an \ address pointer .XX SKIP 2 \ Temporary storage, typically used for storing a 16-bit \ x-coordinate .YY SKIP 2 \ Temporary storage, typically used for storing a 16-bit \ y-coordinate .SUNX SKIP 2 \ The 16-bit x-coordinate of the vertical centre axis \ of the sun (which might be off-screen) .BETA SKIP 1 \ The current pitch angle beta, which is reduced from \ JSTY to a sign-magnitude value between -8 and +8 \ \ This describes how fast we are pitching our ship, and \ determines how fast the universe pitches around us \ \ The sign bit is also stored in BET2, while the \ opposite sign is stored in BET2+1 .BET1 SKIP 1 \ The magnitude of the pitch angle beta, i.e. |beta|, \ which is a positive value between 0 and 8 .XC SKIP 1 \ The x-coordinate of the text cursor (i.e. the text \ column), which can be from 0 to 32 \ \ A value of 0 denotes the leftmost column and 32 the \ rightmost column, but because the top part of the \ screen (the space view) has a border box that \ clashes with columns 0 and 32, text is only shown \ in columns 1-31 .YC SKIP 1 \ The y-coordinate of the text cursor (i.e. the text \ row), which can be from 0 to 23 \ \ The screen actually has 31 character rows if you \ include the dashboard, but the text printing routines \ only work on the top part (the space view), so the \ text cursor only goes up to a maximum of 23, the row \ just before the screen splits \ \ A value of 0 denotes the top row, but because the \ top part of the screen has a border box that clashes \ with row 0, text is always shown at row 1 or greater .QQ22 SKIP 2 \ The two hyperspace countdown counters \ \ Before a hyperspace jump, both QQ22 and QQ22+1 are \ set to 15 \ \ QQ22 is an internal counter that counts down by 1 \ each time TT102 is called, which happens every \ iteration of the main game loop. When it reaches \ zero, the on-screen counter in QQ22+1 gets \ decremented, and QQ22 gets set to 5 and the countdown \ continues (so the first tick of the hyperspace counter \ takes 15 iterations to happen, but subsequent ticks \ take 5 iterations each) \ \ QQ22+1 contains the number that's shown on-screen \ during the countdown. It counts down from 15 to 1, and \ when it hits 0, the hyperspace engines kick in .ECMA SKIP 1 \ The E.C.M. countdown timer, which determines whether \ an E.C.M. system is currently operating \ \ * 0 = E.C.M. is off \ \ * Non-zero = E.C.M. is on and is counting down \ \ The counter starts at 32 when an E.C.M. is activated, \ either by us or by an opponent, and it decreases by 1 \ in each iteration of the main flight loop until it \ reaches zero, at which point the E.C.M. switches off. \ Only one E.C.M. can be active at any one time, so \ there is only one counter .XX15 SKIP 0 \ Temporary storage, typically used for storing screen \ coordinates in line-drawing routines \ \ There are six bytes of storage, from XX15 TO XX15+5. \ The first four bytes have the following aliases: \ \ X1 = XX15 \ Y1 = XX15+1 \ X2 = XX15+2 \ Y2 = XX15+3 \ \ These are typically used for describing lines in terms \ of screen coordinates, i.e. (X1, Y1) to (X2, Y2) \ \ The last two bytes of XX15 do not have aliases .X1 SKIP 1 \ Temporary storage, typically used for x-coordinates in \ the line-drawing routines .Y1 SKIP 1 \ Temporary storage, typically used for y-coordinates in \ line-drawing routines .X2 SKIP 1 \ Temporary storage, typically used for x-coordinates in \ the line-drawing routines .Y2 SKIP 1 \ Temporary storage, typically used for y-coordinates in \ line-drawing routines SKIP 2 \ The last two bytes of the XX15 block .XX12 SKIP 6 \ Temporary storage for a block of values, used in a \ number of places .K SKIP 4 \ Temporary storage, used in a number of places .KL SKIP 1 \ The following bytes implement a key logger that \ enables Elite to scan for concurrent key presses of \ the primary flight keys, plus a secondary flight key \ \ If a key is being pressed that is not in the keyboard \ table at KYTB, it can be stored here (as seen in \ routine DK4, for example) .KY1 SKIP 1 \ "?" is being pressed (slow down) \ \ * 0 = no \ \ * Non-zero = yes .KY2 SKIP 1 \ Space is being pressed (speed up) \ \ * 0 = no \ \ * Non-zero = yes .KY3 SKIP 1 \ "<" is being pressed (roll left) \ \ * 0 = no \ \ * Non-zero = yes .KY4 SKIP 1 \ ">" is being pressed (roll right) \ \ * 0 = no \ \ * Non-zero = yes .KY5 SKIP 1 \ "X" is being pressed (pull up) \ \ * 0 = no \ \ * Non-zero = yes .KY6 SKIP 1 \ "S" is being pressed (pitch down) \ \ * 0 = no \ \ * Non-zero = yes .KY7 SKIP 1 \ "A" is being pressed (fire lasers) \ \ * 0 = no \ \ * Non-zero = yes \ \ This is also set when the joystick fire button has \ been pressed .KY12 SKIP 1 \ TAB is being pressed (energy bomb) \ \ * 0 = no \ \ * Non-zero = yes .KY13 SKIP 1 \ ESCAPE is being pressed (launch escape pod) \ \ * 0 = no \ \ * Non-zero = yes .KY14 SKIP 1 \ "T" is being pressed (target missile) \ \ * 0 = no \ \ * Non-zero = yes .KY15 SKIP 1 \ "U" is being pressed (unarm missile) \ \ * 0 = no \ \ * Non-zero = yes .KY16 SKIP 1 \ "M" is being pressed (fire missile) \ \ * 0 = no \ \ * Non-zero = yes .KY17 SKIP 1 \ "E" is being pressed (activate E.C.M.) \ \ * 0 = no \ \ * Non-zero = yes .KY18 SKIP 1 \ "J" is being pressed (in-system jump) \ \ * 0 = no \ \ * Non-zero = yes .KY19 SKIP 1 \ "C" is being pressed (activate docking computer) \ \ * 0 = no \ \ * Non-zero = yes .LAS SKIP 1 \ Contains the laser power of the laser fitted to the \ current space view (or 0 if there is no laser fitted \ to the current view) \ \ This gets set to bits 0-6 of the laser power byte from \ the commander data block, which contains the laser's \ power (bit 7 doesn't denote laser power, just whether \ or not the laser pulses, so that is not stored here) .MSTG SKIP 1 \ The current missile lock target \ \ * &FF = no target \ \ * 1-12 = the slot number of the ship that our \ missile is locked onto .XX1 SKIP 0 \ This is an alias for INWK that is used in the main \ ship-drawing routine at LL9 .INWK SKIP 33 \ The zero-page internal workspace for the current ship \ data block \ \ As operations on zero page locations are faster and \ have smaller opcodes than operations on the rest of \ the addressable memory, Elite tends to store oft-used \ data here. A lot of the routines in Elite need to \ access and manipulate ship data, so to make this an \ efficient exercise, the ship data is first copied from \ the ship data blocks at K% into INWK (or, when new \ ships are spawned, from the blueprints at XX21) .XX19 SKIP NI% - 33 \ XX19(1 0) shares its location with INWK(34 33), which \ contains the address of the ship line heap .LSP SKIP 1 \ The ball line heap pointer, which contains the number \ of the first free byte after the end of the LSX2 and \ LSY2 heaps .QQ15 SKIP 6 \ The three 16-bit seeds for the selected system, i.e. \ the one in the crosshairs in the Short-range Chart .K5 SKIP 0 \ Temporary storage used to store segment coordinates \ across successive calls to BLINE, the ball line \ routine .XX18 SKIP 0 \ Temporary storage used to store coordinates in the \ LL9 ship-drawing routine .QQ17 SKIP 1 \ Contains a number of flags that affect how text tokens \ are printed, particularly capitalisation \ \ * If all bits are set (255) then text printing is \ disabled \ \ * Bit 7: 0 = ALL CAPS \ 1 = Sentence Case, bit 6 determines the \ case of the next letter to print \ \ * Bit 6: 0 = print the next letter in upper case \ 1 = print the next letter in lower case \ \ * Bits 0-5: If any of bits 0-5 are set, print in \ lower case \ \ So: \ \ * QQ17 = 0 means case is set to ALL CAPS \ \ * QQ17 = %10000000 means Sentence Case, currently \ printing upper case \ \ * QQ17 = %11000000 means Sentence Case, currently \ printing lower case \ \ * QQ17 = %11111111 means printing is disabled .QQ19 SKIP 3 \ Temporary storage, used in a number of places .K6 SKIP 5 \ Temporary storage, typically used for storing \ coordinates during vector calculations .ALP1 SKIP 1 \ Magnitude of the roll angle alpha, i.e. |alpha|, \ which is a positive value between 0 and 31 .ALP2 SKIP 2 \ Bit 7 of ALP2 = sign of the roll angle in ALPHA \ \ Bit 7 of ALP2+1 = opposite sign to ALP2 and ALPHA .BET2 SKIP 2 \ Bit 7 of BET2 = sign of the pitch angle in BETA \ \ Bit 7 of BET2+1 = opposite sign to BET2 and BETA .DELTA SKIP 1 \ Our current speed, in the range 1-40 .DELT4 SKIP 2 \ Our current speed * 64 as a 16-bit value \ \ This is stored as DELT4(1 0), so the high byte in \ DELT4+1 therefore contains our current speed / 4 .U SKIP 1 \ Temporary storage, used in a number of places .Q SKIP 1 \ Temporary storage, used in a number of places .R SKIP 1 \ Temporary storage, used in a number of places .S SKIP 1 \ Temporary storage, used in a number of places .XSAV SKIP 1 \ Temporary storage for saving the value of the X \ register, used in a number of places .YSAV SKIP 1 \ Temporary storage for saving the value of the Y \ register, used in a number of places .XX17 SKIP 1 \ Temporary storage, used in BPRNT to store the number \ of characters to print, and as the edge counter in the \ main ship-drawing routine .QQ11 SKIP 1 \ The type of the current view: \ \ 0 = Space view \ 1 = Data on System screen (red key f6) \ Get commander name ("@", save/load commander) \ In-system jump just arrived ("J") \ Title screen \ Buy Cargo screen (red key f1) \ Mis-jump just arrived (witchspace) \ 4 = Sell Cargo screen (red key f2) \ 6 = Death screen \ 8 = Status Mode screen (red key f8) \ Inventory screen (red key f9) \ 16 = Market Price screen (red key f7) \ 32 = Equip Ship screen (red key f3) \ 64 = Long-range Chart (red key f4) \ 128 = Short-range Chart (red key f5) \ \ This value is typically set by calling routine TT66 .ZZ SKIP 1 \ Temporary storage, typically used for distance values .XX13 SKIP 1 \ Temporary storage, typically used in the line-drawing \ routines .MCNT SKIP 1 \ The main loop counter \ \ This counter determines how often certain actions are \ performed within the main loop .DL SKIP 1 \ Vertical sync flag \ \ DL gets set to 30 every time we reach vertical sync on \ the video system, which happens 50 times a second \ (50Hz). The WSCAN routine uses this to pause until the \ vertical sync, by setting DL to 0 and then monitoring \ its value until it changes to 30 .TYPE SKIP 1 \ The current ship type \ \ This is where we store the current ship type for when \ we are iterating through the ships in the local bubble \ as part of the main flight loop. See the table at XX21 \ for information about ship types .JSTX SKIP 1 \ Our current roll rate \ \ This value is shown in the dashboard's RL indicator, \ and determines the rate at which we are rolling \ \ The value ranges from 1 to 255 with 128 as the centre \ point, so 1 means roll is decreasing at the maximum \ rate, 128 means roll is not changing, and 255 means \ roll is increasing at the maximum rate \ \ This value is updated by "<" and ">" key presses, or \ if joysticks are enabled, from the joystick. If \ keyboard damping is enabled (which it is by default), \ the value is slowly moved towards the centre value of \ 128 (no roll) if there are no key presses or joystick \ movement .JSTY SKIP 1 \ Our current pitch rate \ \ This value is shown in the dashboard's DC indicator, \ and determines the rate at which we are pitching \ \ The value ranges from 1 to 255 with 128 as the centre \ point, so 1 means pitch is decreasing at the maximum \ rate, 128 means pitch is not changing, and 255 means \ pitch is increasing at the maximum rate \ \ This value is updated by "S" and "X" key presses, or \ if joysticks are enabled, from the joystick. If \ keyboard damping is enabled (which it is by default), \ the value is slowly moved towards the centre value of \ 128 (no pitch) if there are no key presses or joystick \ movement .ALPHA SKIP 1 \ The current roll angle alpha, which is reduced from \ JSTX to a sign-magnitude value between -31 and +31 \ \ This describes how fast we are rolling our ship, and \ determines how fast the universe rolls around us \ \ The sign bit is also stored in ALP2, while the \ opposite sign is stored in ALP2+1 .QQ12 SKIP 1 \ Our "docked" status \ \ * 0 = we are not docked \ \ * &FF = we are docked .TGT SKIP 1 \ Temporary storage, typically used as a target value \ for counters when drawing explosion clouds and partial \ circles .SWAP SKIP 1 \ Temporary storage, used to store a flag that records \ whether or not we had to swap a line's start and end \ coordinates around when clipping the line in routine \ LL145 (the flag is used in places like BLINE to swap \ them back) .COL SKIP 1 \ Temporary storage, used to store colour information \ when drawing pixels in the dashboard .FLAG SKIP 1 \ A flag that's used to define whether this is the first \ call to the ball line routine in BLINE, so it knows \ whether to wait for the second call before storing \ segment data in the ball line heap .CNT SKIP 1 \ Temporary storage, typically used for storing the \ number of iterations required when looping .CNT2 SKIP 1 \ Temporary storage, used in the planet-drawing routine \ to store the segment number where the arc of a partial \ circle should start .STP SKIP 1 \ The step size for drawing circles \ \ Circles in Elite are split up into 64 points, and the \ step size determines how many points to skip with each \ straight-line segment, so the smaller the step size, \ the smoother the circle. The values used are: \ \ * 2 for big planets and the circles on the charts \ \ * 4 for medium planets and the launch tunnel \ \ * 8 for small planets and the hyperspace tunnel \ \ As the step size increases we move from smoother \ circles at the top to more polygonal at the bottom. \ See the CIRCLE2 routine for more details .XX4 SKIP 1 \ Temporary storage, used in a number of places .XX20 SKIP 1 \ Temporary storage, used in a number of places .XX14 SKIP 1 \ This byte appears to be unused .RAT SKIP 1 \ Used to store different signs depending on the current \ space view, for use in calculating stardust movement .RAT2 SKIP 1 \ Temporary storage, used to store the pitch and roll \ signs when moving objects and stardust .K2 SKIP 4 \ Temporary storage, used in a number of places ORG &00D1 \ Set the assembly address to &00D1 .T SKIP 1 \ Temporary storage, used in a number of places .K3 SKIP 0 \ Temporary storage, used in a number of places .XX2 SKIP 14 \ Temporary storage, used to store the visibility of the \ ship's faces during the ship-drawing routine at LL9 .K4 SKIP 2 \ Temporary storage, used in a number of places PRINT "ZP workspace from ", ~ZP, "to ", ~P%-1, "inclusive" \ ****************************************************************************** \ \ Name: XX3 \ Type: Workspace \ Address: &0100 to the top of the descending stack \ Category: Workspaces \ Summary: Temporary storage space for complex calculations \ \ ------------------------------------------------------------------------------ \ \ Used as heap space for storing temporary data during calculations. Shared with \ the descending 6502 stack, which works down from &01FF. \ \ ****************************************************************************** ORG &0100 \ Set the assembly address to &0100 .XX3 SKIP 256 \ Temporary storage, typically used for storing tables \ of values such as screen coordinates or ship data \ ****************************************************************************** \ \ Name: T% \ Type: Workspace \ Address: &0300 to &0371 \ Category: Workspaces \ Summary: Current commander data and stardust data blocks \ \ ------------------------------------------------------------------------------ \ \ Contains the current commander data (NT% bytes at location TP), and the \ stardust data blocks (NOST bytes at location SX) \ \ ****************************************************************************** ORG &0300 \ Set the assembly address to &0300 .T% SKIP 0 \ The start of the T% workspace .TP SKIP 1 \ The current mission status, which is always 0 for the \ cassette version of Elite as there are no missions .QQ0 SKIP 1 \ The current system's galactic x-coordinate (0-256) .QQ1 SKIP 1 \ The current system's galactic y-coordinate (0-256) .QQ21 SKIP 6 \ The three 16-bit seeds for the current galaxy \ \ These seeds define system 0 in the current galaxy, so \ they can be used as a starting point to generate all \ 256 systems in the galaxy \ \ Using a galactic hyperdrive rotates each byte to the \ left (rolling each byte within itself) to get the \ seeds for the next galaxy, so after eight galactic \ jumps, the seeds roll around to the first galaxy again .CASH SKIP 4 \ Our current cash pot \ \ The cash stash is stored as a 32-bit unsigned integer, \ with the most significant byte in CASH and the least \ significant in CASH+3. This is big-endian, which is \ the opposite way round to most of the numbers used in \ Elite - to use our notation for multi-byte numbers, \ the amount of cash is CASH(0 1 2 3) .QQ14 SKIP 1 \ Our current fuel level (0-70) \ \ The fuel level is stored as the number of light years \ multiplied by 10, so QQ14 = 1 represents 0.1 light \ years, and the maximum possible value is 70, for 7.0 \ light years .COK SKIP 1 \ Flags used to generate the competition code .GCNT SKIP 1 \ The number of the current galaxy (0-7) \ \ When this is displayed in-game, 1 is added to the \ number, so we start in galaxy 1 in-game, but it's \ stored as galaxy 0 internally \ \ The galaxy number increases by one every time a \ galactic hyperdrive is used, and wraps back around to \ the start after eight galaxies .LASER SKIP 4 \ The specifications of the lasers fitted to each of the \ four space views \ \ * Byte #0 = front view \ \ * Byte #1 = rear view \ \ * Byte #2 = left view \ \ * Byte #3 = right view \ \ The value for each view is as follows: \ \ * 0 = no laser is fitted to this view \ \ * Non-zero = a laser is fitted to this view, with \ the following specification: \ \ * Bits 0-6 contain the laser's power \ \ * Bit 7 determines whether or not the laser pulses \ (0 = pulse laser) or is always on (1 = beam \ laser) SKIP 2 \ These bytes appear to be unused (they were originally \ used for up/down lasers, but they were dropped) .CRGO SKIP 1 \ Our ship's cargo capacity \ \ * 22 = standard cargo bay of 20 tonnes \ \ * 37 = large cargo bay of 35 tonnes \ \ The value is two greater than the actual capacity to \ make the maths in tnpr slightly more efficient .QQ20 SKIP 17 \ The contents of our cargo hold \ \ The amount of market item X that we have in our hold \ can be found in the X-th byte of QQ20. For example: \ \ * QQ20 contains the amount of food (item 0) \ \ * QQ20+7 contains the amount of computers (item 7) \ \ See QQ23 for a list of market item numbers and their \ storage units .ECM SKIP 1 \ E.C.M. system \ \ * 0 = not fitted \ \ * &FF = fitted .BST SKIP 1 \ Fuel scoops (BST stands for "barrel status") \ \ * 0 = not fitted \ \ * &FF = fitted .BOMB SKIP 1 \ Energy bomb \ \ * 0 = not fitted \ \ * &7F = fitted .ENGY SKIP 1 \ Energy unit \ \ * 0 = not fitted \ \ * Non-zero = fitted \ \ The actual value determines the refresh rate of our \ energy banks, as they refresh by ENGY+1 each time (so \ our ship's energy level goes up by 2 each time if we \ have an energy unit fitted, otherwise it goes up by 1) .DKCMP SKIP 1 \ Docking computer \ \ * 0 = not fitted \ \ * &FF = fitted .GHYP SKIP 1 \ Galactic hyperdrive \ \ * 0 = not fitted \ \ * &FF = fitted .ESCP SKIP 1 \ Escape pod \ \ * 0 = not fitted \ \ * &FF = fitted SKIP 4 \ These bytes appear to be unused .NOMSL SKIP 1 \ The number of missiles we have fitted (0-4) .FIST SKIP 1 \ Our legal status (FIST stands for "fugitive/innocent \ status") \ \ * 0 = Clean \ \ * 1-49 = Offender \ \ * 50+ = Fugitive \ \ You get 64 points if you kill a cop, so that's a fast \ ticket to fugitive status .AVL SKIP 17 \ Market availability in the current system \ \ The available amount of market item X is stored in \ the X-th byte of AVL, so for example: \ \ * AVL contains the amount of food (item 0) \ \ * AVL+7 contains the amount of computers (item 7) \ \ See QQ23 for a list of market item numbers and their \ storage units .QQ26 SKIP 1 \ A random value used to randomise market data \ \ This value is set to a new random number for each \ change of system, so we can add a random factor into \ the calculations for market prices .TALLY SKIP 2 \ Our combat rank \ \ The combat rank is stored as the number of kills, in a \ 16-bit number TALLY(1 0) - so the high byte is in \ TALLY+1 and the low byte in TALLY \ \ If the high byte in TALLY+1 is 0 then we have between \ 0 and 255 kills, so our rank is Harmless, Mostly \ Harmless, Poor, Average Above Average or Competent, \ according to the value of the low byte in TALLY: \ \ Harmless %00000000 to %00000111 = 0 to 7 \ Mostly Harmless %00001000 to %00001111 = 8 to 15 \ Poor %00010000 to %00011111 = 16 to 31 \ Average %00100000 to %00111111 = 32 to 63 \ Above Average %01000000 to %01111111 = 64 to 127 \ Competent %10000000 to %11111111 = 128 to 255 \ \ Note that the Competent range also covers kill counts \ from 256 to 511, as follows \ \ If the high byte in TALLY+1 is non-zero then we are \ Competent, Dangerous, Deadly or Elite, according to \ the value of TALLY(1 0): \ \ Competent (1 0) to (1 255) = 256 to 511 kills \ Dangerous (2 0) to (9 255) = 512 to 2559 kills \ Deadly (10 0) to (24 255) = 2560 to 6399 kills \ Elite (25 0) and up = 6400 kills and up \ \ You can see the rating calculation in the STATUS \ subroutine .SVC SKIP 1 \ The save count \ \ When a new commander is created, the save count gets \ set to 128. This value gets halved each time the \ commander file is saved, but it is otherwise unused. \ It is presumably part of the security system for the \ competition, possibly another flag to catch out \ entries with manually altered commander files SKIP 2 \ The commander file checksum \ \ These two bytes are reserved for the commander file \ checksum, so when the current commander block is \ copied from here to the last saved commander block at \ NA%, CHK and CHK2 get overwritten NT% = SVC + 2 - TP \ This sets the variable NT% to the size of the current \ commander data block, which starts at TP and ends at \ SVC+2 (inclusive) .SX SKIP NOST + 1 \ This is where we store the x_hi coordinates for all \ the stardust particles .SXL SKIP NOST + 1 \ This is where we store the x_lo coordinates for all \ the stardust particles PRINT "T% workspace from ", ~T%, "to ", ~P%-1, "inclusive" \ ****************************************************************************** \ \ ELITE RECURSIVE TEXT TOKEN FILE \ \ Produces the binary file WORDS9.bin that gets loaded by elite-loader.asm. \ \ The recursive token table is loaded at &1100 and is moved down to &0400 as \ part of elite-loader.asm, so it ends up at &0400 to &07FF. \ \ ****************************************************************************** ORG CODE_WORDS% \ Set the assembly address to CODE_WORDS% \ ****************************************************************************** \ \ Name: CHAR \ Type: Macro \ Category: Text \ Summary: Macro definition for characters in the recursive token table \ Deep dive: Printing text tokens \ \ ------------------------------------------------------------------------------ \ \ The following macro is used when building the recursive token table: \ \ CHAR 'x' Insert ASCII character "x" \ \ To include an apostrophe, use a backtick character, as in CHAR '`'. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ 'x' The character to insert into the table \ \ ****************************************************************************** MACRO CHAR x IF x = '`' EQUB 39 EOR RE ELSE EQUB x EOR RE ENDIF ENDMACRO \ ****************************************************************************** \ \ Name: TWOK \ Type: Macro \ Category: Text \ Summary: Macro definition for two-letter tokens in the token table \ Deep dive: Printing text tokens \ \ ------------------------------------------------------------------------------ \ \ The following macro is used when building the recursive token table: \ \ TWOK 'x', 'y' Insert two-letter token "xy" \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ 'x' The first letter of the two-letter token to insert into \ the table \ \ 'y' The second letter of the two-letter token to insert into \ the table \ \ ****************************************************************************** MACRO TWOK t, k IF t = 'A' AND k = 'L' EQUB 128 EOR RE ENDIF IF t = 'L' AND k = 'E' EQUB 129 EOR RE ENDIF IF t = 'X' AND k = 'E' EQUB 130 EOR RE ENDIF IF t = 'G' AND k = 'E' EQUB 131 EOR RE ENDIF IF t = 'Z' AND k = 'A' EQUB 132 EOR RE ENDIF IF t = 'C' AND k = 'E' EQUB 133 EOR RE ENDIF IF t = 'B' AND k = 'I' EQUB 134 EOR RE ENDIF IF t = 'S' AND k = 'O' EQUB 135 EOR RE ENDIF IF t = 'U' AND k = 'S' EQUB 136 EOR RE ENDIF IF t = 'E' AND k = 'S' EQUB 137 EOR RE ENDIF IF t = 'A' AND k = 'R' EQUB 138 EOR RE ENDIF IF t = 'M' AND k = 'A' EQUB 139 EOR RE ENDIF IF t = 'I' AND k = 'N' EQUB 140 EOR RE ENDIF IF t = 'D' AND k = 'I' EQUB 141 EOR RE ENDIF IF t = 'R' AND k = 'E' EQUB 142 EOR RE ENDIF IF t = 'A' AND k = '?' EQUB 143 EOR RE ENDIF IF t = 'E' AND k = 'R' EQUB 144 EOR RE ENDIF IF t = 'A' AND k = 'T' EQUB 145 EOR RE ENDIF IF t = 'E' AND k = 'N' EQUB 146 EOR RE ENDIF IF t = 'B' AND k = 'E' EQUB 147 EOR RE ENDIF IF t = 'R' AND k = 'A' EQUB 148 EOR RE ENDIF IF t = 'L' AND k = 'A' EQUB 149 EOR RE ENDIF IF t = 'V' AND k = 'E' EQUB 150 EOR RE ENDIF IF t = 'T' AND k = 'I' EQUB 151 EOR RE ENDIF IF t = 'E' AND k = 'D' EQUB 152 EOR RE ENDIF IF t = 'O' AND k = 'R' EQUB 153 EOR RE ENDIF IF t = 'Q' AND k = 'U' EQUB 154 EOR RE ENDIF IF t = 'A' AND k = 'N' EQUB 155 EOR RE ENDIF IF t = 'T' AND k = 'E' EQUB 156 EOR RE ENDIF IF t = 'I' AND k = 'S' EQUB 157 EOR RE ENDIF IF t = 'R' AND k = 'I' EQUB 158 EOR RE ENDIF IF t = 'O' AND k = 'N' EQUB 159 EOR RE ENDIF ENDMACRO \ ****************************************************************************** \ \ Name: CONT \ Type: Macro \ Category: Text \ Summary: Macro definition for control codes in the recursive token table \ Deep dive: Printing text tokens \ \ ------------------------------------------------------------------------------ \ \ The following macro is used when building the recursive token table: \ \ CONT n Insert control code token {n} \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ n The control code to insert into the table \ \ ****************************************************************************** MACRO CONT n EQUB n EOR RE ENDMACRO \ ****************************************************************************** \ \ Name: RTOK \ Type: Macro \ Category: Text \ Summary: Macro definition for recursive tokens in the recursive token table \ Deep dive: Printing text tokens \ \ ------------------------------------------------------------------------------ \ \ The following macro is used when building the recursive token table: \ \ RTOK n Insert recursive token [n] \ \ * Tokens 0-95 get stored as n + 160 \ \ * Tokens 128-145 get stored as n - 114 \ \ * Tokens 96-127 get stored as n \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ n The number of the recursive token to insert into the \ table, in the range 0 to 145 \ \ ****************************************************************************** MACRO RTOK n IF n >= 0 AND n <= 95 t = n + 160 ELIF n >= 128 t = n - 114 ELSE t = n ENDIF EQUB t EOR RE ENDMACRO \ ****************************************************************************** \ \ Name: QQ18 \ Type: Variable \ Category: Text \ Summary: The recursive token table for tokens 0-148 \ Deep dive: Printing text tokens \ \ ------------------------------------------------------------------------------ \ \ The encodings shown for each recursive text token use the following notation: \ \ {n} Control code n = 0 to 13 \ Two-letter token n = 128 to 159 \ [n] Recursive token n = 0 to 148 \ \ ****************************************************************************** .QQ18 RTOK 111 \ Token 0: "FUEL SCOOPS ON {beep}" RTOK 131 \ CONT 7 \ Encoded as: "[111][131]{7}" EQUB 0 CHAR ' ' \ Token 1: " CHART" CHAR 'C' \ CHAR 'H' \ Encoded as: " CH<138>T" TWOK 'A', 'R' CHAR 'T' EQUB 0 CHAR 'G' \ Token 2: "GOVERNMENT" CHAR 'O' \ TWOK 'V', 'E' \ Encoded as: "GO<150>RNM<146>T" CHAR 'R' CHAR 'N' CHAR 'M' TWOK 'E', 'N' CHAR 'T' EQUB 0 CHAR 'D' \ Token 3: "DATA ON {selected system name}" TWOK 'A', 'T' \ CHAR 'A' \ Encoded as: "D<145>A[131]{3}" RTOK 131 CONT 3 EQUB 0 TWOK 'I', 'N' \ Token 4: "INVENTORY{crlf} TWOK 'V', 'E' \ " CHAR 'N' \ CHAR 'T' \ Encoded as: "<140><150>NT<153>Y{13}" TWOK 'O', 'R' CHAR 'Y' CONT 13 EQUB 0 CHAR 'S' \ Token 5: "SYSTEM" CHAR 'Y' \ CHAR 'S' \ Encoded as: "SYS<156>M" TWOK 'T', 'E' CHAR 'M' EQUB 0 CHAR 'P' \ Token 6: "PRICE" TWOK 'R', 'I' \ TWOK 'C', 'E' \ Encoded as: "P<158><133>" EQUB 0 CONT 2 \ Token 7: "{current system name} MARKET PRICES" CHAR ' ' \ TWOK 'M', 'A' \ Encoded as: "{2} <139>RKET [6]S" CHAR 'R' CHAR 'K' CHAR 'E' CHAR 'T' CHAR ' ' RTOK 6 CHAR 'S' EQUB 0 TWOK 'I', 'N' \ Token 8: "INDUSTRIAL" CHAR 'D' \ TWOK 'U', 'S' \ Encoded as: "<140>D<136>T<158><128>" CHAR 'T' TWOK 'R', 'I' TWOK 'A', 'L' EQUB 0 CHAR 'A' \ Token 9: "AGRICULTURAL" CHAR 'G' \ TWOK 'R', 'I' \ Encoded as: "AG<158>CULTU<148>L" CHAR 'C' CHAR 'U' CHAR 'L' CHAR 'T' CHAR 'U' TWOK 'R', 'A' CHAR 'L' EQUB 0 TWOK 'R', 'I' \ Token 10: "RICH " CHAR 'C' \ CHAR 'H' \ Encoded as: "<158>CH " CHAR ' ' EQUB 0 CHAR 'A' \ Token 11: "AVERAGE " TWOK 'V', 'E' \ TWOK 'R', 'A' \ Encoded as: "A<150><148><131> " TWOK 'G', 'E' CHAR ' ' EQUB 0 CHAR 'P' \ Token 12: "POOR " CHAR 'O' \ TWOK 'O', 'R' \ Encoded as: "PO<153> " CHAR ' ' EQUB 0 TWOK 'M', 'A' \ Token 13: "MAINLY " TWOK 'I', 'N' \ CHAR 'L' \ Encoded as: "<139><140>LY " CHAR 'Y' CHAR ' ' EQUB 0 CHAR 'U' \ Token 14: "UNIT" CHAR 'N' \ CHAR 'I' \ Encoded as: "UNIT" CHAR 'T' EQUB 0 CHAR 'V' \ Token 15: "VIEW " CHAR 'I' \ CHAR 'E' \ Encoded as: "VIEW " CHAR 'W' CHAR ' ' EQUB 0 TWOK 'Q', 'U' \ Token 16: "QUANTITY" TWOK 'A', 'N' \ TWOK 'T', 'I' \ Encoded as: "<154><155><151>TY" CHAR 'T' CHAR 'Y' EQUB 0 TWOK 'A', 'N' \ Token 17: "ANARCHY" TWOK 'A', 'R' \ CHAR 'C' \ Encoded as: "<155><138>CHY" CHAR 'H' CHAR 'Y' EQUB 0 CHAR 'F' \ Token 18: "FEUDAL" CHAR 'E' \ CHAR 'U' \ Encoded as: "FEUD<128>" CHAR 'D' TWOK 'A', 'L' EQUB 0 CHAR 'M' \ Token 19: "MULTI-GOVERNMENT" CHAR 'U' \ CHAR 'L' \ Encoded as: "MUL<151>-[2]" TWOK 'T', 'I' CHAR '-' RTOK 2 EQUB 0 TWOK 'D', 'I' \ Token 20: "DICTATORSHIP" CHAR 'C' \ CHAR 'T' \ Encoded as: "<141>CT<145><153>[25]" TWOK 'A', 'T' TWOK 'O', 'R' RTOK 25 EQUB 0 RTOK 91 \ Token 21: "COMMUNIST" CHAR 'M' \ CHAR 'U' \ Encoded as: "[91]MUN<157>T" CHAR 'N' TWOK 'I', 'S' CHAR 'T' EQUB 0 CHAR 'C' \ Token 22: "CONFEDERACY" TWOK 'O', 'N' \ CHAR 'F' \ Encoded as: "C<159>F<152><144>ACY" TWOK 'E', 'D' TWOK 'E', 'R' CHAR 'A' CHAR 'C' CHAR 'Y' EQUB 0 CHAR 'D' \ Token 23: "DEMOCRACY" CHAR 'E' \ CHAR 'M' \ Encoded as: "DEMOC<148>CY" CHAR 'O' CHAR 'C' TWOK 'R', 'A' CHAR 'C' CHAR 'Y' EQUB 0 CHAR 'C' \ Token 24: "CORPORATE STATE" TWOK 'O', 'R' \ CHAR 'P' \ Encoded as: "C<153>P<153><145>E [43]<145>E" TWOK 'O', 'R' TWOK 'A', 'T' CHAR 'E' CHAR ' ' RTOK 43 TWOK 'A', 'T' CHAR 'E' EQUB 0 CHAR 'S' \ Token 25: "SHIP" CHAR 'H' \ CHAR 'I' \ Encoded as: "SHIP" CHAR 'P' EQUB 0 CHAR 'P' \ Token 26: "PRODUCT" CHAR 'R' \ CHAR 'O' \ Encoded as: "PRODUCT" CHAR 'D' CHAR 'U' CHAR 'C' CHAR 'T' EQUB 0 CHAR ' ' \ Token 27: " LASER" TWOK 'L', 'A' \ CHAR 'S' \ Encoded as: " <149>S<144>" TWOK 'E', 'R' EQUB 0 CHAR 'H' \ Token 28: "HUMAN COLONIAL" CHAR 'U' \ CHAR 'M' \ Encoded as: "HUM<155> COL<159>I<128>" TWOK 'A', 'N' CHAR ' ' CHAR 'C' CHAR 'O' CHAR 'L' TWOK 'O', 'N' CHAR 'I' TWOK 'A', 'L' EQUB 0 CHAR 'H' \ Token 29: "HYPERSPACE " CHAR 'Y' \ CHAR 'P' \ Encoded as: "HYP<144>SPA<133> " TWOK 'E', 'R' CHAR 'S' CHAR 'P' CHAR 'A' TWOK 'C', 'E' CHAR ' ' EQUB 0 CHAR 'S' \ Token 30: "SHORT RANGE CHART" CHAR 'H' \ TWOK 'O', 'R' \ Encoded as: "SH<153>T [42][1]" CHAR 'T' CHAR ' ' RTOK 42 RTOK 1 EQUB 0 TWOK 'D', 'I' \ Token 31: "DISTANCE" RTOK 43 \ TWOK 'A', 'N' \ Encoded as: "<141>[43]<155><133>" TWOK 'C', 'E' EQUB 0 CHAR 'P' \ Token 32: "POPULATION" CHAR 'O' \ CHAR 'P' \ Encoded as: "POPUL<145>I<159>" CHAR 'U' CHAR 'L' TWOK 'A', 'T' CHAR 'I' TWOK 'O', 'N' EQUB 0 CHAR 'G' \ Token 33: "GROSS PRODUCTIVITY" CHAR 'R' \ CHAR 'O' \ Encoded as: "GROSS [26]IVITY" CHAR 'S' CHAR 'S' CHAR ' ' RTOK 26 CHAR 'I' CHAR 'V' CHAR 'I' CHAR 'T' CHAR 'Y' EQUB 0 CHAR 'E' \ Token 34: "ECONOMY" CHAR 'C' \ TWOK 'O', 'N' \ Encoded as: "EC<159>OMY" CHAR 'O' CHAR 'M' CHAR 'Y' EQUB 0 CHAR ' ' \ Token 35: " LIGHT YEARS" CHAR 'L' \ CHAR 'I' \ Encoded as: " LIGHT YE<138>S" CHAR 'G' CHAR 'H' CHAR 'T' CHAR ' ' CHAR 'Y' CHAR 'E' TWOK 'A', 'R' CHAR 'S' EQUB 0 TWOK 'T', 'E' \ Token 36: "TECH.LEVEL" CHAR 'C' \ CHAR 'H' \ Encoded as: "<156>CH.<129><150>L" CHAR '.' TWOK 'L', 'E' TWOK 'V', 'E' CHAR 'L' EQUB 0 CHAR 'C' \ Token 37: "CASH" CHAR 'A' \ CHAR 'S' \ Encoded as: "CASH" CHAR 'H' EQUB 0 CHAR ' ' \ Token 38: " BILLION" TWOK 'B', 'I' \ RTOK 118 \ Encoded as: " <134>[118]I<159>" CHAR 'I' TWOK 'O', 'N' EQUB 0 RTOK 122 \ Token 39: "GALACTIC CHART{galaxy number}" RTOK 1 \ CONT 1 \ Encoded as: "[122][1]{1}" EQUB 0 CHAR 'T' \ Token 40: "TARGET LOST" TWOK 'A', 'R' \ TWOK 'G', 'E' \ Encoded as: "T<138><131>T LO[43]" CHAR 'T' CHAR ' ' CHAR 'L' CHAR 'O' RTOK 43 EQUB 0 RTOK 106 \ Token 41: "MISSILE JAMMED" CHAR ' ' \ CHAR 'J' \ Encoded as: "[106] JAMM<152>" CHAR 'A' CHAR 'M' CHAR 'M' TWOK 'E', 'D' EQUB 0 CHAR 'R' \ Token 42: "RANGE" TWOK 'A', 'N' \ TWOK 'G', 'E' \ Encoded as: "R<155><131>" EQUB 0 CHAR 'S' \ Token 43: "ST" CHAR 'T' \ EQUB 0 \ Encoded as: "ST" RTOK 16 \ Token 44: "QUANTITY OF " CHAR ' ' \ CHAR 'O' \ Encoded as: "[16] OF " CHAR 'F' CHAR ' ' EQUB 0 CHAR 'S' \ Token 45: "SELL" CHAR 'E' \ RTOK 118 \ Encoded as: "SE[118]" EQUB 0 CHAR ' ' \ Token 46: " CARGO{sentence case}" CHAR 'C' \ TWOK 'A', 'R' \ Encoded as: " C<138>GO{6}" CHAR 'G' CHAR 'O' CONT 6 EQUB 0 CHAR 'E' \ Token 47: "EQUIP" TWOK 'Q', 'U' \ CHAR 'I' \ Encoded as: "E<154>IP" CHAR 'P' EQUB 0 CHAR 'F' \ Token 48: "FOOD" CHAR 'O' \ CHAR 'O' \ Encoded as: "FOOD" CHAR 'D' EQUB 0 TWOK 'T', 'E' \ Token 49: "TEXTILES" CHAR 'X' \ TWOK 'T', 'I' \ Encoded as: "<156>X<151>L<137>" CHAR 'L' TWOK 'E', 'S' EQUB 0 TWOK 'R', 'A' \ Token 50: "RADIOACTIVES" TWOK 'D', 'I' \ CHAR 'O' \ Encoded as: "<148><141>OAC<151><150>S" CHAR 'A' CHAR 'C' TWOK 'T', 'I' TWOK 'V', 'E' CHAR 'S' EQUB 0 CHAR 'S' \ Token 51: "SLAVES" TWOK 'L', 'A' \ TWOK 'V', 'E' \ Encoded as: "S<149><150>S" CHAR 'S' EQUB 0 CHAR 'L' \ Token 52: "LIQUOR/WINES" CHAR 'I' \ TWOK 'Q', 'U' \ Encoded as: "LI<154><153>/W<140><137>" TWOK 'O', 'R' CHAR '/' CHAR 'W' TWOK 'I', 'N' TWOK 'E', 'S' EQUB 0 CHAR 'L' \ Token 53: "LUXURIES" CHAR 'U' \ CHAR 'X' \ Encoded as: "LUXU<158><137>" CHAR 'U' TWOK 'R', 'I' TWOK 'E', 'S' EQUB 0 CHAR 'N' \ Token 54: "NARCOTICS" TWOK 'A', 'R' \ CHAR 'C' \ Encoded as: "N<138>CO<151>CS" CHAR 'O' TWOK 'T', 'I' CHAR 'C' CHAR 'S' EQUB 0 RTOK 91 \ Token 55: "COMPUTERS" CHAR 'P' \ CHAR 'U' \ Encoded as: "[91]PUT<144>S" CHAR 'T' TWOK 'E', 'R' CHAR 'S' EQUB 0 TWOK 'M', 'A' \ Token 56: "MACHINERY" CHAR 'C' \ CHAR 'H' \ Encoded as: "<139>CH<140><144>Y" TWOK 'I', 'N' TWOK 'E', 'R' CHAR 'Y' EQUB 0 RTOK 117 \ Token 57: "ALLOYS" CHAR 'O' \ CHAR 'Y' \ Encoded as: "[117]OYS" CHAR 'S' EQUB 0 CHAR 'F' \ Token 58: "FIREARMS" CHAR 'I' \ TWOK 'R', 'E' \ Encoded as: "FI<142><138>MS" TWOK 'A', 'R' CHAR 'M' CHAR 'S' EQUB 0 CHAR 'F' \ Token 59: "FURS" CHAR 'U' \ CHAR 'R' \ Encoded as: "FURS" CHAR 'S' EQUB 0 CHAR 'M' \ Token 60: "MINERALS" TWOK 'I', 'N' \ TWOK 'E', 'R' \ Encoded as: "M<140><144><128>S" TWOK 'A', 'L' CHAR 'S' EQUB 0 CHAR 'G' \ Token 61: "GOLD" CHAR 'O' \ CHAR 'L' \ Encoded as: "GOLD" CHAR 'D' EQUB 0 CHAR 'P' \ Token 62: "PLATINUM" CHAR 'L' \ TWOK 'A', 'T' \ Encoded as: "PL<145><140>UM" TWOK 'I', 'N' CHAR 'U' CHAR 'M' EQUB 0 TWOK 'G', 'E' \ Token 63: "GEM-STONES" CHAR 'M' \ CHAR '-' \ Encoded as: "<131>M-[43]<159><137>" RTOK 43 TWOK 'O', 'N' TWOK 'E', 'S' EQUB 0 TWOK 'A', 'L' \ Token 64: "ALIEN ITEMS" CHAR 'I' \ TWOK 'E', 'N' \ Encoded as: "<128>I<146> [127]S" CHAR ' ' RTOK 127 CHAR 'S' EQUB 0 CHAR '(' \ Token 65: "(Y/N)?" CHAR 'Y' \ CHAR '/' \ Encoded as: "(Y/N)?" CHAR 'N' CHAR ')' CHAR '?' EQUB 0 CHAR ' ' \ Token 66: " CR" CHAR 'C' \ CHAR 'R' \ Encoded as: " CR" EQUB 0 CHAR 'L' \ Token 67: "LARGE" TWOK 'A', 'R' \ TWOK 'G', 'E' \ Encoded as: "L<138><131>" EQUB 0 CHAR 'F' \ Token 68: "FIERCE" CHAR 'I' \ TWOK 'E', 'R' \ Encoded as: "FI<144><133>" TWOK 'C', 'E' EQUB 0 CHAR 'S' \ Token 69: "SMALL" TWOK 'M', 'A' \ RTOK 118 \ Encoded as: "S<139>[118]" EQUB 0 CHAR 'G' \ Token 70: "GREEN" TWOK 'R', 'E' \ TWOK 'E', 'N' \ Encoded as: "G<142><146>" EQUB 0 CHAR 'R' \ Token 71: "RED" TWOK 'E', 'D' \ EQUB 0 \ Encoded as: "R<152>" CHAR 'Y' \ Token 72: "YELLOW" CHAR 'E' \ RTOK 118 \ Encoded as: "YE[118]OW" CHAR 'O' CHAR 'W' EQUB 0 CHAR 'B' \ Token 73: "BLUE" CHAR 'L' \ CHAR 'U' \ Encoded as: "BLUE" CHAR 'E' EQUB 0 CHAR 'B' \ Token 74: "BLACK" TWOK 'L', 'A' \ CHAR 'C' \ Encoded as: "B<149>CK" CHAR 'K' EQUB 0 RTOK 136 \ Token 75: "HARMLESS" EQUB 0 \ \ Encoded as: "[136]" CHAR 'S' \ Token 76: "SLIMY" CHAR 'L' \ CHAR 'I' \ Encoded as: "SLIMY" CHAR 'M' CHAR 'Y' EQUB 0 CHAR 'B' \ Token 77: "BUG-EYED" CHAR 'U' \ CHAR 'G' \ Encoded as: "BUG-EY<152>" CHAR '-' CHAR 'E' CHAR 'Y' TWOK 'E', 'D' EQUB 0 CHAR 'H' \ Token 78: "HORNED" TWOK 'O', 'R' \ CHAR 'N' \ Encoded as: "H<153>N<152>" TWOK 'E', 'D' EQUB 0 CHAR 'B' \ Token 79: "BONY" TWOK 'O', 'N' \ CHAR 'Y' \ Encoded as: "B<159>Y" EQUB 0 CHAR 'F' \ Token 80: "FAT" TWOK 'A', 'T' \ EQUB 0 \ Encoded as: "F<145>" CHAR 'F' \ Token 81: "FURRY" CHAR 'U' \ CHAR 'R' \ Encoded as: "FURRY" CHAR 'R' CHAR 'Y' EQUB 0 CHAR 'R' \ Token 82: "RODENT" CHAR 'O' \ CHAR 'D' \ Encoded as: "ROD<146>T" TWOK 'E', 'N' CHAR 'T' EQUB 0 CHAR 'F' \ Token 83: "FROG" CHAR 'R' \ CHAR 'O' \ Encoded as: "FROG" CHAR 'G' EQUB 0 CHAR 'L' \ Token 84: "LIZARD" CHAR 'I' \ TWOK 'Z', 'A' \ Encoded as: "LI<132>RD" CHAR 'R' CHAR 'D' EQUB 0 CHAR 'L' \ Token 85: "LOBSTER" CHAR 'O' \ CHAR 'B' \ Encoded as: "LOB[43]<144>" RTOK 43 TWOK 'E', 'R' EQUB 0 TWOK 'B', 'I' \ Token 86: "BIRD" CHAR 'R' \ CHAR 'D' \ Encoded as: "<134>RD" EQUB 0 CHAR 'H' \ Token 87: "HUMANOID" CHAR 'U' \ CHAR 'M' \ Encoded as: "HUM<155>OID" TWOK 'A', 'N' CHAR 'O' CHAR 'I' CHAR 'D' EQUB 0 CHAR 'F' \ Token 88: "FELINE" CHAR 'E' \ CHAR 'L' \ Encoded as: "FEL<140>E" TWOK 'I', 'N' CHAR 'E' EQUB 0 TWOK 'I', 'N' \ Token 89: "INSECT" CHAR 'S' \ CHAR 'E' \ Encoded as: "<140>SECT" CHAR 'C' CHAR 'T' EQUB 0 RTOK 11 \ Token 90: "AVERAGE RADIUS" TWOK 'R', 'A' \ TWOK 'D', 'I' \ Encoded as: "[11]<148><141><136>" TWOK 'U', 'S' EQUB 0 CHAR 'C' \ Token 91: "COM" CHAR 'O' \ CHAR 'M' \ Encoded as: "COM" EQUB 0 RTOK 91 \ Token 92: "COMMANDER" CHAR 'M' \ TWOK 'A', 'N' \ Encoded as: "[91]M<155>D<144>" CHAR 'D' TWOK 'E', 'R' EQUB 0 CHAR ' ' \ Token 93: " DESTROYED" CHAR 'D' \ TWOK 'E', 'S' \ Encoded as: " D<137>TROY<152>" CHAR 'T' CHAR 'R' CHAR 'O' CHAR 'Y' TWOK 'E', 'D' EQUB 0 CHAR 'B' \ Token 94: "BY D.BRABEN & I.BELL" CHAR 'Y' \ CHAR ' ' \ Encoded as: "BY D.B<148><147>N & I.<147>[118]" CHAR 'D' CHAR '.' CHAR 'B' TWOK 'R', 'A' TWOK 'B', 'E' CHAR 'N' CHAR ' ' CHAR '&' CHAR ' ' CHAR 'I' CHAR '.' TWOK 'B', 'E' RTOK 118 EQUB 0 RTOK 14 \ Token 95: "UNIT QUANTITY{crlf} CHAR ' ' \ PRODUCT UNIT PRICE FOR SALE{crlf} CHAR ' ' \ {lf}" RTOK 16 \ CONT 13 \ Encoded as: "[14] [16]{13} [26] [14] [6] F<153> CHAR ' ' \ SA<129>{13}{10}" RTOK 26 CHAR ' ' CHAR ' ' CHAR ' ' RTOK 14 CHAR ' ' RTOK 6 CHAR ' ' CHAR 'F' TWOK 'O', 'R' CHAR ' ' CHAR 'S' CHAR 'A' TWOK 'L', 'E' CONT 13 CONT 10 EQUB 0 CHAR 'F' \ Token 96: "FRONT" CHAR 'R' \ TWOK 'O', 'N' \ Encoded as: "FR<159>T" CHAR 'T' EQUB 0 TWOK 'R', 'E' \ Token 97: "REAR" TWOK 'A', 'R' \ EQUB 0 \ Encoded as: "<142><138>" TWOK 'L', 'E' \ Token 98: "LEFT" CHAR 'F' \ CHAR 'T' \ Encoded as: "<129>FT" EQUB 0 TWOK 'R', 'I' \ Token 99: "RIGHT" CHAR 'G' \ CHAR 'H' \ Encoded as: "<158>GHT" CHAR 'T' EQUB 0 RTOK 121 \ Token 100: "ENERGY LOW{beep}" CHAR 'L' \ CHAR 'O' \ Encoded as: "[121]LOW{7}" CHAR 'W' CONT 7 EQUB 0 RTOK 99 \ Token 101: "RIGHT ON COMMANDER!" RTOK 131 \ RTOK 92 \ Encoded as: "[99][131][92]!" CHAR '!' EQUB 0 CHAR 'E' \ Token 102: "EXTRA " CHAR 'X' \ CHAR 'T' \ Encoded as: "EXT<148> " TWOK 'R', 'A' CHAR ' ' EQUB 0 CHAR 'P' \ Token 103: "PULSE LASER" CHAR 'U' \ CHAR 'L' \ Encoded as: "PULSE[27]" CHAR 'S' CHAR 'E' RTOK 27 EQUB 0 TWOK 'B', 'E' \ Token 104: "BEAM LASER" CHAR 'A' \ CHAR 'M' \ Encoded as: "<147>AM[27]" RTOK 27 EQUB 0 CHAR 'F' \ Token 105: "FUEL" CHAR 'U' \ CHAR 'E' \ Encoded as: "FUEL" CHAR 'L' EQUB 0 CHAR 'M' \ Token 106: "MISSILE" TWOK 'I', 'S' \ CHAR 'S' \ Encoded as: "M<157>SI<129>" CHAR 'I' TWOK 'L', 'E' EQUB 0 RTOK 67 \ Token 107: "LARGE CARGO{sentence case} BAY" RTOK 46 \ CHAR ' ' \ Encoded as: "[67][46] BAY" CHAR 'B' CHAR 'A' CHAR 'Y' EQUB 0 CHAR 'E' \ Token 108: "E.C.M.SYSTEM" CHAR '.' \ CHAR 'C' \ Encoded as: "E.C.M.[5]" CHAR '.' CHAR 'M' CHAR '.' RTOK 5 EQUB 0 RTOK 102 \ Token 109: "EXTRA PULSE LASERS" RTOK 103 \ CHAR 'S' \ Encoded as: "[102][103]S" EQUB 0 RTOK 102 \ Token 110: "EXTRA BEAM LASERS" RTOK 104 \ CHAR 'S' \ Encoded as: "[102][104]S" EQUB 0 RTOK 105 \ Token 111: "FUEL SCOOPS" CHAR ' ' \ CHAR 'S' \ Encoded as: "[105] SCOOPS" CHAR 'C' CHAR 'O' CHAR 'O' CHAR 'P' CHAR 'S' EQUB 0 TWOK 'E', 'S' \ Token 112: "ESCAPE POD" CHAR 'C' \ CHAR 'A' \ Encoded as: "<137>CAPE POD" CHAR 'P' CHAR 'E' CHAR ' ' CHAR 'P' CHAR 'O' CHAR 'D' EQUB 0 RTOK 121 \ Token 113: "ENERGY BOMB" CHAR 'B' \ CHAR 'O' \ Encoded as: "[121]BOMB" CHAR 'M' CHAR 'B' EQUB 0 RTOK 121 \ Token 114: "ENERGY UNIT" RTOK 14 \ EQUB 0 \ Encoded as: "[121][14]" RTOK 124 \ Token 115: "DOCKING COMPUTERS" TWOK 'I', 'N' \ CHAR 'G' \ Encoded as: "[124]<140>G [55]" CHAR ' ' RTOK 55 EQUB 0 RTOK 122 \ Token 116: "GALACTIC HYPERSPACE " CHAR ' ' \ RTOK 29 \ Encoded as: "[122] [29]" EQUB 0 CHAR 'A' \ Token 117: "ALL" RTOK 118 \ EQUB 0 \ Encoded as: "A[118]" CHAR 'L' \ Token 118: "LL" CHAR 'L' \ EQUB 0 \ Encoded as: "LL" RTOK 37 \ Token 119: "CASH:{cash} CR{crlf} CHAR ':' \ " CONT 0 \ EQUB 0 \ Encoded as: "[37]:{0}" TWOK 'I', 'N' \ Token 120: "INCOMING MISSILE" RTOK 91 \ TWOK 'I', 'N' \ Encoded as: "<140>[91]<140>G [106]" CHAR 'G' CHAR ' ' RTOK 106 EQUB 0 TWOK 'E', 'N' \ Token 121: "ENERGY " TWOK 'E', 'R' \ CHAR 'G' \ Encoded as: "<146><144>GY " CHAR 'Y' CHAR ' ' EQUB 0 CHAR 'G' \ Token 122: "GALACTIC" CHAR 'A' \ TWOK 'L', 'A' \ Encoded as: "GA<149>C<151>C" CHAR 'C' TWOK 'T', 'I' CHAR 'C' EQUB 0 CONT 13 \ Token 123: "{crlf} RTOK 92 \ COMMANDER'S NAME? " CHAR '`' \ CHAR 'S' \ Encoded as: "{13}[92]'S NAME? " CHAR ' ' CHAR 'N' CHAR 'A' CHAR 'M' CHAR 'E' CHAR '?' CHAR ' ' EQUB 0 CHAR 'D' \ Token 124: "DOCK" CHAR 'O' \ CHAR 'C' \ Encoded as: "DOCK" CHAR 'K' EQUB 0 CONT 5 \ Token 125: "FUEL: {fuel level} LIGHT YEARS{crlf} TWOK 'L', 'E' \ CASH:{cash} CR{crlf} CHAR 'G' \ LEGAL STATUS:" TWOK 'A', 'L' \ CHAR ' ' \ Encoded as: "{5}<129>G<128> [43]<145><136>:" RTOK 43 TWOK 'A', 'T' TWOK 'U', 'S' CHAR ':' EQUB 0 RTOK 92 \ Token 126: "COMMANDER {commander name}{crlf} CHAR ' ' \ {crlf} CONT 4 \ {crlf} CONT 13 \ {sentence case}PRESENT SYSTEM{tab to CONT 13 \ column 21}:{current system name}{crlf} CONT 13 \ HYPERSPACE SYSTEM{tab to column 21}: CONT 6 \ {selected system name}{crlf} RTOK 145 \ CONDITION{tab to column 21}:" CHAR ' ' \ RTOK 5 \ Encoded as: "[92] {4}{13}{13}{13}{6}[145] [5]{9}{2} CONT 9 \ {13}[29][5]{9}{3}{13}C<159><141><151> CONT 2 \ <159>{9}" CONT 13 RTOK 29 RTOK 5 CONT 9 CONT 3 CONT 13 CHAR 'C' TWOK 'O', 'N' TWOK 'D', 'I' TWOK 'T', 'I' TWOK 'O', 'N' CONT 9 EQUB 0 CHAR 'I' \ Token 127: "ITEM" TWOK 'T', 'E' \ CHAR 'M' \ Encoded as: "I<156>M" EQUB 0 CHAR ' ' \ Token 128: " LOAD NEW COMMANDER (Y/N)?{crlf} CHAR ' ' \ {crlf} CHAR 'L' \ " CHAR 'O' \ CHAR 'A' \ Encoded as: " LOAD NEW [92] [65]{13}{13}" CHAR 'D' CHAR ' ' CHAR 'N' CHAR 'E' CHAR 'W' CHAR ' ' RTOK 92 CHAR ' ' RTOK 65 CONT 13 CONT 13 EQUB 0 CONT 6 \ Token 129: "{sentence case}DOCKED" RTOK 124 \ TWOK 'E', 'D' \ Encoded as: "{6}[124]<152>" EQUB 0 TWOK 'R', 'A' \ Token 130: "RATING:" TWOK 'T', 'I' \ CHAR 'N' \ Encoded as: "<148><151>NG:" CHAR 'G' CHAR ':' EQUB 0 CHAR ' ' \ Token 131: " ON " TWOK 'O', 'N' \ CHAR ' ' \ Encoded as: " <159> " EQUB 0 CONT 13 \ Token 132: "{crlf} CONT 8 \ {all caps}EQUIPMENT: {sentence case}" RTOK 47 \ CHAR 'M' \ Encoded as: "{13}{8}[47]M<146>T:{6}" TWOK 'E', 'N' CHAR 'T' CHAR ':' CONT 6 EQUB 0 CHAR 'C' \ Token 133: "CLEAN" TWOK 'L', 'E' \ TWOK 'A', 'N' \ Encoded as: "C<129><155>" EQUB 0 CHAR 'O' \ Token 134: "OFFENDER" CHAR 'F' \ CHAR 'F' \ Encoded as: "OFF<146>D<144>" TWOK 'E', 'N' CHAR 'D' TWOK 'E', 'R' EQUB 0 CHAR 'F' \ Token 135: "FUGITIVE" CHAR 'U' \ CHAR 'G' \ Encoded as: "FUGI<151><150>" CHAR 'I' TWOK 'T', 'I' TWOK 'V', 'E' EQUB 0 CHAR 'H' \ Token 136: "HARMLESS" TWOK 'A', 'R' \ CHAR 'M' \ Encoded as: "H<138>M<129>SS" TWOK 'L', 'E' CHAR 'S' CHAR 'S' EQUB 0 CHAR 'M' \ Token 137: "MOSTLY HARMLESS" CHAR 'O' \ RTOK 43 \ Encoded as: "MO[43]LY [136]" CHAR 'L' CHAR 'Y' CHAR ' ' RTOK 136 EQUB 0 RTOK 12 \ Token 138: "POOR " EQUB 0 \ \ Encoded as: "[12]" RTOK 11 \ Token 139: "AVERAGE " EQUB 0 \ \ Encoded as: "[11]" CHAR 'A' \ Token 140: "ABOVE AVERAGE " CHAR 'B' \ CHAR 'O' \ Encoded as: "ABO<150> [11]" TWOK 'V', 'E' CHAR ' ' RTOK 11 EQUB 0 RTOK 91 \ Token 141: "COMPETENT" CHAR 'P' \ CHAR 'E' \ Encoded as: "[91]PET<146>T" CHAR 'T' TWOK 'E', 'N' CHAR 'T' EQUB 0 CHAR 'D' \ Token 142: "DANGEROUS" TWOK 'A', 'N' \ TWOK 'G', 'E' \ Encoded as: "D<155><131>RO<136>" CHAR 'R' CHAR 'O' TWOK 'U', 'S' EQUB 0 CHAR 'D' \ Token 143: "DEADLY" CHAR 'E' \ CHAR 'A' \ Encoded as: "DEADLY" CHAR 'D' CHAR 'L' CHAR 'Y' EQUB 0 CHAR '-' \ Token 144: "---- E L I T E ----" CHAR '-' \ CHAR '-' \ Encoded as: "---- E L I T E ----" CHAR '-' CHAR ' ' CHAR 'E' CHAR ' ' CHAR 'L' CHAR ' ' CHAR 'I' CHAR ' ' CHAR 'T' CHAR ' ' CHAR 'E' CHAR ' ' CHAR '-' CHAR '-' CHAR '-' CHAR '-' EQUB 0 CHAR 'P' \ Token 145: "PRESENT" TWOK 'R', 'E' \ CHAR 'S' \ Encoded as: "P<142>S<146>T" TWOK 'E', 'N' CHAR 'T' EQUB 0 CONT 8 \ Token 146: "{all caps}GAME OVER" CHAR 'G' \ CHAR 'A' \ Encoded as: "{8}GAME O<150>R" CHAR 'M' CHAR 'E' CHAR ' ' CHAR 'O' TWOK 'V', 'E' CHAR 'R' EQUB 0 CHAR 'P' \ Token 147: "PRESS FIRE OR SPACE,COMMANDER.{crlf} CHAR 'R' \ {crlf} TWOK 'E', 'S' \ " CHAR 'S' \ CHAR ' ' \ Encoded as: "PR<137>S FI<142> <153> SPA<133>,[92]. CHAR 'F' \ {13}{13}" CHAR 'I' TWOK 'R', 'E' CHAR ' ' TWOK 'O', 'R' CHAR ' ' CHAR 'S' CHAR 'P' CHAR 'A' TWOK 'C', 'E' CHAR ',' RTOK 92 CHAR '.' CONT 13 CONT 13 EQUB 0 CHAR '(' \ Token 148: "(C) ACORNSOFT 1984" CHAR 'C' \ CHAR ')' \ Encoded as: "(C) AC<153>N<135>FT 1984" CHAR ' ' CHAR 'A' CHAR 'C' TWOK 'O', 'R' CHAR 'N' TWOK 'S', 'O' CHAR 'F' CHAR 'T' CHAR ' ' CHAR '1' CHAR '9' CHAR '8' CHAR '4' EQUB 0 \ ****************************************************************************** \ \ Save WORDS9.bin \ \ ****************************************************************************** PRINT "WORDS9" PRINT "Assembled at ", ~CODE_WORDS% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_WORDS%) PRINT "Execute at ", ~LOAD_WORDS% PRINT "Reload at ", ~LOAD_WORDS% PRINT "S.WORDS9 ", ~CODE_WORDS%, " ", ~P%, " ", ~LOAD_WORDS%, " ", ~LOAD_WORDS% SAVE "3-assembled-output/WORDS9.bin", CODE_WORDS%, P%, LOAD_WORDS% \ ****************************************************************************** \ \ Name: K% \ Type: Workspace \ Address: &0900 to &0AAF \ Category: Workspaces \ Summary: Ship data blocks and ship line heaps \ Deep dive: Ship data blocks \ The local bubble of universe \ \ ------------------------------------------------------------------------------ \ \ Contains ship data for all the ships, planets, suns and space stations in our \ local bubble of universe, along with their corresponding ship line heaps. \ \ The blocks are pointed to by the lookup table at location UNIV. The first 432 \ bytes of the K% workspace hold ship data on up to 12 ships, with 36 (NI%) \ bytes per ship, and the ship line heap grows downwards from WP at the end of \ the K% workspace. \ \ ****************************************************************************** ORG &0900 \ Set the assembly address to &0900 .K% SKIP NOSH * NI% \ Ship data blocks and ship line heap PRINT "K% workspace from ", ~K%, "to ", ~P%-1, "inclusive" \ ****************************************************************************** \ \ Name: WP \ Type: Workspace \ Address: &0D40 to &0F33 \ Category: Workspaces \ Summary: Ship slots, variables \ \ ****************************************************************************** ORG &0D40 \ Set the assembly address to &0D40 .WP SKIP 0 \ The start of the WP workspace .FRIN SKIP NOSH + 1 \ Slots for the ships in the local bubble of universe \ \ There are #NOSH + 1 slots, but the ship-spawning \ routine at NWSHP only populates #NOSH of them, so \ there are 13 slots but only 12 are used for ships \ (the last slot is effectively used as a null \ terminator when shuffling the slots down in the \ KILLSHP routine) .CABTMP SKIP 0 \ Cabin temperature \ \ The ambient cabin temperature in deep space is 30, \ which is displayed as one notch on the dashboard bar \ \ We get higher temperatures closer to the sun \ \ CABTMP shares a location with MANY, but that's OK as \ MANY+0 would contain the number of ships of type 0, \ and as there is no ship type 0 (they start at 1), the \ byte at MANY+0 is not used for storing a ship type \ and can be used for the cabin temperature instead .MANY SKIP SST \ The number of ships of each type in the local bubble \ of universe \ \ The number of ships of type X in the local bubble is \ stored at MANY+X .SSPR SKIP NTY + 1 - SST \ "Space station present" flag \ \ * Non-zero if we are inside the space station's safe \ zone \ \ * 0 if we aren't (in which case we can show the sun) \ \ This flag is at MANY+SST, which is no coincidence, as \ MANY+SST is a count of how many space stations there \ are in our local bubble, which is the same as saying \ "space station present" .ECMP SKIP 1 \ Our E.C.M. status \ \ * 0 = E.C.M. is off \ \ * Non-zero = E.C.M. is on .MJ SKIP 1 \ Are we in witchspace (i.e. have we mis-jumped)? \ \ * 0 = no, we are in normal space \ \ * &FF = yes, we are in witchspace .LAS2 SKIP 1 \ Laser power for the current laser \ \ * Bits 0-6 contain the laser power of the current \ space view \ \ * Bit 7 denotes whether or not the laser pulses: \ \ * 0 = pulsing laser \ \ * 1 = beam laser (i.e. always on) .MSAR SKIP 1 \ The targeting state of our leftmost missile \ \ * 0 = missile is not looking for a target, or it \ already has a target lock (indicator is not \ yellow/white) \ \ * Non-zero = missile is currently looking for a \ target (indicator is yellow/white) .VIEW SKIP 1 \ The number of the current space view \ \ * 0 = front \ * 1 = rear \ * 2 = left \ * 3 = right .LASCT SKIP 1 \ The laser pulse count for the current laser \ \ This is a counter that defines the gap between the \ pulses of a pulse laser. It is set as follows: \ \ * 0 for a beam laser \ \ * 10 for a pulse laser \ \ It gets decremented every vertical sync (in the LINSCN \ routine, which is called 50 times a second) and is set \ to a non-zero value for pulse lasers only \ \ The laser only fires when the value of LASCT hits \ zero, so for pulse lasers with a value of 10, that \ means the laser fires once every 10 vertical syncs (or \ 5 times a second) \ \ In comparison, beam lasers fire continuously as the \ value of LASCT is always 0 .GNTMP SKIP 1 \ Laser temperature (or "gun temperature") \ \ If the laser temperature exceeds 242 then the laser \ overheats and cannot be fired again until it has \ cooled down .HFX SKIP 1 \ A flag that toggles the hyperspace colour effect \ \ * 0 = no colour effect \ \ * Non-zero = hyperspace colour effect enabled \ \ When HFX is set to 1, the mode 4 screen that makes \ up the top part of the display is temporarily switched \ to mode 5 (the same screen mode as the dashboard), \ which has the effect of blurring and colouring the \ hyperspace rings in the top part of the screen. The \ code to do this is in the LINSCN routine, which is \ called as part of the screen mode routine at IRQ1. \ It's in LINSCN that HFX is checked, and if it is \ non-zero, the top part of the screen is not switched \ to mode 4, thus leaving the top part of the screen in \ the more colourful mode 5 .EV SKIP 1 \ The "extra vessels" spawning counter \ \ This counter is set to 0 on arrival in a system and \ following an in-system jump, and is bumped up when we \ spawn bounty hunters or pirates (i.e. "extra vessels") \ \ It decreases by 1 each time we consider spawning more \ "extra vessels" in part 4 of the main game loop, so \ increasing the value of EV has the effect of delaying \ the spawning of more vessels \ \ In other words, this counter stops bounty hunters and \ pirates from continually appearing, and ensures that \ there's a delay between spawnings .DLY SKIP 1 \ In-flight message delay \ \ This counter is used to keep an in-flight message up \ for a specified time before it gets removed. The value \ in DLY is decremented each time we start another \ iteration of the main game loop at TT100 .de SKIP 1 \ Equipment destruction flag \ \ * Bit 1 denotes whether or not the in-flight message \ about to be shown by the MESS routine is about \ destroyed equipment: \ \ * 0 = the message is shown normally \ \ * 1 = the string " DESTROYED" gets added to the \ end of the message .LSX SKIP 0 \ LSX is an alias that points to the first byte of the \ sun line heap at LSO \ \ * &FF indicates the sun line heap is empty \ \ * Otherwise the LSO heap contains the line data for \ the sun .LSO SKIP 192 \ The ship line heap for the space station (see NWSPS) \ and the sun line heap (see SUN) \ \ The spaces can be shared as our local bubble of \ universe can support either the sun or a space \ station, but not both .LSX2 SKIP 78 \ The ball line heap for storing x-coordinates .LSY2 SKIP 78 \ The ball line heap for storing y-coordinates .SY SKIP NOST + 1 \ This is where we store the y_hi coordinates for all \ the stardust particles .SYL SKIP NOST + 1 \ This is where we store the y_lo coordinates for all \ the stardust particles .SZ SKIP NOST + 1 \ This is where we store the z_hi coordinates for all \ the stardust particles .SZL SKIP NOST + 1 \ This is where we store the z_lo coordinates for all \ the stardust particles .XSAV2 SKIP 1 \ Temporary storage, used for storing the value of the X \ register in the TT26 routine .YSAV2 SKIP 1 \ Temporary storage, used for storing the value of the Y \ register in the TT26 routine .MCH SKIP 1 \ The text token number of the in-flight message that is \ currently being shown, and which will be removed by \ the me2 routine when the counter in DLY reaches zero .FSH SKIP 1 \ Forward shield status \ \ * 0 = empty \ \ * &FF = full .ASH SKIP 1 \ Aft shield status \ \ * 0 = empty \ \ * &FF = full .ENERGY SKIP 1 \ Energy bank status \ \ * 0 = empty \ \ * &FF = full .LASX SKIP 1 \ The x-coordinate of the tip of the laser line .LASY SKIP 1 \ The y-coordinate of the tip of the laser line .COMX SKIP 1 \ The x-coordinate of the compass dot .COMY SKIP 1 \ The y-coordinate of the compass dot .QQ24 SKIP 1 \ Temporary storage, used to store the current market \ item's price in routine TT151 .QQ25 SKIP 1 \ Temporary storage, used to store the current market \ item's availability in routine TT151 .QQ28 SKIP 1 \ The current system's economy (0-7) \ \ * 0 = Rich Industrial \ * 1 = Average Industrial \ * 2 = Poor Industrial \ * 3 = Mainly Industrial \ * 4 = Mainly Agricultural \ * 5 = Rich Agricultural \ * 6 = Average Agricultural \ * 7 = Poor Agricultural .QQ29 SKIP 1 \ Temporary storage, used in a number of places .gov SKIP 1 \ The current system's government type (0-7) .tek SKIP 1 \ The current system's tech level (0-14) .SLSP SKIP 2 \ The address of the bottom of the ship line heap \ \ The ship line heap is a descending block of memory \ that starts at WP and descends down to SLSP. It can be \ extended downwards by the NWSHP routine when adding \ new ships (and their associated ship line heaps), in \ which case SLSP is lowered to provide more heap space, \ assuming there is enough free memory to do so .XX24 SKIP 1 \ This byte appears to be unused .ALTIT SKIP 1 \ Our altitude above the surface of the planet or sun \ \ * 255 = we are a long way above the surface \ \ * 1-254 = our altitude as the square root of: \ \ x_hi^2 + y_hi^2 + z_hi^2 - 6^2 \ \ where our ship is at the origin, the centre of the \ planet/sun is at (x_hi, y_hi, z_hi), and the \ radius of the planet/sun is 6 \ \ * 0 = we have crashed into the surface .QQ2 SKIP 6 \ The three 16-bit seeds for the current system, i.e. \ the one we are currently in .QQ3 SKIP 1 \ The selected system's economy (0-7) \ \ * 0 = Rich Industrial \ * 1 = Average Industrial \ * 2 = Poor Industrial \ * 3 = Mainly Industrial \ * 4 = Mainly Agricultural \ * 5 = Rich Agricultural \ * 6 = Average Agricultural \ * 7 = Poor Agricultural .QQ4 SKIP 1 \ The selected system's government (0-7) .QQ5 SKIP 1 \ The selected system's tech level (0-14) .QQ6 SKIP 2 \ The selected system's population in billions * 10 \ (1-71), so the maximum population is 7.1 billion .QQ7 SKIP 2 \ The selected system's productivity in M CR (96-62480) .QQ8 SKIP 2 \ The distance from the current system to the selected \ system in light years * 10, stored as a 16-bit number \ \ The distance will be 0 if the selected system is the \ current system \ \ The galaxy chart is 102.4 light years wide and 51.2 \ light years tall (see the intra-system distance \ calculations in routine TT111 for details), which \ equates to 1024 x 512 in terms of QQ8 .QQ9 SKIP 1 \ The galactic x-coordinate of the crosshairs in the \ galaxy chart (and, most of the time, the selected \ system's galactic x-coordinate) .QQ10 SKIP 1 \ The galactic y-coordinate of the crosshairs in the \ galaxy chart (and, most of the time, the selected \ system's galactic y-coordinate) .NOSTM SKIP 1 \ The number of stardust particles shown on screen, \ which is 18 (#NOST) for normal space, and 3 for \ witchspace PRINT "WP workspace from ", ~WP, "to ", ~P%-1, "inclusive" \ ****************************************************************************** \ \ ELITE A FILE \ \ Produces the binary file ELTA.bin that gets loaded by elite-bcfs.asm. \ \ The main game code (ELITE A through G, plus the ship data) is loaded at &1128 \ and is moved down to &0F40 as part of elite-loader.asm. \ \ ****************************************************************************** ORG CODE% \ Set the assembly address to CODE% LOAD_A% = LOAD% \ ****************************************************************************** \ \ Name: S% \ Type: Workspace \ Address: &0F40 to &0F50 \ Category: Workspaces \ Summary: Vector addresses, compass colour and configuration settings \ \ ------------------------------------------------------------------------------ \ \ Contains addresses that are used by the loader to set up vectors, the current \ compass colour, and the game's configuration settings. \ \ ****************************************************************************** .S% EQUW TT170 \ The entry point for the main game; once the main code \ has been loaded, decrypted and moved to the right \ place by elite-loader.asm, the game is started by a \ JMP (S%) instruction, which jumps to the main entry \ point at TT170 via this location EQUW TT26 \ WRCHV is set to the address in these two bytes by \ elite-loader.asm, so WRCHV points to TT26 EQUW IRQ1 \ IRQ1V is set to the address in these two bytes by \ elite-loader.asm, so IRQ1V points to IRQ1 EQUW BR1 \ BRKV is set to the address in these two bytes by \ elite-loader.asm, so BRKV points to BR1 .COMC SKIP 1 \ The colour of the dot on the compass \ \ * &F0 = the object in the compass is in front of us, \ so the dot is yellow/white \ \ * &FF = the object in the compass is behind us, so \ the dot is green/cyan .DNOIZ SKIP 1 \ Sound on/off configuration setting \ \ * 0 = sound is on (default) \ \ * Non-zero = sound is off \ \ Toggled by pressing "S" when paused, see the DK4 \ routine for details .DAMP SKIP 1 \ Keyboard damping configuration setting \ \ * 0 = damping is enabled (default) \ \ * &FF = damping is disabled \ \ Toggled by pressing CAPS LOCK when paused, see the \ DKS3 routine for details .DJD SKIP 1 \ Keyboard auto-recentre configuration setting \ \ * 0 = auto-recentre is enabled (default) \ \ * &FF = auto-recentre is disabled \ \ Toggled by pressing "A" when paused, see the DKS3 \ routine for details .PATG SKIP 1 \ Configuration setting to show the author names on the \ start-up screen and enable manual hyperspace mis-jumps \ \ * 0 = no author names or manual mis-jumps (default) \ \ * &FF = show author names and allow manual mis-jumps \ \ Toggled by pressing "X" when paused, see the DKS3 \ routine for details \ \ This needs to be turned on for manual mis-jumps to be \ possible. To do a manual mis-jump, first toggle the \ author display by pausing the game and pressing "X", \ and during the next hyperspace, hold down CTRL to \ force a mis-jump. See routine ee5 for the "AND PATG" \ instruction that implements this logic .FLH SKIP 1 \ Flashing console bars configuration setting \ \ * 0 = static bars (default) \ \ * &FF = flashing bars \ \ Toggled by pressing "F" when paused, see the DKS3 \ routine for details .JSTGY SKIP 1 \ Reverse joystick Y-channel configuration setting \ \ * 0 = standard Y-channel (default) \ \ * &FF = reversed Y-channel \ \ Toggled by pressing "Y" when paused, see the DKS3 \ routine for details .JSTE SKIP 1 \ Reverse both joystick channels configuration setting \ \ * 0 = standard channels (default) \ \ * &FF = reversed channels \ \ Toggled by pressing "J" when paused, see the DKS3 \ routine for details .JSTK SKIP 1 \ Keyboard or joystick configuration setting \ \ * 0 = keyboard (default) \ \ * &FF = joystick \ \ Toggled by pressing "K" when paused, see the DKS3 \ routine for details PRINT "S% workspace from ", ~S%, "to ", ~P%-1, "inclusive" \ ****************************************************************************** \ \ Name: Main flight loop (Part 1 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: Seed the random number generator \ Deep dive: Program flow of the main game loop \ Generating random numbers \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Seed the random number generator \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ M% The entry point for the main flight loop \ \ ****************************************************************************** .M% LDA K% \ We want to seed the random number generator with a \ pretty random number, so fetch the contents of K%, \ which is the x_lo coordinate of the planet. This value \ will be fairly unpredictable, so it's a pretty good \ candidate STA RAND \ Store the seed in the first byte of the four-byte \ random number seed that's stored in RAND \ ****************************************************************************** \ \ Name: Main flight loop (Part 2 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: Calculate the alpha and beta angles from the current pitch and \ roll of our ship \ Deep dive: Program flow of the main game loop \ Pitching and rolling \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Calculate the alpha and beta angles from the current pitch and roll \ \ Here we take the current rate of pitch and roll, as set by the joystick or \ keyboard, and convert them into alpha and beta angles that we can use in the \ matrix functions to rotate space around our ship. The alpha angle covers \ roll, while the beta angle covers pitch (there is no yaw in this version of \ Elite). The angles are in radians, which allows us to use the small angle \ approximation when moving objects in the sky (see the MVEIT routine for more \ on this). Also, the signs of the two angles are stored separately, in both \ the sign and the flipped sign, as this makes calculations easier. \ \ ****************************************************************************** LDX JSTX \ Set X to the current rate of roll in JSTX JSR cntr \ Apply keyboard damping twice (if enabled) so the roll JSR cntr \ rate in X creeps towards the centre by 2 \ The roll rate in JSTX increases if we press ">" (and \ the RL indicator on the dashboard goes to the right) \ \ This rolls our ship to the right (clockwise), but we \ actually implement this by rolling everything else \ to the left (anti-clockwise), so a positive roll rate \ in JSTX translates to a negative roll angle alpha TXA \ Set A and Y to the roll rate but with the sign bit EOR #%10000000 \ flipped (i.e. set them to the sign we want for alpha) TAY AND #%10000000 \ Extract the flipped sign of the roll rate and store STA ALP2 \ in ALP2 (so ALP2 contains the sign of the roll angle \ alpha) STX JSTX \ Update JSTX with the damped value that's still in X EOR #%10000000 \ Extract the correct sign of the roll rate and store STA ALP2+1 \ in ALP2+1 (so ALP2+1 contains the flipped sign of the \ roll angle alpha) TYA \ Set A to the roll rate but with the sign bit flipped BPL P%+7 \ If the value of A is positive, skip the following \ three instructions EOR #%11111111 \ A is negative, so change the sign of A using two's CLC \ complement so that A is now positive and contains ADC #1 \ the absolute value of the roll rate, i.e. |JSTX| LSR A \ Divide the (positive) roll rate in A by 4 LSR A CMP #8 \ If A >= 8, skip the following two instructions BCS P%+4 LSR A \ A < 8, so halve A again CLC \ This instruction has no effect, as we only get here \ if the C flag is clear (if it is set, we skip this \ instruction) STA ALP1 \ Store A in ALP1, so we now have: \ \ ALP1 = |JSTX| / 8 if |JSTX| < 32 \ \ ALP1 = |JSTX| / 4 if |JSTX| >= 32 \ \ This means that at lower roll rates, the roll angle is \ reduced closer to zero than at higher roll rates, \ which gives us finer control over the ship's roll at \ lower roll rates \ \ Because JSTX is in the range -127 to +127, ALP1 is \ in the range 0 to 31 ORA ALP2 \ Store A in ALPHA, but with the sign set to ALP2 (so STA ALPHA \ ALPHA has a different sign to the actual roll rate) LDX JSTY \ Set X to the current rate of pitch in JSTY JSR cntr \ Apply keyboard damping so the pitch rate in X creeps \ towards the centre by 1 TXA \ Set A and Y to the pitch rate but with the sign bit EOR #%10000000 \ flipped TAY AND #%10000000 \ Extract the flipped sign of the pitch rate into A STX JSTY \ Update JSTY with the damped value that's still in X STA BET2+1 \ Store the flipped sign of the pitch rate in BET2+1 EOR #%10000000 \ Extract the correct sign of the pitch rate and store STA BET2 \ it in BET2 TYA \ Set A to the pitch rate but with the sign bit flipped BPL P%+4 \ If the value of A is positive, skip the following \ instruction EOR #%11111111 \ A is negative, so flip the bits ADC #4 \ Add 4 to the (positive) pitch rate, so the maximum \ value is now up to 131 (rather than 127) LSR A \ Divide the (positive) pitch rate in A by 16 LSR A LSR A LSR A CMP #3 \ If A >= 3, skip the following instruction BCS P%+3 LSR A \ A < 3, so halve A again STA BET1 \ Store A in BET1, so we now have: \ \ BET1 = |JSTY| / 32 if |JSTY| < 48 \ \ BET1 = |JSTY| / 16 if |JSTY| >= 48 \ \ This means that at lower pitch rates, the pitch angle \ is reduced closer to zero than at higher pitch rates, \ which gives us finer control over the ship's pitch at \ lower pitch rates \ \ Because JSTY is in the range -131 to +131, BET1 is in \ the range 0 to 8 ORA BET2 \ Store A in BETA, but with the sign set to BET2 (so STA BETA \ BETA has the same sign as the actual pitch rate) \ ****************************************************************************** \ \ Name: Main flight loop (Part 3 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: Scan for flight keys and process the results \ Deep dive: Program flow of the main game loop \ The key logger \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Scan for flight keys and process the results \ \ Flight keys are logged in the key logger at location KY1 onwards, with a \ non-zero value in the relevant location indicating a key press. \ \ The key presses that are processed are as follows: \ \ * Space and "?" to speed up and slow down \ * "U", "T" and "M" to disarm, arm and fire missiles \ * TAB to fire an energy bomb \ * ESCAPE to launch an escape pod \ * "J" to initiate an in-system jump \ * "E" to deploy E.C.M. anti-missile countermeasures \ * "C" to use the docking computer \ * "A" to fire lasers \ \ ****************************************************************************** LDA KY2 \ If Space is being pressed, keep going, otherwise jump BEQ MA17 \ down to MA17 to skip the following LDA DELTA \ The "go faster" key is being pressed, so first we CMP #40 \ fetch the current speed from DELTA into A, and if BCS MA17 \ A >= 40, we are already going at full pelt, so jump \ down to MA17 to skip the following INC DELTA \ We can go a bit faster, so increment the speed in \ location DELTA .MA17 LDA KY1 \ If "?" is being pressed, keep going, otherwise jump BEQ MA4 \ down to MA4 to skip the following DEC DELTA \ The "slow down" key is being pressed, so we decrement \ the current ship speed in DELTA BNE MA4 \ If the speed is still greater than zero, jump to MA4 INC DELTA \ Otherwise we just braked a little too hard, so bump \ the speed back up to the minimum value of 1 .MA4 LDA KY15 \ If "U" is being pressed and the number of missiles AND NOMSL \ in NOMSL is non-zero, keep going, otherwise jump down BEQ MA20 \ to MA20 to skip the following LDY #&EE \ The "disarm missiles" key is being pressed, so call JSR ABORT \ ABORT to disarm the missile and update the missile \ indicators on the dashboard to green/cyan (Y = &EE) LDA #40 \ Call the NOISE routine with A = 40 to make a low, JSR NOISE \ long beep to indicate the missile is now disarmed .MA31 LDA #0 \ Set MSAR to 0 to indicate that no missiles are STA MSAR \ currently armed .MA20 LDA MSTG \ If MSTG is positive (i.e. it does not have bit 7 set), BPL MA25 \ then it indicates we already have a missile locked on \ a target (in which case MSTG contains the ship number \ of the target), so jump to MA25 to skip targeting. Or \ to put it another way, if MSTG = &FF, which means \ there is no current target lock, keep going LDA KY14 \ If "T" is being pressed, keep going, otherwise jump BEQ MA25 \ down to MA25 to skip the following LDX NOMSL \ If the number of missiles in NOMSL is zero, jump down BEQ MA25 \ to MA25 to skip the following STA MSAR \ The "target missile" key is being pressed and we have \ at least one missile, so set MSAR = &FF to denote that \ our missile is currently armed (we know A has the \ value &FF, as we just loaded it from MSTG and checked \ that it was negative) LDY #&E0 \ Change the leftmost missile indicator to yellow/white JSR MSBAR \ on the missile bar (this call changes the leftmost \ indicator because we set X to the number of missiles \ in NOMSL above, and the indicators are numbered from \ right to left, so X is the number of the leftmost \ indicator) .MA25 LDA KY16 \ If "M" is being pressed, keep going, otherwise jump BEQ MA24 \ down to MA24 to skip the following LDA MSTG \ If MSTG = &FF then there is no target lock, so jump to BMI MA64 \ MA64 to skip the following (also skipping the checks \ for TAB, ESCAPE, "J" and "E") JSR FRMIS \ The "fire missile" key is being pressed and we have \ a missile lock, so call the FRMIS routine to fire \ the missile .MA24 LDA KY12 \ If TAB is being pressed, keep going, otherwise jump BEQ MA76 \ down to MA76 to skip the following ASL BOMB \ The "energy bomb" key is being pressed, so double \ the value in BOMB. If we have an energy bomb fitted, \ BOMB will contain &7F (%01111111) before this shift \ and will contain &FE (%11111110) after the shift; if \ we don't have an energy bomb fitted, BOMB will still \ contain 0. The bomb explosion is dealt with in the \ MAL1 routine below - this just registers the fact that \ we've set the bomb ticking .MA76 LDA KY13 \ If ESCAPE is being pressed and we have an escape pod AND ESCP \ fitted, keep going, otherwise skip the next BEQ P%+5 \ instruction JMP ESCAPE \ The button is being pressed to launch an escape pod \ and we have an escape pod fitted, so jump to ESCAPE to \ launch it, and exit the main flight loop using a tail \ call LDA KY18 \ If "J" is being pressed, keep going, otherwise skip BEQ P%+5 \ the next instruction JSR WARP \ Call the WARP routine to do an in-system jump LDA KY17 \ If "E" is being pressed and we have an E.C.M. fitted, AND ECM \ keep going, otherwise jump down to MA64 to skip the BEQ MA64 \ following LDA ECMA \ If ECMA is non-zero, that means an E.C.M. is already BNE MA64 \ operating and is counting down (this can be either \ our E.C.M. or an opponent's), so jump down to MA64 to \ skip the following (as we can't have two E.C.M. \ systems operating at the same time) DEC ECMP \ The E.C.M. button is being pressed and nobody else \ is operating their E.C.M., so decrease the value of \ ECMP to make it non-zero, to denote that our E.C.M. \ is now on JSR ECBLB2 \ Call ECBLB2 to light up the E.C.M. indicator bulb on \ the dashboard, set the E.C.M. countdown timer to 32, \ and start making the E.C.M. sound .MA64 LDA KY19 \ If "C" is being pressed, and we have a docking AND DKCMP \ computer fitted, and we are inside the space station's AND SSPR \ safe zone, keep going, otherwise jump down to MA68 to BEQ MA68 \ skip the following LDA K%+NI%+32 \ Fetch the AI counter (byte #32) of the second ship BMI MA68 \ from the ship data workspace at K%, which is reserved \ for the sun or the space station (in this case it's \ the latter as we are in the safe zone). If byte #32 is \ negative, meaning the station is hostile, then jump \ down to MA68 to skip the following (so we can't use \ the docking computer to dock at a station that has \ turned against us) JMP GOIN \ The Docking Computer button has been pressed and \ we are allowed to dock at the station, so jump to \ GOIN to dock (or "go in"), and exit the main flight \ loop using a tail call .MA68 LDA #0 \ Set LAS = 0, to switch the laser off while we do the STA LAS \ following logic STA DELT4 \ Take the 16-bit value (DELTA 0) - i.e. a two-byte LDA DELTA \ number with DELTA as the high byte and 0 as the low LSR A \ byte - and divide it by 4, storing the 16-bit result ROR DELT4 \ in DELT4(1 0). This has the effect of storing the LSR A \ current speed * 64 in the 16-bit location DELT4(1 0) ROR DELT4 STA DELT4+1 LDA LASCT \ If LASCT is zero, keep going, otherwise the laser is BNE MA3 \ a pulse laser that is between pulses, so jump down to \ MA3 to skip the following LDA KY7 \ If "A" is being pressed, keep going, otherwise jump BEQ MA3 \ down to MA3 to skip the following LDA GNTMP \ If the laser temperature >= 242 then the laser has CMP #242 \ overheated, so jump down to MA3 to skip the following BCS MA3 LDX VIEW \ If the current space view has a laser fitted (i.e. the LDA LASER,X \ laser power for this view is greater than zero), then BEQ MA3 \ keep going, otherwise jump down to MA3 to skip the \ following \ If we get here, then the "fire" button is being \ pressed, our laser hasn't overheated and isn't already \ being fired, and we actually have a laser fitted to \ the current space view, so it's time to hit me with \ those laser beams PHA \ Store the current view's laser power on the stack AND #%01111111 \ Set LAS and LAS2 to bits 0-6 of the laser power STA LAS STA LAS2 LDA #0 \ Call the NOISE routine with A = 0 to make the sound JSR NOISE \ of our laser firing JSR LASLI \ Call LASLI to draw the laser lines PLA \ Restore the current view's laser power into A BPL ma1 \ If the laser power has bit 7 set, then it's an "always \ on" laser rather than a pulsing laser, so keep going, \ otherwise jump down to ma1 to skip the following \ instruction LDA #0 \ This is an "always on" laser (i.e. a beam laser, \ as this version of Elite doesn't have military \ lasers), so set A = 0, which will be stored in LASCT \ to denote that this is not a pulsing laser .ma1 AND #%11111010 \ LASCT will be set to 0 for beam lasers, and to the STA LASCT \ laser power AND %11111010 for pulse lasers, which \ comes to 10 (as pulse lasers have a power of 15). See \ MA23 in part 16 for more on laser pulsing and LASCT \ ****************************************************************************** \ \ Name: Main flight loop (Part 4 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: Copy the ship's data block from K% to the \ zero-page workspace at INWK \ Deep dive: Program flow of the main game loop \ Ship data blocks \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Start looping through all the ships in the local bubble, and for each \ one: \ \ * Copy the ship's data block from K% to INWK \ \ * Set XX0 to point to the ship's blueprint (if this is a ship) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ MAL1 Marks the beginning of the ship analysis loop, so we \ can jump back here from part 12 of the main flight loop \ to work our way through each ship in the local bubble. \ We also jump back here when a ship is removed from the \ bubble, so we can continue processing from the next ship \ \ ****************************************************************************** .MA3 LDX #0 \ We're about to work our way through all the ships in \ our local bubble of universe, so set a counter in X, \ starting from 0, to refer to each ship slot in turn .MAL1 STX XSAV \ Store the current slot number in XSAV LDA FRIN,X \ Fetch the contents of this slot into A. If it is 0 BNE P%+5 \ then this slot is empty and we have no more ships to JMP MA18 \ process, so jump to MA18 below, otherwise A contains \ the type of ship that's in this slot, so skip over the \ JMP MA18 instruction and keep going STA TYPE \ Store the ship type in TYPE JSR GINF \ Call GINF to fetch the address of the ship data block \ for the ship in slot X and store it in INF. The data \ block is in the K% workspace, which is where all the \ ship data blocks are stored \ Next we want to copy the ship data block from INF to \ the zero-page workspace at INWK, so we can process it \ more efficiently LDY #NI%-1 \ There are NI% bytes in each ship data block (and in \ the INWK workspace, so we set a counter in Y so we can \ loop through them .MAL2 LDA (INF),Y \ Load the Y-th byte of INF and store it in the Y-th STA INWK,Y \ byte of INWK DEY \ Decrement the loop counter BPL MAL2 \ Loop back for the next byte until we have copied the \ last byte from INF to INWK LDA TYPE \ If the ship type is negative then this indicates a BMI MA21 \ planet or sun, so jump down to MA21, as the next bit \ sets up a pointer to the ship blueprint, and then \ checks for energy bomb damage, and neither of these \ apply to planets and suns ASL A \ Set Y = ship type * 2 TAY LDA XX21-2,Y \ The ship blueprints at XX21 start with a lookup STA XX0 \ table that points to the individual ship blueprints, \ so this fetches the low byte of this particular ship \ type's blueprint and stores it in XX0 LDA XX21-1,Y \ Fetch the high byte of this particular ship type's STA XX0+1 \ blueprint and store it in XX0+1 \ ****************************************************************************** \ \ Name: Main flight loop (Part 5 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: If an energy bomb has been set off, \ potentially kill this ship \ Deep dive: Program flow of the main game loop \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Continue looping through all the ships in the local bubble, and for each \ one: \ \ * If an energy bomb has been set off and this ship can be killed, kill it \ and increase the kill tally \ \ ****************************************************************************** LDA BOMB \ If we set off our energy bomb (see MA24 above), then BPL MA21 \ BOMB is now negative, so this skips to MA21 if our \ energy bomb is not going off CPY #2*SST \ If the ship in Y is the space station, jump to BA21 BEQ MA21 \ as energy bombs are useless against space stations LDA INWK+31 \ If the ship we are checking has bit 5 set in its ship AND #%00100000 \ byte #31, then it is already exploding, so jump to BNE MA21 \ BA21 as ships can't explode more than once LDA INWK+31 \ The energy bomb is killing this ship, so set bit 7 of ORA #%10000000 \ the ship byte #31 to indicate that it has now been STA INWK+31 \ killed JSR EXNO2 \ Call EXNO2 to process the fact that we have killed a \ ship (so increase the kill tally, make an explosion \ sound and possibly display "RIGHT ON COMMANDER!") \ ****************************************************************************** \ \ Name: Main flight loop (Part 6 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: Move the ship in space and copy the updated \ INWK data block back to K% \ Deep dive: Program flow of the main game loop \ Program flow of the ship-moving routine \ Ship data blocks \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Continue looping through all the ships in the local bubble, and for each \ one: \ \ * Move the ship in space \ \ * Copy the updated ship's data block from INWK back to K% \ \ ****************************************************************************** .MA21 JSR MVEIT \ Call MVEIT to move the ship we are processing in space \ Now that we are done processing this ship, we need to \ copy the ship data back from INWK to the correct place \ in the K% workspace. We already set INF in part 4 to \ point to the ship's data block in K%, so we can simply \ do the reverse of the copy we did before, this time \ copying from INWK to INF LDY #NI%-1 \ Set a counter in Y so we can loop through the NI% \ bytes in the ship data block .MAL3 LDA INWK,Y \ Load the Y-th byte of INWK and store it in the Y-th STA (INF),Y \ byte of INF DEY \ Decrement the loop counter BPL MAL3 \ Loop back for the next byte, until we have copied the \ last byte from INWK back to INF \ ****************************************************************************** \ \ Name: Main flight loop (Part 7 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: Check whether we are docking, scooping or \ colliding with it \ Deep dive: Program flow of the main game loop \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Continue looping through all the ships in the local bubble, and for each \ one: \ \ * Check how close we are to this ship and work out if we are docking, \ scooping or colliding with it \ \ ****************************************************************************** LDA INWK+31 \ Fetch the status of this ship from bits 5 (is ship AND #%10100000 \ exploding?) and bit 7 (has ship been killed?) from \ ship byte #31 into A JSR MAS4 \ Or this value with x_hi, y_hi and z_hi BNE MA65 \ If this value is non-zero, then either the ship is \ far away (i.e. has a non-zero high byte in at least \ one of the three axes), or it is already exploding, \ or has been flagged as being killed - in which case \ jump to MA65 to skip the following, as we can't dock \ scoop or collide with it LDA INWK \ Set A = (x_lo OR y_lo OR z_lo), and if bit 7 of the ORA INWK+3 \ result is set, the ship is still a fair distance ORA INWK+6 \ away (further than 127 in at least one axis), so jump BMI MA65 \ to MA65 to skip the following, as it's too far away to \ dock, scoop or collide with LDX TYPE \ If the current ship type is negative then it's either BMI MA65 \ a planet or a sun, so jump down to MA65 to skip the \ following, as we can't dock with it or scoop it CPX #SST \ If this ship is the space station, jump to ISDK to BEQ ISDK \ check whether we are docking with it AND #%11000000 \ If bit 6 of (x_lo OR y_lo OR z_lo) is set, then the BNE MA65 \ ship is still a reasonable distance away (further than \ 63 in at least one axis), so jump to MA65 to skip the \ following, as it's too far away to dock, scoop or \ collide with CPX #MSL \ If this ship is a missile, jump down to MA65 to skip BEQ MA65 \ the following, as we can't scoop or dock with a \ missile, and it has its own dedicated collision \ checks in the TACTICS routine CPX #OIL \ If ship type >= OIL (i.e. it's a cargo canister, BCS P%+5 \ Thargon or escape pod), skip the JMP instruction and JMP MA58 \ continue on, otherwise jump to MA58 to process a \ potential collision LDA BST \ If we have fuel scoops fitted then BST will be &FF, \ otherwise it will be 0 AND INWK+5 \ Ship byte #5 contains the y_sign of this ship, so a \ negative value here means the canister is below us, \ which means the result of the AND will be negative if \ the canister is below us and we have a fuel scoop \ fitted BPL MA58 \ If the result is positive, then we either have no \ scoop or the canister is above us, and in both cases \ this means we can't scoop the item, so jump to MA58 \ to process a collision \ ****************************************************************************** \ \ Name: Main flight loop (Part 8 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: Process us potentially scooping this item \ Deep dive: Program flow of the main game loop \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Continue looping through all the ships in the local bubble, and for each \ one: \ \ * Process us potentially scooping this item \ \ ****************************************************************************** LDA #3 \ Set A to 3 to denote we may be scooping an escape pod CPX #TGL \ If ship type < Thargon, i.e. it's a canister, jump BCC oily \ to oily to randomly decide the canister's contents BNE slvy2 \ If ship type <> Thargon, i.e. it's an escape pod, \ jump to slvy2 with A set to 3, so we scoop up the \ escape pod as slaves LDA #16 \ Otherwise this is a Thargon, so jump to slvy2 with BNE slvy2 \ A set to 16, so we scoop up the Thargon as alien items \ (this BNE is effectively a JMP as A will never be \ zero) .oily JSR DORND \ Set A and X to random numbers and reduce A to a AND #7 \ random number in the range 0-7 .slvy2 \ By the time we get here, we are scooping, and A \ contains the type of item we are scooping (a random \ number 0-7 if we are scooping a cargo canister, 3 if \ we are scooping an escape pod, or 16 if we are \ scooping a Thargon). These numbers correspond to the \ relevant market items (see QQ23 for a list), so a \ cargo canister can contain anything from food to \ computers, while escape pods contain slaves, and \ Thargons become alien items when scooped STA QQ29 \ Call tnpr with the scooped cargo type stored in QQ29 LDA #1 \ and A set to 1, to work out whether we have room in JSR tnpr \ the hold for the scooped item (A is preserved by this \ call, and the C flag contains the result) LDY #78 \ This instruction has no effect, so presumably it used \ to do something, but didn't get removed BCS MA59 \ If the C flag is set then we have no room in the hold \ for the scooped item, so jump down to MA59 make a \ sound to indicate failure, before destroying the \ canister LDY QQ29 \ Scooping was successful, so set Y to the type of \ item we just scooped, which we stored in QQ29 above ADC QQ20,Y \ Add A (which we set to 1 above) to the number of items STA QQ20,Y \ of type Y in the cargo hold, as we just successfully \ scooped one canister of type Y TYA \ Print recursive token 48 + Y as an in-flight token, ADC #208 \ which will be in the range 48 ("FOOD") to 64 ("ALIEN JSR MESS \ ITEMS"), so this prints the scooped item's name JMP MA60 \ We are done scooping, so jump down to MA60 to set the \ kill flag on the canister, as it no longer exists in \ the local bubble .MA65 JMP MA26 \ If we get here, then the ship we are processing was \ too far away to be scooped, docked or collided with, \ so jump to MA26 to skip over the collision routines \ and move on to missile targeting \ ****************************************************************************** \ \ Name: Main flight loop (Part 9 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: If it is a space station, check whether we \ are successfully docking with it \ Deep dive: Program flow of the main game loop \ Docking checks \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Process docking with a space station \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ GOIN We jump here from part 3 of the main flight loop if the \ docking computer is activated by pressing "C" \ \ ****************************************************************************** .ISDK LDA K%+NI%+32 \ 1. Fetch the AI counter (byte #32) of the second ship BMI MA62 \ in the ship data workspace at K%, which is reserved \ for the sun or the space station (in this case it's \ the latter), and if it's negative, i.e. bit 7 is set, \ meaning the station is hostile, jump down to MA62 to \ fail docking (so trying to dock at a station that we \ have annoyed does not end well) LDA INWK+14 \ 2. If nosev_z_hi < 214, jump down to MA62 to fail CMP #214 \ docking, as the angle of approach is greater than 26 BCC MA62 \ degrees JSR SPS4 \ Call SPS4 to get the vector to the space station \ into XX15 LDA XX15+2 \ 3. Check the sign of the z-axis (bit 7 of XX15+2) and BMI MA62 \ if it is negative, we are facing away from the \ station, so jump to MA62 to fail docking CMP #89 \ 4. If z-axis < 89, jump to MA62 to fail docking, as BCC MA62 \ we are not in the 22.0 degree safe cone of approach LDA INWK+16 \ 5. If |roofv_x_hi| < 80, jump to MA62 to fail docking, AND #%01111111 \ as the slot is more than 36.6 degrees from horizontal CMP #80 BCC MA62 .GOIN \ If we arrive here, either the docking computer has \ been activated, or we just docked successfully LDA #0 \ Set the on-screen hyperspace counter to 0 STA QQ22+1 LDA #8 \ This instruction has no effect, so presumably it used \ to do something, and didn't get removed JSR LAUN \ Show the space station launch tunnel JSR RES4 \ Reset the shields and energy banks, stardust and INWK \ workspace JMP BAY \ Go to the docking bay (i.e. show the Status Mode \ screen) .MA62 \ If we arrive here, docking has just failed LDA DELTA \ If the ship's speed is < 5, jump to MA67 to register CMP #5 \ some damage, but not a huge amount BCC MA67 JMP DEATH \ Otherwise we have just crashed into the station, so \ process our death \ ****************************************************************************** \ \ Name: Main flight loop (Part 10 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: Remove if scooped, or process collisions \ Deep dive: Program flow of the main game loop \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Continue looping through all the ships in the local bubble, and for each \ one: \ \ * Remove scooped item after both successful and failed scooping attempts \ \ * Process collisions \ \ ****************************************************************************** .MA59 \ If we get here then scooping failed JSR EXNO3 \ Make the sound of the cargo canister being destroyed \ and fall through into MA60 to remove the canister \ from our local bubble .MA60 \ If we get here then scooping was successful ASL INWK+31 \ Set bit 7 of the scooped or destroyed item, to denote SEC \ that it has been killed and should be removed from ROR INWK+31 \ the local bubble .MA61 BNE MA26 \ Jump to MA26 to skip over the collision routines and \ to move on to missile targeting (this BNE is \ effectively a JMP as A will never be zero) .MA67 \ If we get here then we have collided with something, \ but not fatally LDA #1 \ Set the speed in DELTA to 1 (i.e. a sudden stop) STA DELTA LDA #5 \ Set the amount of damage in A to 5 (a small dent) and BNE MA63 \ jump down to MA63 to process the damage (this BNE is \ effectively a JMP as A will never be zero) .MA58 \ If we get here, we have collided with something in a \ potentially fatal way ASL INWK+31 \ Set bit 7 of the ship we just collided with, to SEC \ denote that it has been killed and should be removed ROR INWK+31 \ from the local bubble LDA INWK+35 \ Load A with the energy level of the ship we just hit SEC \ Set the amount of damage in A to 128 + A / 2, so ROR A \ this is quite a big dent, and colliding with higher \ energy ships will cause more damage .MA63 JSR OOPS \ The amount of damage is in A, so call OOPS to reduce \ our shields, and if the shields are gone, there's a \ chance of cargo loss or even death JSR EXNO3 \ Make the sound of colliding with the other ship and \ fall through into MA26 to try targeting a missile \ ****************************************************************************** \ \ Name: Main flight loop (Part 11 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: Process missile lock and firing our laser \ Deep dive: Program flow of the main game loop \ Flipping axes between space views \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Continue looping through all the ships in the local bubble, and for each \ one: \ \ * If this is not the front space view, flip the axes of the ship's \ coordinates in INWK \ \ * Process missile lock \ \ * Process our laser firing \ \ ****************************************************************************** .MA26 LDA QQ11 \ If this is not a space view, jump to MA15 to skip BNE MA15 \ missile and laser locking JSR PLUT \ Call PLUT to update the geometric axes in INWK to \ match the view (front, rear, left, right) JSR HITCH \ Call HITCH to see if this ship is in the crosshairs, BCC MA8 \ in which case the C flag will be set (so if there is \ no missile or laser lock, we jump to MA8 to skip the \ following) LDA MSAR \ We have missile lock, so check whether the leftmost BEQ MA47 \ missile is currently armed, and if not, jump to MA47 \ to process laser fire, as we can't lock an unarmed \ missile JSR BEEP \ We have missile lock and an armed missile, so call \ the BEEP subroutine to make a short, high beep LDX XSAV \ Call ABORT2 to store the details of this missile LDY #&0E \ lock, with the targeted ship's slot number in X JSR ABORT2 \ (which we stored in XSAV at the start of this ship's \ loop at MAL1), and set the colour of the missile \ indicator to the colour in Y (red = &0E) .MA47 \ If we get here then the ship is in our sights, but \ we didn't lock a missile, so let's see if we're \ firing the laser LDA LAS \ If we are firing the laser then LAS will contain the BEQ MA8 \ laser power (which we set in MA68 above), so if this \ is zero, jump down to MA8 to skip the following LDX #15 \ We are firing our laser and the ship in INWK is in JSR EXNO \ the crosshairs, so call EXNO to make the sound of \ us making a laser strike on another ship LDA INWK+35 \ Fetch the hit ship's energy from byte #35 and subtract SEC \ our current laser power, and if the result is greater SBC LAS \ than zero, the other ship has survived the hit, so BCS MA14 \ jump down to MA14 to make it angry LDA TYPE \ Did we just hit the space station? If so, jump to CMP #SST \ MA14+2 to make the station hostile, skipping the BEQ MA14+2 \ following as we can't destroy a space station LDA INWK+31 \ Set bit 7 of the enemy ship's byte #31, to indicate ORA #%10000000 \ that it has been killed STA INWK+31 BCS MA8 \ If the enemy ship type is >= SST (i.e. missile, \ asteroid, canister, Thargon or escape pod) then \ jump down to MA8 JSR DORND \ Fetch a random number, and jump to oh if it is BPL oh \ positive (50% chance) LDY #0 \ Fetch the first byte of the hit ship's blueprint, AND (XX0),Y \ which determines the maximum number of bits of \ debris shown when the ship is destroyed, and AND \ with the random number we just fetched STA CNT \ Store the result in CNT, so CNT contains a random \ number between 0 and the maximum number of bits of \ debris that this ship will release when destroyed .um BEQ oh \ We're going to go round a loop using CNT as a counter \ so this checks whether the counter is zero and jumps \ to oh when it gets there (which might be straight \ away) LDX #OIL \ Call SFS1 to spawn a cargo canister from the now LDA #0 \ deceased parent ship, giving the spawned canister an JSR SFS1 \ AI flag of 0 (no AI, zero aggression, no E.C.M.) DEC CNT \ Decrease the loop counter BPL um \ Jump back up to um (this BPL is effectively a JMP as \ CNT will never be negative) .oh JSR EXNO2 \ Call EXNO2 to process the fact that we have killed a \ ship (so increase the kill tally, make an explosion \ sound and so on) .MA14 STA INWK+35 \ Store the hit ship's updated energy in ship byte #35 LDA TYPE \ Call ANGRY to make this ship angry; if this is the JSR ANGRY \ space station this will make it hostile, or if this is \ a ship it will wake up its AI and give it a kick of \ speed (later calls to TACTICS may make the ship start \ to attack us if it has a high enough aggression level) \ ****************************************************************************** \ \ Name: Main flight loop (Part 12 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: For each nearby ship: Draw the ship, remove if killed, loop back \ Deep dive: Program flow of the main game loop \ Drawing ships \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Continue looping through all the ships in the local bubble, and for each \ one: \ \ * Draw the ship \ \ * Process removal of killed ships \ \ * Loop back up to MAL1 to move onto the next ship in the local bubble \ \ ****************************************************************************** .MA8 JSR LL9 \ Call LL9 to draw the ship we're processing on-screen .MA15 LDY #35 \ Fetch the ship's energy from byte #35 and copy it to LDA INWK+35 \ byte #35 in INF (so the ship's data in K% gets STA (INF),Y \ updated) LDA INWK+31 \ If bit 7 of the ship's byte #31 is clear, then the BPL MAC1 \ ship hasn't been killed by energy bomb, collision or \ laser fire, so jump to MAC1 to skip the following AND #%00100000 \ If bit 5 of the ship's byte #31 is clear then the BEQ NBOUN \ ship is no longer exploding, so jump to NBOUN to skip \ the following LDA TYPE \ If the ship we just destroyed was a cop, keep going, CMP #COPS \ otherwise jump to q2 to skip the following BNE q2 LDA FIST \ We shot the sheriff, so update our FIST flag ORA #64 \ ("fugitive/innocent status") to at least 64, which STA FIST \ will instantly make us a fugitive .q2 LDA DLY \ If we already have an in-flight message on-screen (in ORA MJ \ which case DLY > 0), or we are in witchspace (in BNE KS1S \ which case MJ > 0), jump to KS1S to skip showing an \ on-screen bounty for this kill LDY #10 \ Fetch byte #10 of the ship's blueprint, which is the LDA (XX0),Y \ low byte of the bounty awarded when this ship is BEQ KS1S \ killed (in Cr * 10), and if it's zero jump to KS1S as \ there is no on-screen bounty to display TAX \ Put the low byte of the bounty into X INY \ Fetch byte #11 of the ship's blueprint, which is the LDA (XX0),Y \ high byte of the bounty awarded (in Cr * 10), and put TAY \ it into Y JSR MCASH \ Call MCASH to add (Y X) to the cash pot LDA #0 \ Print control code 0 (current cash, right-aligned to JSR MESS \ width 9, then " CR", newline) as an in-flight message .KS1S JMP KS1 \ Process the killing of this ship (which removes this \ ship from its slot and shuffles all the other ships \ down to close up the gap) .NBOUN .MAC1 LDA TYPE \ If the ship we are processing is a planet or sun, BMI MA27 \ jump to MA27 to skip the following two instructions JSR FAROF \ If the ship we are processing is a long way away (its BCC KS1S \ distance in any one direction is > 224, jump to KS1S \ to remove the ship from our local bubble, as it's just \ left the building .MA27 LDY #31 \ Fetch the ship's explosion/killed state from byte #31 LDA INWK+31 \ and copy it to byte #31 in INF (so the ship's data in STA (INF),Y \ K% gets updated) LDX XSAV \ We're done processing this ship, so fetch the ship's \ slot number, which we saved in XSAV back at the start \ of the loop INX \ Increment the slot number to move on to the next slot JMP MAL1 \ And jump back up to the beginning of the loop to get \ the next ship in the local bubble for processing \ ****************************************************************************** \ \ Name: Main flight loop (Part 13 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: Show energy bomb effect, charge shields and energy banks \ Deep dive: Program flow of the main game loop \ Scheduling tasks with the main loop counter \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Show energy bomb effect (if applicable) \ \ * Charge shields and energy banks (every 7 iterations of the main loop) \ \ ****************************************************************************** .MA18 LDA BOMB \ If we set off our energy bomb (see MA24 above), then BPL MA77 \ BOMB is now negative, so this skips to MA21 if our \ energy bomb is not going off ASL BOMB \ We set off our energy bomb, so rotate BOMB to the \ left by one place. BOMB was rotated left once already \ during this iteration of the main loop, back at MA24, \ so if this is the first pass it will already be \ %11111110, and this will shift it to %11111100 - so \ if we set off an energy bomb, it stays activated \ (BOMB > 0) for four iterations of the main loop JSR WSCAN \ Call WSCAN to wait for the vertical sync, so the whole \ screen gets drawn and the following palette change \ won't kick in while the screen is still refreshing LDA #%00110000 \ Set the palette byte at SHEILA &21 to map logical STA VIA+&21 \ colour 0 to physical colour 7 (white), but with only \ one mapping (rather than the 7 mappings required to \ do the mapping properly). This makes the space screen \ flash with black and white stripes. See page 382 of \ the "Advanced User Guide for the BBC Micro" by Bray, \ Dickens and Holmes for details of why this single \ palette change creates a special effect .MA77 LDA MCNT \ Fetch the main loop counter and calculate MCNT mod 8, AND #7 \ jumping to MA22 if it is non-zero (so the following BNE MA22 \ code only runs every 8 iterations of the main loop) LDX ENERGY \ Fetch our ship's energy levels and skip to b if bit 7 BPL b \ is not set, i.e. only charge the shields from the \ energy banks if they are at more than 50% charge LDX ASH \ Call SHD to recharge our aft shield and update the JSR SHD \ shield status in ASH STX ASH LDX FSH \ Call SHD to recharge our forward shield and update JSR SHD \ the shield status in FSH STX FSH .b SEC \ Set A = ENERGY + ENGY + 1, so our ship's energy LDA ENGY \ level goes up by 2 if we have an energy unit fitted, ADC ENERGY \ otherwise it goes up by 1 BCS P%+5 \ If the value of A did not overflow (the maximum STA ENERGY \ energy level is &FF), then store A in ENERGY \ ****************************************************************************** \ \ Name: Main flight loop (Part 14 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: Spawn a space station if we are close enough to the planet \ Deep dive: Program flow of the main game loop \ Scheduling tasks with the main loop counter \ Ship data blocks \ The space station safe zone \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Spawn a space station if we are close enough to the planet (every 32 \ iterations of the main loop) \ \ ****************************************************************************** LDA MJ \ If we are in witchspace, jump down to MA23S to skip BNE MA23S \ the following, as there are no space stations in \ witchspace LDA MCNT \ Fetch the main loop counter and calculate MCNT mod 32, AND #31 \ jumping to MA93 if it is on-zero (so the following BNE MA93 \ code only runs every 32 iterations of the main loop) LDA SSPR \ If we are inside the space station safe zone, jump to BNE MA23S \ MA23S to skip the following, as we already have a \ space station and don't need another TAY \ Set Y = A = 0 (A is 0 as we didn't branch with the \ previous BNE instruction) JSR MAS2 \ Call MAS2 to calculate the largest distance to the BNE MA23S \ planet in any of the three axes, and if it's \ non-zero, jump to MA23S to skip the following, as we \ are too far from the planet to bump into a space \ station \ We now want to spawn a space station, so first we \ need to set up a ship data block for the station in \ INWK that we can then pass to NWSPS to add a new \ station to our bubble of universe. We do this by \ copying the planet data block from K% to INWK so we \ can work on it, but we only need the first 29 bytes, \ as we don't need to worry about bytes #29 to #35 \ for planets (as they don't have rotation counters, \ AI, explosions, missiles, a ship line heap or energy \ levels) LDX #28 \ So we set a counter in X to copy 29 bytes from K%+0 \ to K%+28 .MAL4 LDA K%,X \ Load the X-th byte of K% and store in the X-th byte STA INWK,X \ of the INWK workspace DEX \ Decrement the loop counter BPL MAL4 \ Loop back for the next byte until we have copied the \ first 28 bytes of K% to INWK \ We now check the distance from our ship (at the \ origin) towards the point where we will spawn the \ space station if we are close enough \ \ This point is calculated by starting at the planet's \ centre and adding 2 * nosev, which takes us to a point \ above the planet's surface, at an altitude that \ matches the planet's radius \ \ This point pitches and rolls around the planet as the \ nosev vector rotates with the planet, and if our ship \ is within a distance of (192 0) from this point in all \ three axes, then we spawn the space station at this \ point, with the station's slot facing towards the \ planet, along the nosev vector \ \ This works because in the following, we calculate the \ station's coordinates one axis at a time, and store \ the results in the INWK block, so by the time we have \ calculated and checked all three, the ship data block \ is set up with the correct spawning coordinates INX \ Set X = 0 (as we ended the above loop with X as &FF) LDY #9 \ Call MAS1 with X = 0, Y = 9 to do the following: JSR MAS1 \ \ (x_sign x_hi x_lo) += (nosev_x_hi nosev_x_lo) * 2 \ \ A = |x_sign| BNE MA23S \ If A > 0, jump to MA23S to skip the following, as we \ are too far from the planet in the x-direction to \ bump into a space station LDX #3 \ Call MAS1 with X = 3, Y = 11 to do the following: LDY #11 \ JSR MAS1 \ (y_sign y_hi y_lo) += (nosev_y_hi nosev_y_lo) * 2 \ \ A = |y_sign| BNE MA23S \ If A > 0, jump to MA23S to skip the following, as we \ are too far from the planet in the y-direction to \ bump into a space station LDX #6 \ Call MAS1 with X = 6, Y = 13 to do the following: LDY #13 \ JSR MAS1 \ (z_sign z_hi z_lo) += (nosev_z_hi nosev_z_lo) * 2 \ \ A = |z_sign| BNE MA23S \ If A > 0, jump to MA23S to skip the following, as we \ are too far from the planet in the z-direction to \ bump into a space station LDA #192 \ Call FAROF2 to compare x_hi, y_hi and z_hi with 192, JSR FAROF2 \ which will set the C flag if all three are < 192, or \ clear the C flag if any of them are >= 192 BCC MA23S \ Jump to MA23S if any one of x_hi, y_hi or z_hi are \ >= 192 (i.e. they must all be < 192 for us to be near \ enough to the planet to bump into a space station) LDA QQ11 \ If the current view is not a space view, skip the BNE P%+5 \ following instruction (so we only remove the sun from \ the screen if we are potentially looking at it) JSR WPLS \ Call WPLS to remove the sun from the screen, as we \ can't have both the sun and the space station at the \ same time JSR NWSPS \ Add a new space station to our local bubble of \ universe .MA23S JMP MA23 \ Jump to MA23 to skip the following planet and sun \ altitude checks \ ****************************************************************************** \ \ Name: Main flight loop (Part 15 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: Perform altitude checks with the planet and sun and process fuel \ scooping if appropriate \ Deep dive: Program flow of the main game loop \ Scheduling tasks with the main loop counter \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Perform an altitude check with the planet (every 32 iterations of the main \ loop, on iteration 10 of each 32) \ \ * Perform an altitude check with the sun and process fuel scooping (every \ 32 iterations of the main loop, on iteration 20 of each 32) \ \ ****************************************************************************** .MA22 LDA MJ \ If we are in witchspace, jump down to MA23 to skip BNE MA23 \ the following, as there are no planets or suns to \ bump into in witchspace LDA MCNT \ Fetch the main loop counter and calculate MCNT mod 32, AND #31 \ which tells us the position of this loop in each block \ of 32 iterations .MA93 CMP #10 \ If this is the tenth iteration in this block of 32, BNE MA29 \ do the following, otherwise jump to MA29 to skip the \ planet altitude check and move on to the sun distance \ check LDA #50 \ If our energy bank status in ENERGY is >= 50, skip CMP ENERGY \ printing the following message (so the message is BCC P%+6 \ only shown if our energy is low) ASL A \ Print recursive token 100 ("ENERGY LOW{beep}") as an JSR MESS \ in-flight message LDY #&FF \ Set our altitude in ALTIT to &FF, the maximum STY ALTIT INY \ Set Y = 0 JSR m \ Call m to calculate the maximum distance to the \ planet in any of the three axes, returned in A BNE MA23 \ If A > 0 then we are a fair distance away from the \ planet in at least one axis, so jump to MA23 to skip \ the rest of the altitude check JSR MAS3 \ Set A = x_hi^2 + y_hi^2 + z_hi^2, so using Pythagoras \ we now know that A now contains the square of the \ distance between our ship (at the origin) and the \ centre of the planet at (x_hi, y_hi, z_hi) BCS MA23 \ If the C flag was set by MAS3, then the result \ overflowed (was greater than &FF) and we are still a \ fair distance from the planet, so jump to MA23 as we \ haven't crashed into the planet SBC #36 \ Subtract 37 from x_hi^2 + y_hi^2 + z_hi^2 \ \ The SBC subtracts 37 as we just passed through a BCS \ so we know the C flag is clear \ \ When we do the 3D Pythagoras calculation, we only use \ the high bytes of the coordinates, so that's x_hi, \ y_hi and z_hi and \ \ The planet radius is (0 96 0), as defined in the \ PLANET routine, so the high byte is 96 \ \ When we square the coordinates above and add them, \ the result gets divided by 256 (otherwise the result \ wouldn't fit into one byte), so if we do the same for \ the planet's radius, we get: \ \ 96 * 96 / 256 = 36 \ \ So for the planet, the equivalent figure to test the \ sum of the _hi bytes against is 36, so A now contains \ the high byte of our altitude above the planet \ surface, squared, with an extra 1 subtracted so the \ test in the next instruction will ensure we crash \ even if we are exactly one planet radius away BCC MA28 \ If A < 0 then jump to MA28 as we have crashed into \ the planet STA R \ We are getting close to the planet, so we need to JSR LL5 \ work out how close. We know from the above that A \ contains our altitude squared, so we store A in R \ and call LL5 to calculate: \ \ Q = SQRT(R Q) = SQRT(A Q) \ \ Interestingly, Q doesn't appear to be set to 0 for \ this calculation, so presumably this doesn't make a \ difference LDA Q \ Store the result in ALTIT, our altitude STA ALTIT BNE MA23 \ If our altitude is non-zero then we haven't crashed, \ so jump to MA23 to skip to the next section .MA28 JMP DEATH \ If we get here then we just crashed into the planet \ or got too close to the sun, so jump to DEATH to start \ the funeral preparations and return from the main \ flight loop using a tail call .MA29 CMP #20 \ If this is the 20th iteration in this block of 32, BNE MA23 \ do the following, otherwise jump to MA23 to skip the \ sun altitude check LDA #30 \ Set CABTMP to 30, the cabin temperature in deep space STA CABTMP \ (i.e. one notch on the dashboard bar) LDA SSPR \ If we are inside the space station safe zone, jump to BNE MA23 \ MA23 to skip the following, as we can't have both the \ sun and space station at the same time, so we clearly \ can't be flying near the sun LDY #NI% \ Set Y to NI%, which is the offset in K% for the sun's \ data block, as the second block at K% is reserved for \ the sun (or space station) JSR MAS2 \ Call MAS2 to calculate the largest distance to the BNE MA23 \ sun in any of the three axes, and if it's non-zero, \ jump to MA23 to skip the following, as we are too far \ from the sun for scooping or temperature changes JSR MAS3 \ Set (A ?) = x_hi^2 + y_hi^2 + z_hi^2, so using \ Pythagoras we now know that A now contains the high \ byte of the square of the distance between our ship \ (at the origin) and the heart of the sun at coordinate \ (x_hi, y_hi, z_hi) \ \ If the calculation overflows so it doesn't fit into \ one byte, then A is set to &FF and the C flag is set EOR #%11111111 \ Invert A, so A is now small if we are far from the \ sun and large if we are close to the sun, in the \ range 0 = far away to &FF = extremely close, ouch, \ hot, hot, hot! ADC #30 \ Add the minimum cabin temperature of 30, plus the C \ flag, so we get one of the following: \ \ * If the MAS3 calculation overflowed then we are a \ long way from the sun, A will be zero and the C \ flag will be set, so this addition sets A = 31 \ and clears the C flag \ \ * If the result of the MAS3 calculation fitted into \ one byte, then A will be in the range 0 to 255 and \ the C flag will be clear, so this addition has a \ result in the range 0 to 285, with the higher \ values overflowing the addition and setting the \ C flag \ \ So the C flag is set if the cabin temperature is too \ hot to handle, and if it's clear then A contains the \ cabin temperature STA CABTMP \ Store the updated cabin temperature BCS MA28 \ If the C flag is set then jump to MA28 to die, as \ our temperature is off the scale CMP #224 \ If the cabin temperature < 224 then jump to MA23 to BCC MA23 \ skip fuel scooping, as we aren't close enough LDA BST \ If we don't have fuel scoops fitted, jump to BA23 to BEQ MA23 \ skip fuel scooping, as we can't scoop without fuel \ scoops LDA DELT4+1 \ We are now successfully fuel scooping, so it's time LSR A \ to work out how much fuel we're scooping. Fetch the \ high byte of DELT4, which contains our current speed \ divided by 4, and halve it to get our current speed \ divided by 8 (so it's now a value between 1 and 5, as \ our speed is normally between 1 and 40). This gives \ us the amount of fuel that's being scooped in A, so \ the faster we go, the more fuel we scoop, and because \ the fuel levels are stored as 10 * the fuel in light \ years, that means we just scooped between 0.1 and 0.5 \ light years of free fuel ADC QQ14 \ Set A = A + the current fuel level * 10 (from QQ14) CMP #70 \ If A > 70 then set A = 70 (as 70 is the maximum fuel BCC P%+4 \ level, or 7.0 light years) LDA #70 STA QQ14 \ Store the updated fuel level in QQ14 LDA #160 \ Print recursive token 0 ("FUEL SCOOPS ON") as an JSR MESS \ in-flight message \ ****************************************************************************** \ \ Name: Main flight loop (Part 16 of 16) \ Type: Subroutine \ Category: Main loop \ Summary: Process laser pulsing, E.C.M. energy drain, call stardust routine \ Deep dive: Program flow of the main game loop \ \ ------------------------------------------------------------------------------ \ \ The main flight loop covers most of the flight-specific aspects of Elite. This \ section covers the following: \ \ * Process laser pulsing \ \ * Process E.C.M. energy drain \ \ * Jump to the stardust routine if we are in a space view \ \ * Return from the main flight loop \ \ ****************************************************************************** .MA23 LDA LAS2 \ If the current view has no laser, jump to MA16 to skip BEQ MA16 \ the following LDA LASCT \ If LASCT >= 8, jump to MA16 to skip the following, so CMP #8 \ for a pulse laser with a LASCT between 8 and 10, the BCS MA16 \ laser stays on, but for a LASCT of 7 or less it gets \ turned off and stays off until LASCT reaches zero and \ the next pulse can start (if the fire button is still \ being pressed) \ \ For pulse lasers, LASCT gets set to 10 in ma1 above, \ and it decrements every vertical sync (50 times a \ second), so this means it pulses five times a second, \ with the laser being on for the first 3/10 of each \ pulse and off for the rest of the pulse \ \ If this is a beam laser, LASCT is 0 so we always keep \ going here. This means the laser doesn't pulse, but it \ does get drawn and removed every cycle, in a slightly \ different place each time, so the beams still flicker \ around the screen JSR LASLI2 \ Redraw the existing laser lines, which has the effect \ of removing them from the screen LDA #0 \ Set LAS2 to 0 so if this is a pulse laser, it will STA LAS2 \ skip over the above until the next pulse (this has no \ effect if this is a beam laser) .MA16 LDA ECMP \ If our E.C.M is not on, skip to MA69, otherwise keep BEQ MA69 \ going to drain some energy JSR DENGY \ Call DENGY to deplete our energy banks by 1 BEQ MA70 \ If we have no energy left, jump to MA70 to turn our \ E.C.M. off .MA69 LDA ECMA \ If an E.C.M is going off (ours or an opponent's) then BEQ MA66 \ keep going, otherwise skip to MA66 DEC ECMA \ Decrement the E.C.M. countdown timer, and if it has BNE MA66 \ reached zero, keep going, otherwise skip to MA66 .MA70 JSR ECMOF \ If we get here then either we have either run out of \ energy, or the E.C.M. timer has run down, so switch \ off the E.C.M. .MA66 LDA QQ11 \ If this is not a space view (i.e. QQ11 is non-zero) BNE MA9 \ then jump to MA9 to return from the main flight loop \ (as MA9 is an RTS) JMP STARS \ This is a space view, so jump to the STARS routine to \ process the stardust, and return from the main flight \ loop using a tail call \ ****************************************************************************** \ \ Name: MAS1 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Add an orientation vector coordinate to an INWK coordinate \ Deep dive: The space station safe zone \ \ ------------------------------------------------------------------------------ \ \ Add a doubled nosev vector coordinate, e.g. (nosev_y_hi nosev_y_lo) * 2, to \ an INWK coordinate, e.g. (x_sign x_hi x_lo), storing the result in the INWK \ coordinate. The axes used in each side of the addition are specified by the \ arguments X and Y. \ \ In the comments below, we document the routine as if we are doing the \ following, i.e. if X = 0 and Y = 11: \ \ (x_sign x_hi x_lo) = (x_sign x_hi x_lo) + (nosev_y_hi nosev_y_lo) * 2 \ \ as that way the variable names in the comments contain "x" and "y" to match \ the registers that specify the vector axis to use. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The coordinate to add, as follows: \ \ * If X = 0, add (x_sign x_hi x_lo) \ * If X = 3, add (y_sign y_hi y_lo) \ * If X = 6, add (z_sign z_hi z_lo) \ \ Y The vector to add, as follows: \ \ * If Y = 9, add (nosev_x_hi nosev_x_lo) \ * If Y = 11, add (nosev_y_hi nosev_y_lo) \ * If Y = 13, add (nosev_z_hi nosev_z_lo) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A The highest byte of the result with the sign cleared \ (e.g. |x_sign| when X = 0, etc.) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ MA9 Contains an RTS \ \ ****************************************************************************** .MAS1 LDA INWK,Y \ Set K(2 1) = (nosev_y_hi nosev_y_lo) * 2 ASL A STA K+1 LDA INWK+1,Y ROL A STA K+2 LDA #0 \ Set K+3 bit 7 to the C flag, so the sign bit of the ROR A \ above result goes into K+3 STA K+3 JSR MVT3 \ Add (x_sign x_hi x_lo) to K(3 2 1) STA INWK+2,X \ Store the sign of the result in x_sign LDY K+1 \ Store K(2 1) in (x_hi x_lo) STY INWK,X LDY K+2 STY INWK+1,X AND #%01111111 \ Set A to the sign byte with the sign cleared, \ i.e. |x_sign| when X = 0 .MA9 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MAS2 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Calculate a cap on the maximum distance to the planet or sun \ \ ------------------------------------------------------------------------------ \ \ Given a value in Y that points to the start of a ship data block as an offset \ from K%, calculate the following: \ \ A = A OR x_sign OR y_sign OR z_sign \ \ and clear the sign bit of the result. The K% workspace contains the ship data \ blocks, so the offset in Y must be 0 or a multiple of NI% (as each block in \ K% contains NI% bytes). \ \ The result effectively contains a maximum cap of the three values (though it \ might not be one of the three input values - it's just guaranteed to be \ larger than all of them). \ \ If Y = 0 and A = 0, then this calculates the maximum cap of the highest byte \ containing the distance to the planet, as K%+2 = x_sign, K%+5 = y_sign and \ K%+8 = z_sign (the first slot in the K% workspace represents the planet). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ Y The offset from K% for the start of the ship data block \ to use \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A OR K%+2+Y OR K%+5+Y OR K%+8+Y, with bit 7 cleared \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ m Do not include A in the calculation \ \ ****************************************************************************** .m LDA #0 \ Set A = 0 and fall through into MAS2 to calculate the \ OR of the three bytes at K%+2+Y, K%+5+Y and K%+8+Y .MAS2 ORA K%+2,Y \ Set A = A OR x_sign OR y_sign OR z_sign ORA K%+5,Y ORA K%+8,Y AND #%01111111 \ Clear bit 7 in A RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MAS3 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate A = x_hi^2 + y_hi^2 + z_hi^2 in the K% block \ \ ------------------------------------------------------------------------------ \ \ Given a value in Y that points to the start of a ship data block as an offset \ from K%, calculate the following: \ \ (A ?) = x_hi^2 + y_hi^2 + z_hi^2 \ \ returning A = &FF if the calculation overflows a one-byte result. The K% \ workspace contains the ship data blocks, so the offset in Y must be 0 or a \ multiple of NI% (as each block in K% contains NI% bytes). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ Y The offset from K% for the start of the ship data block \ to use \ \ Returns \ \ A The high byte of x_hi^2 + y_hi^2 + z_hi^2 \ \ C flag The overflow status (i.e. did the result fit into one \ byte): \ \ * Clear if the calculation didn't overflow \ \ * Set if the calculation overflowed (in which case A \ is set to &FF) \ \ ****************************************************************************** .MAS3 LDA K%+1,Y \ Set (A P) = x_hi * x_hi JSR SQUA2 STA R \ Store A (high byte of result) in R LDA K%+4,Y \ Set (A P) = y_hi * y_hi JSR SQUA2 ADC R \ Add A (high byte of second result) to R BCS MA30 \ If the addition of the two high bytes caused a carry \ (i.e. they overflowed), jump to MA30 to return A = &FF STA R \ Store A (sum of the two high bytes) in R LDA K%+7,Y \ Set (A P) = z_hi * z_hi JSR SQUA2 ADC R \ Add A (high byte of third result) to R, so R now \ contains the high byte of the entire sum, i.e. of \ x_hi^2 + y_hi^2 + z_hi^2 BCC P%+4 \ If there is no carry, skip the following instruction \ to return straight from the subroutine .MA30 LDA #&FF \ The calculation has overflowed, so set A = &FF RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MVEIT (Part 1 of 9) \ 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 counter \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .MVEIT LDA INWK+31 \ If bits 5 or 7 of ship byte #31 are set, jump to MV30 AND #%10100000 \ as the ship is either exploding or has been killed, so BNE MV30 \ we don't need to tidy its orientation vectors or apply \ tactics 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 \ ****************************************************************************** \ \ Name: MVEIT (Part 2 of 9) \ Type: Subroutine \ Category: Moving \ Summary: Move current ship: Call tactics routine, remove ship from scanner \ Deep dive: Scheduling tasks with the main loop counter \ \ ------------------------------------------------------------------------------ \ \ This routine has multiple stages. This stage does the following: \ \ * Apply tactics to ships with AI enabled (by calling the TACTICS routine) \ \ * Remove the ship from the scanner, so we can move it \ \ ****************************************************************************** .MV3 LDX TYPE \ If the type of the ship we are moving is positive, BPL P%+5 \ i.e. it is not a planet (types 128 and 130) or sun \ (type 129), then skip the following instruction JMP MV40 \ This item is the planet or sun, so jump to MV40 to \ move it, which ends by jumping back into this routine \ at MV45 (after all the rotation, tactics and scanner \ code, which we don't need to apply to planets or suns) LDA INWK+32 \ Fetch the ship's byte #32 (AI flag) into A BPL MV30 \ If bit 7 of the AI flag is clear, then if this is a \ ship or missile it is dumb and has no AI, and if this \ is the space station it is not hostile, so in both \ cases skip the following as it has no tactics CPX #MSL \ If the ship is a missile, skip straight to MV26 to BEQ MV26 \ call the TACTICS routine, as we do this every \ iteration of the main loop for missiles only LDA MCNT \ Fetch the main loop counter EOR XSAV \ Fetch the slot number of the ship we are moving, EOR AND #7 \ with the loop counter and apply mod 8 to the result. BNE MV30 \ The result will be zero when "counter mod 8" matches \ the slot number mod 8, so this makes sure we call \ TACTICS 12 times every 8 main loop iterations, like \ this: \ \ Iteration 0, apply tactics to slots 0 and 8 \ Iteration 1, apply tactics to slots 1 and 9 \ Iteration 2, apply tactics to slots 2 and 10 \ Iteration 3, apply tactics to slots 3 and 11 \ Iteration 4, apply tactics to slot 4 \ Iteration 5, apply tactics to slot 5 \ Iteration 6, apply tactics to slot 6 \ Iteration 7, apply tactics to slot 7 \ Iteration 8, apply tactics to slots 0 and 8 \ ... \ \ and so on .MV26 JSR TACTICS \ Call TACTICS to apply AI tactics to this ship .MV30 JSR SCAN \ Draw the ship on the scanner, which has the effect of \ removing it, as it's already at this point and hasn't \ yet moved \ ****************************************************************************** \ \ Name: MVEIT (Part 3 of 9) \ Type: Subroutine \ Category: Moving \ Summary: Move current ship: Move ship forward according to its speed \ \ ------------------------------------------------------------------------------ \ \ This routine has multiple stages. This stage does the following: \ \ * Move the ship forward (along the vector pointing in the direction of \ travel) according to its speed: \ \ (x, y, z) += nosev_hi * speed / 64 \ \ ****************************************************************************** LDA INWK+27 \ Set Q = the ship's speed byte #27 * 4 ASL A ASL A STA Q LDA INWK+10 \ Set A = |nosev_x_hi| AND #%01111111 JSR FMLTU \ Set R = A * Q / 256 STA R \ = |nosev_x_hi| * speed / 64 LDA INWK+10 \ If nosev_x_hi is positive, then: LDX #0 \ JSR MVT1-2 \ (x_sign x_hi x_lo) = (x_sign x_hi x_lo) + R \ \ If nosev_x_hi is negative, then: \ \ (x_sign x_hi x_lo) = (x_sign x_hi x_lo) - R \ \ So in effect, this does: \ \ (x_sign x_hi x_lo) += nosev_x_hi * speed / 64 LDA INWK+12 \ Set A = |nosev_y_hi| AND #%01111111 JSR FMLTU \ Set R = A * Q / 256 STA R \ = |nosev_y_hi| * speed / 64 LDA INWK+12 \ If nosev_y_hi is positive, then: LDX #3 \ JSR MVT1-2 \ (y_sign y_hi y_lo) = (y_sign y_hi y_lo) + R \ \ If nosev_y_hi is negative, then: \ \ (y_sign y_hi y_lo) = (y_sign y_hi y_lo) - R \ \ So in effect, this does: \ \ (y_sign y_hi y_lo) += nosev_y_hi * speed / 64 LDA INWK+14 \ Set A = |nosev_z_hi| AND #%01111111 JSR FMLTU \ Set R = A * Q / 256 STA R \ = |nosev_z_hi| * speed / 64 LDA INWK+14 \ If nosev_y_hi is positive, then: LDX #6 \ JSR MVT1-2 \ (z_sign z_hi z_lo) = (z_sign z_hi z_lo) + R \ \ If nosev_z_hi is negative, then: \ \ (z_sign z_hi z_lo) = (z_sign z_hi z_lo) - R \ \ So in effect, this does: \ \ (z_sign z_hi z_lo) += nosev_z_hi * speed / 64 \ ****************************************************************************** \ \ Name: MVEIT (Part 4 of 9) \ Type: Subroutine \ Category: Moving \ Summary: Move current ship: Apply acceleration to ship's speed as a one-off \ \ ------------------------------------------------------------------------------ \ \ This routine has multiple stages. This stage does the following: \ \ * Apply acceleration to the ship's speed (if acceleration is non-zero), \ and then zero the acceleration as it's a one-off change \ \ ****************************************************************************** LDA INWK+27 \ Set A = the ship's speed in byte #24 + the ship's CLC \ acceleration in byte #28 ADC INWK+28 BPL P%+4 \ If the result is positive, skip the following \ instruction LDA #0 \ Set A to 0 to stop the speed from going negative LDY #15 \ We now fetch byte #15 from the ship's blueprint, which \ contains the ship's maximum speed, so set Y = 15 to \ use as an index CMP (XX0),Y \ If A < the ship's maximum speed, skip the following BCC P%+4 \ instruction LDA (XX0),Y \ Set A to the ship's maximum speed STA INWK+27 \ We have now calculated the new ship's speed after \ accelerating and keeping the speed within the ship's \ limits, so store the updated speed in byte #27 LDA #0 \ We have added the ship's acceleration, so we now set STA INWK+28 \ it back to 0 in byte #28, as it's a one-off change \ ****************************************************************************** \ \ Name: MVEIT (Part 5 of 9) \ Type: Subroutine \ Category: Moving \ Summary: Move current ship: Rotate ship's location by our pitch and roll \ Deep dive: Rotating the universe \ \ ------------------------------------------------------------------------------ \ \ This routine has multiple stages. This stage does the following: \ \ * Rotate the ship's location in space by the amount of pitch and roll of \ our ship. See below for a deeper explanation of this routine \ \ ****************************************************************************** LDX ALP1 \ Fetch the magnitude of the current roll into X, so \ if the roll angle is alpha, X contains |alpha| LDA INWK \ Set P = ~x_lo (i.e. with all its bits flipped) so that EOR #%11111111 \ we can pass x_lo to MLTU2 below) STA P LDA INWK+1 \ Set A = x_hi JSR MLTU2-2 \ Set (A P+1 P) = (A ~P) * X \ = (x_hi x_lo) * alpha STA P+2 \ Store the high byte of the result in P+2, so we now \ have: \ \ P(2 1 0) = (x_hi x_lo) * alpha LDA ALP2+1 \ Fetch the flipped sign of the current roll angle alpha EOR INWK+2 \ from ALP2+1 and EOR with byte #2 (x_sign), so if the \ flipped roll angle and x_sign have the same sign, A \ will be positive, else it will be negative. So A will \ contain the sign bit of x_sign * flipped alpha sign, \ which is the opposite to the sign of the above result, \ so we now have: \ \ (A P+2 P+1) = - (x_sign x_hi x_lo) * alpha / 256 LDX #3 \ Set (A P+2 P+1) = (y_sign y_hi y_lo) + (A P+2 P+1) JSR MVT6 \ = y - x * alpha / 256 STA K2+3 \ Set K2(3) = A = the sign of the result LDA P+1 \ Set K2(1) = P+1, the low byte of the result STA K2+1 EOR #%11111111 \ Set P = ~K2+1 (i.e. with all its bits flipped) so STA P \ that we can pass K2+1 to MLTU2 below) LDA P+2 \ Set K2(2) = A = P+2 STA K2+2 \ So we now have result 1 above: \ \ K2(3 2 1) = (A P+2 P+1) \ = y - x * alpha / 256 LDX BET1 \ Fetch the magnitude of the current pitch into X, so \ if the pitch angle is beta, X contains |beta| JSR MLTU2-2 \ Set (A P+1 P) = (A ~P) * X \ = K2(2 1) * beta STA P+2 \ Store the high byte of the result in P+2, so we now \ have: \ \ P(2 1 0) = K2(2 1) * beta LDA K2+3 \ Fetch the sign of the above result in K(3 2 1) from EOR BET2 \ K2+3 and EOR with BET2, the sign of the current pitch \ rate, so if the pitch and K(3 2 1) have the same sign, \ A will be positive, else it will be negative. So A \ will contain the sign bit of K(3 2 1) * beta, which is \ the same as the sign of the above result, so we now \ have: \ \ (A P+2 P+1) = K2(3 2 1) * beta / 256 LDX #6 \ Set (A P+2 P+1) = (z_sign z_hi z_lo) + (A P+2 P+1) JSR MVT6 \ = z + K2 * beta / 256 STA INWK+8 \ Set z_sign = A = the sign of the result LDA P+1 \ Set z_lo = P+1, the low byte of the result STA INWK+6 EOR #%11111111 \ Set P = ~z_lo (i.e. with all its bits flipped) so that STA P \ we can pass z_lo to MLTU2 below) LDA P+2 \ Set z_hi = P+2 STA INWK+7 \ So we now have result 2 above: \ \ (z_sign z_hi z_lo) = (A P+2 P+1) \ = z + K2 * beta / 256 JSR MLTU2 \ MLTU2 doesn't change Q, and Q was set to beta in \ the previous call to MLTU2, so this call does: \ \ (A P+1 P) = (A ~P) * Q \ = (z_hi z_lo) * beta STA P+2 \ Set P+2 = A = the high byte of the result, so we \ now have: \ \ P(2 1 0) = (z_hi z_lo) * beta LDA K2+3 \ Set y_sign = K2+3 STA INWK+5 EOR BET2 \ EOR y_sign with BET2, the sign of the current pitch EOR INWK+8 \ rate, and z_sign. If the result is positive jump to BPL MV43 \ MV43, otherwise this means beta * z and y have \ different signs, i.e. P(2 1) and K2(3 2 1) have \ different signs, so we need to add them in order to \ calculate K2(2 1) - P(2 1) LDA P+1 \ Set (y_hi y_lo) = K2(2 1) + P(2 1) ADC K2+1 STA INWK+3 LDA P+2 ADC K2+2 STA INWK+4 JMP MV44 \ Jump to MV44 to continue the calculation .MV43 LDA K2+1 \ Reversing the logic above, we need to subtract P(2 1) SBC P+1 \ and K2(3 2 1) to calculate K2(2 1) - P(2 1), so this STA INWK+3 \ sets (y_hi y_lo) = K2(2 1) - P(2 1) LDA K2+2 SBC P+2 STA INWK+4 BCS MV44 \ If the above subtraction did not underflow, then \ jump to MV44, otherwise we need to negate the result LDA #1 \ Negate (y_sign y_hi y_lo) using two's complement, SBC INWK+3 \ first doing the low bytes: STA INWK+3 \ \ y_lo = 1 - y_lo LDA #0 \ Then the high bytes: SBC INWK+4 \ STA INWK+4 \ y_hi = 0 - y_hi LDA INWK+5 \ And finally flip the sign in y_sign EOR #%10000000 STA INWK+5 .MV44 \ So we now have result 3 above: \ \ (y_sign y_hi y_lo) = K2(2 1) - P(2 1) \ = K2 - beta * z LDX ALP1 \ Fetch the magnitude of the current roll into X, so \ if the roll angle is alpha, X contains |alpha| LDA INWK+3 \ Set P = ~y_lo (i.e. with all its bits flipped) so that EOR #&FF \ we can pass y_lo to MLTU2 below) STA P LDA INWK+4 \ Set A = y_hi JSR MLTU2-2 \ Set (A P+1 P) = (A ~P) * X \ = (y_hi y_lo) * alpha STA P+2 \ Store the high byte of the result in P+2, so we now \ have: \ \ P(2 1 0) = (y_hi y_lo) * alpha LDA ALP2 \ Fetch the correct sign of the current roll angle alpha EOR INWK+5 \ from ALP2 and EOR with byte #5 (y_sign), so if the \ correct roll angle and y_sign have the same sign, A \ will be positive, else it will be negative. So A will \ contain the sign bit of x_sign * correct alpha sign, \ which is the same as the sign of the above result, \ so we now have: \ \ (A P+2 P+1) = (y_sign y_hi y_lo) * alpha / 256 LDX #0 \ Set (A P+2 P+1) = (x_sign x_hi x_lo) + (A P+2 P+1) JSR MVT6 \ = x + y * alpha / 256 STA INWK+2 \ Set x_sign = A = the sign of the result LDA P+2 \ Set x_hi = P+2, the high byte of the result STA INWK+1 LDA P+1 \ Set x_lo = P+1, the low byte of the result STA INWK \ So we now have result 4 above: \ \ x = x + alpha * y \ \ and the rotation of (x, y, z) is done \ ****************************************************************************** \ \ Name: MVEIT (Part 6 of 9) \ Type: Subroutine \ Category: Moving \ Summary: Move current ship: Move the ship in space according to our speed \ Deep dive: A sense of scale \ \ ------------------------------------------------------------------------------ \ \ This routine has multiple stages. This stage does the following: \ \ * Move the ship in space according to our speed (we already moved it \ according to its own speed in part 3). \ \ We do this by subtracting our speed (i.e. the distance we travel in this \ iteration of the loop) from the other ship's z-coordinate. We subtract because \ they appear to be "moving" in the opposite direction to us, and the whole \ MVEIT routine is about moving the other ships rather than us (even though we \ are the one doing the moving). \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ MV45 Rejoin the MVEIT routine after the rotation, tactics and \ scanner code \ \ ****************************************************************************** .MV45 LDA DELTA \ Set R to our speed in DELTA STA R LDA #%10000000 \ Set A to zeroes but with bit 7 set, so that (A R) is \ a 16-bit number containing -R, or -speed LDX #6 \ Set X to the z-axis so the call to MVT1 does this: JSR MVT1 \ \ (z_sign z_hi z_lo) = (z_sign z_hi z_lo) + (A R) \ = (z_sign z_hi z_lo) - speed LDA TYPE \ If the ship type is not the sun (129) then skip the AND #%10000001 \ next instruction, otherwise return from the subroutine CMP #129 \ as we don't need to rotate the sun around its origin. BNE P%+3 \ Having both the AND and the CMP is a little odd, as \ the sun is the only ship type with bits 0 and 7 set, \ so the AND has no effect and could be removed RTS \ Return from the subroutine, as the ship we are moving \ is the sun and doesn't need any of the following \ ****************************************************************************** \ \ Name: MVEIT (Part 7 of 9) \ Type: Subroutine \ Category: Moving \ Summary: Move current ship: Rotate ship's orientation vectors by pitch/roll \ Deep dive: Orientation vectors \ Pitching and rolling \ \ ------------------------------------------------------------------------------ \ \ 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. \ \ ****************************************************************************** LDY #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 vector \ ****************************************************************************** \ \ Name: MVEIT (Part 8 of 9) \ 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 angle \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** 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 MVS5 \ ****************************************************************************** \ \ Name: MVEIT (Part 9 of 9) \ Type: Subroutine \ Category: Moving \ Summary: Move current ship: Redraw on scanner, if it hasn't been destroyed \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .MV5 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 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MVT1 \ Type: Subroutine \ Category: Moving \ Summary: Calculate (x_sign x_hi x_lo) = (x_sign x_hi x_lo) + (A R) \ \ ------------------------------------------------------------------------------ \ \ Add the signed delta (A R) to a ship's coordinate, along the axis given in X. \ Mathematically speaking, this routine translates the ship along a single axis \ by a signed delta. Taking the example of X = 0, the x-axis, it does the \ following: \ \ (x_sign x_hi x_lo) = (x_sign x_hi x_lo) + (A R) \ \ (In practice, MVT1 is only ever called directly with A = 0 or 128, otherwise \ it is always called via MVT-2, which clears A apart from the sign bit. The \ routine is written to cope with a non-zero delta_hi, so it supports a full \ 16-bit delta, but it appears that delta_hi is only ever used to hold the \ sign of the delta.) \ \ The comments below assume we are adding delta to the x-axis, though the axis \ is determined by the value of X. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ (A R) The signed delta, so A = delta_hi and R = delta_lo \ \ X Determines which coordinate axis of INWK to change: \ \ * X = 0 adds the delta to (x_lo, x_hi, x_sign) \ \ * X = 3 adds the delta to (y_lo, y_hi, y_sign) \ \ * X = 6 adds the delta to (z_lo, z_hi, z_sign) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ MVT1-2 Clear bits 0-6 of A before entering MVT1 \ \ ****************************************************************************** AND #%10000000 \ Clear bits 0-6 of A .MVT1 ASL A \ Set the C flag to the sign bit of the delta, leaving \ delta_hi << 1 in A STA S \ Set S = delta_hi << 1 \ \ This also clears bit 0 of S LDA #0 \ Set T = just the sign bit of delta (in bit 7) ROR A STA T LSR S \ Set S = delta_hi >> 1 \ = |delta_hi| \ \ This also clear the C flag, as we know that bit 0 of \ S was clear before the LSR EOR INWK+2,X \ If T EOR x_sign has bit 7 set, then x_sign and delta BMI MV10 \ have different signs, so jump to MV10 \ At this point, we know x_sign and delta have the same \ sign, that sign is in T, and S contains |delta_hi|, \ so now we want to do: \ \ (x_sign x_hi x_lo) = (x_sign x_hi x_lo) + (S R) \ \ and then set the sign of the result to the same sign \ as x_sign and delta LDA R \ First we add the low bytes, so: ADC INWK,X \ STA INWK,X \ x_lo = x_lo + R LDA S \ Then we add the high bytes: ADC INWK+1,X \ STA INWK+1,X \ x_hi = x_hi + S LDA INWK+2,X \ And finally we add any carry into x_sign, and if the ADC #0 \ sign of x_sign and delta in T is negative, make sure ORA T \ the result is negative (by OR'ing with T) STA INWK+2,X RTS \ Return from the subroutine .MV10 \ If we get here, we know x_sign and delta have \ different signs, with delta's sign in T, and \ |delta_hi| in S, so now we want to do: \ \ (x_sign x_hi x_lo) = (x_sign x_hi x_lo) - (S R) \ \ and then set the sign of the result according to \ the signs of x_sign and delta LDA INWK,X \ First we subtract the low bytes, so: SEC \ SBC R \ x_lo = x_lo - R STA INWK,X LDA INWK+1,X \ Then we subtract the high bytes: SBC S \ STA INWK+1,X \ x_hi = x_hi - S LDA INWK+2,X \ And finally we subtract any borrow from bits 0-6 of AND #%01111111 \ x_sign, and give the result the opposite sign bit to T SBC #0 \ (i.e. give it the sign of the original x_sign) ORA #%10000000 EOR T STA INWK+2,X BCS MV11 \ If the C flag is set by the above SBC, then our sum \ above didn't underflow and is correct - to put it \ another way, (x_sign x_hi x_lo) >= (S R) so the result \ should indeed have the same sign as x_sign, so jump to \ MV11 to return from the subroutine \ Otherwise our subtraction underflowed because \ (x_sign x_hi x_lo) < (S R), so we now need to flip the \ subtraction around by using two's complement to this: \ \ (S R) - (x_sign x_hi x_lo) \ \ and then we need to give the result the same sign as \ (S R), the delta, as that's the dominant figure in the \ sum LDA #1 \ First we subtract the low bytes, so: SBC INWK,X \ STA INWK,X \ x_lo = 1 - x_lo LDA #0 \ Then we subtract the high bytes: SBC INWK+1,X \ STA INWK+1,X \ x_hi = 0 - x_hi LDA #0 \ And then we subtract the sign bytes: SBC INWK+2,X \ \ x_sign = 0 - x_sign AND #%01111111 \ Finally, we set the sign bit to the sign in T, the ORA T \ sign of the original delta, as the delta is the STA INWK+2,X \ dominant figure in the sum .MV11 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MVT3 \ Type: Subroutine \ Category: Moving \ Summary: Calculate K(3 2 1) = (x_sign x_hi x_lo) + K(3 2 1) \ \ ------------------------------------------------------------------------------ \ \ Add an INWK position coordinate - i.e. x, y or z - to K(3 2 1), like this: \ \ K(3 2 1) = (x_sign x_hi x_lo) + K(3 2 1) \ \ The INWK coordinate to add to K(3 2 1) is specified by X. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The coordinate to add to K(3 2 1), as follows: \ \ * If X = 0, add (x_sign x_hi x_lo) \ \ * If X = 3, add (y_sign y_hi y_lo) \ \ * If X = 6, add (z_sign z_hi z_lo) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A Contains a copy of the high byte of the result, K+3 \ \ X X is preserved \ \ ****************************************************************************** .MVT3 LDA K+3 \ Set S = K+3 STA S AND #%10000000 \ Set T = sign bit of K(3 2 1) STA T EOR INWK+2,X \ If x_sign has a different sign to K(3 2 1), jump to BMI MV13 \ MV13 to process the addition as a subtraction LDA K+1 \ Set K(3 2 1) = K(3 2 1) + (x_sign x_hi x_lo) CLC \ starting with the low bytes ADC INWK,X STA K+1 LDA K+2 \ Then the middle bytes ADC INWK+1,X STA K+2 LDA K+3 \ And finally the high bytes ADC INWK+2,X AND #%01111111 \ Setting the sign bit of K+3 to T, the original sign ORA T \ of K(3 2 1) STA K+3 RTS \ Return from the subroutine .MV13 LDA S \ Set S = |K+3| (i.e. K+3 with the sign bit cleared) AND #%01111111 STA S LDA INWK,X \ Set K(3 2 1) = (x_sign x_hi x_lo) - K(3 2 1) SEC \ starting with the low bytes SBC K+1 STA K+1 LDA INWK+1,X \ Then the middle bytes SBC K+2 STA K+2 LDA INWK+2,X \ And finally the high bytes, doing A = |x_sign| - |K+3| AND #%01111111 \ and setting the C flag for testing below SBC S ORA #%10000000 \ Set the sign bit of K+3 to the opposite sign of T, EOR T \ i.e. the opposite sign to the original K(3 2 1) STA K+3 BCS MV14 \ If the C flag is set, i.e. |x_sign| >= |K+3|, then \ the sign of K(3 2 1). In this case, we want the \ result to have the same sign as the largest argument, \ which is (x_sign x_hi x_lo), which we know has the \ opposite sign to K(3 2 1), and that's what we just set \ the sign of K(3 2 1) to... so we can jump to MV14 to \ return from the subroutine LDA #1 \ We need to swap the sign of the result in K(3 2 1), SBC K+1 \ which we do by calculating 0 - K(3 2 1), which we can STA K+1 \ do with 1 - C - K(3 2 1), as we know the C flag is \ clear. We start with the low bytes LDA #0 \ Then the middle bytes SBC K+2 STA K+2 LDA #0 \ And finally the high bytes SBC K+3 AND #%01111111 \ Set the sign bit of K+3 to the same sign as T, ORA T \ i.e. the same sign as the original K(3 2 1), as STA K+3 \ that's the largest argument .MV14 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MVS4 \ Type: Subroutine \ Category: Moving \ Summary: Apply pitch and roll to an orientation vector \ Deep dive: Orientation vectors \ Pitching and rolling \ \ ------------------------------------------------------------------------------ \ \ 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) \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Name: MVS5 \ 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 angle \ \ ------------------------------------------------------------------------------ \ \ 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) \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Name: MVT6 \ Type: Subroutine \ Category: Moving \ Summary: Calculate (A P+2 P+1) = (x_sign x_hi x_lo) + (A P+2 P+1) \ \ ------------------------------------------------------------------------------ \ \ Do the following calculation, for the coordinate given by X (so this is what \ it does for the x-coordinate): \ \ (A P+2 P+1) = (x_sign x_hi x_lo) + (A P+2 P+1) \ \ A is a sign bit and is not included in the calculation, but bits 0-6 of A are \ preserved. Bit 7 is set to the sign of the result. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The sign of P(2 1) in bit 7 \ \ P(2 1) The 16-bit value we want to add the coordinate to \ \ X The coordinate to add, as follows: \ \ * If X = 0, add to (x_sign x_hi x_lo) \ \ * If X = 3, add to (y_sign y_hi y_lo) \ \ * If X = 6, add to (z_sign z_hi z_lo) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A The sign of the result (in bit 7) \ \ ****************************************************************************** .MVT6 TAY \ Store argument A into Y, for later use EOR INWK+2,X \ Set A = A EOR x_sign BMI MV50 \ If the sign is negative, i.e. A and x_sign have \ different signs, jump to MV50 \ The signs are the same, so we can add the two \ arguments and keep the sign to get the result LDA P+1 \ First we add the low bytes: CLC \ ADC INWK,X \ P+1 = P+1 + x_lo STA P+1 LDA P+2 \ And then the high bytes: ADC INWK+1,X \ STA P+2 \ P+2 = P+2 + x_hi TYA \ Restore the original A argument that we stored earlier \ so that we keep the original sign RTS \ Return from the subroutine .MV50 LDA INWK,X \ First we subtract the low bytes: SEC \ SBC P+1 \ P+1 = x_lo - P+1 STA P+1 LDA INWK+1,X \ And then the high bytes: SBC P+2 \ STA P+2 \ P+2 = x_hi - P+2 BCC MV51 \ If the last subtraction underflowed, then the C flag \ will be clear and x_hi < P+2, so jump to MV51 to \ negate the result TYA \ Restore the original A argument that we stored earlier EOR #%10000000 \ but flip bit 7, which flips the sign. We do this \ because x_hi >= P+2 so we want the result to have the \ same sign as x_hi (as it's the dominant side in this \ calculation). The sign of x_hi is x_sign, and x_sign \ has the opposite sign to A, so we flip the sign in A \ to return the correct result RTS \ Return from the subroutine .MV51 LDA #1 \ Our subtraction underflowed, so we negate the result SBC P+1 \ using two's complement, first with the low byte: STA P+1 \ \ P+1 = 1 - P+1 LDA #0 \ And then the high byte: SBC P+2 \ STA P+2 \ P+2 = 0 - P+2 TYA \ Restore the original A argument that we stored earlier \ as this is the correct sign for the result. This is \ because x_hi < P+2, so we want to return the same sign \ as P+2, the dominant side RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MV40 \ Type: Subroutine \ Category: Moving \ Summary: Rotate the planet or sun's location in space by the amount of \ pitch and roll of our ship \ Deep dive: Rotating the universe \ \ ------------------------------------------------------------------------------ \ \ We implement this using the same equations as in part 5 of MVEIT, where we \ rotated the current ship's location by our pitch and roll. Specifically, the \ calculation is as follows: \ \ 1. K2 = y - alpha * x \ 2. z = z + beta * K2 \ 3. y = K2 - beta * z \ 4. x = x + alpha * y \ \ ****************************************************************************** .MV40 LDA ALPHA \ Set Q = -ALPHA, so Q contains the angle we want to EOR #%10000000 \ roll the planet through (i.e. in the opposite STA Q \ direction to our ship's roll angle alpha) LDA INWK \ Set P(1 0) = (x_hi x_lo) STA P LDA INWK+1 STA P+1 LDA INWK+2 \ Set A = x_sign JSR MULT3 \ Set K(3 2 1 0) = (A P+1 P) * Q \ \ which also means: \ \ K(3 2 1) = (A P+1 P) * Q / 256 \ = x * -alpha / 256 \ = - alpha * x / 256 LDX #3 \ Set K(3 2 1) = (y_sign y_hi y_lo) + K(3 2 1) JSR MVT3 \ = y - alpha * x / 256 LDA K+1 \ Set K2(2 1) = P(1 0) = K(2 1) STA K2+1 STA P LDA K+2 \ Set K2+2 = K+2 STA K2+2 STA P+1 \ Set P+1 = K+2 LDA BETA \ Set Q = beta, the pitch angle of our ship STA Q LDA K+3 \ Set K+3 to K2+3, so now we have result 1 above: STA K2+3 \ \ K2(3 2 1) = K(3 2 1) \ = y - alpha * x / 256 \ We also have: \ \ A = K+3 \ \ P(1 0) = K(2 1) \ \ so combined, these mean: \ \ (A P+1 P) = K(3 2 1) \ = K2(3 2 1) JSR MULT3 \ Set K(3 2 1 0) = (A P+1 P) * Q \ \ which also means: \ \ K(3 2 1) = (A P+1 P) * Q / 256 \ = K2(3 2 1) * beta / 256 \ = beta * K2 / 256 LDX #6 \ K(3 2 1) = (z_sign z_hi z_lo) + K(3 2 1) JSR MVT3 \ = z + beta * K2 / 256 LDA K+1 \ Set P = K+1 STA P STA INWK+6 \ Set z_lo = K+1 LDA K+2 \ Set P+1 = K+2 STA P+1 STA INWK+7 \ Set z_hi = K+2 LDA K+3 \ Set A = z_sign = K+3, so now we have: STA INWK+8 \ \ (z_sign z_hi z_lo) = K(3 2 1) \ = z + beta * K2 / 256 \ So we now have result 2 above: \ \ z = z + beta * K2 EOR #%10000000 \ Flip the sign bit of A to give A = -z_sign JSR MULT3 \ Set K(3 2 1 0) = (A P+1 P) * Q \ = (-z_sign z_hi z_lo) * beta \ = -z * beta LDA K+3 \ Set T to the sign bit of K(3 2 1 0), i.e. to the sign AND #%10000000 \ bit of -z * beta STA T EOR K2+3 \ If K2(3 2 1 0) has a different sign to K(3 2 1 0), BMI MV1 \ then EOR'ing them will produce a 1 in bit 7, so jump \ to MV1 to take this into account \ If we get here, K and K2 have the same sign, so we can \ add them together to get the result we're after, and \ then set the sign afterwards LDA K \ We now do the following sum: \CLC \ ADC K2 \ (A y_hi y_lo -) = K(3 2 1 0) + K2(3 2 1 0) \ \ starting with the low bytes (which we don't keep) \ \ The CLC instruction is commented out in the original \ source. It isn't needed because MULT3 clears the C \ flag, so this is an example of the authors finding \ one more precious byte to save LDA K+1 \ We then do the middle bytes, which go into y_lo ADC K2+1 STA INWK+3 LDA K+2 \ And then the high bytes, which go into y_hi ADC K2+2 STA INWK+4 LDA K+3 \ And then the sign bytes into A, so overall we have the ADC K2+3 \ following, if we drop the low bytes from the result: \ \ (A y_hi y_lo) = (K + K2) / 256 JMP MV2 \ Jump to MV2 to skip the calculation for when K and K2 \ have different signs .MV1 LDA K \ If we get here then K2 and K have different signs, so SEC \ instead of adding, we need to subtract to get the SBC K2 \ result we want, like this: \ \ (A y_hi y_lo -) = K(3 2 1 0) - K2(3 2 1 0) \ \ starting with the low bytes (which we don't keep) LDA K+1 \ We then do the middle bytes, which go into y_lo SBC K2+1 STA INWK+3 LDA K+2 \ And then the high bytes, which go into y_hi SBC K2+2 STA INWK+4 LDA K2+3 \ Now for the sign bytes, so first we extract the sign AND #%01111111 \ byte from K2 without the sign bit, so P = |K2+3| STA P LDA K+3 \ And then we extract the sign byte from K without the AND #%01111111 \ sign bit, so A = |K+3| SBC P \ And finally we subtract the sign bytes, so P = A - P STA P \ By now we have the following, if we drop the low bytes \ from the result: \ \ (A y_hi y_lo) = (K - K2) / 256 \ \ so now we just need to make sure the sign of the \ result is correct BCS MV2 \ If the C flag is set, then the last subtraction above \ didn't underflow and the result is correct, so jump to \ MV2 as we are done with this particular stage LDA #1 \ Otherwise the subtraction above underflowed, as K2 is SBC INWK+3 \ the dominant part of the subtraction, so we need to STA INWK+3 \ negate the result using two's complement, starting \ with the low bytes: \ \ y_lo = 1 - y_lo LDA #0 \ And then the high bytes: SBC INWK+4 \ STA INWK+4 \ y_hi = 0 - y_hi LDA #0 \ And finally the sign bytes: SBC P \ \ A = 0 - P ORA #%10000000 \ We now force the sign bit to be negative, so that the \ final result below gets the opposite sign to K, which \ we want as K2 is the dominant part of the sum .MV2 EOR T \ T contains the sign bit of K, so if K is negative, \ this flips the sign of A STA INWK+5 \ Store A in y_sign \ So we now have result 3 above: \ \ y = K2 + K \ = K2 - beta * z LDA ALPHA \ Set A = alpha STA Q LDA INWK+3 \ Set P(1 0) = (y_hi y_lo) STA P LDA INWK+4 STA P+1 LDA INWK+5 \ Set A = y_sign JSR MULT3 \ Set K(3 2 1 0) = (A P+1 P) * Q \ = (y_sign y_hi y_lo) * alpha \ = y * alpha LDX #0 \ Set K(3 2 1) = (x_sign x_hi x_lo) + K(3 2 1) JSR MVT3 \ = x + y * alpha / 256 LDA K+1 \ Set (x_sign x_hi x_lo) = K(3 2 1) STA INWK \ = x + y * alpha / 256 LDA K+2 STA INWK+1 LDA K+3 STA INWK+2 \ So we now have result 4 above: \ \ x = x + y * alpha JMP MV45 \ We have now finished rotating the planet or sun by \ our pitch and roll, so jump back into the MVEIT \ routine at MV45 to apply all the other movements \ ****************************************************************************** \ \ Save ELTA.bin \ \ ****************************************************************************** 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.ELTA ", ~CODE%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_A% SAVE "3-assembled-output/ELTA.bin", CODE%, P%, LOAD% \ ****************************************************************************** \ \ ELITE B FILE \ \ Produces the binary file ELTB.bin that gets loaded by elite-bcfs.asm. \ \ ****************************************************************************** CODE_B% = P% LOAD_B% = LOAD% + P% - CODE% \ ****************************************************************************** \ \ Name: NA% \ Type: Variable \ Category: Save and load \ Summary: The data block for the last saved commander \ Deep dive: Commander save files \ The competition code \ \ ------------------------------------------------------------------------------ \ \ 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. \ \ ****************************************************************************** .NA% EQUS "JAMESON" \ The current commander name, which defaults to JAMESON EQUB 13 \ \ The commander name can be up to seven 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 &E8030000 \ CASH = Amount of cash (100 Cr), #9-12 ENDIF EQUB 70 \ QQ14 = Fuel level, #13 EQUB 0 \ COK = Competition flags, #14 EQUB 0 \ GCNT = Galaxy number, 0-7, #15 EQUB POW+(128 AND Q%) \ LASER = Front laser, #16 EQUB (POW+128) AND Q% \ LASER+1 = Rear laser, #17 EQUB 0 \ LASER+2 = Left laser, #18 EQUB 0 \ LASER+3 = Right laser, #19 EQUW 0 \ These bytes appear to be unused (they were originally \ used for up/down lasers, but they were dropped), \ #20-21 EQUB 22 + (15 AND Q%) \ CRGO = Cargo capacity, #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% AND 127 \ BOMB = Energy bomb, #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 EQUD 0 \ These four bytes appear to be unused, #47-50 EQUB 3 + (Q% AND 1) \ NOMSL = Number of missiles, #51 EQUB 0 \ FIST = Legal status ("fugitive/innocent status"), #52 EQUB 16 \ 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 128 \ SVC = Save count, #73 \ ****************************************************************************** \ \ Name: CHK2 \ Type: Variable \ Category: Save and load \ Summary: Second checksum byte for the saved commander data file \ Deep dive: Commander save files \ The competition code \ \ ------------------------------------------------------------------------------ \ \ 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). \ \ ****************************************************************************** .CHK2 EQUB &03 EOR &A9 \ The checksum value for the default commander, EOR'd \ with &A9 to make it harder to tamper with the checksum \ byte, #74 \ ****************************************************************************** \ \ Name: CHK \ Type: Variable \ Category: Save and load \ Summary: First checksum byte for the saved commander data file \ Deep dive: Commander save files \ The competition code \ \ ------------------------------------------------------------------------------ \ \ 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). \ \ ****************************************************************************** .CHK EQUB &03 \ The checksum value for the default commander, #75 \ ****************************************************************************** \ \ Name: UNIV \ Type: Variable \ Category: Universe \ Summary: Table of pointers to the local universe's ship data blocks \ Deep dive: The local bubble of universe \ Ship data blocks \ \ ****************************************************************************** .UNIV FOR I%, 0, NOSH EQUW K% + I% * NI% \ Address of block no. I%, of size NI%, in workspace K% NEXT \ ****************************************************************************** \ \ Name: TWOS \ Type: Variable \ Category: Drawing pixels \ Summary: Ready-made single-pixel character row bytes for mode 4 \ Deep dive: Drawing monochrome pixels on the BBC Micro \ \ ------------------------------------------------------------------------------ \ \ Ready-made bytes for plotting one-pixel points in mode 4 (the top part of the \ split screen). See the PIXEL routine for details. \ \ ****************************************************************************** .TWOS EQUB %10000000 EQUB %01000000 EQUB %00100000 EQUB %00010000 EQUB %00001000 EQUB %00000100 EQUB %00000010 EQUB %00000001 \ ****************************************************************************** \ \ Name: TWOS2 \ Type: Variable \ Category: Drawing pixels \ Summary: Ready-made double-pixel character row bytes for mode 4 \ Deep dive: Drawing monochrome pixels on the BBC Micro \ \ ------------------------------------------------------------------------------ \ \ Ready-made bytes for plotting two-pixel dashes in mode 4 (the top part of the \ split screen). See the PIXEL routine for details. \ \ ****************************************************************************** .TWOS2 EQUB %11000000 EQUB %01100000 EQUB %00110000 EQUB %00011000 EQUB %00001100 EQUB %00000110 EQUB %00000011 EQUB %00000011 \ ****************************************************************************** \ \ Name: CTWOS \ Type: Variable \ Category: Drawing pixels \ Summary: Ready-made single-pixel character row bytes for mode 5 \ Deep dive: Drawing colour pixels on the BBC Micro \ \ ------------------------------------------------------------------------------ \ \ Ready-made bytes for plotting one-pixel points in mode 5 (the bottom part of \ the split screen). See the dashboard routines SCAN, DIL2 and CPIX2 for \ details. \ \ There is one extra row to support the use of CTWOS+1,X indexing in the CPIX2 \ routine. The extra row is a repeat of the first row, and saves us from having \ to work out whether CTWOS+1+X needs to be wrapped around when drawing a \ two-pixel dash that crosses from one character block into another. See CPIX2 \ for more details. \ \ ****************************************************************************** .CTWOS EQUB %10001000 EQUB %01000100 EQUB %00100010 EQUB %00010001 EQUB %10001000 \ ****************************************************************************** \ \ Name: LOIN (Part 1 of 7) \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a line: Calculate the line gradient in the form of deltas \ Deep dive: Bresenham's line algorithm \ \ ------------------------------------------------------------------------------ \ \ This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. \ This stage calculates the line deltas. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X1 The screen x-coordinate of the start of the line \ \ Y1 The screen y-coordinate of the start of the line \ \ X2 The screen x-coordinate of the end of the line \ \ Y2 The screen y-coordinate of the end of the line \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Y Y is preserved \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ LL30 LL30 is a synonym for LOIN and draws a line from \ (X1, Y1) to (X2, Y2) \ \ ****************************************************************************** .LL30 SKIP 0 \ LL30 is a synonym for LOIN \ \ In the BBC Micro cassette and disc versions of Elite, \ LL30 and LOIN are synonyms for the same routine, \ presumably because the two developers each had their \ own line routines to start with, and then chose one of \ them for the final game .LOIN STY YSAV \ Store Y into YSAV, so we can preserve it across the \ call to this subroutine LDA #128 \ Set S = 128, which is the starting point for the STA S \ slope error (representing half a pixel) ASL A \ Set SWAP = 0, as %10000000 << 1 = 0 STA SWAP LDA X2 \ Set A = X2 - X1 SBC X1 \ = delta_x \ \ This subtraction works as the ASL A above sets the C \ flag BCS LI1 \ If X2 > X1 then A is already positive and we can skip \ the next three instructions EOR #%11111111 \ Negate the result in A by flipping all the bits and ADC #1 \ adding 1, i.e. using two's complement to make it \ positive SEC \ Set the C flag, ready for the subtraction below .LI1 STA P \ Store A in P, so P = |X2 - X1|, or |delta_x| LDA Y2 \ Set A = Y2 - Y1 SBC Y1 \ = delta_y \ \ This subtraction works as we either set the C flag \ above, or we skipped that SEC instruction with a BCS BCS LI2 \ If Y2 > Y1 then A is already positive and we can skip \ the next two instructions EOR #%11111111 \ Negate the result in A by flipping all the bits and ADC #1 \ adding 1, i.e. using two's complement to make it \ positive .LI2 STA Q \ Store A in Q, so Q = |Y2 - Y1|, or |delta_y| CMP P \ If Q < P, jump to STPX to step along the x-axis, as BCC STPX \ the line is closer to being horizontal than vertical JMP STPY \ Otherwise Q >= P so jump to STPY to step along the \ y-axis, as the line is closer to being vertical than \ horizontal \ ****************************************************************************** \ \ Name: LOIN (Part 2 of 7) \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a line: Line has a shallow gradient, step right along x-axis \ Deep dive: Bresenham's line algorithm \ \ ------------------------------------------------------------------------------ \ \ This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. \ If we get here, then: \ \ * |delta_y| < |delta_x| \ \ * The line is closer to being horizontal than vertical \ \ * We are going to step right along the x-axis \ \ * We potentially swap coordinates to make sure X1 < X2 \ \ ****************************************************************************** .STPX LDX X1 \ Set X = X1 CPX X2 \ If X1 < X2, jump down to LI3, as the coordinates are BCC LI3 \ already in the order that we want DEC SWAP \ Otherwise decrement SWAP from 0 to &FF, to denote that \ we are swapping the coordinates around LDA X2 \ Swap the values of X1 and X2 STA X1 STX X2 TAX \ Set X = X1 LDA Y2 \ Swap the values of Y1 and Y2 LDY Y1 STA Y1 STY Y2 .LI3 \ By this point we know the line is horizontal-ish and \ X1 < X2, so we're going from left to right as we go \ from X1 to X2 LDA Y1 \ Set A to the y-coordinate in Y1 LSR A \ Set A = A >> 3 LSR A \ = y div 8 LSR A \ \ So A now contains the number of the character row \ that will contain the start of the line ORA #&60 \ As A < 32, this effectively adds &60 to A, which gives \ us the screen address of the character row (as each \ character row takes up 256 bytes, and the first \ character row is at screen address &6000, or page &60) STA SCH \ Store the page number of the character row in SCH, so \ the high byte of SC is set correctly for drawing the \ start of our line LDA Y1 \ Set Y = Y1 mod 8, which is the pixel row within the AND #7 \ character block at which we want to draw the start of TAY \ our line (as each character block has 8 rows) TXA \ Set A = bits 3-7 of X1 AND #%11111000 STA SC \ Store this value in SC, so SC(1 0) now contains the \ screen address of the far left end (x-coordinate = 0) \ of the horizontal pixel row that we want to draw the \ start of our line on TXA \ Set X = X1 mod 8, which is the horizontal pixel number AND #7 \ within the character block where the line starts (as TAX \ each pixel line in the character block is 8 pixels \ wide) LDA TWOS,X \ Fetch a one-pixel byte from TWOS where pixel X is set, STA R \ and store it in R \ The following calculates: \ \ Q = Q / P \ = |delta_y| / |delta_x| \ \ using the same shift-and-subtract algorithm that's \ documented in TIS2 LDA Q \ Set A = |delta_y| LDX #%11111110 \ Set Q to have bits 1-7 set, so we can rotate through 7 STX Q \ loop iterations, getting a 1 each time, and then \ getting a 0 on the 8th iteration... and we can also \ use Q to catch our result bits into bit 0 each time .LIL1 ASL A \ Shift A to the left BCS LI4 \ If bit 7 of A was set, then jump straight to the \ subtraction CMP P \ If A < P, skip the following subtraction BCC LI5 .LI4 SBC P \ A >= P, so set A = A - P SEC \ Set the C flag to rotate into the result in Q .LI5 ROL Q \ Rotate the counter in Q 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 LIL1 \ If we still have set bits in Q, loop back to TIL2 to \ do the next iteration of 7 \ We now have: \ \ Q = A / P \ = |delta_y| / |delta_x| \ \ and the C flag is clear LDX P \ Set X = P + 1 INX \ = |delta_x| + 1 \ \ We add 1 so we can skip the first pixel plot if the \ line is being drawn with swapped coordinates LDA Y2 \ Set A = Y2 - Y1 - 1 (as the C flag is clear following SBC Y1 \ the above division) BCS DOWN \ If Y2 >= Y1 - 1 then jump to DOWN, as we need to draw \ the line to the right and down \ ****************************************************************************** \ \ Name: LOIN (Part 3 of 7) \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a shallow line going right and up or left and down \ Deep dive: Bresenham's line algorithm \ \ ------------------------------------------------------------------------------ \ \ This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. \ If we get here, then: \ \ * The line is going right and up (no swap) or left and down (swap) \ \ * X1 < X2 and Y1-1 > Y2 \ \ * Draw from (X1, Y1) at bottom left to (X2, Y2) at top right, omitting the \ first pixel \ \ ****************************************************************************** LDA SWAP \ If SWAP > 0 then we swapped the coordinates above, so BNE LI6 \ jump down to LI6 to skip plotting the first pixel \ \ This appears to be a bug that omits the last pixel \ of this type of shallow line, rather than the first \ pixel, which makes the treatment of this kind of line \ different to the other kinds of slope (they all have a \ BEQ instruction at this point, rather than a BNE) \ \ The result is a rather messy line join when a shallow \ line that goes right and up or left and down joins a \ line with any of the other three types of slope \ \ This bug was fixed in the advanced versions of Elite, \ where the BNE is replaced by a BEQ to bring it in line \ with the other three slopes DEX \ Decrement the counter in X because we're about to plot \ the first pixel .LIL2 \ We now loop along the line from left to right, using X \ as a decreasing counter, and at each count we plot a \ single pixel using the pixel mask in R LDA R \ Fetch the pixel byte from R EOR (SC),Y \ Store R into screen memory at SC(1 0), using EOR STA (SC),Y \ logic so it merges with whatever is already on-screen .LI6 LSR R \ Shift the single pixel in R to the right to step along \ the x-axis, so the next pixel we plot will be at the \ next x-coordinate along BCC LI7 \ If the pixel didn't fall out of the right end of R \ into the C flag, then jump to LI7 ROR R \ Otherwise we need to move over to the next character \ block, so first rotate R right so the set C flag goes \ back into the left end, giving %10000000 LDA SC \ Add 8 to SC, so SC(1 0) now points to the next ADC #8 \ character along to the right STA SC .LI7 LDA S \ Set S = S + Q to update the slope error ADC Q STA S BCC LIC2 \ If the addition didn't overflow, jump to LIC2 DEY \ Otherwise we just overflowed, so decrement Y to move \ to the pixel line above BPL LIC2 \ If Y is positive we are still within the same \ character block, so skip to LIC2 DEC SCH \ Otherwise we need to move up into the character block LDY #7 \ above, so decrement the high byte of the screen \ address and set the pixel line to the last line in \ that character block .LIC2 DEX \ Decrement the counter in X BNE LIL2 \ If we haven't yet reached the right end of the line, \ loop back to LIL2 to plot the next pixel along LDY YSAV \ Restore Y from YSAV, so that it's preserved RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: LOIN (Part 4 of 7) \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a shallow line going right and down or left and up \ Deep dive: Bresenham's line algorithm \ \ ------------------------------------------------------------------------------ \ \ This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. \ If we get here, then: \ \ * The line is going right and down (no swap) or left and up (swap) \ \ * X1 < X2 and Y1-1 <= Y2 \ \ * Draw from (X1, Y1) at top left to (X2, Y2) at bottom right, omitting the \ first pixel \ \ ****************************************************************************** .DOWN LDA SWAP \ If SWAP = 0 then we didn't swap the coordinates above, BEQ LI9 \ so jump down to LI9 to skip plotting the first pixel DEX \ Decrement the counter in X because we're about to plot \ the first pixel .LIL3 \ We now loop along the line from left to right, using X \ as a decreasing counter, and at each count we plot a \ single pixel using the pixel mask in R LDA R \ Fetch the pixel byte from R EOR (SC),Y \ Store R into screen memory at SC(1 0), using EOR STA (SC),Y \ logic so it merges with whatever is already on-screen .LI9 LSR R \ Shift the single pixel in R to the right to step along \ the x-axis, so the next pixel we plot will be at the \ next x-coordinate along BCC LI10 \ If the pixel didn't fall out of the right end of R \ into the C flag, then jump to LI10 ROR R \ Otherwise we need to move over to the next character \ block, so first rotate R right so the set C flag goes \ back into the left end, giving %10000000 LDA SC \ Add 8 to SC, so SC(1 0) now points to the next ADC #8 \ character along to the right STA SC .LI10 LDA S \ Set S = S + Q to update the slope error ADC Q STA S BCC LIC3 \ If the addition didn't overflow, jump to LIC3 INY \ Otherwise we just overflowed, so increment Y to move \ to the pixel line below CPY #8 \ If Y < 8 we are still within the same character block, BNE LIC3 \ so skip to LIC3 INC SCH \ Otherwise we need to move down into the character LDY #0 \ block below, so increment the high byte of the screen \ address and set the pixel line to the first line in \ that character block .LIC3 DEX \ Decrement the counter in X BNE LIL3 \ If we haven't yet reached the right end of the line, \ loop back to LIL3 to plot the next pixel along LDY YSAV \ Restore Y from YSAV, so that it's preserved RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: LOIN (Part 5 of 7) \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a line: Line has a steep gradient, step up along y-axis \ Deep dive: Bresenham's line algorithm \ \ ------------------------------------------------------------------------------ \ \ This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. \ If we get here, then: \ \ * |delta_y| >= |delta_x| \ \ * The line is closer to being vertical than horizontal \ \ * We are going to step up along the y-axis \ \ * We potentially swap coordinates to make sure Y1 >= Y2 \ \ ****************************************************************************** .STPY LDY Y1 \ Set A = Y = Y1 TYA LDX X1 \ Set X = X1 CPY Y2 \ If Y1 >= Y2, jump down to LI15, as the coordinates are BCS LI15 \ already in the order that we want DEC SWAP \ Otherwise decrement SWAP from 0 to &FF, to denote that \ we are swapping the coordinates around LDA X2 \ Swap the values of X1 and X2 STA X1 STX X2 TAX \ Set X = X1 LDA Y2 \ Swap the values of Y1 and Y2 STA Y1 STY Y2 TAY \ Set Y = A = Y1 .LI15 \ By this point we know the line is vertical-ish and \ Y1 >= Y2, so we're going from top to bottom as we go \ from Y1 to Y2 LSR A \ Set A = A >> 3 LSR A \ = y div 8 LSR A \ \ So A now contains the number of the character row \ that will contain the (X1, Y1) pixel ORA #&60 \ As A < 32, this effectively adds &60 to A, which gives \ us the screen address of the character row (as each \ character row takes up 256 bytes, and the first \ character row is at screen address &6000, or page &60) STA SCH \ Store the page number of the character row in SCH, so \ the high byte of SC is set correctly for drawing the \ start of our line TXA \ Set A = bits 3-7 of X1 AND #%11111000 STA SC \ Store this value in SC, so SC(1 0) now contains the \ screen address of the far left end (x-coordinate = 0) \ of the horizontal pixel row that we want to draw the \ start of our line on TXA \ Set X = X1 mod 8, which is the horizontal pixel number AND #7 \ within the character block where the line starts (as TAX \ each pixel line in the character block is 8 pixels \ wide) LDA TWOS,X \ Fetch a one-pixel byte from TWOS where pixel X is set, STA R \ and store it in R LDA Y1 \ Set Y = Y1 mod 8, which is the pixel row within the AND #7 \ character block at which we want to draw the start of TAY \ our line (as each character block has 8 rows) \ The following calculates: \ \ P = P / Q \ = |delta_x| / |delta_y| \ \ using the same shift-and-subtract algorithm \ documented in TIS2 LDA P \ Set A = |delta_x| LDX #1 \ Set Q to have bits 1-7 clear, so we can rotate through STX P \ 7 loop iterations, getting a 1 each time, and then \ getting a 1 on the 8th iteration... and we can also \ use P to catch our result bits into bit 0 each time .LIL4 ASL A \ Shift A to the left BCS LI13 \ If bit 7 of A was set, then jump straight to the \ subtraction CMP Q \ If A < Q, skip the following subtraction BCC LI14 .LI13 SBC Q \ A >= Q, so set A = A - Q SEC \ Set the C flag to rotate into the result in Q .LI14 ROL P \ Rotate the counter in P 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) BCC LIL4 \ If we still have set bits in P, loop back to TIL2 to \ do the next iteration of 7 \ We now have: \ \ P = A / Q \ = |delta_x| / |delta_y| \ \ and the C flag is set LDX Q \ Set X = Q + 1 INX \ = |delta_y| + 1 \ \ We add 1 so we can skip the first pixel plot if the \ line is being drawn with swapped coordinates LDA X2 \ Set A = X2 - X1 (the C flag is set as we didn't take SBC X1 \ the above BCC) BCC LFT \ If X2 < X1 then jump to LFT, as we need to draw the \ line to the left and down \ ****************************************************************************** \ \ Name: LOIN (Part 6 of 7) \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a steep line going up and left or down and right \ Deep dive: Bresenham's line algorithm \ \ ------------------------------------------------------------------------------ \ \ This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. \ If we get here, then: \ \ * The line is going up and left (no swap) or down and right (swap) \ \ * X1 < X2 and Y1 >= Y2 \ \ * Draw from (X1, Y1) at top left to (X2, Y2) at bottom right, omitting the \ first pixel \ \ ****************************************************************************** CLC \ Clear the C flag LDA SWAP \ If SWAP = 0 then we didn't swap the coordinates above, BEQ LI17 \ so jump down to LI17 to skip plotting the first pixel DEX \ Decrement the counter in X because we're about to plot \ the first pixel .LIL5 \ We now loop along the line from left to right, using X \ as a decreasing counter, and at each count we plot a \ single pixel using the pixel mask in R LDA R \ Fetch the pixel byte from R EOR (SC),Y \ Store R into screen memory at SC(1 0), using EOR STA (SC),Y \ logic so it merges with whatever is already on-screen .LI17 DEY \ Decrement Y to step up along the y-axis BPL LI16 \ If Y is positive we are still within the same \ character block, so skip to LI16 DEC SCH \ Otherwise we need to move up into the character block LDY #7 \ above, so decrement the high byte of the screen \ address and set the pixel line to the last line in \ that character block .LI16 LDA S \ Set S = S + P to update the slope error ADC P STA S BCC LIC5 \ If the addition didn't overflow, jump to LIC5 LSR R \ Otherwise we just overflowed, so shift the single \ pixel in R to the right, so the next pixel we plot \ will be at the next x-coordinate along BCC LIC5 \ If the pixel didn't fall out of the right end of R \ into the C flag, then jump to LIC5 ROR R \ Otherwise we need to move over to the next character \ block, so first rotate R right so the set C flag goes \ back into the left end, giving %10000000 LDA SC \ Add 8 to SC, so SC(1 0) now points to the next ADC #8 \ character along to the right STA SC .LIC5 DEX \ Decrement the counter in X BNE LIL5 \ If we haven't yet reached the right end of the line, \ loop back to LIL5 to plot the next pixel along LDY YSAV \ Restore Y from YSAV, so that it's preserved RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: LOIN (Part 7 of 7) \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a steep line going up and right or down and left \ Deep dive: Bresenham's line algorithm \ \ ------------------------------------------------------------------------------ \ \ This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. \ If we get here, then: \ \ * The line is going up and right (no swap) or down and left (swap) \ \ * X1 >= X2 and Y1 >= Y2 \ \ * Draw from (X1, Y1) at bottom left to (X2, Y2) at top right, omitting the \ first pixel \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ HL6 Contains an RTS \ \ ****************************************************************************** .LFT LDA SWAP \ If SWAP = 0 then we didn't swap the coordinates above, BEQ LI18 \ so jump down to LI18 to skip plotting the first pixel DEX \ Decrement the counter in X because we're about to plot \ the first pixel .LIL6 LDA R \ Fetch the pixel byte from R EOR (SC),Y \ Store R into screen memory at SC(1 0), using EOR STA (SC),Y \ logic so it merges with whatever is already on-screen .LI18 DEY \ Decrement Y to step up along the y-axis BPL LI19 \ If Y is positive we are still within the same \ character block, so skip to LI19 DEC SCH \ Otherwise we need to move up into the character block LDY #7 \ above, so decrement the high byte of the screen \ address and set the pixel line to the last line in \ that character block .LI19 LDA S \ Set S = S + P to update the slope error ADC P STA S BCC LIC6 \ If the addition didn't overflow, jump to LIC6 ASL R \ Otherwise we just overflowed, so shift the single \ pixel in R to the left, so the next pixel we plot \ will be at the previous x-coordinate BCC LIC6 \ If the pixel didn't fall out of the left end of R \ into the C flag, then jump to LIC6 ROL R \ Otherwise we need to move over to the next character \ block, so first rotate R left so the set C flag goes \ back into the right end, giving %0000001 LDA SC \ Subtract 7 from SC, so SC(1 0) now points to the SBC #7 \ previous character along to the left STA SC CLC \ Clear the C flag so it doesn't affect the additions \ if we loop back .LIC6 DEX \ Decrement the counter in X BNE LIL6 \ If we haven't yet reached the left end of the line, \ loop back to LIL6 to plot the next pixel along LDY YSAV \ Restore Y from YSAV, so that it's preserved .HL6 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: NLIN3 \ Type: Subroutine \ Category: Drawing lines \ Summary: Print a title and draw a horizontal line at row 19 to box it in \ \ ------------------------------------------------------------------------------ \ \ This routine print a text token at the cursor position and draws a horizontal \ line at pixel row 19. It is used for the Status Mode screen, the Short-range \ Chart, the Market Price screen and the Equip Ship screen. \ \ ****************************************************************************** .NLIN3 JSR TT27 \ Print the text token in A \ Fall through into NLIN4 to draw a horizontal line at \ pixel row 19 \ ****************************************************************************** \ \ Name: NLIN4 \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a horizontal line at pixel row 19 to box in a title \ \ ------------------------------------------------------------------------------ \ \ This routine is used on the Inventory screen to draw a horizontal line at \ pixel row 19 to box in the title. \ \ ****************************************************************************** .NLIN4 LDA #19 \ Jump to NLIN2 to draw a horizontal line at pixel row BNE NLIN2 \ 19, returning from the subroutine with using a tail \ call (this BNE is effectively a JMP as A will never \ be zero) \ ****************************************************************************** \ \ Name: NLIN \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a horizontal line at pixel row 23 to box in a title \ \ ------------------------------------------------------------------------------ \ \ Draw a horizontal line at pixel row 23 and move the text cursor down one \ line. \ \ ****************************************************************************** .NLIN LDA #23 \ Set A = 23 so NLIN2 below draws a horizontal line at \ pixel row 23 INC YC \ Move the text cursor down one line \ Fall through into NLIN2 to draw the horizontal line \ at row 23 \ ****************************************************************************** \ \ Name: NLIN2 \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a screen-wide horizontal line at the pixel row in A \ \ ------------------------------------------------------------------------------ \ \ This draws a line from (2, A) to (254, A), which is almost screen-wide and \ fits in nicely between the border boxes without clashing with it. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The pixel row on which to draw the horizontal line \ \ ****************************************************************************** .NLIN2 STA Y1 \ Set Y1 = A LDX #2 \ Set X1 = 2, so (X1, Y1) = (2, A) STX X1 LDX #254 \ Set X2 = 254, so (X2, Y2) = (254, A) STX X2 BNE HLOIN \ Call HLOIN to draw a horizontal line from (2, A) to \ (254, A) and return from the subroutine (this BNE is \ effectively a JMP as A will never be zero) \ ****************************************************************************** \ \ Name: HLOIN2 \ Type: Subroutine \ Category: Drawing lines \ Summary: Remove a line from the sun line heap and draw it on-screen \ \ ------------------------------------------------------------------------------ \ \ Specifically, this does the following: \ \ * Set X1 and X2 to the x-coordinates of the ends of the horizontal line with \ centre YY(1 0) and length A to the left and right \ \ * Set the Y-th byte of the LSO block to 0 (i.e. remove this line from the \ sun line heap) \ \ * Draw a horizontal line from (X1, Y) to (X2, Y) \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ YY(1 0) The x-coordinate of the centre point of the line \ \ A The half-width of the line, i.e. the contents of the \ Y-th byte of the sun line heap \ \ Y The number of the entry in the sun line heap (which is \ also the y-coordinate of the line) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Y Y is preserved \ \ ****************************************************************************** .HLOIN2 JSR EDGES \ Call EDGES to calculate X1 and X2 for the horizontal \ line centred on YY(1 0) and with half-width A STY Y1 \ Set Y1 = Y LDA #0 \ Set the Y-th byte of the LSO block to 0 STA LSO,Y \ Fall through into HLOIN to draw a horizontal line from \ (X1, Y) to (X2, Y) \ ****************************************************************************** \ \ Name: HLOIN \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a horizontal line from (X1, Y1) to (X2, Y1) \ Deep dive: Drawing monochrome pixels on the BBC Micro \ \ ------------------------------------------------------------------------------ \ \ We do not draw a pixel at the right end of the line. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Y Y is preserved \ \ ****************************************************************************** .HLOIN STY YSAV \ Store Y into YSAV, so we can preserve it across the \ call to this subroutine LDX X1 \ Set X = X1 CPX X2 \ If X1 = X2 then the start and end points are the same, BEQ HL6 \ so return from the subroutine (as HL6 contains an RTS) BCC HL5 \ If X1 < X2, jump to HL5 to skip the following code, as \ (X1, Y1) is already the left point LDA X2 \ Swap the values of X1 and X2, so we know that (X1, Y1) STA X1 \ is on the left and (X2, Y1) is on the right STX X2 TAX \ Set X = X1 .HL5 DEC X2 \ Decrement X2 so we do not draw a pixel at the end \ point LDA Y1 \ Set A to the y-coordinate in Y1 LSR A \ Set A = A >> 3 LSR A \ = y div 8 LSR A \ \ So A now contains the number of the character row \ that will contain our horizontal line ORA #&60 \ As A < 32, this effectively adds &60 to A, which gives \ us the screen address of the character row (as each \ character row takes up 256 bytes, and the first \ character row is at screen address &6000, or page &60) STA SCH \ Store the page number of the character row in SCH, so \ the high byte of SC is set correctly for drawing our \ line LDA Y1 \ Set A = Y1 mod 8, which is the pixel row within the AND #7 \ character block at which we want to draw our line (as \ each character block has 8 rows) STA SC \ Store this value in SC, so SC(1 0) now contains the \ screen address of the far left end (x-coordinate = 0) \ of the horizontal pixel row that we want to draw our \ horizontal line on TXA \ Set Y = bits 3-7 of X1 AND #%11111000 TAY .HL1 TXA \ Set T = bits 3-7 of X1, which will contain the AND #%11111000 \ character number of the start of the line * 8 STA T LDA X2 \ Set A = bits 3-7 of X2, which will contain the AND #%11111000 \ character number of the end of the line * 8 SEC \ Set A = A - T, which will contain the number of SBC T \ character blocks we need to fill - 1 * 8 BEQ HL2 \ If A = 0 then the start and end character blocks are \ the same, so the whole line fits within one block, so \ jump down to HL2 to draw the line \ Otherwise the line spans multiple characters, so we \ start with the left character, then do any characters \ in the middle, and finish with the right character LSR A \ Set R = A / 8, so R now contains the number of LSR A \ character blocks we need to fill - 1 LSR A STA R LDA X1 \ Set X = X1 mod 8, which is the horizontal pixel number AND #7 \ within the character block where the line starts (as TAX \ each pixel line in the character block is 8 pixels \ wide) LDA TWFR,X \ Fetch a ready-made byte with X pixels filled in at the \ right end of the byte (so the filled pixels start at \ point X and go all the way to the end of the byte), \ which is the shape we want for the left end of the \ line EOR (SC),Y \ Store this into screen memory at SC(1 0), using EOR STA (SC),Y \ logic so it merges with whatever is already on-screen, \ so we have now drawn the line's left cap TYA \ Set Y = Y + 8 so (SC),Y points to the next character ADC #8 \ block along, on the same pixel row as before TAY LDX R \ Fetch the number of character blocks we need to fill \ from R DEX \ Decrement the number of character blocks in X BEQ HL3 \ If X = 0 then we only have the last block to do (i.e. \ the right cap), so jump down to HL3 to draw it CLC \ Otherwise clear the C flag so we can do some additions \ while we draw the character blocks with full-width \ lines in them .HLL1 LDA #%11111111 \ Store a full-width eight-pixel horizontal line in EOR (SC),Y \ SC(1 0) so that it draws the line on-screen, using EOR STA (SC),Y \ logic so it merges with whatever is already on-screen TYA \ Set Y = Y + 8 so (SC),Y points to the next character ADC #8 \ block along, on the same pixel row as before TAY DEX \ Decrement the number of character blocks in X BNE HLL1 \ Loop back to draw more full-width lines, if we have \ any more to draw .HL3 LDA X2 \ Now to draw the last character block at the right end AND #7 \ of the line, so set X = X2 mod 8, which is the TAX \ horizontal pixel number where the line ends LDA TWFL,X \ Fetch a ready-made byte with X pixels filled in at the \ left end of the byte (so the filled pixels start at \ the left edge and go up to point X), which is the \ shape we want for the right end of the line EOR (SC),Y \ Store this into screen memory at SC(1 0), using EOR STA (SC),Y \ logic so it merges with whatever is already on-screen, \ so we have now drawn the line's right cap LDY YSAV \ Restore Y from YSAV, so that it's preserved across the \ call to this subroutine RTS \ Return from the subroutine .HL2 \ If we get here then the entire horizontal line fits \ into one character block LDA X1 \ Set X = X1 mod 8, which is the horizontal pixel number AND #7 \ within the character block where the line starts (as TAX \ each pixel line in the character block is 8 pixels \ wide) LDA TWFR,X \ Fetch a ready-made byte with X pixels filled in at the STA T \ right end of the byte (so the filled pixels start at \ point X and go all the way to the end of the byte) LDA X2 \ Set X = X2 mod 8, which is the horizontal pixel number AND #7 \ where the line ends TAX LDA TWFL,X \ Fetch a ready-made byte with X pixels filled in at the \ left end of the byte (so the filled pixels start at \ the left edge and go up to point X) AND T \ We now have two bytes, one (T) containing pixels from \ the starting point X1 onwards, and the other (A) \ containing pixels up to the end point at X2, so we can \ get the actual line we want to draw by AND'ing them \ together. For example, if we want to draw a line from \ point 2 to point 5 (within the row of 8 pixels \ numbered from 0 to 7), we would have this: \ \ T = %00111111 \ A = %11111100 \ T AND A = %00111100 \ \ So we can stick T AND A in screen memory to get the \ line we want, which is what we do here by setting \ A = A AND T EOR (SC),Y \ Store our horizontal line byte into screen memory at STA (SC),Y \ SC(1 0), using EOR logic so it merges with whatever is \ already on-screen LDY YSAV \ Restore Y from YSAV, so that it's preserved RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TWFL \ Type: Variable \ Category: Drawing lines \ Summary: Ready-made character rows for the left end of a horizontal line in \ mode 4 \ \ ------------------------------------------------------------------------------ \ \ Ready-made bytes for plotting horizontal line end caps in mode 4 (the top part \ of the split screen). This table provides a byte with pixels at the left end, \ which is used for the right end of the line. \ \ See the HLOIN routine for details. \ \ ****************************************************************************** .TWFL EQUB %10000000 EQUB %11000000 EQUB %11100000 EQUB %11110000 EQUB %11111000 EQUB %11111100 EQUB %11111110 \ ****************************************************************************** \ \ Name: TWFR \ Type: Variable \ Category: Drawing lines \ Summary: Ready-made character rows for the right end of a horizontal line \ in mode 4 \ \ ------------------------------------------------------------------------------ \ \ Ready-made bytes for plotting horizontal line end caps in mode 4 (the top part \ of the split screen). This table provides a byte with pixels at the right end, \ which is used for the left end of the line. \ \ See the HLOIN routine for details. \ \ ****************************************************************************** .TWFR EQUB %11111111 EQUB %01111111 EQUB %00111111 EQUB %00011111 EQUB %00001111 EQUB %00000111 EQUB %00000011 EQUB %00000001 \ ****************************************************************************** \ \ Name: PX3 \ Type: Subroutine \ Category: Drawing pixels \ Summary: Plot a single pixel at (X, Y) within a character block \ \ ------------------------------------------------------------------------------ \ \ This routine is called from PIXEL to set 1 pixel within a character block for \ a distant point (i.e. where the distance ZZ >= &90). See the PIXEL routine for \ details, as this routine is effectively part of PIXEL. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The x-coordinate of the pixel within the character block \ \ Y The y-coordinate of the pixel within the character block \ \ SC(1 0) The screen address of the character block \ \ T1 The value of Y to restore on exit, so Y is preserved by \ the call to PIXEL \ \ ****************************************************************************** .PX3 LDA TWOS,X \ Fetch a one-pixel byte from TWOS and EOR it into SC+Y EOR (SC),Y STA (SC),Y LDY T1 \ Restore Y from T1, so Y is preserved by the routine RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PIX1 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (YY+1 SYL+Y) = (A P) + (S R) and draw stardust particle \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ (YY+1 SYL+Y) = (A P) + (S R) \ \ and draw a stardust particle at (X1,Y1) with distance ZZ. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ (A P) A is the angle ALPHA or BETA, P is always 0 \ \ (S R) YY(1 0) or YY(1 0) + Q * A \ \ Y Stardust particle number \ \ X1 The x-coordinate offset \ \ Y1 The y-coordinate offset \ \ ZZ The distance of the point, with bigger distances drawing \ smaller points: \ \ * ZZ < 80 Double-height four-pixel square \ \ * 80 <= ZZ <= 143 Single-height two-pixel dash \ \ * ZZ > 143 Single-height one-pixel dot \ \ ****************************************************************************** .PIX1 JSR ADD \ Set (A X) = (A P) + (S R) STA YY+1 \ Set YY+1 to A, the high byte of the result TXA \ Set SYL+Y to X, the low byte of the result STA SYL,Y \ Fall through into PIXEL2 to draw the stardust particle \ at (X1,Y1) \ ****************************************************************************** \ \ Name: PIXEL2 \ Type: Subroutine \ Category: Drawing pixels \ Summary: Draw a stardust particle relative to the screen centre \ \ ------------------------------------------------------------------------------ \ \ Draw a point (X1, Y1) from the middle of the screen with a size determined by \ a distance value. Used to draw stardust particles. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X1 The x-coordinate offset \ \ Y1 The y-coordinate offset (positive means up the screen \ from the centre, negative means down the screen) \ \ ZZ The distance of the point, with bigger distances drawing \ smaller points: \ \ * ZZ < 80 Double-height four-pixel square \ \ * 80 <= ZZ <= 143 Single-height two-pixel dash \ \ * ZZ > 143 Single-height one-pixel dot \ \ ****************************************************************************** .PIXEL2 LDA X1 \ Fetch the x-coordinate offset into A BPL PX1 \ If the x-coordinate offset is positive, jump to PX1 \ to skip the following negation EOR #%01111111 \ The x-coordinate offset is negative, so flip all the CLC \ bits apart from the sign bit and add 1, to convert it ADC #1 \ from a sign-magnitude number to a signed number .PX1 EOR #%10000000 \ Set X = X1 + 128 TAX \ \ So X is now the offset converted to an x-coordinate, \ centred on x-coordinate 128 LDA Y1 \ Fetch the y-coordinate offset into A and clear the AND #%01111111 \ sign bit, so A = |Y1| CMP #96 \ If |Y1| >= 96 then it's off the screen (as 96 is half BCS PX4 \ the screen height), so return from the subroutine (as \ PX4 contains an RTS) LDA Y1 \ Fetch the y-coordinate offset into A BPL PX2 \ If the y-coordinate offset is positive, jump to PX2 \ to skip the following negation EOR #%01111111 \ The y-coordinate offset is negative, so flip all the ADC #1 \ bits apart from the sign bit and subtract 1, to negate \ it to a positive number, i.e. A is now |Y1| .PX2 STA T \ Set A = #Y + 1 - Y1 LDA #Y+1 \ SBC T \ So if Y1 is positive we display the point up from the \ centre at y-coordinate 97, while a negative Y1 means \ down from the centre \ Fall through into PIXEL to draw the stardust at the \ screen coordinates in (X, A) \ ****************************************************************************** \ \ Name: PIXEL \ Type: Subroutine \ Category: Drawing pixels \ Summary: Draw a one-pixel dot, two-pixel dash or four-pixel square \ Deep dive: Drawing monochrome pixels on the BBC Micro \ \ ------------------------------------------------------------------------------ \ \ Draw a point at screen coordinate (X, A) with the point size determined by the \ distance in ZZ. This applies to the top part of the screen (the monochrome \ mode 4 portion). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The screen x-coordinate of the point to draw \ \ A The screen y-coordinate of the point to draw \ \ ZZ The distance of the point, with bigger distances drawing \ smaller points: \ \ * ZZ < 80 Double-height four-pixel square \ \ * 80 <= ZZ <= 143 Single-height two-pixel dash \ \ * ZZ > 143 Single-height one-pixel dot \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Y Y is preserved \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ PX4 Contains an RTS \ \ ****************************************************************************** .PIXEL STY T1 \ Store Y in T1 so we can restore it at the end of the \ subroutine TAY \ Copy A into Y, for use later LSR A \ Set SCH = &60 + A >> 3 LSR A LSR A ORA #&60 STA SCH TXA \ Set SC = (X >> 3) * 8 AND #%11111000 STA SC TYA \ Set Y = Y mod 8, which is the pixel row within the AND #7 \ character block at which we want to draw our pixel TAY \ (as each character block has 8 rows) TXA \ Set X = X mod 8, which is the horizontal pixel number AND #7 \ within the character block where the pixel lies (as TAX \ each pixel line in the character block is 8 pixels \ wide) LDA ZZ \ If distance in ZZ >= 144, then this point is a very CMP #144 \ long way away, so jump to PX3 to fetch a one-pixel BCS PX3 \ point from TWOS and EOR it into SC+Y LDA TWOS2,X \ Otherwise fetch a two-pixel dash from TWOS2 and EOR it EOR (SC),Y \ into SC+Y STA (SC),Y LDA ZZ \ If distance in ZZ >= 80, then this point is a medium CMP #80 \ distance away, so jump to PX13 to stop drawing, as a BCS PX13 \ two-pixel dash is enough \ Otherwise we keep going to draw another 2 pixel point \ either above or below the one we just drew, to make a \ four-pixel square DEY \ Reduce Y by 1 to point to the pixel row above the one BPL PX14 \ we just plotted, and if it is still positive, jump to \ PX14 to draw our second two-pixel dash LDY #1 \ Reducing Y by 1 made it negative, which means Y was \ 0 before we did the DEY above, so set Y to 1 to point \ to the pixel row after the one we just plotted .PX14 LDA TWOS2,X \ Fetch a two-pixel dash from TWOS2 and EOR it into this EOR (SC),Y \ second row to make a four-pixel square STA (SC),Y .PX13 LDY T1 \ Restore Y from T1, so Y is preserved by the routine .PX4 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: BLINE \ Type: Subroutine \ Category: Drawing circles \ Summary: Draw a circle segment and add it to the ball line heap \ Deep dive: The ball line heap \ Drawing circles \ \ ------------------------------------------------------------------------------ \ \ Draw a single segment of a circle, adding the point to the ball line heap. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ CNT The number of this segment \ \ STP The step size for the circle \ \ K6(1 0) The x-coordinate of the new point on the circle, as \ a screen coordinate \ \ (T X) The y-coordinate of the new point on the circle, as \ an offset from the centre of the circle \ \ FLAG Set to &FF for the first call, so it sets up the first \ point in the heap but waits until the second call before \ drawing anything (as we need two points, i.e. two calls, \ before we can draw a line) \ \ K4(1 0) Pixel y-coordinate of the centre of the circle \ \ K5(1 0) Screen x-coordinate of the previous point added to the \ ball line heap (if this is not the first point) \ \ K5(3 2) Screen y-coordinate of the previous point added to the \ ball line heap (if this is not the first point) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ CNT CNT is updated to CNT + STP \ \ A The new value of CNT \ \ K5(1 0) Screen x-coordinate of the point that we just added to \ the ball line heap \ \ K5(3 2) Screen y-coordinate of the point that we just added to \ the ball line heap \ \ FLAG Set to 0 \ \ ****************************************************************************** .BLINE TXA \ Set K6(3 2) = (T X) + K4(1 0) ADC K4 \ = y-coord of centre + y-coord of new point STA K6+2 \ LDA K4+1 \ so K6(3 2) now contains the y-coordinate of the new ADC T \ point on the circle but as a screen coordinate, to go STA K6+3 \ along with the screen x-coordinate in K6(1 0) LDA FLAG \ If FLAG = 0, jump down to BL1 BEQ BL1 INC FLAG \ Flag is &FF so this is the first call to BLINE, so \ increment FLAG to set it to 0, as then the next time \ we call BLINE it can draw the first line, from this \ point to the next .BL5 \ The following inserts a &FF marker into the LSY2 line \ heap to indicate that the next call to BLINE should \ store both the (X1, Y1) and (X2, Y2) points. We do \ this on the very first call to BLINE (when FLAG is \ &FF), and on subsequent calls if the segment does not \ fit on-screen, in which case we don't draw or store \ that segment, and we start a new segment with the next \ call to BLINE that does fit on-screen LDY LSP \ If byte LSP-1 of LSY2 = &FF, jump to BL7 to tidy up LDA #&FF \ and return from the subroutine, as the point that has CMP LSY2-1,Y \ been passed to BLINE is the start of a segment, so all BEQ BL7 \ we need to do is save the coordinate in K5, without \ moving the pointer in LSP STA LSY2,Y \ Otherwise we just tried to plot a segment but it \ didn't fit on-screen, so put the &FF marker into the \ heap for this point, so the next call to BLINE starts \ a new segment INC LSP \ Increment LSP to point to the next point in the heap BNE BL7 \ Jump to BL7 to tidy up and return from the subroutine \ (this BNE is effectively a JMP, as LSP will never be \ zero) .BL1 LDA K5 \ Set XX15 = K5 = x_lo of previous point STA XX15 LDA K5+1 \ Set XX15+1 = K5+1 = x_hi of previous point STA XX15+1 LDA K5+2 \ Set XX15+2 = K5+2 = y_lo of previous point STA XX15+2 LDA K5+3 \ Set XX15+3 = K5+3 = y_hi of previous point STA XX15+3 LDA K6 \ Set XX15+4 = x_lo of new point STA XX15+4 LDA K6+1 \ Set XX15+5 = x_hi of new point STA XX15+5 LDA K6+2 \ Set XX12 = y_lo of new point STA XX12 LDA K6+3 \ Set XX12+1 = y_hi of new point STA XX12+1 JSR LL145 \ Call LL145 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 BL5 \ If the C flag is set then the line is not visible on \ screen anyway, so jump to BL5, to avoid drawing and \ storing this line LDA SWAP \ If SWAP = 0, then we didn't have to swap the line BEQ BL9 \ coordinates around during the clipping process, so \ jump to BL9 to skip the following swap LDA X1 \ Otherwise the coordinates were swapped by the call to LDY X2 \ LL145 above, so we swap (X1, Y1) and (X2, Y2) back STA X2 \ again STY X1 LDA Y1 LDY Y2 STA Y2 STY Y1 .BL9 LDY LSP \ Set Y = LSP LDA LSY2-1,Y \ If byte LSP-1 of LSY2 is not &FF, jump down to BL8 CMP #&FF \ to skip the following (X1, Y1) code BNE BL8 \ Byte LSP-1 of LSY2 is &FF, which indicates that we \ need to store (X1, Y1) in the heap LDA X1 \ Store X1 in the LSP-th byte of LSX2 STA LSX2,Y LDA Y1 \ Store Y1 in the LSP-th byte of LSY2 STA LSY2,Y INY \ Increment Y to point to the next byte in LSX2/LSY2 .BL8 LDA X2 \ Store X2 in the LSP-th byte of LSX2 STA LSX2,Y LDA Y2 \ Store Y2 in the LSP-th byte of LSX2 STA LSY2,Y INY \ Increment Y to point to the next byte in LSX2/LSY2 STY LSP \ Update LSP to point to the same as Y JSR LOIN \ Draw a line from (X1, Y1) to (X2, Y2) LDA XX13 \ If XX13 is non-zero, jump up to BL5 to add a &FF BNE BL5 \ marker to the end of the line heap. XX13 is non-zero \ after the call to the clipping routine LL145 above 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, and that's what inserting the &FF \ marker does .BL7 LDA K6 \ Copy the data for this step point from K6(3 2 1 0) STA K5 \ into K5(3 2 1 0), for use in the next call to BLINE: LDA K6+1 \ STA K5+1 \ * K5(1 0) = screen x-coordinate of this point LDA K6+2 \ STA K5+2 \ * K5(3 2) = screen y-coordinate of this point LDA K6+3 \ STA K5+3 \ They now become the "previous point" in the next call LDA CNT \ Set CNT = CNT + STP CLC ADC STP STA CNT RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: FLIP \ Type: Subroutine \ Category: Stardust \ Summary: Reflect the stardust particles in the screen diagonal and redraw \ the stardust field \ \ ------------------------------------------------------------------------------ \ \ Swap the x- and y-coordinates of all the stardust particles and draw the new \ set of particles. Called by LOOK1 when we switch views. \ \ This is a quick way of making the stardust field in the new view feel \ different without having to generate a whole new field. If you look carefully \ at the stardust field when you switch views, you can just about see that the \ new field is a reflection of the previous field in the screen diagonal, i.e. \ in the line from bottom left to top right. This is the line where x = y when \ the origin is in the middle of the screen, and positive x and y are right and \ up, which is the coordinate system we use for stardust). \ \ ****************************************************************************** .FLIP \LDA MJ \ These instructions are commented out in the original \BNE FLIP-1 \ source. They would have the effect of not swapping the \ stardust if we had mis-jumped into witchspace LDY NOSTM \ Set Y to the current number of stardust particles, so \ we can use it as a counter through all the stardust .FLL1 LDX SY,Y \ Copy the Y-th particle's y-coordinate from SY+Y into X LDA SX,Y \ Copy the Y-th particle's x-coordinate from SX+Y into STA Y1 \ both Y1 and the particle's y-coordinate STA SY,Y TXA \ Copy the Y-th particle's original y-coordinate into STA X1 \ both X1 and the particle's x-coordinate, so the x- and STA SX,Y \ y-coordinates are now swapped and (X1, Y1) contains \ the particle's new coordinates LDA SZ,Y \ Fetch the Y-th particle's distance from SZ+Y into ZZ STA ZZ JSR PIXEL2 \ Draw a stardust particle at (X1,Y1) with distance ZZ DEY \ Decrement the counter to point to the next particle of \ stardust BNE FLL1 \ Loop back to FLL1 until we have moved all the stardust \ particles RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: STARS \ Type: Subroutine \ Category: Stardust \ Summary: The main routine for processing the stardust \ \ ------------------------------------------------------------------------------ \ \ Called at the very end of the main flight loop. \ \ ****************************************************************************** .STARS \LDA #&FF \ These instructions are commented out in the original \STA COL \ source, but they would set the stardust colour to \ white. That said, COL is only used when updating the \ dashboard, so this would have no effect - perhaps it's \ left over from experiments with a colour top part of \ the screen? Who knows... LDX VIEW \ Load the current view into X: \ \ 0 = front \ 1 = rear \ 2 = left \ 3 = right BEQ STARS1 \ If this is view 0, jump to STARS1 to process the \ stardust for the front view DEX \ If this is view 2 or 3, jump to STARS2 (via ST11) to BNE ST11 \ process the stardust for the left or right views JMP STARS6 \ Otherwise this is the rear view, so jump to STARS6 to \ process the stardust for the rear view .ST11 JMP STARS2 \ Jump to STARS2 for the left or right views, as it's \ too far for the branch instruction above \ ****************************************************************************** \ \ Name: STARS1 \ Type: Subroutine \ Category: Stardust \ Summary: Process the stardust for the front view \ Deep dive: Stardust in the front view \ \ ------------------------------------------------------------------------------ \ \ This moves the stardust towards us according to our speed (so the dust rushes \ past us), and applies our current pitch and roll to each particle of dust, so \ the stardust moves correctly when we steer our ship. \ \ When a stardust particle rushes past us and falls off the side of the screen, \ its memory is recycled as a new particle that's positioned randomly on-screen. \ \ These are the calculations referred to in the commentary: \ \ 1. q = 64 * speed / z_hi \ 2. z = z - speed * 64 \ 3. y = y + |y_hi| * q \ 4. x = x + |x_hi| * q \ \ 5. y = y + alpha * x / 256 \ 6. x = x - alpha * y / 256 \ \ 7. x = x + 2 * (beta * y / 256) ^ 2 \ 8. y = y - beta * 256 \ \ For more information see the associated deep dive. \ \ ****************************************************************************** .STARS1 LDY NOSTM \ Set Y to the current number of stardust particles, so \ we can use it as a counter through all the stardust \ In the following, we're going to refer to the 16-bit \ space coordinates of the current particle of stardust \ (i.e. the Y-th particle) like this: \ \ x = (x_hi x_lo) \ y = (y_hi y_lo) \ z = (z_hi z_lo) \ \ These values are stored in (SX+Y SXL+Y), (SY+Y SYL+Y) \ and (SZ+Y SZL+Y) respectively .STL1 JSR DV42 \ Call DV42 to set the following: \ \ (P R) = 256 * DELTA / z_hi \ = 256 * speed / z_hi \ \ The maximum value returned is P = 2 and R = 128 (see \ DV42 for an explanation) LDA R \ Set A = R, so now: \ \ (P A) = 256 * speed / z_hi LSR P \ Rotate (P A) right by 2 places, which sets P = 0 (as P ROR A \ has a maximum value of 2) and leaves: LSR P \ ROR A \ A = 64 * speed / z_hi ORA #1 \ Make sure A is at least 1, and store it in Q, so we STA Q \ now have result 1 above: \ \ Q = 64 * speed / z_hi LDA SZL,Y \ We now calculate the following: SBC DELT4 \ STA SZL,Y \ (z_hi z_lo) = (z_hi z_lo) - DELT4(1 0) \ \ starting with the low bytes LDA SZ,Y \ And then we do the high bytes STA ZZ \ SBC DELT4+1 \ We also set ZZ to the original value of z_hi, which we STA SZ,Y \ use below to remove the existing particle \ \ So now we have result 2 above: \ \ z = z - DELT4(1 0) \ = z - speed * 64 JSR MLU1 \ Call MLU1 to set: \ \ Y1 = y_hi \ \ (A P) = |y_hi| * Q \ \ So Y1 contains the original value of y_hi, which we \ use below to remove the existing particle \ We now calculate: \ \ (S R) = YY(1 0) = (A P) + y STA YY+1 \ First we do the low bytes with: LDA P \ ADC SYL,Y \ YY+1 = A STA YY \ R = YY = P + y_lo STA R \ \ so we get this: \ \ (? R) = YY(1 0) = (A P) + y_lo LDA Y1 \ And then we do the high bytes with: ADC YY+1 \ STA YY+1 \ S = YY+1 = y_hi + YY+1 STA S \ \ so we get our result: \ \ (S R) = YY(1 0) = (A P) + (y_hi y_lo) \ = |y_hi| * Q + y \ \ which is result 3 above, and (S R) is set to the new \ value of y LDA SX,Y \ Set X1 = A = x_hi STA X1 \ \ So X1 contains the original value of x_hi, which we \ use below to remove the existing particle JSR MLU2 \ Set (A P) = |x_hi| * Q \ We now calculate: \ \ XX(1 0) = (A P) + x STA XX+1 \ First we do the low bytes: LDA P \ ADC SXL,Y \ XX(1 0) = (A P) + x_lo STA XX LDA X1 \ And then we do the high bytes: ADC XX+1 \ STA XX+1 \ XX(1 0) = XX(1 0) + (x_hi 0) \ \ so we get our result: \ \ XX(1 0) = (A P) + x \ = |x_hi| * Q + x \ \ which is result 4 above, and we also have: \ \ A = XX+1 = (|x_hi| * Q + x) / 256 \ \ i.e. A is the new value of x, divided by 256 EOR ALP2+1 \ EOR with the flipped sign of the roll angle alpha, so \ A has the opposite sign to the flipped roll angle \ alpha, i.e. it gets the same sign as alpha JSR MLS1 \ Call MLS1 to calculate: \ \ (A P) = A * ALP1 \ = (x / 256) * alpha JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = (x / 256) * alpha + y \ = y + alpha * x / 256 STA YY+1 \ Set YY(1 0) = (A X) to give: STX YY \ \ YY(1 0) = y + alpha * x / 256 \ \ which is result 5 above, and we also have: \ \ A = YY+1 = y + alpha * x / 256 \ \ i.e. A is the new value of y, divided by 256 EOR ALP2 \ EOR A with the correct sign of the roll angle alpha, \ so A has the opposite sign to the roll angle alpha JSR MLS2 \ Call MLS2 to calculate: \ \ (S R) = XX(1 0) \ = x \ \ (A P) = A * ALP1 \ = -y / 256 * alpha JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = -y / 256 * alpha + x STA XX+1 \ Set XX(1 0) = (A X), which gives us result 6 above: STX XX \ \ x = x - alpha * y / 256 LDX BET1 \ Fetch the pitch magnitude into X LDA YY+1 \ Set A to y_hi and set it to the flipped sign of beta EOR BET2+1 JSR MULTS-2 \ Call MULTS-2 to calculate: \ \ (A P) = X * A \ = -beta * y_hi STA Q \ Store the high byte of the result in Q, so: \ \ Q = -beta * y_hi / 256 JSR MUT2 \ Call MUT2 to calculate: \ \ (S R) = XX(1 0) = x \ \ (A P) = Q * A \ = (-beta * y_hi / 256) * (-beta * y_hi / 256) \ = (beta * y / 256) ^ 2 ASL P \ Double (A P), store the top byte in A and set the C ROL A \ flag to bit 7 of the original A, so this does: STA T \ \ (T P) = (A P) << 1 \ = 2 * (beta * y / 256) ^ 2 LDA #0 \ Set bit 7 in A to the sign bit from the A in the ROR A \ calculation above and apply it to T, so we now have: ORA T \ \ (A P) = (A P) * 2 \ = 2 * (beta * y / 256) ^ 2 \ \ with the doubling retaining the sign of (A P) JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = 2 * (beta * y / 256) ^ 2 + x STA XX+1 \ Store the high byte A in XX+1 TXA \ Store the low byte X in x_lo STA SXL,Y \ So (XX+1 x_lo) now contains: \ \ x = x + 2 * (beta * y / 256) ^ 2 \ \ which is result 7 above LDA YY \ Set (S R) = YY(1 0) = y STA R \ LDA YY+1 \ The call to MAD and the two store instructions are \JSR MAD \ commented out in the original source \STA S \STX R STA S LDA #0 \ Set P = 0 STA P LDA BETA \ Set A = -beta, so: EOR #%10000000 \ \ (A P) = (-beta 0) \ = -beta * 256 JSR PIX1 \ Call PIX1 to calculate the following: \ \ (YY+1 y_lo) = (A P) + (S R) \ = -beta * 256 + y \ \ i.e. y = y - beta * 256, which is result 8 above \ \ PIX1 also draws a particle at (X1, Y1) with distance \ ZZ, which will remove the old stardust particle, as we \ set X1, Y1 and ZZ to the original values for this \ particle during the calculations above \ We now have our newly moved stardust particle at \ x-coordinate (XX+1 x_lo) and y-coordinate (YY+1 y_lo) \ and distance z_hi, so we draw it if it's still on \ screen, otherwise we recycle it as a new bit of \ stardust and draw that LDA XX+1 \ Set X1 and x_hi to the high byte of XX in XX+1, so STA X1 \ the new x-coordinate is in (x_hi x_lo) and the high STA SX,Y \ byte is in X1 AND #%01111111 \ If |x_hi| >= 120 then jump to KILL1 to recycle this CMP #120 \ particle, as it's gone off the side of the screen, BCS KILL1 \ and rejoin at STC1 with the new particle LDA YY+1 \ Set Y1 and y_hi to the high byte of YY in YY+1, so STA SY,Y \ the new x-coordinate is in (y_hi y_lo) and the high STA Y1 \ byte is in Y1 AND #%01111111 \ If |y_hi| >= 120 then jump to KILL1 to recycle this CMP #120 \ particle, as it's gone off the top or bottom of the BCS KILL1 \ screen, and rejoin at STC1 with the new particle LDA SZ,Y \ If z_hi < 16 then jump to KILL1 to recycle this CMP #16 \ particle, as it's so close that it's effectively gone BCC KILL1 \ past us, and rejoin at STC1 with the new particle STA ZZ \ Set ZZ to the z-coordinate in z_hi .STC1 JSR PIXEL2 \ Draw a stardust particle at (X1,Y1) with distance ZZ, \ i.e. draw the newly moved particle at (x_hi, y_hi) \ with distance z_hi DEY \ Decrement the loop counter to point to the next \ stardust particle BEQ P%+5 \ If we have just done the last particle, skip the next \ instruction to return from the subroutine JMP STL1 \ We have more stardust to process, so jump back up to \ STL1 for the next particle RTS \ Return from the subroutine .KILL1 \ Our particle of stardust just flew past us, so let's \ recycle that particle, starting it at a random \ position that isn't too close to the centre point JSR DORND \ Set A and X to random numbers ORA #4 \ Make sure A is at least 4 and store it in Y1 and y_hi, STA Y1 \ so the new particle starts at least 4 pixels above or STA SY,Y \ below the centre of the screen JSR DORND \ Set A and X to random numbers ORA #8 \ Make sure A is at least 8 and store it in X1 and x_hi, STA X1 \ so the new particle starts at least 8 pixels either STA SX,Y \ side of the centre of the screen JSR DORND \ Set A and X to random numbers ORA #144 \ Make sure A is at least 144 and store it in ZZ and STA SZ,Y \ z_hi so the new particle starts in the far distance STA ZZ LDA Y1 \ Set A to the new value of y_hi. This has no effect as \ STC1 starts with a jump to PIXEL2, which starts with a \ LDA instruction JMP STC1 \ Jump up to STC1 to draw this new particle \ ****************************************************************************** \ \ Name: STARS6 \ Type: Subroutine \ Category: Stardust \ Summary: Process the stardust for the rear view \ Deep dive: Stardust in the front view \ \ ------------------------------------------------------------------------------ \ \ This routine is very similar to STARS1, which processes stardust for the front \ view. The main difference is that the direction of travel is reversed, so the \ signs in the calculations are different, as well as the order of the first \ batch of calculations. \ \ When a stardust particle falls away into the far distance, it is removed from \ the screen and its memory is recycled as a new particle, positioned randomly \ along one of the four edges of the screen. \ \ These are the calculations referred to in the commentary: \ \ 1. q = 64 * speed / z_hi \ 2. z = z - speed * 64 \ 3. y = y + |y_hi| * q \ 4. x = x + |x_hi| * q \ \ 5. y = y + alpha * x / 256 \ 6. x = x - alpha * y / 256 \ \ 7. x = x + 2 * (beta * y / 256) ^ 2 \ 8. y = y - beta * 256 \ \ For more information see the associated deep dive. \ \ ****************************************************************************** .STARS6 LDY NOSTM \ Set Y to the current number of stardust particles, so \ we can use it as a counter through all the stardust .STL6 JSR DV42 \ Call DV42 to set the following: \ \ (P R) = 256 * DELTA / z_hi \ = 256 * speed / z_hi \ \ The maximum value returned is P = 2 and R = 128 (see \ DV42 for an explanation) LDA R \ Set A = R, so now: \ \ (P A) = 256 * speed / z_hi LSR P \ Rotate (P A) right by 2 places, which sets P = 0 (as P ROR A \ has a maximum value of 2) and leaves: LSR P \ ROR A \ A = 64 * speed / z_hi ORA #1 \ Make sure A is at least 1, and store it in Q, so we STA Q \ now have result 1 above: \ \ Q = 64 * speed / z_hi LDA SX,Y \ Set X1 = A = x_hi STA X1 \ \ So X1 contains the original value of x_hi, which we \ use below to remove the existing particle JSR MLU2 \ Set (A P) = |x_hi| * Q \ We now calculate: \ \ XX(1 0) = x - (A P) STA XX+1 \ First we do the low bytes: LDA SXL,Y \ SBC P \ XX(1 0) = x_lo - (A P) STA XX LDA X1 \ And then we do the high bytes: SBC XX+1 \ STA XX+1 \ XX(1 0) = (x_hi 0) - XX(1 0) \ \ so we get our result: \ \ XX(1 0) = x - (A P) \ = x - |x_hi| * Q \ \ which is result 2 above, and we also have: JSR MLU1 \ Call MLU1 to set: \ \ Y1 = y_hi \ \ (A P) = |y_hi| * Q \ \ So Y1 contains the original value of y_hi, which we \ use below to remove the existing particle \ We now calculate: \ \ (S R) = YY(1 0) = y - (A P) STA YY+1 \ First we do the low bytes with: LDA SYL,Y \ SBC P \ YY+1 = A STA YY \ R = YY = y_lo - P STA R \ \ so we get this: \ \ (? R) = YY(1 0) = y_lo - (A P) LDA Y1 \ And then we do the high bytes with: SBC YY+1 \ STA YY+1 \ S = YY+1 = y_hi - YY+1 STA S \ \ so we get our result: \ \ (S R) = YY(1 0) = (y_hi y_lo) - (A P) \ = y - |y_hi| * Q \ \ which is result 3 above, and (S R) is set to the new \ value of y LDA SZL,Y \ We now calculate the following: ADC DELT4 \ STA SZL,Y \ (z_hi z_lo) = (z_hi z_lo) + DELT4(1 0) \ \ starting with the low bytes LDA SZ,Y \ And then we do the high bytes STA ZZ \ ADC DELT4+1 \ We also set ZZ to the original value of z_hi, which we STA SZ,Y \ use below to remove the existing particle \ \ So now we have result 4 above: \ \ z = z + DELT4(1 0) \ = z + speed * 64 LDA XX+1 \ EOR x with the correct sign of the roll angle alpha, EOR ALP2 \ so A has the opposite sign to the roll angle alpha JSR MLS1 \ Call MLS1 to calculate: \ \ (A P) = A * ALP1 \ = (-x / 256) * alpha JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = (-x / 256) * alpha + y \ = y - alpha * x / 256 STA YY+1 \ Set YY(1 0) = (A X) to give: STX YY \ \ YY(1 0) = y - alpha * x / 256 \ \ which is result 5 above, and we also have: \ \ A = YY+1 = y - alpha * x / 256 \ \ i.e. A is the new value of y, divided by 256 EOR ALP2+1 \ EOR with the flipped sign of the roll angle alpha, so \ A has the opposite sign to the flipped roll angle \ alpha, i.e. it gets the same sign as alpha JSR MLS2 \ Call MLS2 to calculate: \ \ (S R) = XX(1 0) \ = x \ \ (A P) = A * ALP1 \ = y / 256 * alpha JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = y / 256 * alpha + x STA XX+1 \ Set XX(1 0) = (A X), which gives us result 6 above: STX XX \ \ x = x + alpha * y / 256 LDA YY+1 \ Set A to y_hi and set it to the flipped sign of beta EOR BET2+1 LDX BET1 \ Fetch the pitch magnitude into X JSR MULTS-2 \ Call MULTS-2 to calculate: \ \ (A P) = X * A \ = beta * y_hi STA Q \ Store the high byte of the result in Q, so: \ \ Q = beta * y_hi / 256 LDA XX+1 \ Set S = x_hi STA S EOR #%10000000 \ Flip the sign of A, so A now contains -x JSR MUT1 \ Call MUT1 to calculate: \ \ R = XX = x_lo \ \ (A P) = Q * A \ = (beta * y_hi / 256) * (-beta * y_hi / 256) \ = (-beta * y / 256) ^ 2 ASL P \ Double (A P), store the top byte in A and set the C ROL A \ flag to bit 7 of the original A, so this does: STA T \ \ (T P) = (A P) << 1 \ = 2 * (-beta * y / 256) ^ 2 LDA #0 \ Set bit 7 in A to the sign bit from the A in the ROR A \ calculation above and apply it to T, so we now have: ORA T \ \ (A P) = -2 * (beta * y / 256) ^ 2 \ \ with the doubling retaining the sign of (A P) JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = -2 * (beta * y / 256) ^ 2 + x STA XX+1 \ Store the high byte A in XX+1 TXA \ Store the low byte X in x_lo STA SXL,Y \ So (XX+1 x_lo) now contains: \ \ x = x - 2 * (beta * y / 256) ^ 2 \ \ which is result 7 above LDA YY \ Set (S R) = YY(1 0) = y STA R LDA YY+1 STA S \EOR #128 \ These instructions are commented out in the original \JSR MAD \ source \STA S \STX R LDA #0 \ Set P = 0 STA P LDA BETA \ Set A = beta, so (A P) = (beta 0) = beta * 256 JSR PIX1 \ Call PIX1 to calculate the following: \ \ (YY+1 y_lo) = (A P) + (S R) \ = beta * 256 + y \ \ i.e. y = y + beta * 256, which is result 8 above \ \ PIX1 also draws a particle at (X1, Y1) with distance \ ZZ, which will remove the old stardust particle, as we \ set X1, Y1 and ZZ to the original values for this \ particle during the calculations above \ We now have our newly moved stardust particle at \ x-coordinate (XX+1 x_lo) and y-coordinate (YY+1 y_lo) \ and distance z_hi, so we draw it if it's still on \ screen, otherwise we recycle it as a new bit of \ stardust and draw that LDA XX+1 \ Set X1 and x_hi to the high byte of XX in XX+1, so STA X1 \ the new x-coordinate is in (x_hi x_lo) and the high STA SX,Y \ byte is in X1 LDA YY+1 \ Set Y1 and y_hi to the high byte of YY in YY+1, so STA SY,Y \ the new x-coordinate is in (y_hi y_lo) and the high STA Y1 \ byte is in Y1 AND #%01111111 \ If |y_hi| >= 110 then jump to KILL6 to recycle this CMP #110 \ particle, as it's gone off the top or bottom of the BCS KILL6 \ screen, and rejoin at STC6 with the new particle LDA SZ,Y \ If z_hi >= 160 then jump to KILL6 to recycle this CMP #160 \ particle, as it's so far away that it's too far to BCS KILL6 \ see, and rejoin at STC1 with the new particle STA ZZ \ Set ZZ to the z-coordinate in z_hi .STC6 JSR PIXEL2 \ Draw a stardust particle at (X1,Y1) with distance ZZ, \ i.e. draw the newly moved particle at (x_hi, y_hi) \ with distance z_hi DEY \ Decrement the loop counter to point to the next \ stardust particle BEQ ST3 \ If we have just done the last particle, skip the next \ instruction to return from the subroutine JMP STL6 \ We have more stardust to process, so jump back up to \ STL6 for the next particle .ST3 RTS \ Return from the subroutine .KILL6 JSR DORND \ Set A and X to random numbers AND #%01111111 \ Clear the sign bit of A to get |A| ADC #10 \ Make sure A is at least 10 and store it in z_hi and STA SZ,Y \ ZZ, so the new particle starts close to us STA ZZ LSR A \ Divide A by 2 and randomly set the C flag BCS ST4 \ Jump to ST4 half the time LSR A \ Randomly set the C flag again LDA #252 \ Set A to either +126 or -126 (252 >> 1) depending on ROR A \ the C flag, as this is a sign-magnitude number with \ the C flag rotated into its sign bit STA X1 \ Set x_hi and X1 to A, so this particle starts on STA SX,Y \ either the left or right edge of the screen JSR DORND \ Set A and X to random numbers STA Y1 \ Set y_hi and Y1 to random numbers, so the particle STA SY,Y \ starts anywhere along either the left or right edge JMP STC6 \ Jump up to STC6 to draw this new particle .ST4 JSR DORND \ Set A and X to random numbers STA X1 \ Set x_hi and X1 to random numbers, so the particle STA SX,Y \ starts anywhere along the x-axis LSR A \ Randomly set the C flag LDA #230 \ Set A to either +115 or -115 (230 >> 1) depending on ROR A \ the C flag, as this is a sign-magnitude number with \ the C flag rotated into its sign bit STA Y1 \ Set y_hi and Y1 to A, so the particle starts anywhere STA SY,Y \ along either the top or bottom edge of the screen BNE STC6 \ Jump up to STC6 to draw this new particle (this BNE is \ effectively a JMP as A will never be zero) \ ****************************************************************************** \ \ Name: PRXS \ Type: Variable \ Category: Equipment \ Summary: Equipment prices \ \ ------------------------------------------------------------------------------ \ \ Equipment prices are stored as 10 * the actual value, so we can support prices \ with fractions of credits (0.1 Cr). This is used for the price of fuel only. \ \ ****************************************************************************** .PRXS EQUW 1 \ 0 Fuel, calculated in EQSHP 140.0 Cr (full tank) EQUW 300 \ 1 Missile 30.0 Cr EQUW 4000 \ 2 Large Cargo Bay 400.0 Cr EQUW 6000 \ 3 E.C.M. System 600.0 Cr EQUW 4000 \ 4 Extra Pulse Lasers 400.0 Cr EQUW 10000 \ 5 Extra Beam Lasers 1000.0 Cr EQUW 5250 \ 6 Fuel Scoops 525.0 Cr EQUW 10000 \ 7 Escape Pod 1000.0 Cr EQUW 9000 \ 8 Energy Bomb 900.0 Cr EQUW 15000 \ 9 Energy Unit 1500.0 Cr EQUW 10000 \ 10 Docking Computer 1000.0 Cr EQUW 50000 \ 11 Galactic Hyperspace 5000.0 Cr \ ****************************************************************************** \ \ Name: STATUS \ Type: Subroutine \ Category: Status \ Summary: Show the Status Mode screen (red key f8) \ Deep dive: Combat rank \ \ ****************************************************************************** .st4 \ We call this from st5 below with the high byte of the \ kill tally in A, which is non-zero, and want to return \ with the following in X, depending on our rating: \ \ Competent = 6 \ Dangerous = 7 \ Deadly = 8 \ Elite = 9 \ \ The high bytes of the top tier ratings are as follows, \ so this a relatively simple calculation: \ \ Competent = 1 \ Dangerous = 2 to 9 \ Deadly = 10 to 24 \ Elite = 25 and up LDX #9 \ Set X to 9 for an Elite rating CMP #25 \ If A >= 25, jump to st3 to print out our rating, as we BCS st3 \ are Elite DEX \ Decrement X to 8 for a Deadly rating CMP #10 \ If A >= 10, jump to st3 to print out our rating, as we BCS st3 \ are Deadly DEX \ Decrement X to 7 for a Dangerous rating CMP #2 \ If A >= 2, jump to st3 to print out our rating, as we BCS st3 \ are Dangerous DEX \ Decrement X to 6 for a Competent rating BNE st3 \ Jump to st3 to print out our rating, as we are \ Competent (this BNE is effectively a JMP as A will \ never be zero) .STATUS LDA #8 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 8 (Status \ Mode screen) JSR TT111 \ Select the system closest to galactic coordinates \ (QQ9, QQ10) LDA #7 \ Move the text cursor to column 7 STA XC LDA #126 \ Print recursive token 126, which prints the top JSR NLIN3 \ four lines of the Status Mode screen: \ \ COMMANDER {commander name} \ \ \ Present System : {current system name} \ Hyperspace System : {selected system name} \ Condition : \ \ and draw a horizontal line at pixel row 19 to box \ in the title LDA #15 \ Set A to token 129 ("{sentence case}DOCKED") LDY QQ12 \ Fetch the docked status from QQ12, and if we are BNE st6 \ docked, jump to st6 to print "Docked" for our \ ship's condition LDA #230 \ Otherwise we are in space, so start off by setting A \ to token 70 ("GREEN") LDY MANY+AST \ Set Y to the number of asteroids in our local bubble \ of universe LDX FRIN+2,Y \ The ship slots at FRIN are ordered with the first two \ slots reserved for the planet and sun/space station, \ and then any ships, so if the slot at FRIN+2+Y is not \ empty (i.e. is non-zero), then that means the number \ of non-asteroids in the vicinity is at least 1 BEQ st6 \ So if X = 0, there are no ships in the vicinity, so \ jump to st6 to print "Green" for our ship's condition LDY ENERGY \ Otherwise we have ships in the vicinity, so we load \ our energy levels into Y CPY #128 \ Set the C flag if Y >= 128, so C is set if we have \ more than half of our energy banks charged ADC #1 \ Add 1 + C to A, so if C is not set (i.e. we have low \ energy levels) then A is set to token 231 ("RED"), \ and if C is set (i.e. we have healthy energy levels) \ then A is set to token 232 ("YELLOW") .st6 JSR plf \ Print the text token in A (which contains our ship's \ condition) followed by a newline LDA #125 \ Print recursive token 125, which prints the next JSR spc \ three lines of the Status Mode screen: \ \ Fuel: {fuel level} Light Years \ Cash: {cash} Cr \ Legal Status: \ \ followed by a space LDA #19 \ Set A to token 133 ("CLEAN") LDY FIST \ Fetch our legal status, and if it is 0, we are clean, BEQ st5 \ so jump to st5 to print "Clean" CPY #50 \ Set the C flag if Y >= 50, so C is set if we have \ a legal status of 50+ (i.e. we are a fugitive) ADC #1 \ Add 1 + C to A, so if C is not set (i.e. we have a \ legal status between 1 and 49) then A is set to token \ 134 ("OFFENDER"), and if C is set (i.e. we have a \ legal status of 50+) then A is set to token 135 \ ("FUGITIVE") .st5 JSR plf \ Print the text token in A (which contains our legal \ status) followed by a newline LDA #16 \ Print recursive token 130 ("RATING:") followed by a JSR spc \ space LDA TALLY+1 \ Fetch the high byte of the kill tally, and if it is BNE st4 \ not zero, then we have more than 256 kill points, so \ jump to st4 to work out whether we are Competent, \ Dangerous, Deadly or Elite \ Otherwise we have fewer than 256 kill pointss, so we \ are one of Harmless, Mostly Harmless, Poor, Average, \ Above Average or Competent TAX \ Set X to 0 (as A is 0) LDA TALLY \ Set A to the lower byte of tally, with bits 0 and 1 LSR A \ shifted off to the right, so we can now analyse bits LSR A \ 2 to 7 by shifting A to the right one bit at a time .st5L \ We now loop through bits 2 to 7, shifting each of them \ off the end of A until there are no set bits left, and \ incrementing X before each shift, so at the end of the \ process, X contains the position of the leftmost 1 in \ A. Looking at the rank values in TALLY: \ \ Harmless = %00000000 to %00000111 \ Mostly Harmless = %00001000 to %00001111 \ Poor = %00010000 to %00011111 \ Average = %00100000 to %00111111 \ Above Average = %01000000 to %01111111 \ Competent = %10000000 to %11111111 \ \ we can see that the values returned by this process \ are: \ \ Harmless = 1 \ Mostly Harmless = 2 \ Poor = 3 \ Average = 4 \ Above Average = 5 \ Competent = 6 INX \ Increment X to count the number of shifts LSR A \ Shift A to the right BNE st5L \ Keep looping around until A = 0, which means there are \ no set bits left in A .st3 TXA \ A now contains our rating as a value of 1 to 9, so \ transfer X to A, so we can print it out CLC \ Print recursive token 135 + A, which will be in the ADC #21 \ range 136 ("HARMLESS") to 144 ("---- E L I T E ----") JSR plf \ followed by a newline LDA #18 \ Print recursive token 132, which prints the next bit JSR plf2 \ of the Status Mode screen: \ \ EQUIPMENT: \ \ followed by a newline and an indent of 6 characters LDA CRGO \ If our ship's cargo capacity is < 26 (i.e. we do not CMP #26 \ have a cargo bay extension), skip the following two BCC P%+7 \ instructions LDA #107 \ We do have a cargo bay extension, so print recursive JSR plf2 \ token 107 ("LARGE CARGO{sentence case} BAY"), followed \ by a newline and an indent of 6 characters LDA BST \ If we don't have fuel scoops fitted, skip the BEQ P%+7 \ following two instructions LDA #111 \ We do have fuel scoops fitted, so print recursive JSR plf2 \ token 111 ("FUEL SCOOPS"), followed by a newline and \ an indent of 6 characters LDA ECM \ If we don't have an E.C.M. fitted, skip the following BEQ P%+7 \ two instructions LDA #108 \ We do have an E.C.M. fitted, so print recursive token JSR plf2 \ 108 ("E.C.M.SYSTEM"), followed by a newline and an \ indent of 6 characters LDA #113 \ We now cover the four pieces of equipment whose flags STA XX4 \ are stored in BOMB through BOMB+3, and whose names \ correspond with text tokens 113 through 116: \ \ BOMB+0 = BOMB = token 113 = Energy bomb \ BOMB+1 = ENGY = token 114 = Energy unit \ BOMB+2 = DKCMP = token 115 = Docking computer \ BOMB+3 = GHYP = token 116 = Galactic hyperdrive \ \ We can print these out using a loop, so we set XX4 to \ 113 as a counter (and we also set A as well, to pass \ through to plf2) .stqv TAY \ Fetch byte BOMB+0 through BOMB+4 for values of XX4 LDX BOMB-113,Y \ from 113 through 117 BEQ P%+5 \ If it is zero then we do not own that piece of \ equipment, so skip the next instruction JSR plf2 \ Print the recursive token in A from 113 ("ENERGY \ BOMB") through 116 ("GALACTIC HYPERSPACE "), followed \ by a newline and an indent of 6 characters INC XX4 \ Increment the counter (and A as well) LDA XX4 CMP #117 \ If A < 117, loop back up to stqv to print the next BCC stqv \ piece of equipment LDX #0 \ Now to print our ship's lasers, so set a counter in X \ to count through the four views (0 = front, 1 = rear, \ 2 = left, 3 = right) .st STX CNT \ Store the view number in CNT LDY LASER,X \ Fetch the laser power for view X, and if we do not BEQ st1 \ have a laser fitted to that view, jump to st1 to move \ on to the next one TXA \ Print recursive token 96 + X, which will print from 96 CLC \ ("FRONT") through to 99 ("RIGHT"), followed by a space ADC #96 JSR spc LDA #103 \ Set A to token 103 ("PULSE LASER") LDX CNT \ If the laser power for view X has bit 7 clear, then it LDY LASER,X \ is a pulse laser, so skip the following instruction BPL P%+4 LDA #104 \ Set A to token 104 ("BEAM LASER") JSR plf2 \ Print the text token in A (which contains the laser \ type) followed by a newline and an indent of 6 \ characters .st1 LDX CNT \ Increment the counter in X and CNT to point to the INX \ next view CPX #4 \ If this isn't the last of the four views, jump back up BCC st \ to st to print out the next one RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: plf2 \ Type: Subroutine \ Category: Text \ Summary: Print text followed by a newline and indent of 6 characters \ \ ------------------------------------------------------------------------------ \ \ Print a text token followed by a newline, and indent the next line to text \ column 6. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ ****************************************************************************** .plf2 JSR plf \ Print the text token in A followed by a newline LDX #6 \ Move the text cursor to column 6 STX XC RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TENS \ Type: Variable \ Category: Text \ Summary: A constant used when printing large numbers in BPRNT \ Deep dive: Printing decimal numbers \ \ ------------------------------------------------------------------------------ \ \ Contains the four low bytes of the value 100,000,000,000 (100 billion). \ \ The maximum number of digits that we can print with the BPRNT routine is 11, \ so the biggest number we can print is 99,999,999,999. This maximum number \ plus 1 is 100,000,000,000, which in hexadecimal is: \ \ 17 48 76 E8 00 \ \ The TENS variable contains the lowest four bytes in this number, with the \ most significant byte first, i.e. 48 76 E8 00. This value is used in the \ BPRNT routine when working out which decimal digits to print when printing a \ number. \ \ ****************************************************************************** .TENS EQUD &00E87648 \ ****************************************************************************** \ \ Name: pr2 \ Type: Subroutine \ Category: Text \ Summary: Print an 8-bit number, left-padded to 3 digits, and optional point \ \ ------------------------------------------------------------------------------ \ \ Print the 8-bit number in X to 3 digits, left-padding with spaces for numbers \ with fewer than 3 digits (so numbers < 100 are right-aligned). Optionally \ include a decimal point. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The number to print \ \ C flag If set, include a decimal point \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ pr2+2 Print the 8-bit number in X to the number of digits in A \ \ ****************************************************************************** .pr2 LDA #3 \ Set A to the number of digits (3) LDY #0 \ Zero the Y register, so we can fall through into TT11 \ to print the 16-bit number (Y X) to 3 digits, which \ effectively prints X to 3 digits as the high byte is \ zero \ ****************************************************************************** \ \ Name: TT11 \ Type: Subroutine \ Category: Text \ Summary: Print a 16-bit number, left-padded to n digits, and optional point \ \ ------------------------------------------------------------------------------ \ \ Print the 16-bit number in (Y X) to a specific number of digits, left-padding \ with spaces for numbers with fewer digits (so lower numbers will be right- \ aligned). Optionally include a decimal point. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The low byte of the number to print \ \ Y The high byte of the number to print \ \ A The number of digits \ \ C flag If set, include a decimal point \ \ ****************************************************************************** .TT11 STA U \ We are going to use the BPRNT routine (below) to \ print this number, so we store the number of digits \ in U, as that's what BPRNT takes as an argument LDA #0 \ BPRNT takes a 32-bit number in K to K+3, with the STA K \ most significant byte first (big-endian), so we set STA K+1 \ the two most significant bytes to zero (K and K+1) STY K+2 \ and store (Y X) in the least two significant bytes STX K+3 \ (K+2 and K+3), so we are going to print the 32-bit \ number (0 0 Y X) \ Finally we fall through into BPRNT to print out the \ number in K to K+3, which now contains (Y X), to A \ digits (as U = A), using the same C flag as when pr2 \ was called to control the decimal point \ ****************************************************************************** \ \ Name: BPRNT \ Type: Subroutine \ Category: Text \ Summary: Print a 32-bit number, left-padded to a specific number of digits, \ with an optional decimal point \ Deep dive: Printing decimal numbers \ \ ------------------------------------------------------------------------------ \ \ Print the 32-bit number stored in K(0 1 2 3) to a specific number of digits, \ left-padding with spaces for numbers with fewer digits (so lower numbers are \ right-aligned). Optionally include a decimal point. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K(0 1 2 3) The number to print, stored with the most significant \ byte in K and the least significant in K+3 (i.e. as a \ big-endian number, which is the opposite way to how the \ 6502 assembler stores addresses, for example) \ \ U The maximum number of digits to print, including the \ decimal point (spaces will be used on the left to pad \ out the result to this width, so the number is right- \ aligned to this width). U must be 11 or less \ \ C flag If set, include a decimal point followed by one \ fractional digit (i.e. show the number to 1 decimal \ place). In this case, the number in K(0 1 2 3) contains \ 10 * the number we end up printing, so to print 123.4, \ we would pass 1234 in K(0 1 2 3) and would set the C \ flag to include the decimal point \ \ ****************************************************************************** .BPRNT LDX #11 \ Set T to the maximum number of digits allowed (11 STX T \ characters, which is the number of digits in 10 \ billion). We will use this as a flag when printing \ characters in TT37 below PHP \ Make a copy of the status register (in particular \ the C flag) so we can retrieve it later BCC TT30 \ If the C flag is clear, we do not want to print a \ decimal point, so skip the next two instructions DEC T \ As we are going to show a decimal point, decrement DEC U \ both the number of characters and the number of \ digits (as one of them is now a decimal point) .TT30 LDA #11 \ Set A to 11, the maximum number of digits allowed SEC \ Set the C flag so we can do subtraction without the \ C flag affecting the result STA XX17 \ Store the maximum number of digits allowed (11) in \ XX17 SBC U \ Set U = 11 - U + 1, so U now contains the maximum STA U \ number of digits minus the number of digits we want INC U \ to display, plus 1 (so this is the number of digits \ we should skip before starting to print the number \ itself, and the plus 1 is there to ensure we print at \ least one digit) LDY #0 \ In the main loop below, we use Y to count the number \ of times we subtract 10 billion to get the leftmost \ digit, so set this to zero STY S \ In the main loop below, we use location S as an \ 8-bit overflow for the 32-bit calculations, so \ we need to set this to 0 before joining the loop JMP TT36 \ Jump to TT36 to start the process of printing this \ number's digits .TT35 \ This subroutine multiplies K(S 0 1 2 3) by 10 and \ stores the result back in K(S 0 1 2 3), using the fact \ that K * 10 = (K * 2) + (K * 2 * 2 * 2) ASL K+3 \ Set K(S 0 1 2 3) = K(S 0 1 2 3) * 2 by rotating left ROL K+2 ROL K+1 ROL K ROL S LDX #3 \ Now we want to make a copy of the newly doubled K in \ XX15, so we can use it for the first (K * 2) in the \ equation above, so set up a counter in X for copying \ four bytes, starting with the last byte in memory \ (i.e. the least significant) .tt35 LDA K,X \ Copy the X-th byte of K(0 1 2 3) to the X-th byte of STA XX15,X \ XX15(0 1 2 3), so that XX15 will contain a copy of \ K(0 1 2 3) once we've copied all four bytes DEX \ Decrement the loop counter BPL tt35 \ Loop back to copy the next byte until we have copied \ all four LDA S \ Store the value of location S, our overflow byte, in STA XX15+4 \ XX15+4, so now XX15(4 0 1 2 3) contains a copy of \ K(S 0 1 2 3), which is the value of (K * 2) that we \ want to use in our calculation ASL K+3 \ Now to calculate the (K * 2 * 2 * 2) part. We still ROL K+2 \ have (K * 2) in K(S 0 1 2 3), so we just need to shift ROL K+1 \ it twice. This is the first one, so we do this: ROL K \ ROL S \ K(S 0 1 2 3) = K(S 0 1 2 3) * 2 = K * 4 ASL K+3 \ And then we do it again, so that means: ROL K+2 \ ROL K+1 \ K(S 0 1 2 3) = K(S 0 1 2 3) * 2 = K * 8 ROL K ROL S CLC \ Clear the C flag so we can do addition without the \ C flag affecting the result LDX #3 \ By now we've got (K * 2) in XX15(4 0 1 2 3) and \ (K * 8) in K(S 0 1 2 3), so the final step is to add \ these two 32-bit numbers together to get K * 10. \ So we set a counter in X for four bytes, starting \ with the last byte in memory (i.e. the least \ significant) .tt36 LDA K,X \ Fetch the X-th byte of K into A ADC XX15,X \ Add the X-th byte of XX15 to A, with carry STA K,X \ Store the result in the X-th byte of K DEX \ Decrement the loop counter BPL tt36 \ Loop back to add the next byte, moving from the least \ significant byte to the most significant, until we \ have added all four LDA XX15+4 \ Finally, fetch the overflow byte from XX15(4 0 1 2 3) ADC S \ And add it to the overflow byte from K(S 0 1 2 3), \ with carry STA S \ And store the result in the overflow byte from \ K(S 0 1 2 3), so now we have our desired result, i.e. \ \ K(S 0 1 2 3) = K(S 0 1 2 3) * 10 LDY #0 \ In the main loop below, we use Y to count the number \ of times we subtract 10 billion to get the leftmost \ digit, so set this to zero so we can rejoin the main \ loop for another subtraction process .TT36 \ This is the main loop of our digit-printing routine. \ In the following loop, we are going to count the \ number of times that we can subtract 10 million and \ store that count in Y, which we have already set to 0 LDX #3 \ Our first calculation concerns 32-bit numbers, so \ set up a counter for a four-byte loop SEC \ Set the C flag so we can do subtraction without the \ C flag affecting the result .tt37 \ We now loop through each byte in turn to do this: \ \ XX15(4 0 1 2 3) = K(S 0 1 2 3) - 100,000,000,000 LDA K,X \ Subtract the X-th byte of TENS (i.e. 10 billion) from SBC TENS,X \ the X-th byte of K STA XX15,X \ Store the result in the X-th byte of XX15 DEX \ Decrement the loop counter BPL tt37 \ Loop back to subtract the next byte, moving from the \ least significant byte to the most significant, until \ we have subtracted all four LDA S \ Subtract the fifth byte of 10 billion (i.e. &17) from SBC #&17 \ the fifth (overflow) byte of K, which is S STA XX15+4 \ Store the result in the overflow byte of XX15 BCC TT37 \ If subtracting 10 billion took us below zero, jump to \ TT37 to print out this digit, which is now in Y LDX #3 \ We now want to copy XX15(4 0 1 2 3) back into \ K(S 0 1 2 3), so we can loop back up to do the next \ subtraction, so set up a counter for a four-byte loop .tt38 LDA XX15,X \ Copy the X-th byte of XX15(0 1 2 3) to the X-th byte STA K,X \ of K(0 1 2 3), so that K(0 1 2 3) will contain a copy \ of XX15(0 1 2 3) once we've copied all four bytes DEX \ Decrement the loop counter BPL tt38 \ Loop back to copy the next byte, until we have copied \ all four LDA XX15+4 \ Store the value of location XX15+4, our overflow STA S \ byte in S, so now K(S 0 1 2 3) contains a copy of \ XX15(4 0 1 2 3) INY \ We have now managed to subtract 10 billion from our \ number, so increment Y, which is where we are keeping \ a count of the number of subtractions so far JMP TT36 \ Jump back to TT36 to subtract the next 10 billion .TT37 TYA \ If we get here then Y contains the digit that we want \ to print (as Y has now counted the total number of \ subtractions of 10 billion), so transfer Y into A BNE TT32 \ If the digit is non-zero, jump to TT32 to print it LDA T \ Otherwise the digit is zero. If we are already \ printing the number then we will want to print a 0, \ but if we haven't started printing the number yet, \ then we probably don't, as we don't want to print \ leading zeroes unless this is the only digit before \ the decimal point \ \ To help with this, we are going to use T as a flag \ that tells us whether we have already started \ printing digits: \ \ * If T <> 0 we haven't printed anything yet \ \ * If T = 0 then we have started printing digits \ \ We initially set T above to the maximum number of \ characters allowed, less 1 if we are printing a \ decimal point, so the first time we enter the digit \ printing routine at TT37, it is definitely non-zero BEQ TT32 \ If T = 0, jump straight to the print routine at TT32, \ as we have already started printing the number, so we \ definitely want to print this digit too DEC U \ We initially set U to the number of digits we want to BPL TT34 \ skip before starting to print the number. If we get \ here then we haven't printed any digits yet, so \ decrement U to see if we have reached the point where \ we should start printing the number, and if not, jump \ to TT34 to set up things for the next digit LDA #' ' \ We haven't started printing any digits yet, but we BNE tt34 \ have reached the point where we should start printing \ our number, so call TT26 (via tt34) to print a space \ so that the number is left-padded with spaces (this \ BNE is effectively a JMP as A will never be zero) .TT32 LDY #0 \ We are printing an actual digit, so first set T to 0, STY T \ to denote that we have now started printing digits as \ opposed to spaces CLC \ The digit value is in A, so add ASCII "0" to get the ADC #'0' \ ASCII character number to print .tt34 JSR TT26 \ Call TT26 to print the character in A and fall through \ into TT34 to get things ready for the next digit .TT34 DEC T \ Decrement T but keep T >= 0 (by incrementing it BPL P%+4 \ again if the above decrement made T negative) INC T DEC XX17 \ Decrement the total number of characters left to \ print, which we stored in XX17 BMI RR3+1 \ If the result is negative, we have printed all the \ characters, so return from the subroutine (as RR3 \ contains an ORA #&60 instruction, so RR3+1 is &60, \ which is the opcode for an RTS) BNE P%+10 \ If the result is positive (> 0) then we still have \ characters left to print, so loop back to TT35 (via \ the JMP TT35 instruction below) to print the next \ digit PLP \ If we get here then we have printed the exact number \ of digits that we wanted to, so restore the C flag \ that we stored at the start of the routine BCC P%+7 \ If the C flag is clear, we don't want a decimal point, \ so loop back to TT35 (via the JMP TT35 instruction \ below) to print the next digit LDA #'.' \ Otherwise the C flag is set, so print the decimal JSR TT26 \ point JMP TT35 \ Loop back to TT35 to print the next digit \ ****************************************************************************** \ \ Name: BELL \ Type: Subroutine \ Category: Sound \ Summary: Make a standard system beep \ \ ------------------------------------------------------------------------------ \ \ This is the standard system beep, as made by the ASCII 7 "BELL" control code. \ \ ****************************************************************************** .BELL LDA #7 \ Control code 7 makes a beep, so load this into A \ Fall through into the TT26 print routine to \ actually make the sound \ ****************************************************************************** \ \ Name: TT26 \ Type: Subroutine \ Category: Text \ Summary: Print a character at the text cursor by poking into screen memory \ Deep dive: Drawing text \ \ ------------------------------------------------------------------------------ \ \ Print a character at the text cursor (XC, YC), do a beep, print a newline, \ or delete left (backspace). \ \ WRCHV is set to point here by the loading process. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The character to be printed. Can be one of the \ following: \ \ * 7 (beep) \ \ * 10-13 (line feeds and carriage returns) \ \ * 32-95 (ASCII capital letters, numbers and \ punctuation) \ \ * 127 (delete the character to the left of the text \ cursor and move the cursor to the left) \ \ XC Contains the text column to print at (the x-coordinate) \ \ YC Contains the line number to print on (the y-coordinate) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A is preserved \ \ X X is preserved \ \ Y Y is preserved \ \ C flag The C flag is cleared \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ RR3+1 Contains an RTS \ \ RREN Prints the character definition pointed to by P(2 1) at \ the screen address pointed to by (A SC). Used by the \ BULB routine \ \ rT9 Contains an RTS \ \ ****************************************************************************** .TT26 STA K3 \ Store the A, X and Y registers, so we can restore STY YSAV2 \ them at the end (so they don't get changed by this STX XSAV2 \ routine) LDY QQ17 \ Load the QQ17 flag, which contains the text printing \ flags CPY #255 \ If QQ17 = 255 then printing is disabled, so jump to BEQ RR4 \ RR4, which doesn't print anything, it just restores \ the registers and returns from the subroutine CMP #7 \ If this is a beep character (A = 7), jump to R5, BEQ R5 \ which will emit the beep, restore the registers and \ return from the subroutine CMP #32 \ If this is an ASCII character (A >= 32), jump to RR1 BCS RR1 \ below, which will print the character, restore the \ registers and return from the subroutine CMP #10 \ If this is control code 10 (line feed) then jump to BEQ RRX1 \ RRX1, which will move down a line, restore the \ registers and return from the subroutine LDX #1 \ If we get here, then this is control code 11-13, of STX XC \ which only 13 is used. This code prints a newline, \ which we can achieve by moving the text cursor \ to the start of the line (carriage return) and down \ one line (line feed). These two lines do the first \ bit by setting XC = 1, and we then fall through into \ the line feed routine that's used by control code 10 .RRX1 INC YC \ Print a line feed, simply by incrementing the row \ number (y-coordinate) of the text cursor, which is \ stored in YC BNE RR4 \ Jump to RR4 to restore the registers and return from \ the subroutine (this BNE is effectively a JMP as Y \ will never be zero) .RR1 \ If we get here, then the character to print is an \ ASCII character in the range 32-95. The quickest way \ to display text on-screen is to poke the character \ pixel by pixel, directly into screen memory, so \ that's what the rest of this routine does \ \ The first step, then, is to get hold of the bitmap \ definition for the character we want to draw on the \ screen (i.e. we need the pixel shape of this \ character). The MOS ROM contains bitmap definitions \ of the system's ASCII characters, starting from &C000 \ for space (ASCII 32) and ending with the £ symbol \ (ASCII 126) \ \ There are definitions for 32 characters in each of the \ three pages of MOS memory, as each definition takes up \ 8 bytes (8 rows of 8 pixels) and 32 * 8 = 256 bytes = \ 1 page. So: \ \ ASCII 32-63 are defined in &C000-&C0FF (page 0) \ ASCII 64-95 are defined in &C100-&C1FF (page 1) \ ASCII 96-126 are defined in &C200-&C2F0 (page 2) \ \ The following code reads the relevant character \ bitmap from the above locations in ROM and pokes \ those values into the correct position in screen \ memory, thus printing the character on-screen \ \ It's a long way from 10 PRINT "Hello world!":GOTO 10 \LDX #LO(K3) \ These instructions are commented out in the original \INX \ source, but they call OSWORD 10, which reads the \STX P+1 \ character bitmap for the character number in K3 and \DEX \ stores it in the block at K3+1, while also setting \ \ P+1 to point to the character definition. This is \LDY #HI(K3) \ exactly what the following uncommented code does, \STY P+2 \ just without calling OSWORD. Presumably the code \ \ below is faster than using the system call, as this \LDA #10 \ version takes up 15 bytes, while the version below \JSR OSWORD \ (which ends with STA P+1 and SYX P+2) is 17 bytes. \ Every efficiency saving helps, especially as this \ routine is run each time the game prints a character \ \ If you want to switch this code back on, uncomment \ the above block, and comment out the code below from \ TAY to STX P+2. You will also need to uncomment the \ LDA YC instruction a few lines down (in RR2), just to \ make sure the rest of the code doesn't shift in \ memory. To be honest I can't see a massive difference \ in speed, but there you go TAY \ Copy the character number from A to Y, as we are \ about to pull A apart to work out where this \ character definition lives in memory \ Now we want to set X to point to the relevant page \ number for this character - i.e. &C0, &C1 or &C2. \ The following logic is easier to follow if we look \ at the three character number ranges in binary: \ \ Bit # 76543210 \ \ 32 = %00100000 Page 0 of bitmap definitions \ 63 = %00111111 \ \ 64 = %01000000 Page 1 of bitmap definitions \ 95 = %01011111 \ \ 96 = %01100000 Page 2 of bitmap definitions \ 125 = %01111101 \ \ We'll refer to this below LDX #&BF \ Set X to point to the first font page in ROM minus 1, \ which is &C0 - 1, or &BF ASL A \ If bit 6 of the character is clear (A is 32-63) ASL A \ then skip the following instruction BCC P%+4 LDX #&C1 \ A is 64-126, so set X to point to page &C1 ASL A \ If bit 5 of the character is clear (A is 64-95) BCC P%+3 \ then skip the following instruction INX \ Increment X \ \ By this point, we started with X = &BF, and then \ we did the following: \ \ If A = 32-63: skip then INX so X = &C0 \ If A = 64-95: X = &C1 then skip so X = &C1 \ If A = 96-126: X = &C1 then INX so X = &C2 \ \ In other words, X points to the relevant page. But \ what about the value of A? That gets shifted to the \ left three times during the above code, which \ multiplies the number by 8 but also drops bits 7, 6 \ and 5 in the process. Look at the above binary \ figures and you can see that if we cleared bits 5-7, \ then that would change 32-53 to 0-31... but it would \ do exactly the same to 64-95 and 96-125. And because \ we also multiply this figure by 8, A now points to \ the start of the character's definition within its \ page (because there are 8 bytes per character \ definition) \ \ Or, to put it another way, X contains the high byte \ (the page) of the address of the definition that we \ want, while A contains the low byte (the offset into \ the page) of the address STA P+1 \ Store the address of this character's definition in STX P+2 \ P(2 1) LDA XC \ Fetch XC, the x-coordinate (column) of the text cursor \ into A ASL A \ Multiply A by 8, and store in SC. As each character is ASL A \ 8 pixels wide, and the special screen mode Elite uses ASL A \ for the top part of the screen is 256 pixels across STA SC \ with one bit per pixel, this value is not only the \ screen address offset of the text cursor from the left \ side of the screen, it's also the least significant \ byte of the screen address where we want to print this \ character, as each row of on-screen pixels corresponds \ to one page. To put this more explicitly, the screen \ starts at &6000, so the text rows are stored in screen \ memory like this: \ \ Row 1: &6000 - &60FF YC = 1, XC = 0 to 31 \ Row 2: &6100 - &61FF YC = 2, XC = 0 to 31 \ Row 3: &6200 - &62FF YC = 3, XC = 0 to 31 \ \ and so on LDA YC \ Fetch YC, the y-coordinate (row) of the text cursor CPY #127 \ If the character number (which is in Y) <> 127, then BNE RR2 \ skip to RR2 to print that character, otherwise this is \ the delete character, so continue on DEC XC \ We want to delete the character to the left of the \ text cursor and move the cursor back one, so let's \ do that by decrementing YC. Note that this doesn't \ have anything to do with the actual deletion below, \ we're just updating the cursor so it's in the right \ position following the deletion ADC #&5E \ A contains YC (from above) and the C flag is set (from TAX \ the CPY #127 above), so these instructions do this: \ \ X = YC + &5E + 1 \ = YC + &5F \ Because YC starts at 0 for the first text row, this \ means that X will be &5F for row 0, &60 for row 1 and \ so on. In other words, X is now set to the page number \ for the row before the one containing the text cursor, \ and given that we set SC above to point to the offset \ in memory of the text cursor within the row's page, \ this means that (X SC) now points to the character \ above the text cursor LDY #&F8 \ Set Y = &F8, so the following call to ZES2 will count \ Y upwards from &F8 to &FF JSR ZES2 \ Call ZES2, which zero-fills from address (X SC) + Y to \ (X SC) + &FF. (X SC) points to the character above the \ text cursor, and adding &FF to this would point to the \ cursor, so adding &F8 points to the character before \ the cursor, which is the one we want to delete. So \ this call zero-fills the character to the left of the \ cursor, which erases it from the screen BEQ RR4 \ We are done deleting, so restore the registers and \ return from the subroutine (this BNE is effectively \ a JMP as ZES2 always returns with the Z flag set) .RR2 \ Now to actually print the character INC XC \ Once we print the character, we want to move the text \ cursor to the right, so we do this by incrementing \ XC. Note that this doesn't have anything to do \ with the actual printing below, we're just updating \ the cursor so it's in the right position following \ the print \LDA YC \ This instruction is commented out in the original \ source. It isn't required because we only just did a \ LDA YC before jumping to RR2, so this is presumably \ an example of the authors squeezing the code to save \ 2 bytes and 3 cycles \ \ If you want to re-enable the commented block near the \ start of this routine, you should uncomment this \ instruction as well CMP #24 \ If the text cursor is on the screen (i.e. YC < 24, so BCC RR3 \ we are on rows 0-23), then jump to RR3 to print the \ character JSR TTX66 \ Otherwise we are off the bottom of the screen, so \ clear the screen and draw a border box JMP RR4 \ And restore the registers and return from the \ subroutine .RR3 \ A contains the value of YC - the screen row where we \ want to print this character - so now we need to \ convert this into a screen address, so we can poke \ the character data to the right place in screen \ memory ORA #&60 \ We already stored the least significant byte \ of this screen address in SC above (see the STA SC \ instruction above), so all we need is the most \ significant byte. As mentioned above, in Elite's \ square mode 4 screen, each row of text on-screen \ takes up exactly one page, so the first row is page \ &60xx, the second row is page &61xx, so we can get \ the page for character (XC, YC) by OR'ing with &60. \ To see this in action, consider that our two values \ are, in binary: \ \ YC is between: %00000000 \ and: %00010111 \ &60 is: %01100000 \ \ so YC OR &60 effectively adds &60 to YC, giving us \ the page number that we want .RREN STA SC+1 \ Store the page number of the destination screen \ location in SC+1, so SC now points to the full screen \ location where this character should go LDY #7 \ We want to print the 8 bytes of character data to the \ screen (one byte per row), so set up a counter in Y \ to count these bytes .RRL1 LDA (P+1),Y \ The character definition is at P(2 1) - we set this up \ above - so load the Y-th byte from P(2 1), which will \ contain the bitmap for the Y-th row of the character EOR (SC),Y \ If we EOR this value with the existing screen \ contents, then it's reversible (so reprinting the \ same character in the same place will revert the \ screen to what it looked like before we printed \ anything); this means that printing a white pixel \ onto a white background results in a black pixel, but \ that's a small price to pay for easily erasable text STA (SC),Y \ Store the Y-th byte at the screen address for this \ character location DEY \ Decrement the loop counter BPL RRL1 \ Loop back for the next byte to print to the screen .RR4 LDY YSAV2 \ We're done printing, so restore the values of the LDX XSAV2 \ A, X and Y registers that we saved above and clear LDA K3 \ the C flag, so everything is back to how it was CLC .rT9 RTS \ Return from the subroutine .R5 JSR BEEP \ Call the BEEP subroutine to make a short, high beep JMP RR4 \ Jump to RR4 to restore the registers and return from \ the subroutine using a tail call \ ****************************************************************************** \ \ Name: DIALS (Part 1 of 4) \ Type: Subroutine \ Category: Dashboard \ Summary: Update the dashboard: speed indicator \ Deep dive: The dashboard indicators \ \ ------------------------------------------------------------------------------ \ \ This routine updates the dashboard. First we draw all the indicators in the \ right part of the dashboard, from top (speed) to bottom (energy banks), and \ then we move on to the left part, again drawing from top (forward shield) to \ bottom (altitude). \ \ This first section starts us off with the speedometer in the top right. \ \ ****************************************************************************** .DIALS LDA #&D0 \ Set SC(1 0) = &78D0, which is the screen address for STA SC \ the character block containing the left end of the LDA #&78 \ top indicator in the right part of the dashboard, the STA SC+1 \ one showing our speed JSR PZW \ Call PZW to set A to the colour for dangerous values \ and X to the colour for safe values STX K+1 \ Set K+1 (the colour we should show for low values) to \ X (the colour to use for safe values) STA K \ Set K (the colour we should show for high values) to \ A (the colour to use for dangerous values) \ The above sets the following indicators to show red \ for high values and yellow/white for low values LDA #14 \ Set T1 to 14, the threshold at which we change the STA T1 \ indicator's colour LDA DELTA \ Fetch our ship's speed into A, in the range 0-40 \LSR A \ Draw the speed indicator using a range of 0-31, and JSR DIL-1 \ increment SC to point to the next indicator (the roll \ indicator). The LSR is commented out as it isn't \ required with a call to DIL-1, so perhaps this was \ originally a call to DIL that got optimised \ ****************************************************************************** \ \ Name: DIALS (Part 2 of 4) \ Type: Subroutine \ Category: Dashboard \ Summary: Update the dashboard: pitch and roll indicators \ Deep dive: The dashboard indicators \ \ ****************************************************************************** LDA #0 \ Set R = P = 0 for the low bytes in the call to the ADD STA R \ routine below STA P LDA #8 \ Set S = 8, which is the value of the centre of the STA S \ roll indicator LDA ALP1 \ Fetch the roll angle alpha as a value between 0 and LSR A \ 31, and divide by 4 to get a value of 0 to 7 LSR A ORA ALP2 \ Apply the roll sign to the value, and flip the sign, EOR #%10000000 \ so it's now in the range -7 to +7, with a positive \ roll angle alpha giving a negative value in A JSR ADD \ We now add A to S to give us a value in the range 1 to \ 15, which we can pass to DIL2 to draw the vertical \ bar on the indicator at this position. We use the ADD \ routine like this: \ \ (A X) = (A 0) + (S 0) \ \ and just take the high byte of the result. We use ADD \ rather than a normal ADC because ADD separates out the \ sign bit and does the arithmetic using absolute values \ and separate sign bits, which we want here rather than \ the two's complement that ADC uses JSR DIL2 \ Draw a vertical bar on the roll indicator at offset A \ and increment SC to point to the next indicator (the \ pitch indicator) LDA BETA \ Fetch the pitch angle beta as a value between -8 and \ +8 LDX BET1 \ Fetch the magnitude of the pitch angle beta, and if it BEQ P%+4 \ is 0 (i.e. we are not pitching), skip the next \ instruction SBC #1 \ The pitch angle beta is non-zero, so set A = A - 1 \ (the C flag is set by the call to DIL2 above, so we \ don't need to do a SEC). This gives us a value of A \ from -7 to +7 because these are magnitude-based \ numbers with sign bits, rather than two's complement \ numbers JSR ADD \ We now add A to S to give us a value in the range 1 to \ 15, which we can pass to DIL2 to draw the vertical \ bar on the indicator at this position (see the JSR ADD \ above for more on this) JSR DIL2 \ Draw a vertical bar on the pitch indicator at offset A \ and increment SC to point to the next indicator (the \ four energy banks) \ ****************************************************************************** \ \ Name: DIALS (Part 3 of 4) \ Type: Subroutine \ Category: Dashboard \ Summary: Update the dashboard: four energy banks \ Deep dive: The dashboard indicators \ \ ------------------------------------------------------------------------------ \ \ This and the next section only run once every four iterations of the main \ loop, so while the speed, pitch and roll indicators update every iteration, \ the other indicators update less often. \ \ ****************************************************************************** LDA MCNT \ Fetch the main loop counter and calculate MCNT mod 4, AND #3 \ jumping to rT9 if it is non-zero. rT9 contains an RTS, BNE rT9 \ so the following code only runs every 4 iterations of \ the main loop, otherwise we return from the subroutine LDY #0 \ Set Y = 0, for use in various places below JSR PZW \ Call PZW to set A to the colour for dangerous values \ and X to the colour for safe values STX K \ Set K (the colour we should show for high values) to X \ (the colour to use for safe values) STA K+1 \ Set K+1 (the colour we should show for low values) to \ A (the colour to use for dangerous values) \ The above sets the following indicators to show red \ for low values and yellow/white for high values, which \ we use not only for the energy banks, but also for the \ shield levels and current fuel LDX #3 \ Set up a counter in X so we can zero the four bytes at \ XX12, so we can then calculate each of the four energy \ banks' values before drawing them later STX T1 \ Set T1 to 3, the threshold at which we change the \ indicator's colour .DLL23 STY XX12,X \ Set the X-th byte of XX12 to 0 DEX \ Decrement the counter BPL DLL23 \ Loop back for the next byte until the four bytes at \ XX12 are all zeroed LDX #3 \ Set up a counter in X to loop through the 4 energy \ bank indicators, so we can calculate each of the four \ energy banks' values and store them in XX12 LDA ENERGY \ Set A = Q = ENERGY / 4, so they are both now in the LSR A \ range 0-63 (so that's a maximum of 16 in each of the LSR A \ banks, and a maximum of 15 in the top bank) STA Q \ Set Q to A, so we can use Q to hold the remaining \ energy as we work our way through each bank, from the \ full ones at the bottom to the empty ones at the top .DLL24 SEC \ Set A = A - 16 to reduce the energy count by a full SBC #16 \ bank BCC DLL26 \ If the C flag is clear then A < 16, so this bank is \ not full to the brim, and is therefore the last one \ with any energy in it, so jump to DLL26 STA Q \ This bank is full, so update Q with the energy of the \ remaining banks LDA #16 \ Store this bank's level in XX12 as 16, as it is full, STA XX12,X \ with XX12+3 for the bottom bank and XX12+0 for the top LDA Q \ Set A to the remaining energy level again DEX \ Decrement X to point to the next bank, i.e. the one \ above the bank we just processed BPL DLL24 \ Loop back to DLL24 until we have either processed all \ four banks, or jumped out early to DLL26 if the top \ banks have no charge BMI DLL9 \ Jump to DLL9 as we have processed all four banks (this \ BMI is effectively a JMP as A will never be positive) .DLL26 LDA Q \ If we get here then the bank we just checked is not STA XX12,X \ fully charged, so store its value in XX12 (using Q, \ which contains the energy of the remaining banks - \ i.e. this one) \ Now that we have the four energy bank values in XX12, \ we can draw them, starting with the top bank in XX12 \ and looping down to the bottom bank in XX12+3, using Y \ as a loop counter, which was set to 0 above .DLL9 LDA XX12,Y \ Fetch the value of the Y-th indicator, starting from \ the top STY P \ Store the indicator number in P for retrieval later JSR DIL \ Draw the energy bank using a range of 0-15, and \ increment SC to point to the next indicator (the \ next energy bank down) LDY P \ Restore the indicator number into Y INY \ Increment the indicator number CPY #4 \ Check to see if we have drawn the last energy bank BNE DLL9 \ Loop back to DLL9 if we have more banks to draw, \ otherwise we are done \ ****************************************************************************** \ \ Name: DIALS (Part 4 of 4) \ Type: Subroutine \ Category: Dashboard \ Summary: Update the dashboard: shields, fuel, laser & cabin temp, altitude \ Deep dive: The dashboard indicators \ \ ****************************************************************************** LDA #&78 \ Set SC(1 0) = &7810, which is the screen address for STA SC+1 \ the character block containing the left end of the LDA #&10 \ top indicator in the left part of the dashboard, the STA SC \ one showing the forward shield LDA FSH \ Draw the forward shield indicator using a range of JSR DILX \ 0-255, and increment SC to point to the next indicator \ (the aft shield) LDA ASH \ Draw the aft shield indicator using a range of 0-255, JSR DILX \ and increment SC to point to the next indicator (the \ fuel level) LDA QQ14 \ Draw the fuel level indicator using a range of 0-63, JSR DILX+2 \ and increment SC to point to the next indicator (the \ cabin temperature) JSR PZW \ Call PZW to set A to the colour for dangerous values \ and X to the colour for safe values STX K+1 \ Set K+1 (the colour we should show for low values) to \ X (the colour to use for safe values) STA K \ Set K (the colour we should show for high values) to \ A (the colour to use for dangerous values) \ The above sets the following indicators to show red \ for high values and yellow/white for low values, which \ we use for the cabin and laser temperature bars LDX #11 \ Set T1 to 11, the threshold at which we change the STX T1 \ cabin and laser temperature indicators' colours LDA CABTMP \ Draw the cabin temperature indicator using a range of JSR DILX \ 0-255, and increment SC to point to the next indicator \ (the laser temperature) LDA GNTMP \ Draw the laser temperature indicator using a range of JSR DILX \ 0-255, and increment SC to point to the next indicator \ (the altitude) LDA #240 \ Set T1 to 240, the threshold at which we change the STA T1 \ altitude indicator's colour. As the altitude has a \ range of 0-255, pixel 16 will not be filled in, and \ 240 would change the colour when moving between pixels \ 15 and 16, so this effectively switches off the colour \ change for the altitude indicator STA K+1 \ Set K+1 (the colour we should show for low values) to \ 240, or &F0 (dashboard colour 2, yellow/white), so the \ altitude indicator always shows in this colour LDA ALTIT \ Draw the altitude indicator using a range of 0-255 JSR DILX JMP COMPAS \ We have now drawn all the indicators, so jump to \ COMPAS to draw the compass, returning from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: PZW \ Type: Subroutine \ Category: Dashboard \ Summary: Fetch the current dashboard colours, to support flashing \ \ ------------------------------------------------------------------------------ \ \ Set A and X to the colours we should use for indicators showing dangerous and \ safe values respectively. This enables us to implement flashing indicators, \ which is one of the game's configurable options. \ \ If flashing is enabled, the colour returned in A (dangerous values) will be \ red for 8 iterations of the main loop, and yellow/white for the next 8, before \ going back to red. If we always use PZW to decide which colours we should use \ when updating indicators, flashing colours will be automatically taken care of \ for us. \ \ The values returned are &F0 for yellow/white and &0F for red. These are mode 5 \ bytes that contain 4 pixels, with the colour of each pixel given in two bits, \ the high bit from the first nibble (bits 4-7) and the low bit from the second \ nibble (bits 0-3). So in &F0 each pixel is %10, or colour 2 (yellow or white, \ depending on the dashboard palette), while in &0F each pixel is %01, or colour \ 1 (red). \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A The colour to use for indicators with dangerous values \ \ X The colour to use for indicators with safe values \ \ ****************************************************************************** .PZW LDX #&F0 \ Set X to dashboard colour 2 (yellow/white) LDA MCNT \ A will be non-zero for 8 out of every 16 main loop AND #%00001000 \ counts, when bit 4 is set, so this is what we use to \ flash the "danger" colour AND FLH \ A will be zeroed if flashing colours are disabled BEQ P%+4 \ If A is zero, skip to the LDA instruction below TXA \ Otherwise flashing colours are enabled and it's the \ main loop iteration where we flash them, so set A to \ colour 2 (yellow/white) and use the BIT trick below to \ return from the subroutine EQUB &2C \ Skip the next instruction by turning it into \ &2C &A9 &0F, or BIT &0FA9, which does nothing apart \ from affect the flags LDA #&0F \ Set A to dashboard colour 1 (red) RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DILX \ Type: Subroutine \ Category: Dashboard \ Summary: Update a bar-based indicator on the dashboard \ Deep dive: The dashboard indicators \ \ ------------------------------------------------------------------------------ \ \ The range of values shown on the indicator depends on which entry point is \ called. For the default entry point of DILX, the range is 0-255 (as the value \ passed in A is one byte). The other entry points are shown below. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The value to be shown on the indicator (so the larger \ the value, the longer the bar) \ \ T1 The threshold at which we change the indicator's colour \ from the low value colour to the high value colour. The \ threshold is in pixels, so it should have a value from \ 0-16, as each bar indicator is 16 pixels wide \ \ K The colour to use when A is a high value, as a \ four-pixel mode 5 character row byte \ \ K+1 The colour to use when A is a low value, as a \ four-pixel mode 5 character row byte \ \ SC(1 0) The screen address of the first character block in the \ indicator \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ DILX+2 The range of the indicator is 0-64 (for the fuel \ indicator) \ \ DIL-1 The range of the indicator is 0-32 (for the speed \ indicator) \ \ DIL The range of the indicator is 0-16 (for the energy \ banks) \ \ ****************************************************************************** .DILX LSR A \ If we call DILX, we set A = A / 16, so A is 0-15 LSR A LSR A \ If we call DILX+2, we set A = A / 4, so A is 0-15 LSR A \ If we call DIL-1, we set A = A / 2, so A is 0-15 .DIL \ If we call DIL, we leave A alone, so A is 0-15 STA Q \ Store the indicator value in Q, now reduced to 0-15, \ which is the length of the indicator to draw in pixels LDX #&FF \ Set R = &FF, to use as a mask for drawing each row of STX R \ each character block of the bar, starting with a full \ character's width of 4 pixels CMP T1 \ If A >= T1 then we have passed the threshold where we BCS DL30 \ change bar colour, so jump to DL30 to set A to the \ "high value" colour LDA K+1 \ Set A to K+1, the "low value" colour to use BNE DL31 \ Jump down to DL31 (this BNE is effectively a JMP as A \ will never be zero) .DL30 LDA K \ Set A to K, the "high value" colour to use .DL31 STA COL \ Store the colour of the indicator in COL LDY #2 \ We want to start drawing the indicator on the third \ line in this character row, so set Y to point to that \ row's offset LDX #3 \ Set up a counter in X for the width of the indicator, \ which is 4 characters (each of which is 4 pixels wide, \ to give a total width of 16 pixels) .DL1 LDA Q \ Fetch the indicator value (0-15) from Q into A CMP #4 \ If Q < 4, then we need to draw the end cap of the BCC DL2 \ indicator, which is less than a full character's \ width, so jump down to DL2 to do this SBC #4 \ Otherwise we can draw a four-pixel wide block, so STA Q \ subtract 4 from Q so it contains the amount of the \ indicator that's left to draw after this character LDA R \ Fetch the shape of the indicator row that we need to \ display from R, so we can use it as a mask when \ painting the indicator. It will be &FF at this point \ (i.e. a full four-pixel row) .DL5 AND COL \ Fetch the four-pixel mode 5 colour byte from COL, and \ only keep pixels that have their equivalent bits set \ in the mask byte in A STA (SC),Y \ Draw the shape of the mask on pixel row Y of the \ character block we are processing INY \ Draw the next pixel row, incrementing Y STA (SC),Y INY \ And draw the third pixel row, incrementing Y STA (SC),Y TYA \ Add 6 to Y, so Y is now 8 more than when we started CLC \ this loop iteration, so Y now points to the address ADC #6 \ of the first line of the indicator bar in the next TAY \ character block (as each character is 8 bytes of \ screen memory) DEX \ Decrement the loop counter for the next character \ block along in the indicator BMI DL6 \ If we just drew the last character block then we are \ done drawing, so jump down to DL6 to finish off BPL DL1 \ Loop back to DL1 to draw the next character block of \ the indicator (this BPL is effectively a JMP as A will \ never be negative following the previous BMI) .DL2 EOR #3 \ If we get here then we are drawing the indicator's STA Q \ end cap, so Q is < 4, and this EOR flips the bits, so \ instead of containing the number of indicator columns \ we need to fill in on the left side of the cap's \ character block, Q now contains the number of blank \ columns there should be on the right side of the cap's \ character block LDA R \ Fetch the current mask from R, which will be &FF at \ this point, so we need to turn Q of the columns on the \ right side of the mask to black to get the correct end \ cap shape for the indicator .DL3 ASL A \ Shift the mask left so bit 0 is cleared, and then AND #%11101111 \ clear bit 4, which has the effect of shifting zeroes \ from the left into each nibble (i.e. xxxx xxxx becomes \ xxx0 xxx0, which blanks out the last column in the \ four-pixel mode 5 character block) DEC Q \ Decrement the counter for the number of columns to \ blank out BPL DL3 \ If we still have columns to blank out in the mask, \ loop back to DL3 until the mask is correct for the \ end cap PHA \ Store the mask byte on the stack while we use the \ accumulator for a bit LDA #0 \ Change the mask so no bits are set, so the characters STA R \ after the one we're about to draw will be all blank LDA #99 \ Set Q to a high number (99, why not) so we will keep STA Q \ drawing blank characters until we reach the end of \ the indicator row PLA \ Restore the mask byte from the stack so we can use it \ to draw the end cap of the indicator JMP DL5 \ Jump back up to DL5 to draw the mask byte on-screen .DL6 INC SC+1 \ Increment the high byte of SC to point to the next \ character row on-screen (as each row takes up exactly \ one page of 256 bytes) - so this sets up SC to point \ to the next indicator, i.e. the one below the one we \ just drew .DL9 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DIL2 \ Type: Subroutine \ Category: Dashboard \ Summary: Update the roll or pitch indicator on the dashboard \ Deep dive: The dashboard indicators \ \ ------------------------------------------------------------------------------ \ \ The indicator can show a vertical bar in 16 positions, with a value of 8 \ showing the bar in the middle of the indicator. \ \ In practice this routine is only ever called with A in the range 1 to 15, so \ the vertical bar never appears in the leftmost position (though it does appear \ in the rightmost). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The offset of the vertical bar to show in the indicator, \ from 0 at the far left, to 8 in the middle, and 15 at \ the far right \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag The C flag is set \ \ ****************************************************************************** .DIL2 LDY #1 \ We want to start drawing the vertical indicator bar on \ the second line in the indicator's character block, so \ set Y to point to that row's offset STA Q \ Store the offset of the vertical bar to draw in Q \ We are now going to work our way along the indicator \ on the dashboard, from left to right, working our way \ along one character block at a time. Y will be used as \ a pixel row counter to work our way through the \ character blocks, so each time we draw a character \ block, we will increment Y by 8 to move on to the next \ block (as each character block contains 8 rows) .DLL10 SEC \ Set A = Q - 4, so that A contains the offset of the LDA Q \ vertical bar from the start of this character block SBC #4 BCS DLL11 \ If Q >= 4 then the character block we are drawing does \ not contain the vertical indicator bar, so jump to \ DLL11 to draw a blank character block LDA #&FF \ Set A to a high number (and &FF is as high as they go) LDX Q \ Set X to the offset of the vertical bar, which we know \ is within this character block STA Q \ Set Q to a high number (&FF, why not) so we will keep \ drawing blank characters after this one until we reach \ the end of the indicator row LDA CTWOS,X \ CTWOS is a table of ready-made one-pixel mode 5 bytes, \ just like the TWOS and TWOS2 tables for mode 4 (see \ the PIXEL routine for details of how they work). This \ fetches a mode 5 one-pixel byte with the pixel \ position at X, so the pixel is at the offset that we \ want for our vertical bar AND #&F0 \ The four-pixel mode 5 colour byte &F0 represents four \ pixels of colour %10 (3), which is yellow in the \ normal dashboard palette and white if we have an \ escape pod fitted. We AND this with A so that we only \ keep the pixel that matches the position of the \ vertical bar (i.e. A is acting as a mask on the \ four-pixel colour byte) BNE DLL12 \ Jump to DLL12 to skip the code for drawing a blank, \ and move on to drawing the indicator (this BNE is \ effectively a JMP as A is always non-zero) .DLL11 \ If we get here then we want to draw a blank for this \ character block STA Q \ Update Q with the new offset of the vertical bar, so \ it becomes the offset after the character block we \ are about to draw LDA #0 \ Change the mask so no bits are set, so all of the \ character blocks we display from now on will be blank .DLL12 STA (SC),Y \ Draw the shape of the mask on pixel row Y of the \ character block we are processing INY \ Draw the next pixel row, incrementing Y STA (SC),Y INY \ And draw the third pixel row, incrementing Y STA (SC),Y INY \ And draw the fourth pixel row, incrementing Y STA (SC),Y TYA \ Add 5 to Y, so Y is now 8 more than when we started CLC \ this loop iteration, so Y now points to the address ADC #5 \ of the first line of the indicator bar in the next TAY \ character block (as each character is 8 bytes of \ screen memory) CPY #30 \ If Y < 30 then we still have some more character BCC DLL10 \ blocks to draw, so loop back to DLL10 to display the \ next one along INC SC+1 \ Increment the high byte of SC to point to the next \ character row on-screen (as each row takes up exactly \ one page of 256 bytes) - so this sets up SC to point \ to the next indicator, i.e. the one below the one we \ just drew RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TVT1 \ Type: Variable \ Category: Drawing the screen \ Summary: Palette data for space and the two dashboard colour schemes \ \ ------------------------------------------------------------------------------ \ \ Palette bytes for use with the split-screen mode (see IRQ1 below for more \ details). \ \ Palette data is given as a set of bytes, with each byte mapping a logical \ colour to a physical one. In each byte, the logical colour is given in bits \ 4-7 and the physical colour in bits 0-3. See page 379 of the "Advanced User \ Guide for the BBC Micro" by Bray, Dickens and Holmes for details of how \ palette mapping works, as in modes 4 and 5 we have to do multiple palette \ commands to change the colours correctly, and the physical colour value is \ EOR'd with 7, just to make things even more confusing. \ \ Similarly, the palette at TVT1+16 is for the monochrome space view, where \ logical colour 1 is mapped to physical colour 0 EOR 7 = 7 (white), and \ logical colour 0 is mapped to physical colour 7 EOR 7 = 0 (black). Each of \ these mappings requires six calls to SHEILA &21 - see page 379 of the \ "Advanced User Guide for the BBC Micro" by Bray, Dickens and Holmes for an \ explanation. \ \ The mode 5 palette table has two blocks which overlap. The block used depends \ on whether or not we have an escape pod fitted. The block at TVT1 is used for \ the standard dashboard colours, while TVT1+8 is used for the dashboard when an \ escape pod is fitted. The colours are as follows: \ \ Normal (TVT1) Escape pod (TVT1+8) \ \ Colour 0 Black Black \ Colour 1 Red Red \ Colour 2 Yellow White \ Colour 3 Green Cyan \ \ ****************************************************************************** .TVT1 EQUB &D4, &C4 \ This block of palette data is used to create two EQUB &94, &84 \ palettes used in three different places, all of them EQUB &F5, &E5 \ redefining four colours in mode 5: EQUB &B5, &A5 \ \ 12 bytes from TVT1 (i.e. the first 6 rows): applied EQUB &76, &66 \ when the T1 timer runs down at the switch from the EQUB &36, &26 \ space view to the dashboard, so this is the standard \ dashboard palette EQUB &E1, &F1 \ EQUB &B1, &A1 \ 8 bytes from TVT1+8 (i.e. the last 4 rows): applied \ when the T1 timer runs down at the switch from the \ space view to the dashboard, and we have an escape \ pod fitted, so this is the escape pod dashboard \ palette \ \ 8 bytes from TVT1+8 (i.e. the last 4 rows): applied \ at vertical sync in LINSCN when HFX is non-zero, to \ create the hyperspace effect in LINSCN (where the \ whole screen is switched to mode 5 at vertical sync) EQUB &F0, &E0 \ 12 bytes of palette data at TVT1+16, used to set the EQUB &B0, &A0 \ mode 4 palette in LINSCN when we hit vertical sync, EQUB &D0, &C0 \ so the palette is set to monochrome when we start to EQUB &90, &80 \ draw the first row of the screen EQUB &77, &67 EQUB &37, &27 \ ****************************************************************************** \ \ Name: IRQ1 \ Type: Subroutine \ Category: Drawing the screen \ Summary: The main screen-mode interrupt handler (IRQ1V points here) \ Deep dive: The split-screen mode in BBC Micro Elite \ \ ------------------------------------------------------------------------------ \ \ The main interrupt handler, which implements Elite's split-screen mode. \ \ IRQ1V is set to point to IRQ1 by the loading process. \ \ ****************************************************************************** .LINSCN \ This is called from the interrupt handler below, at \ the start of each vertical sync (i.e. when the screen \ refresh starts) LDA #30 \ Set the line scan counter to a non-zero value, so STA DL \ routines like WSCAN can set DL to 0 and then wait for \ it to change to non-zero to catch the vertical sync STA VIA+&44 \ Set 6522 System VIA T1C-L timer 1 low-order counter \ (SHEILA &44) to 30 LDA #VSCAN \ Set 6522 System VIA T1C-L timer 1 high-order counter STA VIA+&45 \ (SHEILA &45) to VSCAN (57) to start the T1 counter \ counting down from 14622 at a rate of 1 MHz LDA HFX \ If HFX is non-zero, jump to VNT1 to set the mode 5 BNE VNT1 \ palette instead of switching to mode 4, which will \ have the effect of blurring and colouring the top \ screen. This is how the white hyperspace rings turn \ to colour when we do a hyperspace jump, and is \ triggered by setting HFX to 1 in routine LL164 LDA #%00001000 \ Set the Video ULA control register (SHEILA &20) to STA VIA+&20 \ %00001000, which is the same as switching to mode 4 \ (i.e. the top part of the screen) but with no cursor .VNT3 LDA TVT1+16,Y \ Copy the Y-th palette byte from TVT1+16 to SHEILA &21 STA VIA+&21 \ to map logical to actual colours for the bottom part \ of the screen (i.e. the dashboard) DEY \ Decrement the palette byte counter BPL VNT3 \ Loop back to VNT3 until we have copied all the \ palette bytes LDA LASCT \ Decrement the value of LASCT, but if we go too far BEQ P%+5 \ and it becomes negative, bump it back up again (this DEC LASCT \ controls the pulsing of pulse lasers) LDA SVN \ If SVN is non-zero, we are in the process of saving BNE jvec \ the commander file, so jump to jvec to pass control \ to the next interrupt handler, so we don't break file \ saving by blocking the interrupt chain PLA \ Otherwise restore Y from the stack TAY LDA VIA+&41 \ Read 6522 System VIA input register IRA (SHEILA &41) LDA &FC \ Set A to the interrupt accumulator save register, \ which restores A to the value it had on entering the \ interrupt RTI \ Return from interrupts, so this interrupt is not \ passed on to the next interrupt handler, but instead \ the interrupt terminates here .IRQ1 TYA \ Store Y on the stack PHA LDY #11 \ Set Y as a counter for 12 bytes, to use when setting \ the dashboard palette below LDA #%00000010 \ Read the 6522 System VIA status byte bit 1 (SHEILA BIT VIA+&4D \ &4D), which is set if vertical sync has occurred on \ the video system BNE LINSCN \ If we are on the vertical sync pulse, jump to LINSCN \ to set up the timers to enable us to switch the \ screen mode between the space view and dashboard BVC jvec \ Read the 6522 System VIA status byte bit 6, which is \ set if timer 1 has timed out. We set the timer in \ LINSCN above, so this means we only run the next bit \ if the screen redraw has reached the boundary between \ the space view and the dashboard. Otherwise bit 6 is \ clear and we aren't at the boundary, so we jump to \ jvec to pass control to the next interrupt handler ASL A \ Double the value in A to 4 STA VIA+&20 \ Set the Video ULA control register (SHEILA &20) to \ %00000100, which is the same as switching to mode 5, \ (i.e. the bottom part of the screen) but with no \ cursor LDA ESCP \ If an escape pod is fitted, jump to VNT1 to set the BNE VNT1 \ mode 5 palette differently (so the dashboard is a \ different colour if we have an escape pod) LDA TVT1,Y \ Copy the Y-th palette byte from TVT1 to SHEILA &21 STA VIA+&21 \ to map logical to actual colours for the bottom part \ of the screen (i.e. the dashboard) DEY \ Decrement the palette byte counter BPL P%-7 \ Loop back to the LDA TVT1,Y instruction until we have \ copied all the palette bytes .jvec PLA \ Restore Y from the stack TAY JMP (VEC) \ Jump to the address in VEC, which was set to the \ original IRQ1V vector by the loading process, so this \ instruction passes control to the next interrupt \ handler .VNT1 LDY #7 \ Set Y as a counter for 8 bytes LDA TVT1+8,Y \ Copy the Y-th palette byte from TVT1+8 to SHEILA &21 STA VIA+&21 \ to map logical to actual colours for the bottom part \ of the screen (i.e. the dashboard) DEY \ Decrement the palette byte counter BPL VNT1+2 \ Loop back to the LDA TVT1+8,Y instruction until we \ have copied all the palette bytes BMI jvec \ Jump up to jvec to pass control to the next interrupt \ handler (this BMI is effectively a JMP as we didn't \ loop back with the BPL above, so BMI is always true) \ ****************************************************************************** \ \ Name: ESCAPE \ Type: Subroutine \ Category: Flight \ Summary: Launch our escape pod \ \ ------------------------------------------------------------------------------ \ \ This routine displays our doomed Cobra Mk III disappearing off into the ether \ before arranging our replacement ship. Called when we press ESCAPE during \ flight and have an escape pod fitted. \ \ ****************************************************************************** .ESCAPE LDA MJ \ Store the value of MJ on the stack (the "are we in PHA \ witchspace?" flag) JSR RES2 \ Reset a number of flight variables and workspaces LDX #CYL \ Set the current ship type to a Cobra Mk III, so we STX TYPE \ can show our ship disappear into the distance when we \ eject in our pod JSR FRS1 \ Call FRS1 to launch the Cobra Mk III straight ahead, \ like a missile launch, but with our ship instead LDA #8 \ Set the Cobra's byte #27 (speed) to 8 STA INWK+27 LDA #194 \ Set the Cobra's byte #30 (pitch counter) to 194, so it STA INWK+30 \ pitches up as we pull away LSR A \ Set the Cobra's byte #32 (AI flag) to %01100001, so it STA INWK+32 \ has no AI, and we can use this value as a counter to \ do the following loop 97 times .ESL1 JSR MVEIT \ Call MVEIT to move the Cobra in space JSR LL9 \ Call LL9 to draw the Cobra on-screen DEC INWK+32 \ Decrement the counter in byte #32 BNE ESL1 \ Loop back to keep moving the Cobra until the AI flag \ is 0, which gives it time to drift away from our pod JSR SCAN \ Call SCAN to remove the Cobra from the scanner (by \ redrawing it) JSR RESET \ Call RESET to reset our ship and various controls PLA \ Restore the witchspace flag from before the escape pod BEQ P%+5 \ launch, and if we were in normal space, skip the \ following instruction JMP DEATH \ Launching an escape pod in witchspace is fatal, so \ jump to DEATH to begin the funeral and return from the \ subroutine using a tail call LDX #16 \ We lose all our cargo when using our escape pod, so \ up a counter in X so we can zero the 17 cargo slots \ in QQ20 .ESL2 STA QQ20,X \ Set the X-th byte of QQ20 to zero (as we know A = 0 \ from the BEQ above), so we no longer have any of item \ type X in the cargo hold DEX \ Decrement the counter BPL ESL2 \ Loop back to ESL2 until we have emptied the entire \ cargo hold STA FIST \ Launching an escape pod also clears our criminal \ record, so set our legal status in FIST to 0 ("clean") STA ESCP \ The escape pod is a one-use item, so set ESCP to 0 so \ we no longer have one fitted LDA #70 \ Our replacement ship is delivered with a full tank of STA QQ14 \ fuel, so set the current fuel level in QQ14 to 70, or \ 7.0 light years JMP BAY \ Go to the docking bay (i.e. show the Status Mode \ screen) and return from the subroutine with a tail \ call \ ****************************************************************************** \ \ Save ELTB.bin \ \ ****************************************************************************** PRINT "ELITE B" PRINT "Assembled at ", ~CODE_B% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_B%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_B% PRINT "S.ELTB ", ~CODE_B%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_B% SAVE "3-assembled-output/ELTB.bin", CODE_B%, P%, LOAD% \ ****************************************************************************** \ \ ELITE C FILE \ \ Produces the binary file ELTC.bin that gets loaded by elite-bcfs.asm. \ \ ****************************************************************************** CODE_C% = P% LOAD_C% = LOAD% +P% - CODE% \ ****************************************************************************** \ \ Name: TACTICS (Part 1 of 7) \ Type: Subroutine \ Category: Tactics \ Summary: Apply tactics: Process missiles, both enemy missiles and our own \ Deep dive: Program flow of the tactics routine \ \ ------------------------------------------------------------------------------ \ \ This section implements missile tactics and is entered at TA18 from the main \ entry point below, if the current ship is a missile. Specifically: \ \ * If E.C.M. is active, destroy the missile \ \ * If the missile is hostile towards us, then check how close it is. If it \ hasn't reached us, jump to part 3 so it can streak towards us, otherwise \ we've been hit, so process a large amount of damage to our ship \ \ * Otherwise see how close the missile is to its target. If it has not yet \ reached its target, give the target a chance to activate its E.C.M. if it \ has one, otherwise jump to TA19 with K3 set to the vector from the target \ to the missile \ \ * If it has reached its target and the target is the space station, destroy \ the missile, potentially damaging us if we are nearby \ \ * If it has reached its target and the target is a ship, destroy the missile \ and the ship, potentially damaging us if we are nearby \ \ ****************************************************************************** .TA34 \ If we get here, the missile is hostile LDA #0 \ Set A to x_hi OR y_hi OR z_hi JSR MAS4 BEQ P%+5 \ If A = 0 then the missile is very close to our ship, \ so skip the following instruction JMP TA21 \ Jump down to part 3 to set up the vectors and skip \ straight to aggressive manoeuvring JSR TA87+3 \ The missile has hit our ship, so call TA87+3 to set \ bit 7 of the missile's byte #31, which marks the \ missile as being killed JSR EXNO3 \ Make the sound of the missile exploding LDA #250 \ Call OOPS to damage the ship by 250, which is a pretty JMP OOPS \ big hit, and return from the subroutine using a tail \ call .TA18 \ This is the entry point for missile tactics and is \ called from the main TACTICS routine below LDA ECMA \ If an E.C.M. is currently active (either ours or an BNE TA35 \ opponent's), jump to TA35 to destroy this missile LDA INWK+32 \ Fetch the AI flag from byte #32 and if bit 6 is set ASL A \ (i.e. missile is hostile), jump up to TA34 to check BMI TA34 \ whether the missile has hit us LSR A \ Otherwise shift A right again. We know bits 6 and 7 \ are now clear, so this leaves bits 0-5. Bits 1-5 \ contain the target's slot number, and bit 0 is cleared \ in FRMIS when a missile is launched, so A contains \ the slot number shifted left by 1 (i.e. doubled) so we \ can use it as an index for the two-byte address table \ at UNIV TAX \ Copy the address of the target ship's data block from LDA UNIV,X \ UNIV(X+1 X) to V(1 0) STA V LDA UNIV+1,X STA V+1 LDY #2 \ K3(2 1 0) = (x_sign x_hi x_lo) - x-coordinate of JSR TAS1 \ target ship LDY #5 \ K3(5 4 3) = (y_sign y_hi z_lo) - y-coordinate of JSR TAS1 \ target ship LDY #8 \ K3(8 7 6) = (z_sign z_hi z_lo) - z-coordinate of JSR TAS1 \ target ship \ So K3 now contains the vector from the target ship to \ the missile LDA K3+2 \ Set A = OR of all the sign and high bytes of the ORA K3+5 \ above, clearing bit 7 (i.e. ignore the signs) ORA K3+8 AND #%01111111 ORA K3+1 ORA K3+4 ORA K3+7 BNE TA64 \ If the result is non-zero, then the missile is some \ distance from the target, so jump down to TA64 see if \ the target activates its E.C.M. LDA INWK+32 \ Fetch the AI flag from byte #32 and if only bits 7 and CMP #%10000010 \ 1 are set (AI is enabled and the target is slot 1, the BEQ TA35 \ space station), jump to TA35 to destroy this missile, \ as the space station ain't kidding around LDY #31 \ Fetch byte #31 (the exploding flag) of the target ship LDA (V),Y \ into A BIT M32+1 \ M32 contains an LDY #32 instruction, so M32+1 contains \ 32, so this instruction tests A with %00100000, which \ checks bit 5 of A (the "already exploding?" bit) BNE TA35 \ If the target ship is already exploding, jump to TA35 \ to destroy this missile ORA #%10000000 \ Otherwise set bit 7 of the target's byte #31 to mark STA (V),Y \ the ship as having been killed, so it explodes .TA35 LDA INWK \ Set A = x_lo OR y_lo OR z_lo of the missile ORA INWK+3 ORA INWK+6 BNE TA87 \ If A is non-zero then the missile is not near our \ ship, so jump to TA87 to skip damaging our ship LDA #80 \ Otherwise the missile just got destroyed near us, so JSR OOPS \ call OOPS to damage the ship by 80, which is nowhere \ near as bad as the 250 damage from a missile slamming \ straight into us, but it's still pretty nasty .TA87 JSR EXNO2 \ Call EXNO2 to process the fact that we have killed a \ missile (so increase the kill tally, make an explosion \ sound and so on) ASL INWK+31 \ Set bit 7 of the missile's byte #31 flag to mark it as SEC \ having been killed, so it explodes ROR INWK+31 .TA1 RTS \ Return from the subroutine .TA64 \ If we get here then the missile has not reached the \ target JSR DORND \ Set A and X to random numbers CMP #16 \ If A >= 16 (94% chance), jump down to TA19 with the BCS TA19 \ vector from the target to the missile in K3 .M32 LDY #32 \ Fetch byte #32 for the target and shift bit 0 (E.C.M.) LDA (V),Y \ into the C flag LSR A BCC TA19 \ If the C flag is clear then the target does not have \ E.C.M. fitted, so jump down to TA19 with the vector \ from the target to the missile in K3 JMP ECBLB2 \ The target has E.C.M., so jump to ECBLB2 to set it \ off, returning from the subroutine using a tail call \ ****************************************************************************** \ \ Name: TACTICS (Part 2 of 7) \ Type: Subroutine \ Category: Tactics \ Summary: Apply tactics: Escape pod, station, lone Thargon, safe-zone pirate \ Deep dive: Program flow of the tactics routine \ Aggression and hostility in ship tactics \ \ ------------------------------------------------------------------------------ \ \ This section contains the main entry point at TACTICS, which is called from \ part 2 of MVEIT for ships that have the AI flag set (i.e. bit 7 of byte #32). \ This part does the following: \ \ * If this is a missile, jump up to the missile code in part 1 \ \ * If this is an escape pod, point it at the planet and jump to the \ manoeuvring code in part 7 \ \ * If this is the space station and it is hostile, consider spawning a cop \ (45% chance, up to a maximum of four) and we're done \ \ * If this is a lone Thargon without a mothership, set it adrift aimlessly \ and we're done \ \ * If this is a pirate and we are within the space station safe zone, stop \ the pirate from attacking by removing all its aggression \ \ * Recharge the ship's energy banks by 1 \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The ship type \ \ ****************************************************************************** .TACTICS CPX #MSL \ If this is a missile, jump up to TA18 to implement BEQ TA18 \ missile tactics CPX #ESC \ If this is not an escape pod, skip the following two BNE P%+8 \ instructions JSR SPS1 \ This is an escape pod, so call SPS1 to calculate the \ vector to the planet and store it in XX15 JMP TA15 \ Jump down to TA15 CPX #SST \ If this is not the space station, jump down to TA13 BNE TA13 \ We only call the tactics routine for the space station \ when it is hostile, so if we get here then this is the \ station, and we already know it's hostile, so we need \ to spawn some cops JSR DORND \ Set A and X to random numbers CMP #140 \ If A < 140 (55% chance) then return from the BCC TA14-1 \ subroutine (as TA14-1 contains an RTS) LDA MANY+COPS \ We only call the tactics routine for the space station CMP #4 \ when it is hostile, so first check the number of cops BCS TA14-1 \ in the vicinity, and if we already have 4 or more, we \ don't need to spawn any more, so return from the \ subroutine (as TA14-1 contains an RTS) LDX #COPS \ Set X to the ship type for a cop LDA #%11110001 \ Set the AI flag to give the ship E.C.M., enable AI and \ make it very aggressive (56 out of 63) JMP SFS1 \ Jump to SFS1 to spawn the ship, returning from the \ subroutine using a tail call .TA13 CPX #TGL \ If this is not a Thargon, jump down to TA14 BNE TA14 LDA MANY+THG \ If there is at least one Thargoid in the vicinity, BNE TA14 \ jump down to TA14 LSR INWK+32 \ This is a Thargon but there is no Thargoid mothership, ASL INWK+32 \ so clear bit 0 of the AI flag to disable its E.C.M. LSR INWK+27 \ And halve the Thargon's speed RTS \ Return from the subroutine .TA14 CPX #CYL \ If A >= #CYL, i.e. this is a Cobra Mk III trader (as BCS TA62 \ asteroids and cargo canisters never have AI), jump \ down to TA62 CPX #COPS \ If this is a cop, jump down to TA62 BEQ TA62 LDA SSPR \ If we aren't within range of the space station, jump BEQ TA62 \ down to TA62 LDA INWK+32 \ This is a pirate or bounty hunter, but we are inside AND #%10000001 \ the space station's safe zone, so clear bits 1-6 of STA INWK+32 \ the AI flag to set it to zero aggression, because even \ pirates aren't crazy enough to breach the station's \ no-fire zone .TA62 LDY #14 \ If the ship's energy is greater or equal to the LDA INWK+35 \ maximum value from the ship's blueprint pointed to by CMP (XX0),Y \ XX0, then skip the next instruction BCS TA21 INC INWK+35 \ The ship's energy is not at maximum, so recharge the \ energy banks by 1 \ ****************************************************************************** \ \ Name: TACTICS (Part 3 of 7) \ Type: Subroutine \ Category: Tactics \ Summary: Apply tactics: Calculate dot product to determine ship's aim \ Deep dive: Program flow of the tactics routine \ Aggression and hostility in ship tactics \ \ ------------------------------------------------------------------------------ \ \ This section sets up some vectors and calculates dot products. Specifically: \ \ * Calculate the dot product of the ship's nose vector (i.e. the direction it \ is pointing) with the vector between us and the ship. This value will help \ us work out later on whether the enemy ship is pointing towards us, and \ therefore whether it can hit us with its lasers. \ \ ****************************************************************************** .TA21 LDX #8 \ We now want to copy the ship's x, y and z coordinates \ from INWK to K3, so set up a counter for 9 bytes .TAL1 LDA INWK,X \ Copy the X-th byte from INWK to the X-th byte of K3 STA K3,X DEX \ Decrement the counter BPL TAL1 \ Loop back until we have copied all 9 bytes .TA19 \ If this is a missile that's heading for its target \ (not us, one of the other ships), then the missile \ routine at TA18 above jumps here after setting K3 to \ the vector from the target to the missile JSR TAS2 \ Normalise the vector in K3 and store the normalised \ version in XX15, so XX15 contains the normalised \ vector from our ship to the ship we are applying AI \ tactics to (or the normalised vector from the target \ to the missile - in both cases it's the vector from \ the potential victim to the attacker) LDY #10 \ Set (A X) = nosev . XX15 JSR TAS3 STA CNT \ Store the high byte of the dot product in CNT. The \ bigger the value, the more aligned the two ships are, \ with a maximum magnitude of 36 (96 * 96 >> 8). If CNT \ is positive, the ships are facing in a similar \ direction, if it's negative they are facing in \ opposite directions \ ****************************************************************************** \ \ Name: TACTICS (Part 4 of 7) \ Type: Subroutine \ Category: Tactics \ Summary: Apply tactics: Check energy levels, maybe launch escape pod if low \ Deep dive: Program flow of the tactics routine \ \ ------------------------------------------------------------------------------ \ \ This section works out what kind of condition the ship is in. Specifically: \ \ * Rarely (2.5% chance) roll the ship by a noticeable amount \ \ * If the ship has at least half its energy banks full, jump to part 6 to \ consider firing the lasers \ \ * If the ship is not into the last 1/8th of its energy, jump to part 5 to \ consider firing a missile \ \ * If the ship is into the last 1/8th of its energy, then rarely (10% chance) \ the ship launches an escape pod and is left drifting in space \ \ ****************************************************************************** LDA TYPE \ If this is not a missile, skip the following CMP #MSL \ instruction BNE P%+5 JMP TA20 \ This is a missile, so jump down to TA20 to get \ straight into some aggressive manoeuvring JSR DORND \ Set A and X to random numbers CMP #250 \ If A < 250 (97.5% chance), jump down to TA7 to skip BCC TA7 \ the following JSR DORND \ Set A and X to random numbers ORA #104 \ Bump A up to at least 104 and store in the roll STA INWK+29 \ counter, to gives the ship a noticeable roll .TA7 LDY #14 \ Set A = the ship's maximum energy / 2 LDA (XX0),Y LSR A CMP INWK+35 \ If the ship's current energy in byte #35 > A, i.e. the BCC TA3 \ ship has at least half of its energy banks charged, \ jump down to TA3 LSR A \ If the ship's current energy in byte #35 > A / 4, i.e. LSR A \ the ship is not into the last 1/8th of its energy, CMP INWK+35 \ jump down to ta3 to consider firing a missile BCC ta3 JSR DORND \ Set A and X to random numbers CMP #230 \ If A < 230 (90% chance), jump down to ta3 to consider BCC ta3 \ firing a missile LDA TYPE \ If this is a Thargoid, jump down to ta3 to consider CMP #THG \ launching a Thargon BEQ ta3 \ By this point, the ship has run out of both energy and \ luck, so it's time to bail LDA #%00000000 \ Set the AI flag to 0 to disable AI, set aggression to STA INWK+32 \ zero and disable any E.C.M., so the ship's a sitting \ duck JMP SESCP \ Jump to SESCP to spawn an escape pod from the ship, \ returning from the subroutine using a tail call \ ****************************************************************************** \ \ Name: TACTICS (Part 5 of 7) \ Type: Subroutine \ Category: Tactics \ Summary: Apply tactics: Consider whether to launch a missile at us \ Deep dive: Program flow of the tactics routine \ \ ------------------------------------------------------------------------------ \ \ This section considers whether to launch a missile. Specifically: \ \ * If the ship doesn't have any missiles, skip to the next part \ \ * If an E.C.M. is firing, skip to the next part \ \ * Randomly decide whether to fire a missile (or, in the case of Thargoids, \ release a Thargon), and if we do, we're done \ \ ****************************************************************************** .ta3 \ If we get here then the ship has less than half energy \ so there may not be enough juice for lasers, but let's \ see if we can fire a missile LDA INWK+31 \ Set A = bits 0-2 of byte #31, the number of missiles AND #%00000111 \ the ship has left BEQ TA3 \ If it doesn't have any missiles, jump to TA3 STA T \ Store the number of missiles in T JSR DORND \ Set A and X to random numbers AND #31 \ Restrict A to a random number in the range 0-31 CMP T \ If A >= T, which is quite likely, though less likely BCS TA3 \ with higher numbers of missiles, jump to TA3 to skip \ firing a missile LDA ECMA \ If an E.C.M. is currently active (either ours or an BNE TA3 \ opponent's), jump to TA3 to skip firing a missile DEC INWK+31 \ We're done with the checks, so it's time to fire off a \ missile, so reduce the missile count in byte #31 by 1 LDA TYPE \ Fetch the ship type into A CMP #THG \ If this is not a Thargoid, jump down to TA16 to launch BNE TA16 \ a missile LDX #TGL \ This is a Thargoid, so instead of launching a missile, LDA INWK+32 \ the mothership launches a Thargon, so call SFS1 to JMP SFS1 \ spawn a Thargon from the parent ship, and return from \ the subroutine using a tail call .TA16 JMP SFRMIS \ Jump to SFRMIS to spawn a missile as a child of the \ current ship, make a noise and print a message warning \ of incoming missiles, and return from the subroutine \ using a tail call \ ****************************************************************************** \ \ Name: TACTICS (Part 6 of 7) \ Type: Subroutine \ Category: Tactics \ Summary: Apply tactics: Consider firing a laser at us, if aim is true \ Deep dive: Program flow of the tactics routine \ \ ------------------------------------------------------------------------------ \ \ This section looks at potentially firing the ship's laser at us. Specifically: \ \ * If the ship is not pointing at us, skip to the next part \ \ * If the ship is pointing at us but not accurately, fire its laser at us and \ skip to the next part \ \ * If we are in the ship's crosshairs, register some damage to our ship, slow \ down the attacking ship, make the noise of us being hit by laser fire, and \ we're done \ \ ****************************************************************************** .TA3 \ If we get here then the ship either has plenty of \ energy, or levels are low but it couldn't manage to \ launch a missile, so maybe we can fire the laser? LDA #0 \ Set A to x_hi OR y_hi OR z_hi JSR MAS4 AND #%11100000 \ If any of the hi bytes have any of bits 5-7 set, then BNE TA4 \ jump to TA4 to skip the laser checks, as the ship is \ too far away from us to hit us with a laser LDX CNT \ Set X = the dot product set above in CNT. If this is \ positive, this ship and our ship are facing in similar \ directions, but if it's negative then we are facing \ each other, so for us to be in the enemy ship's line \ of fire, X needs to be negative. The value in X can \ have a maximum magnitude of 36, which would mean we \ were facing each other square on, so in the following \ code we check X like this: \ \ X = 0 to -31, we are not in the enemy ship's line \ of fire, so they can't shoot at us \ \ X = -32 to -34, we are in the enemy ship's line \ of fire, so they can shoot at us, but they can't \ hit us as we're not dead in their crosshairs \ \ X = -35 to -36, we are bang in the middle of the \ enemy ship's crosshairs, so they can not only \ shoot us, they can hit us CPX #160 \ If X < 160, i.e. X > -32, then we are not in the enemy BCC TA4 \ ship's line of fire, so jump to TA4 to skip the laser \ checks LDA INWK+31 \ Set bit 6 in byte #31 to denote that the ship is ORA #%01000000 \ firing its laser at us STA INWK+31 CPX #163 \ If X < 163, i.e. X > -35, then we are not in the enemy BCC TA4 \ ship's crosshairs, so jump to TA4 to skip the laser \ checks .HIT LDY #19 \ We are being hit by enemy laser fire, so fetch the LDA (XX0),Y \ enemy ship's byte #19 from their ship's blueprint \ into A LSR A \ Halve the enemy ship's byte #19 (which contains both \ the laser power and number of missiles) to get the \ amount of damage we should take JSR OOPS \ Call OOPS to take some damage, which could do anything \ from reducing the shields and energy, all the way to \ losing cargo or dying (if the latter, we don't come \ back from this subroutine) DEC INWK+28 \ Halve the attacking ship's acceleration in byte #28 LDA ECMA \ If an E.C.M. is currently active (either ours or an BNE TA10 \ opponent's), return from the subroutine without making \ the laser-strike sound (as TA10 contains an RTS) LDA #8 \ Call the NOISE routine with A = 8 to make the sound JMP NOISE \ of us being hit by lasers, returning from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: TACTICS (Part 7 of 7) \ Type: Subroutine \ Category: Tactics \ Summary: Apply tactics: Set pitch, roll, and acceleration \ Deep dive: Program flow of the tactics routine \ Aggression and hostility in ship tactics \ \ ------------------------------------------------------------------------------ \ \ This section looks at manoeuvring the ship. Specifically: \ \ * Work out which direction the ship should be moving, depending on whether \ it's an escape pod, where it is, which direction it is pointing, and how \ aggressive it is \ \ * Set the pitch and roll counters to head in that direction \ \ * Speed up or slow down, depending on where the ship is in relation to us \ \ ****************************************************************************** .TA4 LDA INWK+7 \ If z_hi >= 3 then the ship is quite far away, so jump CMP #3 \ down to TA5 BCS TA5 LDA INWK+1 \ Otherwise set A = x_hi OR y_hi and extract bits 1-7 ORA INWK+4 AND #%11111110 BEQ TA15 \ If A = 0 then the ship is pretty close to us, so jump \ to TA15 so it heads away from us .TA5 \ If we get here then the ship is quite far away JSR DORND \ Set A and X to random numbers ORA #%10000000 \ Set bit 7 of A, so the following comparison ignores \ the AI flag in bit 7 (as we already know bit 7 is set \ in byte #32) CMP INWK+32 \ If A >= byte #32 (the ship's AI flag) then jump down BCS TA15 \ to TA15 so it heads away from us \ We get here if byte #32 > A, where byte #32 is \ composed of the following: \ \ * Bit 7 set = AI is enabled \ \ * Bits 1-6 = aggression level (0 to 63) \ \ * Bit 0 set = ship has E.C.M. \ \ We set bit 7 of A above, so if we get here we know the \ ship has AI enabled, and the comparison then boils \ down to the following: \ \ Aggression level * 2 + E.C.M. > random number 0-127 \ \ In other words, higher aggression levels increase the \ chances of a ship changing direction to head towards \ us - or, to put it another way, ships with higher \ aggression levels are spoiling for a fight, with \ E.C.M. making them even more aggressive \ \ Thargoids and missiles both have an aggression level \ of 63 out of 63, which explains an awful lot \ \ Interestingly, escape pods also have a maximum \ agression level, but in this case it makes them fly \ towards the planet rather than towards us .TA20 \ If this is a missile we will have jumped straight \ here, but we also get here if the ship is either far \ away and aggressive, or not too close LDA XX15 \ Reverse the signs of XX15 and the dot product in CNT, EOR #%10000000 \ starting with the x-coordinate STA XX15 LDA XX15+1 \ Then reverse the sign of the y-coordinate EOR #%10000000 STA XX15+1 LDA XX15+2 \ And then the z-coordinate, so now the XX15 vector goes EOR #%10000000 \ from the enemy ship to our ship (it was previously the STA XX15+2 \ other way round) LDA CNT \ And finally change the sign of the dot product in CNT, EOR #%10000000 \ so now it's positive if the ships are facing each STA CNT \ other, and negative if they are facing the same way .TA15 \ If we get here, then one of the following is true: \ \ * This is an escape pod and XX15 is pointing towards \ the planet \ \ * The ship is pretty close to us, or it's just not \ very aggressive (though there is a random factor \ at play here too). XX15 is still pointing from our \ ship towards the enemy ship \ \ * The ship is aggressive (though again, there's an \ element of randomness here). XX15 is pointing from \ the enemy ship towards our ship \ \ * This is a missile heading for a target. XX15 is \ pointing from the missile towards the target \ \ We now want to move the ship in the direction of XX15, \ which will make aggressive ships head towards us, and \ ships that are too close turn away. Escape pods, \ meanwhile, head off towards the planet in search of a \ space station, and missiles home in on their targets LDY #16 \ Set (A X) = roofv . XX15 JSR TAS3 \ \ This will be positive if XX15 is pointing in the same \ direction as an arrow out of the top of the ship, in \ other words if the ship should pull up to head in the \ direction of XX15 EOR #%10000000 \ Set the ship's pitch counter to 3, with the opposite AND #%10000000 \ sign to the dot product result, which gently pitches ORA #%00000011 \ the ship towards the direction of the XX15 vector STA INWK+30 LDA INWK+29 \ Fetch the roll counter from byte #29 into A and clear AND #%01111111 \ the sign bit (to give an endless clockwise roll) CMP #16 \ If A >= 16 then jump to TA6, as the ship is already BCS TA6 \ in the process of rolling LDY #22 \ Set (A X) = sidev . XX15 JSR TAS3 \ \ This will be positive if XX15 is pointing in the same \ direction as an arrow out of the right side of the \ ship, in other words if the ship should roll right to \ head in the direction of XX15 EOR INWK+30 \ Set the ship's roll counter to 5, with the sign set to AND #%10000000 \ positive (clockwise roll) if the pitch counter and dot EOR #%10000101 \ product have different signs, negative (anti-clockwise STA INWK+29 \ roll) if they have the same sign .TA6 LDA CNT \ Fetch the dot product, and if it's negative jump to BMI TA9 \ TA9, as the ships are facing away from each other and \ the ship might want to slow down to take another shot CMP #22 \ The dot product is positive, so the ships are facing BCC TA9 \ each other. If A < 22 then the ships are not heading \ directly towards each other, so jump to TA9 to slow \ down LDA #3 \ Otherwise set the acceleration in byte #28 to 3 STA INWK+28 RTS \ Return from the subroutine .TA9 AND #%01111111 \ Clear the sign bit of the dot product in A CMP #18 \ If A < 18 then the ship is way off the XX15 vector, so BCC TA10 \ return from the subroutine (TA10 contains an RTS) \ without slowing down, as it still has quite a bit of \ turning to do to get on course LDA #&FF \ Otherwise set A = -1 LDX TYPE \ If this is not a missile then skip the ASL instruction CPX #MSL BNE P%+3 ASL A \ This is a missile, so set A = -2, as missiles are more \ nimble and can brake more quickly STA INWK+28 \ Set the ship's acceleration to A .TA10 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TAS1 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate K3 = (x_sign x_hi x_lo) - V(1 0) \ \ ------------------------------------------------------------------------------ \ \ Calculate one of the following, depending on the value in Y: \ \ K3(2 1 0) = (x_sign x_hi x_lo) - x-coordinate in V(1 0) \ \ K3(5 4 3) = (y_sign y_hi z_lo) - y-coordinate in V(1 0) \ \ K3(8 7 6) = (z_sign z_hi z_lo) - z-coordinate in V(1 0) \ \ where the first coordinate is from the ship data block in INWK, and the second \ coordinate is from the ship data block pointed to by V(1 0). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ V(1 0) The address of the ship data block to subtract \ \ Y The coordinate in the V(1 0) block to subtract: \ \ * If Y = 2, subtract the x-coordinate and store the \ result in K3(2 1 0) \ \ * If Y = 5, subtract the y-coordinate and store the \ result in K3(5 4 3) \ \ * If Y = 8, subtract the z-coordinate and store the \ result in K3(8 7 6) \ \ ****************************************************************************** .TAS1 LDA (V),Y \ Copy the sign byte of the V(1 0) coordinate into K+3, EOR #%10000000 \ flipping it in the process STA K+3 DEY \ Copy the high byte of the V(1 0) coordinate into K+2 LDA (V),Y STA K+2 DEY \ Copy the high byte of the V(1 0) coordinate into K+1, LDA (V),Y \ so now: STA K+1 \ \ K(3 2 1) = - coordinate in V(1 0) STY U \ Copy the index (now 0, 3 or 6) into U and X LDX U JSR MVT3 \ Call MVT3 to add the same coordinates, but this time \ from INWK, so this would look like this for the \ x-axis: \ \ K(3 2 1) = (x_sign x_hi x_lo) + K(3 2 1) \ = (x_sign x_hi x_lo) - coordinate in V(1 0) LDY U \ Restore the index into Y, though this instruction has \ no effect, as Y is not used again, either here or \ following calls to this routine STA K3+2,X \ Store K(3 2 1) in K3+X(2 1 0), starting with the sign \ byte LDA K+2 \ And then doing the high byte STA K3+1,X LDA K+1 \ And finally the low byte STA K3,X RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: HITCH \ Type: Subroutine \ Category: Tactics \ Summary: Work out if the ship in INWK is in our crosshairs \ Deep dive: In the crosshairs \ \ ------------------------------------------------------------------------------ \ \ This is called by the main flight loop to see if we have laser or missile lock \ on an enemy ship. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Set if the ship is in our crosshairs, clear if it isn't \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ HI1 Contains an RTS \ \ ****************************************************************************** .HITCH CLC \ Clear the C flag so we can return with it cleared if \ our checks fail LDA INWK+8 \ Set A = z_sign BNE HI1 \ If A is non-zero then the ship is behind us and can't \ be in our crosshairs, so return from the subroutine \ with the C flag clear (as HI1 contains an RTS) LDA TYPE \ If the ship type has bit 7 set then it is the planet BMI HI1 \ or sun, which we can't target or hit with lasers, so \ return from the subroutine with the C flag clear (as \ HI1 contains an RTS) LDA INWK+31 \ Fetch bit 5 of byte #31 (the exploding flag) and OR AND #%00100000 \ with x_hi and y_hi ORA INWK+1 ORA INWK+4 BNE HI1 \ If this value is non-zero then either the ship is \ exploding (so we can't target it), or the ship is too \ far away from our line of fire to be targeted, so \ return from the subroutine with the C flag clear (as \ HI1 contains an RTS) LDA INWK \ Set A = x_lo JSR SQUA2 \ Set (A P) = A * A = x_lo^2 STA S \ Set (S R) = (A P) = x_lo^2 LDA P STA R LDA INWK+3 \ Set A = y_lo JSR SQUA2 \ Set (A P) = A * A = y_lo^2 TAX \ Store the high byte in X LDA P \ Add the two low bytes, so: ADC R \ STA R \ R = P + R TXA \ Restore the high byte into A and add S to give the ADC S \ following: \ \ (A R) = (S R) + (A P) = x_lo^2 + y_lo^2 BCS FR1-2 \ If the addition just overflowed then there is no way \ our crosshairs are within the ship's targetable area, \ so return from the subroutine with the C flag clear \ (as FR1-2 contains a CLC then an RTS) STA S \ Set (S R) = (A P) = x_lo^2 + y_lo^2 LDY #2 \ Fetch the ship's blueprint and set A to the high byte LDA (XX0),Y \ of the targetable area of the ship CMP S \ We now compare the high bytes of the targetable area \ and the calculation in (S R): \ \ * If A >= S then then the C flag will be set \ \ * If A < S then the C flag will be C clear BNE HI1 \ If A <> S we have just set the C flag correctly, so \ return from the subroutine (as HI1 contains an RTS) DEY \ The high bytes were identical, so now we fetch the LDA (XX0),Y \ low byte of the targetable area into A CMP R \ We now compare the low bytes of the targetable area \ and the calculation in (S R): \ \ * If A >= R then the C flag will be set \ \ * If A < R then the C flag will be C clear .HI1 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: FRS1 \ Type: Subroutine \ Category: Tactics \ Summary: Launch a ship straight ahead of us, below the laser sights \ \ ------------------------------------------------------------------------------ \ \ This is used in three places: \ \ * When we launch a missile, in which case the missile is the ship that is \ launched ahead of us \ \ * When we launch our escape pod, in which case it's our abandoned Cobra Mk \ III that is launched ahead of us \ \ * The fq1 entry point is used to launch a bunch of cargo canisters ahead of \ us as part of the death screen \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The type of ship to launch ahead of us \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Set if the ship was successfully launched, clear if it \ wasn't (as there wasn't enough free memory) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ fq1 Used to add a cargo canister to the universe \ \ ****************************************************************************** .FRS1 JSR ZINF \ Call ZINF to reset the INWK ship workspace LDA #28 \ Set y_lo = 28 STA INWK+3 LSR A \ Set z_lo = 14, so the launched ship starts out STA INWK+6 \ ahead of us LDA #%10000000 \ Set y_sign to be negative, so the launched ship is STA INWK+5 \ launched just below our line of sight LDA MSTG \ Set A to the missile lock target, shifted left so the ASL A \ slot number is in bits 1-5 ORA #%10000000 \ Set bit 7 and store the result in byte #32, the AI STA INWK+32 \ flag launched ship for the launched ship. For missiles \ this enables AI (bit 7), makes it friendly towards us \ (bit 6), sets the target to the value of MSTG (bits \ 1-5), and sets its lock status as launched (bit 0). \ It doesn't matter what it does for our abandoned \ Cobra, as the AI flag gets overwritten once we return \ from the subroutine back to the ESCAPE routine that \ called FRS1 in the first place .fq1 LDA #&60 \ Set byte #14 (nosev_z_hi) to 1 (&60), so the launched STA INWK+14 \ ship is pointing away from us ORA #128 \ Set byte #22 (sidev_x_hi) to -1 (&D0), so the launched STA INWK+22 \ ship has the same orientation as spawned ships, just \ pointing away from us (if we set sidev to +1 instead, \ this ship would be a mirror image of all the other \ ships, which are spawned with -1 in nosev and +1 in \ sidev) LDA DELTA \ Set byte #27 (speed) to 2 * DELTA, so the launched ROL A \ ship flies off at twice our speed STA INWK+27 TXA \ Add a new ship of type X to our local bubble of JMP NWSHP \ universe and return from the subroutine using a tail \ call \ ****************************************************************************** \ \ Name: FRMIS \ Type: Subroutine \ Category: Tactics \ Summary: Fire a missile from our ship \ \ ------------------------------------------------------------------------------ \ \ We fired a missile, so send it streaking away from us to unleash mayhem and \ destruction on our sworn enemies. \ \ ****************************************************************************** .FRMIS LDX #MSL \ Call FRS1 to launch a missile straight ahead of us JSR FRS1 BCC FR1 \ If FRS1 returns with the C flag clear, then there \ isn't room in the universe for our missile, so jump \ down to FR1 to display a "missile jammed" message LDX MSTG \ Fetch the slot number of the missile's target JSR GINF \ Get the address of the data block for the target ship \ and store it in INF LDA FRIN,X \ Fetch the ship type of the missile's target into A JSR ANGRY \ Call ANGRY to make the target ship angry; if it is the \ space station this will make it hostile, or if this is \ a ship it will wake up its AI and give it a kick of \ speed LDY #0 \ We have just launched a missile, so we need to remove JSR ABORT \ missile lock and hide the leftmost indicator on the \ dashboard by setting it to black (Y = 0) DEC NOMSL \ Reduce the number of missiles we have by 1 LDA #48 \ Call the NOISE routine with A = 48 to make the sound JMP NOISE \ of a missile launch, returning from the subroutine \ using a tail call \ ****************************************************************************** \ \ Name: ANGRY \ Type: Subroutine \ Category: Tactics \ Summary: If this is a space station then make it hostile, or if this is a \ ship then enable the ship's AI and give it a kick of speed \ Deep dive: Aggression and hostility in ship tactics \ \ ------------------------------------------------------------------------------ \ \ This routine makes a ship angry. For the space station this means setting the \ hostile flag, while for other ships it means enabling the ship's AI and giving \ it a kick of turning acceleration. Later calls to TACTICS may make the ship \ start to attack us if it has a high enough aggression level. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The type of ship we're going to irritate \ \ INF The address of the data block for the ship we're going \ to infuriate \ \ ****************************************************************************** .ANGRY CMP #SST \ If this is the space station, jump to AN2 to make the BEQ AN2 \ space station hostile BCS HI1 \ If A >= #SST then this is a missile, asteroid, cargo \ canister, Thargon or escape pod, and they can't get \ angry, so return from the subroutine (as HI1 contains \ an RTS) CMP #CYL \ If this is not a Cobra Mk III trader, skip the BNE P%+5 \ following instruction JSR AN2 \ Call AN2 to make the space station hostile LDY #32 \ Fetch the ship's byte #32 (AI flag) LDA (INF),Y BEQ HI1 \ If the AI flag is zero then this ship has no AI and \ zero aggression, so return from the subroutine (as \ HI1 contains an RTS) ORA #%10000000 \ Otherwise set bit 7 (AI enabled) to ensure AI is STA (INF),Y \ definitely enabled, so the ship can start acting \ according to its aggression level LDY #28 \ Set the ship's byte #28 (acceleration) to 2, so it LDA #2 \ speeds up STA (INF),Y ASL A \ Set the ship's byte #30 (pitch counter) to 4, so it LDY #30 \ starts diving STA (INF),Y RTS \ Return from the subroutine .AN2 ASL K%+NI%+32 \ Fetch the AI counter (byte #32) of the second ship SEC \ in the ship data workspace at K%, which is reserved ROR K%+NI%+32 \ for the sun or the space station (in this case it's \ the latter), and set bit 7 to make it hostile CLC \ Clear the C flag, which isn't used by calls to this \ routine, but it does set up the entry point FR1-2 \ so that it clears the C flag and does an RTS RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: FR1 \ Type: Subroutine \ Category: Tactics \ Summary: Display the "missile jammed" message \ \ ------------------------------------------------------------------------------ \ \ This is shown if there isn't room in the local bubble of universe for a new \ missile. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ FR1-2 Clear the C flag and return from the subroutine \ \ ****************************************************************************** .FR1 LDA #201 \ Print recursive token 41 ("MISSILE JAMMED") as an JMP MESS \ in-flight message and return from the subroutine using \ a tail call \ ****************************************************************************** \ \ Name: SESCP \ Type: Subroutine \ Category: Flight \ Summary: Spawn an escape pod from the current (parent) ship \ Deep dive: Aggression and hostility in ship tactics \ \ ------------------------------------------------------------------------------ \ \ This is called when an enemy ship has run out of both energy and luck, so it's \ time to bail. \ \ ****************************************************************************** .SESCP LDX #ESC \ Set X to the ship type for an escape pod LDA #%11111110 \ Set A to use as an AI flag that has AI enabled, an \ aggression level of 63 out of 63, and no E.C.M. \ \ When spawning an escape pod, this high agression level \ makes the pod turn towards the planet rather than \ towards us \ \ This instruction is also used as an entry point to \ spawn missile (when calling via the SFS1-2 entry \ point), in which case the missile has AI (bit 7 set), \ is hostile (bit 6 set) and has been launched (bit 0 \ clear); the target slot number is set to 31, but this \ is ignored as the hostile flag means we are the target \ Fall through into SFS1 to spawn the escape pod or \ missile \ ****************************************************************************** \ \ Name: SFS1 \ Type: Subroutine \ Category: Universe \ Summary: Spawn a child ship from the current (parent) ship \ \ ------------------------------------------------------------------------------ \ \ If the parent is a space station then the child ship is spawned coming out of \ the slot, and if the child is a cargo canister, it is sent tumbling through \ space. Otherwise the child ship is spawned with the same ship data as the \ parent, just with damping disabled and the ship type and AI flag that are \ passed in A and X. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A AI flag for the new ship (see the documentation on ship \ data byte #32 for details) \ \ X The ship type of the child to spawn \ \ INF Address of the parent's ship data block \ \ TYPE The type of the parent ship \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Set if ship successfully added, clear if it failed \ \ INF INF is preserved \ \ XX0 XX0 is preserved \ \ INWK The whole INWK workspace is preserved \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ SFS1-2 Used to add a missile to the local bubble that that has \ AI (bit 7 set), is hostile (bit 6 set) and has been \ launched (bit 0 clear); the target slot number is set to \ 31, but this is ignored as the hostile flags means we \ are the target \ \ ****************************************************************************** .SFS1 STA T1 \ Store the child ship's AI flag in T1 \ Before spawning our child ship, we need to save the \ INF and XX00 variables and the whole INWK workspace, \ so we can restore them later when returning from the \ subroutine LDA XX0 \ Store XX0(1 0) on the stack, so we can restore it PHA \ later when returning from the subroutine LDA XX0+1 PHA LDA INF \ Store INF(1 0) on the stack, so we can restore it PHA \ later when returning from the subroutine LDA INF+1 PHA LDY #NI%-1 \ Now we want to store the current INWK data block in \ temporary memory so we can restore it when we are \ done, and we also want to copy the parent's ship data \ into INWK, which we can do at the same time, so set up \ a counter in Y for NI% bytes .FRL2 LDA INWK,Y \ Copy the Y-th byte of INWK to the Y-th byte of STA XX3,Y \ temporary memory in XX3, so we can restore it later \ when returning from the subroutine LDA (INF),Y \ Copy the Y-th byte of the parent ship's data block to STA INWK,Y \ the Y-th byte of INWK DEY \ Decrement the loop counter BPL FRL2 \ Loop back to copy the next byte until we have done \ them all \ INWK now contains the ship data for the parent ship, \ so now we need to tweak the data before creating the \ new child ship (in this way, the child inherits things \ like location from the parent) LDA TYPE \ Fetch the ship type of the parent into A CMP #SST \ If the parent is not a space station, jump to rx to BNE rx \ skip the following \ The parent is a space station, so the child needs to \ launch out of the space station's slot. The space \ station's nosev vector points out of the station's \ slot, so we want to move the ship along this vector. \ We do this by taking the unit vector in nosev and \ doubling it, so we spawn our ship 2 units along the \ vector from the space station's centre TXA \ Store the child's ship type in X on the stack PHA LDA #32 \ Set the child's byte #27 (speed) to 32 STA INWK+27 LDX #0 \ Add 2 * nosev_x_hi to (x_lo, x_hi, x_sign) to get the LDA INWK+10 \ child's x-coordinate JSR SFS2 LDX #3 \ Add 2 * nosev_y_hi to (y_lo, y_hi, y_sign) to get the LDA INWK+12 \ child's y-coordinate JSR SFS2 LDX #6 \ Add 2 * nosev_z_hi to (z_lo, z_hi, z_sign) to get the LDA INWK+14 \ child's z-coordinate JSR SFS2 PLA \ Restore the child's ship type from the stack into X TAX .rx LDA T1 \ Restore the child ship's AI flag from T1 and store it STA INWK+32 \ in the child's byte #32 (AI) LSR INWK+29 \ Clear bit 0 of the child's byte #29 (roll counter) so ASL INWK+29 \ that its roll dampens (so if we are spawning from a \ space station, for example, the spawned ship won't \ keep rolling forever) TXA \ Copy the child's ship type from X into A CMP #OIL \ If the child we are spawning is not a cargo canister, BNE NOIL \ jump to NOIL to skip us setting up the pitch and roll \ for the canister JSR DORND \ Set A and X to random numbers ASL A \ Set the child's byte #30 (pitch counter) to a random STA INWK+30 \ value, and at the same time set the C flag randomly TXA \ Set the child's byte #27 (speed) to a random value AND #%00001111 \ between 0 and 15 STA INWK+27 LDA #&FF \ Set the child's byte #29 (roll counter) to a full ROR A \ roll with no damping (as bits 0 to 6 are set), so the STA INWK+29 \ canister tumbles through space, with the direction in \ bit 7 set randomly, depending on the C flag from above LDA #OIL \ Set A to the ship type of a cargo canister .NOIL JSR NWSHP \ Add a new ship of type A to the local bubble \ We have now created our child ship, so we need to \ restore all the variables we saved at the start of \ the routine, so they are preserved when we return \ from the subroutine PLA \ Restore INF(1 0) from the stack STA INF+1 PLA STA INF LDX #NI%-1 \ Now to restore the INWK workspace that we saved into \ XX3 above, so set a counter in X for NI% bytes .FRL3 LDA XX3,X \ Copy the Y-th byte of XX3 to the Y-th byte of INWK STA INWK,X DEX \ Decrement the loop counter BPL FRL3 \ Loop back to copy the next byte until we have done \ them all PLA \ Restore XX0(1 0) from the stack STA XX0+1 PLA STA XX0 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SFS2 \ Type: Subroutine \ Category: Moving \ Summary: Move a ship in space along one of the coordinate axes \ \ ------------------------------------------------------------------------------ \ \ Move a ship's coordinates by a certain amount in the direction of one of the \ axes, where X determines the axis. Mathematically speaking, this routine \ translates the ship along a single axis by a signed delta. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The amount of movement, i.e. the signed delta \ \ X Determines which coordinate axis of INWK to move: \ \ * X = 0 moves the ship along the x-axis \ \ * X = 3 moves the ship along the y-axis \ \ * X = 6 moves the ship along the z-axis \ \ ****************************************************************************** .SFS2 ASL A \ Set R = |A * 2|, with the C flag set to bit 7 of A STA R LDA #0 \ Set bit 7 of A to the C flag, i.e. the sign bit from ROR A \ the original argument in A JMP MVT1 \ Add the delta R with sign A to (x_lo, x_hi, x_sign) \ (or y or z, depending on the value in X) and return \ from the subroutine using a tail call \ ****************************************************************************** \ \ Name: LL164 \ Type: Subroutine \ Category: Drawing circles \ Summary: Make the hyperspace sound and draw the hyperspace tunnel \ \ ------------------------------------------------------------------------------ \ \ See the IRQ1 routine for details on the multi-coloured effect that's used. \ \ ****************************************************************************** .LL164 LDA #56 \ Call the NOISE routine with A = 56 to make the sound JSR NOISE \ of the hyperspace drive being engaged LDA #1 \ Set HFX to 1, which switches the screen mode to a full STA HFX \ mode 5 screen, therefore making the hyperspace rings \ multi-coloured and all zig-zaggy (see the IRQ1 routine \ for details) LDA #4 \ Set the step size for the hyperspace rings to 4, so \ there are more sections in the rings and they are \ quite round (compared to the step size of 8 used in \ the much more polygonal launch rings) JSR HFS2 \ Call HFS2 to draw the hyperspace tunnel rings DEC HFX \ Set HFX back to 0, so we switch back to the normal \ split-screen mode RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: LAUN \ Type: Subroutine \ Category: Drawing circles \ Summary: Make the launch sound and draw the launch tunnel \ \ ------------------------------------------------------------------------------ \ \ This is shown when launching from or docking with the space station. \ \ ****************************************************************************** .LAUN LDA #48 \ Call the NOISE routine with A = 48 to make the sound JSR NOISE \ of the ship launching from the station LDA #8 \ Set the step size for the launch tunnel rings to 8, so \ there are fewer sections in the rings and they are \ quite polygonal (compared to the step size of 4 used \ in the much rounder hyperspace rings) \ Fall through into HFS2 to draw the launch tunnel rings \ ****************************************************************************** \ \ Name: HFS2 \ Type: Subroutine \ Category: Drawing circles \ Summary: Draw the launch or hyperspace tunnel \ \ ------------------------------------------------------------------------------ \ \ The animation gets drawn like this. First, we draw a circle of radius 8 at the \ centre, and then double the radius, draw another circle, double the radius \ again and draw a circle, and we keep doing this until the radius is bigger \ than 160 (which goes beyond the edge of the screen, which is 256 pixels wide, \ equivalent to a radius of 128). We then repeat this whole process for an \ initial circle of radius 9, then radius 10, all the way up to radius 15. \ \ This has the effect of making the tunnel appear to be racing towards us as we \ hurtle out into hyperspace or through the space station's docking tunnel. \ \ The hyperspace effect is done in a full mode 5 screen, which makes the rings \ all coloured and zig-zaggy, while the launch screen is in the normal \ monochrome mode 4 screen. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The step size of the straight lines making up the rings \ (4 for launch, 8 for hyperspace) \ \ ****************************************************************************** .HFS2 STA STP \ Store the step size in A JSR TTX66 \ Clear the screen and draw a border box JSR HFS1 \ Call HFS1 below and then fall through into the same \ routine, so this effectively runs HFS1 twice, and as \ HFS1 draws 8 concentric rings, this means we draw 16 \ of them in all .HFS1 LDA #128 \ Set K3 = 128 (the x-coordinate of the centre of the STA K3 \ screen) LDX #Y \ Set K4 = #Y (the y-coordinate of the centre of the STX K4 \ screen) ASL A \ Set A = 0 STA XX4 \ Set XX4 = 0, which we will use as a counter for \ drawing eight concentric rings STA K3+1 \ Set the high bytes of K3(1 0) and K4(1 0) to 0 STA K4+1 .HFL5 JSR HFL1 \ Call HFL1 below to draw a set of rings, with each one \ twice the radius of the previous one, until they won't \ fit on-screen INC XX4 \ Increment the counter and fetch it into X LDX XX4 CPX #8 \ If we haven't drawn 8 sets of rings yet, loop back to BNE HFL5 \ HFL5 to draw the next ring RTS \ Return from the subroutine .HFL1 LDA XX4 \ Set K to the ring number in XX4 (0-7) + 8, so K has AND #7 \ a value of 8 to 15, which we will use as the starting CLC \ radius for our next set of rings ADC #8 STA K .HFL2 LDA #1 \ Set LSP = 1 to reset the ball line heap STA LSP JSR CIRCLE2 \ Call CIRCLE2 to draw a circle with the centre at \ (K3(1 0), K4(1 0)) and radius K ASL K \ Double the radius in K BCS HF8 \ If the radius had a 1 in bit 7 before the above shift, \ then doubling K will means the circle will no longer \ fit on the screen (which is width 256), so jump to \ HF8 to stop drawing circles LDA K \ If the radius in K <= 160, loop back to HFL2 to draw CMP #160 \ another one BCC HFL2 .HF8 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: STARS2 \ Type: Subroutine \ Category: Stardust \ Summary: Process the stardust for the left or right view \ Deep dive: Stardust in the side views \ \ ------------------------------------------------------------------------------ \ \ This moves the stardust sideways according to our speed and which side we are \ looking out of, and applies our current pitch and roll to each particle of \ dust, so the stardust moves correctly when we steer our ship. \ \ These are the calculations referred to in the commentary: \ \ 1. delta_x = 8 * 256 * speed / z_hi \ 2. x = x + delta_x \ \ 3. x = x + beta * y \ 4. y = y - beta * x \ \ 5. x = x - alpha * x * y \ 6. y = y + alpha * y * y + alpha \ \ For more information see the associated deep dive. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The view to process: \ \ * X = 1 for left view \ \ * X = 2 for right view \ \ ****************************************************************************** .STARS2 LDA #0 \ Set A to 0 so we can use it to capture a sign bit CPX #2 \ If X >= 2 then the C flag is set ROR A \ Roll the C flag into the sign bit of A and store in STA RAT \ RAT, so: \ \ * Left view, C is clear so RAT = 0 (positive) \ \ * Right view, C is set so RAT = 128 (negative) \ \ RAT represents the end of the x-axis where we want new \ stardust particles to come from: positive for the left \ view where new particles come in from the right, \ negative for the right view where new particles come \ in from the left EOR #%10000000 \ Set RAT2 to the opposite sign, so: STA RAT2 \ \ * Left view, RAT2 = 128 (negative) \ \ * Right view, RAT2 = 0 (positive) \ \ RAT2 represents the direction in which stardust \ particles should move along the x-axis: negative for \ the left view where particles go from right to left, \ positive for the right view where particles go from \ left to right JSR ST2 \ Call ST2 to flip the signs of the following if this is \ the right view: ALPHA, ALP2, ALP2+1, BET2 and BET2+1 LDY NOSTM \ Set Y to the current number of stardust particles, so \ we can use it as a counter through all the stardust .STL2 LDA SZ,Y \ Set A = ZZ = z_hi STA ZZ \ We also set ZZ to the original value of z_hi, which we \ use below to remove the existing particle LSR A \ Set A = z_hi / 8 LSR A LSR A JSR DV41 \ Call DV41 to set the following: \ \ (P R) = 256 * DELTA / A \ = 256 * speed / (z_hi / 8) \ = 8 * 256 * speed / z_hi \ \ This represents the distance we should move this \ particle along the x-axis, let's call it delta_x LDA P \ Set S = P but with the sign from RAT2, so we now have EOR RAT2 \ the distance delta_x with the correct sign in (S R): STA S \ \ (S R) = delta_x \ = 8 * 256 * speed / z_hi \ \ So (S R) is the delta, signed to match the direction \ the stardust should move in, which is result 1 above LDA SXL,Y \ Set (A P) = (x_hi x_lo) STA P \ = x LDA SX,Y STA X1 \ Set X1 = A, so X1 contains the original value of x_hi, \ which we use below to remove the existing particle JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = x + delta_x STA S \ Set (S R) = (A X) STX R \ = x + delta_x LDA SY,Y \ Set A = y_hi STA Y1 \ Set Y1 = A, so Y1 contains the original value of y_hi, \ which we use below to remove the existing particle EOR BET2 \ Give A the correct sign of A * beta, i.e. y_hi * beta LDX BET1 \ Fetch |beta| from BET1, the pitch angle JSR MULTS-2 \ Call MULTS-2 to calculate: \ \ (A P) = X * A \ = beta * y_hi JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = beta * y + x + delta_x STX XX \ Set XX(1 0) = (A X), which gives us results 2 and 3 STA XX+1 \ above, done at the same time: \ \ x = x + delta_x + beta * y LDX SYL,Y \ Set (S R) = (y_hi y_lo) STX R \ = y LDX Y1 STX S LDX BET1 \ Fetch |beta| from BET1, the pitch angle EOR BET2+1 \ Give A the opposite sign to x * beta JSR MULTS-2 \ Call MULTS-2 to calculate: \ \ (A P) = X * A \ = -beta * x JSR ADD \ Call ADD to calculate: \ \ (A X) = (A P) + (S R) \ = -beta * x + y STX YY \ Set YY(1 0) = (A X), which gives us result 4 above: STA YY+1 \ \ y = y - beta * x LDX ALP1 \ Set X = |alpha| from ALP2, the roll angle EOR ALP2 \ Give A the correct sign of A * alpha, i.e. y_hi * \ alpha JSR MULTS-2 \ Call MULTS-2 to calculate: \ \ (A P) = X * A \ = alpha * y STA Q \ Set Q = high byte of alpha * y LDA XX \ Set (S R) = XX(1 0) STA R \ = x LDA XX+1 \ STA S \ and set A = y_hi at the same time EOR #%10000000 \ Flip the sign of A = -x_hi JSR MAD \ Call MAD to calculate: \ \ (A X) = Q * A + (S R) \ = alpha * y * -x + x STA XX+1 \ Store the high byte A in XX+1 TXA \ Store the low byte X in x_lo STA SXL,Y \ So (XX+1 x_lo) now contains result 5 above: \ \ x = x - alpha * x * y LDA YY \ Set (S R) = YY(1 0) STA R \ = y LDA YY+1 \ STA S \ and set A = y_hi at the same time JSR MAD \ Call MAD to calculate: \ \ (A X) = Q * A + (S R) \ = alpha * y * y_hi + y STA S \ Set (S R) = (A X) STX R \ = y + alpha * y * y LDA #0 \ Set P = 0 STA P LDA ALPHA \ Set A = alpha, so: \ \ (A P) = (alpha 0) \ = alpha / 256 JSR PIX1 \ Call PIX1 to calculate the following: \ \ (YY+1 y_lo) = (A P) + (S R) \ = alpha * 256 + y + alpha * y * y \ \ i.e. y = y + alpha / 256 + alpha * y^2, which is \ result 6 above \ \ PIX1 also draws a particle at (X1, Y1) with distance \ ZZ, which will remove the old stardust particle, as we \ set X1, Y1 and ZZ to the original values for this \ particle during the calculations above \ We now have our newly moved stardust particle at \ x-coordinate (XX+1 x_lo) and y-coordinate (YY+1 y_lo) \ and distance z_hi, so we draw it if it's still on \ screen, otherwise we recycle it as a new bit of \ stardust and draw that LDA XX+1 \ Set X1 and x_hi to the high byte of XX in XX+1, so STA SX,Y \ the new x-coordinate is in (x_hi x_lo) and the high STA X1 \ byte is in X1 AND #%01111111 \ If |x_hi| >= 116 then jump to KILL2 to recycle this CMP #116 \ particle, as it's gone off the side of the screen, BCS KILL2 \ and rejoin at STC2 with the new particle LDA YY+1 \ Set Y1 and y_hi to the high byte of YY in YY+1, so STA SY,Y \ the new x-coordinate is in (y_hi y_lo) and the high STA Y1 \ byte is in Y1 AND #%01111111 \ If |y_hi| >= 116 then jump to ST5 to recycle this CMP #116 \ particle, as it's gone off the top or bottom of the BCS ST5 \ screen, and rejoin at STC2 with the new particle .STC2 JSR PIXEL2 \ Draw a stardust particle at (X1,Y1) with distance ZZ, \ i.e. draw the newly moved particle at (x_hi, y_hi) \ with distance z_hi DEY \ Decrement the loop counter to point to the next \ stardust particle BEQ ST2 \ If we have just done the last particle, skip the next \ instruction to return from the subroutine JMP STL2 \ We have more stardust to process, so jump back up to \ STL2 for the next particle \ Fall through into ST2 to restore the signs of the \ following if this is the right view: ALPHA, ALP2, \ ALP2+1, BET2 and BET2+1 .ST2 LDA ALPHA \ If this is the right view, flip the sign of ALPHA EOR RAT STA ALPHA LDA ALP2 \ If this is the right view, flip the sign of ALP2 EOR RAT STA ALP2 EOR #%10000000 \ If this is the right view, flip the sign of ALP2+1 STA ALP2+1 LDA BET2 \ If this is the right view, flip the sign of BET2 EOR RAT STA BET2 EOR #%10000000 \ If this is the right view, flip the sign of BET2+1 STA BET2+1 RTS \ Return from the subroutine .KILL2 JSR DORND \ Set A and X to random numbers STA Y1 \ Set y_hi and Y1 to random numbers, so the particle STA SY,Y \ starts anywhere along the y-axis LDA #115 \ Make sure A is at least 115 and has the sign in RAT ORA RAT STA X1 \ Set x_hi and X1 to A, so this particle starts on the STA SX,Y \ correct edge of the screen for new particles BNE STF1 \ Jump down to STF1 to set the z-coordinate (this BNE is \ effectively a JMP as A will never be zero) .ST5 JSR DORND \ Set A and X to random numbers STA X1 \ Set x_hi and X1 to random numbers, so the particle STA SX,Y \ starts anywhere along the x-axis LDA #110 \ Make sure A is at least 110 and has the sign in AL2+1, ORA ALP2+1 \ the flipped sign of the roll angle alpha STA Y1 \ Set y_hi and Y1 to A, so the particle starts at the STA SY,Y \ top or bottom edge, depending on the current roll \ angle alpha .STF1 JSR DORND \ Set A and X to random numbers ORA #8 \ Make sure A is at least 8 and store it in z_hi and STA ZZ \ ZZ, so the new particle starts at any distance from STA SZ,Y \ us, but not too close BNE STC2 \ Jump up to STC2 to draw this new particle (this BNE is \ effectively a JMP as A will never be zero) \ ****************************************************************************** \ \ Name: SNE \ Type: Variable \ Category: Maths (Geometry) \ Summary: Sine/cosine table \ Deep dive: The sine, cosine and arctan tables \ Drawing circles \ Drawing ellipses \ \ ------------------------------------------------------------------------------ \ \ This lookup table contains sine values for the first half of a circle, from 0 \ to 180 degrees (0 to PI radians). In terms of circle or ellipse line segments, \ there are 64 segments in a circle, so this contains sine values for segments \ 0 to 31. \ \ In terms of segments, to calculate the sine of the angle at segment x, we look \ up the value in SNE + x, and to calculate the cosine of the angle we look up \ the value in SNE + ((x + 16) mod 32). \ \ In terms of radians, to calculate the following: \ \ sin(theta) * 256 \ \ where theta is in radians, we look up the value in: \ \ SNE + (theta * 10) \ \ To calculate the following: \ \ cos(theta) * 256 \ \ where theta is in radians, look up the value in: \ \ SNE + ((theta * 10) + 16) mod 32 \ \ Theta must be between 0 and 3.1 radians, so theta * 10 is between 0 and 31. \ \ ****************************************************************************** .SNE FOR I%, 0, 31 N = ABS(SIN((I% / 64) * 2 * PI)) IF N >= 1 EQUB 255 ELSE EQUB INT(256 * N + 0.5) ENDIF NEXT \ ****************************************************************************** \ \ Name: MU5 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Set K(3 2 1 0) = (A A A A) and clear the C flag \ \ ------------------------------------------------------------------------------ \ \ In practice this is only called via a BEQ following an AND instruction, in \ which case A = 0, so this routine effectively does this: \ \ K(3 2 1 0) = 0 \ \ ****************************************************************************** .MU5 STA K \ Set K(3 2 1 0) to (A A A A) STA K+1 STA K+2 STA K+3 CLC \ Clear the C flag RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MULT3 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate K(3 2 1 0) = (A P+1 P) * Q \ Deep dive: Shift-and-add multiplication \ \ ------------------------------------------------------------------------------ \ \ Calculate the following multiplication between a signed 24-bit number and a \ signed 8-bit number, returning the result as a signed 32-bit number: \ \ K(3 2 1 0) = (A P+1 P) * Q \ \ The algorithm is the same shift-and-add algorithm as in routine MULT1, but \ extended to cope with more bits. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag The C flag is cleared \ \ ****************************************************************************** .MULT3 STA R \ Store the high byte of (A P+1 P) in R AND #%01111111 \ Set K+2 to |A|, the high byte of K(2 1 0) STA K+2 LDA Q \ Set A to bits 0-6 of Q, so A = |Q| AND #%01111111 BEQ MU5 \ If |Q| = 0, jump to MU5 to set K(3 2 1 0) to 0, \ returning from the subroutine using a tail call SEC \ Set T = |Q| - 1 SBC #1 STA T \ We now use the same shift-and-add algorithm as MULT1 \ to calculate the following: \ \ K(2 1 0) = K(2 1 0) * |Q| \ \ so we start with the first shift right, in which we \ take (K+2 P+1 P) and shift it right, storing the \ result in K(2 1 0), ready for the multiplication loop \ (so the multiplication loop actually calculates \ (|A| P+1 P) * |Q|, as the following sets K(2 1 0) to \ (|A| P+1 P) shifted right) LDA P+1 \ Set A = P+1 LSR K+2 \ Shift the high byte in K+2 to the right ROR A \ Shift the middle byte in A to the right and store in STA K+1 \ K+1 (so K+1 contains P+1 shifted right) LDA P \ Shift the middle byte in P to the right and store in ROR A \ K, so K(2 1 0) now contains (|A| P+1 P) shifted right STA K \ We now use the same shift-and-add algorithm as MULT1 \ to calculate the following: \ \ K(2 1 0) = K(2 1 0) * |Q| LDA #0 \ Set A = 0 so we can start building the answer in A LDX #24 \ Set up a counter in X to count the 24 bits in K(2 1 0) .MUL2 BCC P%+4 \ If C (i.e. the next bit from K) is set, do the ADC T \ addition for this bit of K: \ \ A = A + T + C \ = A + |Q| - 1 + 1 \ = A + |Q| ROR A \ Shift A right by one place to catch the next digit ROR K+2 \ next digit of our result in the left end of K(2 1 0), ROR K+1 \ while also shifting K(2 1 0) right to fetch the next ROR K \ bit for the calculation into the C flag \ \ On the last iteration of this loop, the bit falling \ off the end of K will be bit 0 of the original A, as \ we did one shift before the loop and we are doing 24 \ iterations. We set A to 0 before looping, so this \ means the loop exits with the C flag clear DEX \ Decrement the loop counter BNE MUL2 \ Loop back for the next bit until K(2 1 0) has been \ rotated all the way \ The result (|A| P+1 P) * |Q| is now in (A K+2 K+1 K), \ but it is positive and doesn't have the correct sign \ of the final result yet STA T \ Save the high byte of the result into T LDA R \ Fetch the sign byte from the original (A P+1 P) \ argument that we stored in R EOR Q \ EOR with Q so the sign bit is the same as that of \ (A P+1 P) * Q AND #%10000000 \ Extract the sign bit ORA T \ Apply this to the high byte of the result in T, so \ that A now has the correct sign for the result, and \ (A K+2 K+1 K) therefore contains the correctly signed \ result STA K+3 \ Store A in K+3, so K(3 2 1 0) now contains the result RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MLS2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (S R) = XX(1 0) and (A P) = A * ALP1 \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ (S R) = XX(1 0) \ \ (A P) = A * ALP1 \ \ where ALP1 is the magnitude of the current roll angle alpha, in the range \ 0-31. \ \ ****************************************************************************** .MLS2 LDX XX \ Set (S R) = XX(1 0), starting with the low bytes STX R LDX XX+1 \ And then doing the high bytes STX S \ Fall through into MLS1 to calculate (A P) = A * ALP1 \ ****************************************************************************** \ \ Name: MLS1 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A P) = ALP1 * A \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ (A P) = ALP1 * A \ \ where ALP1 is the magnitude of the current roll angle alpha, in the range \ 0-31. \ \ This routine uses an unrolled version of MU11. MU11 calculates P * X, so we \ use the same algorithm but with P set to ALP1 and X set to A. The unrolled \ version here can skip the bit tests for bits 5-7 of P as we know P < 32, so \ only 5 shifts with bit tests are needed (for bits 0-4), while the other 3 \ shifts can be done without a test (for bits 5-7). \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ MULTS-2 Calculate (A P) = X * A \ \ ****************************************************************************** .MLS1 LDX ALP1 \ Set P to the roll angle alpha magnitude in ALP1 STX P \ (0-31), so now we calculate P * A .MULTS TAX \ Set X = A, so now we can calculate P * X instead of \ P * A to get our result, and we can use the algorithm \ from MU11 to do that, just unrolled (as MU11 returns \ P * X) AND #%10000000 \ Set T to the sign bit of A STA T TXA \ Set A = |A| AND #127 BEQ MU6 \ If A = 0, jump to MU6 to set P(1 0) = 0 and return \ from the subroutine using a tail call TAX \ Set T1 = X - 1 DEX \ STX T1 \ We subtract 1 as the C flag will be set when we want \ to do an addition in the loop below LDA #0 \ Set A = 0 so we can start building the answer in A LSR P \ Set P = P >> 1 \ and C flag = bit 0 of P \ We are now going to work our way through the bits of \ P, and do a shift-add for any bits that are set, \ keeping the running total in A, but instead of using a \ loop like MU11, we just unroll it, starting with bit 0 BCC P%+4 \ If C (i.e. the next bit from P) is set, do the ADC T1 \ addition for this bit of P: \ \ A = A + T1 + C \ = A + X - 1 + 1 \ = A + X ROR A \ Shift A right to catch the next digit of our result, \ which the next ROR sticks into the left end of P while \ also extracting the next bit of P ROR P \ Add the overspill from shifting A to the right onto \ the start of P, and shift P right to fetch the next \ bit for the calculation into the C flag BCC P%+4 \ Repeat the shift-and-add loop for bit 1 ADC T1 ROR A ROR P BCC P%+4 \ Repeat the shift-and-add loop for bit 2 ADC T1 ROR A ROR P BCC P%+4 \ Repeat the shift-and-add loop for bit 3 ADC T1 ROR A ROR P BCC P%+4 \ Repeat the shift-and-add loop for bit 4 ADC T1 ROR A ROR P LSR A \ Just do the "shift" part for bit 5 ROR P LSR A \ Just do the "shift" part for bit 6 ROR P LSR A \ Just do the "shift" part for bit 7 ROR P ORA T \ Give A the sign bit of the original argument A that \ we put into T above RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SQUA \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Clear bit 7 of A and calculate (A P) = A * A \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of unsigned 8-bit numbers, after first \ clearing bit 7 of A: \ \ (A P) = A * A \ \ ****************************************************************************** .SQUA AND #%01111111 \ Clear bit 7 of A and fall through into SQUA2 to set \ (A P) = A * A \ ****************************************************************************** \ \ Name: SQUA2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A P) = A * A \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of unsigned 8-bit numbers: \ \ (A P) = A * A \ \ ****************************************************************************** .SQUA2 STA P \ Copy A into P and X TAX BNE MU11 \ If X = 0 fall through into MU1 to return a 0, \ otherwise jump to MU11 to return P * X \ ****************************************************************************** \ \ Name: MU1 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Copy X into P and A, and clear the C flag \ \ ------------------------------------------------------------------------------ \ \ Used to return a 0 result quickly from MULTU below. \ \ ****************************************************************************** .MU1 CLC \ Clear the C flag STX P \ Copy X into P and A TXA RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MLU1 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate Y1 = y_hi and (A P) = |y_hi| * Q for Y-th stardust \ \ ------------------------------------------------------------------------------ \ \ Do the following assignment, and multiply the Y-th stardust particle's \ y-coordinate with an unsigned number Q: \ \ Y1 = y_hi \ \ (A P) = |y_hi| * Q \ \ ****************************************************************************** .MLU1 LDA SY,Y \ Set Y1 the Y-th byte of SY STA Y1 \ Fall through into MLU2 to calculate: \ \ (A P) = |A| * Q \ ****************************************************************************** \ \ Name: MLU2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A P) = |A| * Q \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of a sign-magnitude 8-bit number P with an \ unsigned number Q: \ \ (A P) = |A| * Q \ \ ****************************************************************************** .MLU2 AND #%01111111 \ Clear the sign bit in P, so P = |A| STA P \ Fall through into MULTU to calculate: \ \ (A P) = P * Q \ = |A| * Q \ ****************************************************************************** \ \ Name: MULTU \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A P) = P * Q \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of unsigned 8-bit numbers: \ \ (A P) = P * Q \ \ ****************************************************************************** .MULTU LDX Q \ Set X = Q BEQ MU1 \ If X = Q = 0, jump to MU1 to copy X into P and A, \ clear the C flag and return from the subroutine using \ a tail call \ Otherwise fall through into MU11 to set (A P) = P * X \ ****************************************************************************** \ \ Name: MU11 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A P) = P * X \ Deep dive: Shift-and-add multiplication \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of two unsigned 8-bit numbers: \ \ (A P) = P * X \ \ This uses the same shift-and-add approach as MULT1, but it's simpler as we \ are dealing with unsigned numbers in P and X. \ \ ****************************************************************************** .MU11 DEX \ Set T = X - 1 STX T \ \ We subtract 1 as the C flag will be set when we want \ to do an addition in the loop below LDA #0 \ Set A = 0 so we can start building the answer in A LDX #8 \ Set up a counter in X to count the 8 bits in P LSR P \ Set P = P >> 1 \ and C flag = bit 0 of P \ We are now going to work our way through the bits of \ P, and do a shift-add for any bits that are set, \ keeping the running total in A. We just did the first \ shift right, so we now need to do the first add and \ loop through the other bits in P .MUL6 BCC P%+4 \ If C (i.e. the next bit from P) is set, do the ADC T \ addition for this bit of P: \ \ A = A + T + C \ = A + X - 1 + 1 \ = A + X ROR A \ Shift A right to catch the next digit of our result, \ which the next ROR sticks into the left end of P while \ also extracting the next bit of P ROR P \ Add the overspill from shifting A to the right onto \ the start of P, and shift P right to fetch the next \ bit for the calculation into the C flag DEX \ Decrement the loop counter BNE MUL6 \ Loop back for the next bit until P has been rotated \ all the way RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MU6 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Set P(1 0) = (A A) \ \ ------------------------------------------------------------------------------ \ \ In practice this is only called via a BEQ following an AND instruction, in \ which case A = 0, so this routine effectively does this: \ \ P(1 0) = 0 \ \ ****************************************************************************** .MU6 STA P+1 \ Set P(1 0) = (A A) STA P RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: FMLTU2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate A = K * sin(A) \ Deep dive: The sine, cosine and arctan tables \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ A = K * sin(A) \ \ Because this routine uses the sine lookup table SNE, we can also call this \ routine to calculate cosine multiplication. To calculate the following: \ \ A = K * cos(B) \ \ call this routine with B + 16 in the accumulator, as sin(B + 16) = cos(B). \ \ ****************************************************************************** .FMLTU2 AND #%00011111 \ Restrict A to bits 0-5 (so it's in the range 0-31) TAX \ Set Q = sin(A) * 256 LDA SNE,X STA Q LDA K \ Set A to the radius in K \ Fall through into FMLTU to do the following: \ \ (A ?) = A * Q \ = K * sin(A) * 256 \ \ which is equivalent to: \ \ A = K * sin(A) \ ****************************************************************************** \ \ Name: FMLTU \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate A = A * Q / 256 \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of two unsigned 8-bit numbers, returning only \ the high byte of the result: \ \ (A ?) = A * Q \ \ or, to put it another way: \ \ A = A * Q / 256 \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag The C flag is set \ \ ****************************************************************************** .FMLTU EOR #%11111111 \ Flip the bits in A, set the C flag and rotate right, SEC \ so the C flag now contains bit 0 of A inverted, and P ROR A \ contains A inverted and shifted right by one, with bit STA P \ 7 set to a 1. We can now use P as our source of bits \ to shift right, just as in MU11, just with the logic \ reversed LDA #0 \ Set A = 0 so we can start building the answer in A .MUL3 BCS MU7 \ If C (i.e. the next bit from P) is set, do not do the \ addition for this bit of P, and instead skip to MU7 \ to just do the shifts ADC Q \ Do the addition for this bit of P: \ \ A = A + Q + C \ = A + Q ROR A \ Shift A right to catch the next digit of our result. \ If we were interested in the low byte of the result we \ would want to save the bit that falls off the end, but \ we aren't, so we can ignore it LSR P \ Shift P right to fetch the next bit for the \ calculation into the C flag BNE MUL3 \ Loop back to MUL3 if P still contains some set bits \ (so we loop through the bits of P until we get to the \ 1 we inserted before the loop, and then we stop) \ If we get here then the C flag is set as we just \ rotated a 1 out of the right end of P RTS \ Return from the subroutine .MU7 LSR A \ Shift A right to catch the next digit of our result, \ pushing a 0 into bit 7 as we aren't adding anything \ here (we can't use a ROR here as the C flag is set, so \ a ROR would push a 1 into bit 7) LSR P \ Fetch the next bit from P into the C flag BNE MUL3 \ Loop back to MUL3 if P still contains some set bits \ (so we loop through the bits of P until we get to the \ 1 we inserted before the loop, and then we stop) \ If we get here then the C flag is set as we just \ rotated a 1 out of the right end of P RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: Unused duplicate of MULTU \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: An unused duplicate of the MULTU routine \ \ ------------------------------------------------------------------------------ \ \ This is a duplicate of the MULTU routine, but with no entry label, so it can't \ be called by name. It is unused, and could have been culled to save a few \ bytes (24 to be precise), but it's still here, unnamed, unloved and unvisited, \ through no fault of its own. \ \ ****************************************************************************** LDX Q BEQ MU1 DEX STX T LDA #0 LDX #8 LSR P .MUL6K \ This label is a duplicate of a label in the MULTU \ routine \ \ In the original source this label is MUL6, but \ because BeebAsm doesn't allow us to redefine labels, \ I have renamed it to MUL6K BCC P%+4 ADC T ROR A ROR P DEX BNE MUL6K RTS \ ****************************************************************************** \ \ Name: MLTU2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A P+1 P) = (A ~P) * Q \ Deep dive: Shift-and-add multiplication \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of an unsigned 16-bit number and an unsigned \ 8-bit number: \ \ (A P+1 P) = (A ~P) * Q \ \ where ~P means P EOR %11111111 (i.e. P with all its bits flipped). In other \ words, if you wanted to calculate &1234 * &56, you would: \ \ * Set A to &12 \ * Set P to &34 EOR %11111111 = &CB \ * Set Q to &56 \ \ before calling MLTU2. \ \ This routine is like a mash-up of MU11 and FMLTU. It uses part of FMLTU's \ inverted argument trick to work out whether or not to do an addition, and like \ MU11 it sets up a counter in X to extract bits from (P+1 P). But this time we \ extract 16 bits from (P+1 P), so the result is a 24-bit number. The core of \ the algorithm is still the shift-and-add approach explained in MULT1, just \ with more bits. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Q Q is preserved \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ MLTU2-2 Set Q to X, so this calculates (A P+1 P) = (A ~P) * X \ \ ****************************************************************************** STX Q \ Store X in Q .MLTU2 EOR #%11111111 \ Flip the bits in A and rotate right, storing the LSR A \ result in P+1, so we now calculate (P+1 P) * Q STA P+1 LDA #0 \ Set A = 0 so we can start building the answer in A LDX #16 \ Set up a counter in X to count the 16 bits in (P+1 P) ROR P \ Set P = P >> 1 with bit 7 = bit 0 of A \ and C flag = bit 0 of P .MUL7 BCS MU21 \ If C (i.e. the next bit from P) is set, do not do the \ addition for this bit of P, and instead skip to MU21 \ to just do the shifts ADC Q \ Do the addition for this bit of P: \ \ A = A + Q + C \ = A + Q ROR A \ Rotate (A P+1 P) to the right, so we capture the next ROR P+1 \ digit of the result in P+1, and extract the next digit ROR P \ of (P+1 P) in the C flag DEX \ Decrement the loop counter BNE MUL7 \ Loop back for the next bit until P has been rotated \ all the way RTS \ Return from the subroutine .MU21 LSR A \ Shift (A P+1 P) to the right, so we capture the next ROR P+1 \ digit of the result in P+1, and extract the next digit ROR P \ of (P+1 P) in the C flag DEX \ Decrement the loop counter BNE MUL7 \ Loop back for the next bit until P has been rotated \ all the way RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MUT3 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: An unused routine that does the same as MUT2 \ \ ------------------------------------------------------------------------------ \ \ This routine is never actually called, but it is identical to MUT2, as the \ extra instructions have no effect. \ \ ****************************************************************************** .MUT3 LDX ALP1 \ Set P = ALP1, though this gets overwritten by the STX P \ following, so this has no effect \ Fall through into MUT2 to do the following: \ \ (S R) = XX(1 0) \ (A P) = Q * A \ ****************************************************************************** \ \ Name: MUT2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (S R) = XX(1 0) and (A P) = Q * A \ \ ------------------------------------------------------------------------------ \ \ Do the following assignment, and multiplication of two signed 8-bit numbers: \ \ (S R) = XX(1 0) \ (A P) = Q * A \ \ ****************************************************************************** .MUT2 LDX XX+1 \ Set S = XX+1 STX S \ Fall through into MUT1 to do the following: \ \ R = XX \ (A P) = Q * A \ ****************************************************************************** \ \ Name: MUT1 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate R = XX and (A P) = Q * A \ \ ------------------------------------------------------------------------------ \ \ Do the following assignment, and multiplication of two signed 8-bit numbers: \ \ R = XX \ (A P) = Q * A \ \ ****************************************************************************** .MUT1 LDX XX \ Set R = XX STX R \ Fall through into MULT1 to do the following: \ \ (A P) = Q * A \ ****************************************************************************** \ \ Name: MULT1 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A P) = Q * A \ Deep dive: Shift-and-add multiplication \ \ ------------------------------------------------------------------------------ \ \ Do the following multiplication of two 8-bit sign-magnitude numbers: \ \ (A P) = Q * A \ \ ****************************************************************************** .MULT1 TAX \ Store A in X AND #%01111111 \ Set P = |A| >> 1 LSR A \ and C flag = bit 0 of A STA P TXA \ Restore argument A EOR Q \ Set bit 7 of A and T if Q and A have different signs, AND #%10000000 \ clear bit 7 if they have the same signs, 0 all other STA T \ bits, i.e. T contains the sign bit of Q * A LDA Q \ Set A = |Q| AND #%01111111 BEQ mu10 \ If |Q| = 0 jump to mu10 (with A set to 0) TAX \ Set T1 = |Q| - 1 DEX \ STX T1 \ We subtract 1 as the C flag will be set when we want \ to do an addition in the loop below \ We are now going to work our way through the bits of \ P, and do a shift-add for any bits that are set, \ keeping the running total in A. We already set up \ the first shift at the start of this routine, as \ P = |A| >> 1 and C = bit 0 of A, so we now need to set \ up a loop to sift through the other 7 bits in P LDA #0 \ Set A = 0 so we can start building the answer in A LDX #7 \ Set up a counter in X to count the 7 bits remaining \ in P .MUL4 BCC P%+4 \ If C (i.e. the next bit from P) is set, do the ADC T1 \ addition for this bit of P: \ \ A = A + T1 + C \ = A + |Q| - 1 + 1 \ = A + |Q| ROR A \ As mentioned above, this ROR shifts A right and \ catches bit 0 in C - giving another digit for our \ result - and the next ROR sticks that bit into the \ left end of P while also extracting the next bit of P \ for the next addition ROR P \ Add the overspill from shifting A to the right onto \ the start of P, and shift P right to fetch the next \ bit for the calculation DEX \ Decrement the loop counter BNE MUL4 \ Loop back for the next bit until P has been rotated \ all the way LSR A \ Rotate (A P) once more to get the final result, as ROR P \ we only pushed 7 bits through the above process ORA T \ Set the sign bit of the result that we stored in T RTS \ Return from the subroutine .mu10 STA P \ If we get here, the result is 0 and A = 0, so set \ P = 0 so (A P) = 0 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MULT12 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (S R) = Q * A \ \ ------------------------------------------------------------------------------ \ \ Calculate: \ \ (S R) = Q * A \ \ ****************************************************************************** .MULT12 JSR MULT1 \ Set (A P) = Q * A STA S \ Set (S R) = (A P) LDA P \ = Q * A STA R RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TAS3 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Calculate the dot product of XX15 and an orientation vector \ \ ------------------------------------------------------------------------------ \ \ Calculate the dot product of the vector in XX15 and one of the orientation \ vectors, as determined by the value of Y. If vect is the orientation vector, \ we calculate this: \ \ (A X) = vect . XX15 \ = vect_x * XX15 + vect_y * XX15+1 + vect_z * XX15+2 \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ Y The orientation vector: \ \ * If Y = 10, calculate nosev . XX15 \ \ * If Y = 16, calculate roofv . XX15 \ \ * If Y = 22, calculate sidev . XX15 \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ (A X) The result of the dot product \ \ ****************************************************************************** .TAS3 LDX INWK,Y \ Set Q = the Y-th byte of INWK, i.e. vect_x STX Q LDA XX15 \ Set A = XX15 JSR MULT12 \ Set (S R) = Q * A \ = vect_x * XX15 LDX INWK+2,Y \ Set Q = the Y+2-th byte of INWK, i.e. vect_y STX Q LDA XX15+1 \ Set A = XX15+1 JSR MAD \ Set (A X) = Q * A + (S R) \ = vect_y * XX15+1 + vect_x * XX15 STA S \ Set (S R) = (A X) STX R LDX INWK+4,Y \ Set Q = the Y+2-th byte of INWK, i.e. vect_z STX Q LDA XX15+2 \ Set A = XX15+2 \ Fall through into MAD to set: \ \ (A X) = Q * A + (S R) \ = vect_z * XX15+2 + vect_y * XX15+1 + \ vect_x * XX15 \ ****************************************************************************** \ \ Name: MAD \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A X) = Q * A + (S R) \ \ ------------------------------------------------------------------------------ \ \ Calculate \ \ (A X) = Q * A + (S R) \ \ ****************************************************************************** .MAD JSR MULT1 \ Call MULT1 to set (A P) = Q * A \ Fall through into ADD to do: \ \ (A X) = (A P) + (S R) \ = Q * A + (S R) \ ****************************************************************************** \ \ Name: ADD \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A X) = (A P) + (S R) \ Deep dive: Adding sign-magnitude numbers \ \ ------------------------------------------------------------------------------ \ \ Add two 16-bit sign-magnitude numbers together, calculating: \ \ (A X) = (A P) + (S R) \ \ ****************************************************************************** .ADD STA T1 \ Store argument A in T1 AND #%10000000 \ Extract the sign (bit 7) of A and store it in T STA T EOR S \ EOR bit 7 of A with S. If they have different bit 7s BMI MU8 \ (i.e. they have different signs) then bit 7 in the \ EOR result will be 1, which means the EOR result is \ negative. So the AND, EOR and BMI together mean "jump \ to MU8 if A and S have different signs" \ If we reach here, then A and S have the same sign, so \ we can add them and set the sign to get the result LDA R \ Add the least significant bytes together into X: CLC \ ADC P \ X = P + R TAX LDA S \ Add the most significant bytes together into A. We ADC T1 \ stored the original argument A in T1 earlier, so we \ can do this with: \ \ A = A + S + C \ = T1 + S + C ORA T \ If argument A was negative (and therefore S was also \ negative) then make sure result A is negative by \ OR'ing the result with the sign bit from argument A \ (which we stored in T) RTS \ Return from the subroutine .MU8 \ If we reach here, then A and S have different signs, \ so we can subtract their absolute values and set the \ sign to get the result LDA S \ Clear the sign (bit 7) in S and store the result in AND #%01111111 \ U, so U now contains |S| STA U LDA P \ Subtract the least significant bytes into X: SEC \ SBC R \ X = P - R TAX LDA T1 \ Restore the A of the argument (A P) from T1 and AND #%01111111 \ clear the sign (bit 7), so A now contains |A| SBC U \ Set A = |A| - |S| \ At this point we have |A P| - |S R| in (A X), so we \ need to check whether the subtraction above was the \ right way round (i.e. that we subtracted the smaller \ absolute value from the larger absolute value) BCS MU9 \ If |A| >= |S|, our subtraction was the right way \ round, so jump to MU9 to set the sign \ If we get here, then |A| < |S|, so our subtraction \ above was the wrong way round (we actually subtracted \ the larger absolute value from the smaller absolute \ value). So let's subtract the result we have in (A X) \ from zero, so that the subtraction is the right way \ round STA U \ Store A in U TXA \ Set X = 0 - X using two's complement (to negate a EOR #&FF \ number in two's complement, you can invert the bits ADC #1 \ and add one - and we know the C flag is clear as we TAX \ didn't take the BCS branch above, so the ADC will do \ the correct addition) LDA #0 \ Set A = 0 - A, which we can do this time using a SBC U \ subtraction with the C flag clear ORA #%10000000 \ We now set the sign bit of A, so that the EOR on the \ next line will give the result the opposite sign to \ argument A (as T contains the sign bit of argument \ A). This is the same as giving the result the same \ sign as argument S (as A and S have different signs), \ which is what we want, as S has the larger absolute \ value .MU9 EOR T \ If we get here from the BCS above, then |A| >= |S|, \ so we want to give the result the same sign as \ argument A, so if argument A was negative, we flip \ the sign of the result with an EOR (to make it \ negative) RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TIS1 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (A ?) = (-X * A + (S R)) / 96 \ Deep dive: Shift-and-subtract division \ \ ------------------------------------------------------------------------------ \ \ Calculate the following expression between sign-magnitude numbers, ignoring \ the low byte of the result: \ \ (A ?) = (-X * A + (S R)) / 96 \ \ This uses the same shift-and-subtract algorithm as TIS2, just with the \ quotient A hard-coded to 96. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Q Gets set to the value of argument X \ \ ****************************************************************************** .TIS1 STX Q \ Set Q = X EOR #%10000000 \ Flip the sign bit in A JSR MAD \ Set (A X) = Q * A + (S R) \ = X * -A + (S R) .DVID96 TAX \ Set T to the sign bit of the result AND #%10000000 STA T TXA \ Set A to the high byte of the result with the sign bit AND #%01111111 \ cleared, so (A ?) = |X * A + (S R)| \ The following is identical to TIS2, except Q is \ hard-coded to 96, so this does A = A / 96 LDX #254 \ Set T1 to have bits 1-7 set, so we can rotate through STX T1 \ 7 loop iterations, getting a 1 each time, and then \ getting a 0 on the 8th iteration... and we can also \ use T1 to catch our result bits into bit 0 each time .DVL3 ASL A \ Shift A to the left CMP #96 \ If A < 96 skip the following subtraction BCC DV4 SBC #96 \ Set A = A - 96 \ \ Going into this subtraction we know the C flag is \ set as we passed through the BCC above, and we also \ know that A >= 96, so the C flag will still be set \ once we are done .DV4 ROL T1 \ Rotate the counter in T1 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 DVL3 \ If we still have set bits in T1, loop back to DVL3 to \ do the next iteration of 7 LDA T1 \ Fetch the result from T1 into A ORA T \ Give A the sign of the result that we stored above RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DV42 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (P R) = 256 * DELTA / z_hi \ \ ------------------------------------------------------------------------------ \ \ Calculate the following division and remainder: \ \ P = DELTA / (the Y-th stardust particle's z_hi coordinate) \ \ R = remainder as a fraction of A, where 1.0 = 255 \ \ Another way of saying the above is this: \ \ (P R) = 256 * DELTA / z_hi \ \ DELTA is a value between 1 and 40, and the minimum z_hi is 16 (dust particles \ are removed at lower values than this), so this means P is between 0 and 2 \ (as 40 / 16 = 2.5, so the maximum result is P = 2 and R = 128. \ \ This uses the same shift-and-subtract algorithm as TIS2, but this time we \ keep the remainder. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ Y The number of the stardust particle to process \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag The C flag is cleared \ \ ****************************************************************************** .DV42 LDA SZ,Y \ Fetch the Y-th dust particle's z_hi coordinate into A \ Fall through into DV41 to do: \ \ (P R) = 256 * DELTA / A \ = 256 * DELTA / Y-th stardust particle's z_hi \ ****************************************************************************** \ \ Name: DV41 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (P R) = 256 * DELTA / A \ \ ------------------------------------------------------------------------------ \ \ Calculate the following division and remainder: \ \ P = DELTA / A \ \ R = remainder as a fraction of A, where 1.0 = 255 \ \ Another way of saying the above is this: \ \ (P R) = 256 * DELTA / A \ \ This uses the same shift-and-subtract algorithm as TIS2, but this time we \ keep the remainder. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag The C flag is cleared \ \ ****************************************************************************** .DV41 STA Q \ Store A in Q LDA DELTA \ Fetch the speed from DELTA into A \ Fall through into DVID4 to do: \ \ (P R) = 256 * A / Q \ = 256 * DELTA / A \ ****************************************************************************** \ \ Name: DVID4 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (P R) = 256 * A / Q \ Deep dive: Shift-and-subtract division \ \ ------------------------------------------------------------------------------ \ \ Calculate the following division and remainder: \ \ P = A / Q \ \ R = remainder as a fraction of Q, where 1.0 = 255 \ \ Another way of saying the above is this: \ \ (P R) = 256 * A / Q \ \ This uses the same shift-and-subtract algorithm as TIS2, but this time we \ keep the remainder. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag The C flag is cleared \ \ ****************************************************************************** .DVID4 LDX #8 \ Set a counter in X to count the 8 bits in A ASL A \ Shift A left and store in P (we will build the result STA P \ in P) LDA #0 \ Set A = 0 for us to build a remainder .DVL4 ROL A \ Shift A to the left BCS DV8 \ If the C flag is set (i.e. bit 7 of A was set) then \ skip straight to the subtraction CMP Q \ If A < Q skip the following subtraction BCC DV5 .DV8 SBC Q \ A >= Q, so set A = A - Q SEC \ Set the C flag, so that P gets a 1 shifted into bit 0 .DV5 ROL P \ Shift P to the left, pulling the C flag into bit 0 DEX \ Decrement the loop counter BNE DVL4 \ Loop back for the next bit until we have done all 8 \ bits of P JMP LL28+4 \ Jump to LL28+4 to convert the remainder in A into an \ integer representation of the fractional value A / Q, \ in R, where 1.0 = 255. LL28+4 always returns with the \ C flag cleared, and we return from the subroutine \ using a tail call \ ****************************************************************************** \ \ Name: DVID3B2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate K(3 2 1 0) = (A P+1 P) / (z_sign z_hi z_lo) \ Deep dive: Shift-and-subtract division \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ K(3 2 1 0) = (A P+1 P) / (z_sign z_hi z_lo) \ \ The actual division here is done as an 8-bit calculation using LL31, but this \ routine shifts both the numerator (the top part of the division) and the \ denominator (the bottom part of the division) around to get the multi-byte \ result we want. \ \ Specifically, it shifts both of them to the left as far as possible, keeping a \ tally of how many shifts get done in each one - and specifically, the \ difference in the number of shifts between the top and bottom (as shifting \ both of them once in the same direction won't change the result). It then \ divides the two highest bytes with the simple 8-bit routine in LL31, and \ shifts the result by the difference in the number of shifts, which acts as a \ scale factor to get the correct result. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ K(3 2 1 0) The result of the division \ \ X X is preserved \ \ ****************************************************************************** .DVID3B2 STA P+2 \ Set P+2 = A LDA INWK+6 \ Set Q = z_lo STA Q LDA INWK+7 \ Set R = z_hi STA R LDA INWK+8 \ Set S = z_sign STA S .DVID3B \ Given the above assignments, we now want to calculate \ the following to get the result we want: \ \ K(3 2 1 0) = P(2 1 0) / (S R Q) LDA P \ Make sure P(2 1 0) is at least 1 ORA #1 STA P LDA P+2 \ Set T to the sign of P+2 * S (i.e. the sign of the EOR S \ result) and store it in T AND #%10000000 STA T LDY #0 \ Set Y = 0 to store the scale factor LDA P+2 \ Clear the sign bit of P+2, so the division can be done AND #%01111111 \ with positive numbers and we'll set the correct sign \ below, once all the maths is done \ \ This also leaves A = P+2, which we use below .DVL9 \ We now shift (A P+1 P) left until A >= 64, counting \ the number of shifts in Y. This makes the top part of \ the division as large as possible, thus retaining as \ much accuracy as we can. When we come to return the \ final result, we shift the result by the number of \ places in Y, and in the correct direction CMP #64 \ If A >= 64, jump down to DV14 BCS DV14 ASL P \ Shift (A P+1 P) to the left ROL P+1 ROL A INY \ Increment the scale factor in Y BNE DVL9 \ Loop up to DVL9 (this BNE is effectively a JMP, as Y \ will never be zero) .DV14 \ If we get here, A >= 64 and contains the highest byte \ of the numerator, scaled up by the number of left \ shifts in Y STA P+2 \ Store A in P+2, so we now have the scaled value of \ the numerator in P(2 1 0) LDA S \ Set A = |S| AND #%01111111 BMI DV9 \ If bit 7 of A is set, jump down to DV9 to skip the \ left-shifting of the denominator (though this branch \ instruction has no effect as bit 7 of the above AND \ can never be set, which is why this instruction was \ removed from later versions) .DVL6 \ We now shift (S R Q) left until bit 7 of S is set, \ reducing Y by the number of shifts. This makes the \ bottom part of the division as large as possible, thus \ retaining as much accuracy as we can. When we come to \ return the final result, we shift the result by the \ total number of places in Y, and in the correct \ direction, to give us the correct result \ \ We set A to |S| above, so the following actually \ shifts (A R Q) DEY \ Decrement the scale factor in Y ASL Q \ Shift (A R Q) to the left ROL R ROL A BPL DVL6 \ Loop up to DVL6 to do another shift, until bit 7 of A \ is set and we can't shift left any further .DV9 \ We have now shifted both the numerator and denominator \ left as far as they will go, keeping a tally of the \ overall scale factor of the various shifts in Y. We \ can now divide just the two highest bytes to get our \ result STA Q \ Set Q = A, the highest byte of the denominator LDA #254 \ Set R to have bits 1-7 set, so we can pass this to STA R \ LL31 to act as the bit counter in the division LDA P+2 \ Set A to the highest byte of the numerator JSR LL31 \ Call LL31 to calculate: \ \ R = 256 * A / Q \ = 256 * numerator / denominator \ The result of our division is now in R, so we just \ need to shift it back by the scale factor in Y LDA #0 \ Set K(3 2 1) = 0 to hold the result (we populate K STA K+1 \ next) STA K+2 STA K+3 TYA \ If Y is positive, jump to DV12 BPL DV12 \ If we get here then Y is negative, so we need to shift \ the result R to the left by Y places, and then set the \ correct sign for the result LDA R \ Set A = R .DVL8 ASL A \ Shift (K+3 K+2 K+1 A) left ROL K+1 ROL K+2 ROL K+3 INY \ Increment the scale factor in Y BNE DVL8 \ Loop back to DVL8 until we have shifted left by Y \ places STA K \ Store A in K so the result is now in K(3 2 1 0) LDA K+3 \ Set K+3 to the sign in T, which we set above to the ORA T \ correct sign for the result STA K+3 RTS \ Return from the subroutine .DV13 \ If we get here then Y is zero, so we don't need to \ shift the result R, we just need to set the correct \ sign for the result LDA R \ Store R in K so the result is now in K(3 2 1 0) STA K LDA T \ Set K+3 to the sign in T, which we set above to the STA K+3 \ correct sign for the result RTS \ Return from the subroutine .DV12 BEQ DV13 \ We jumped here having set A to the scale factor in Y, \ so this jumps up to DV13 if Y = 0 \ If we get here then Y is positive and non-zero, so we \ need to shift the result R to the right by Y places \ and then set the correct sign for the result. We also \ know that K(3 2 1) will stay 0, as we are shifting the \ lowest byte to the right, so no set bits will make \ their way into the top three bytes LDA R \ Set A = R .DVL10 LSR A \ Shift A right DEY \ Decrement the scale factor in Y BNE DVL10 \ Loop back to DVL10 until we have shifted right by Y \ places STA K \ Store the shifted A in K so the result is now in \ K(3 2 1 0) LDA T \ Set K+3 to the sign in T, which we set above to the STA K+3 \ correct sign for the result RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: cntr \ Type: Subroutine \ Category: Dashboard \ Summary: Apply damping to the pitch or roll dashboard indicator \ \ ------------------------------------------------------------------------------ \ \ Apply damping to the value in X, where X ranges from 1 to 255 with 128 as the \ centre point (so X represents a position on a centre-based dashboard slider, \ such as pitch or roll). If the value is in the left-hand side of the slider \ (1-127) then it bumps the value up by 1 so it moves towards the centre, and \ if it's in the right-hand side, it reduces it by 1, also moving it towards the \ centre. \ \ ****************************************************************************** .cntr LDA DAMP \ If DAMP is non-zero, then keyboard damping is not BNE RE1 \ enabled, so jump to RE1 to return from the subroutine TXA \ If X < 128, then it's in the left-hand side of the BPL BUMP \ dashboard slider, so jump to BUMP to bump it up by 1, \ to move it closer to the centre DEX \ Otherwise X >= 128, so it's in the right-hand side BMI RE1 \ of the dashboard slider, so decrement X by 1, and if \ it's still >= 128, jump to RE1 to return from the \ subroutine, otherwise fall through to BUMP to undo \ the bump and then return .BUMP INX \ Bump X up by 1, and if it hasn't overshot the end of BNE RE1 \ the dashboard slider, jump to RE1 to return from the \ subroutine, otherwise fall through to REDU to drop \ it down by 1 again .REDU DEX \ Reduce X by 1, and if we have reached 0 jump up to BEQ BUMP \ BUMP to add 1, because we need the value to be in the \ range 1 to 255 .RE1 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: BUMP2 \ Type: Subroutine \ Category: Dashboard \ Summary: Bump up the value of the pitch or roll dashboard indicator \ \ ------------------------------------------------------------------------------ \ \ Increase ("bump up") X by A, where X is either the current rate of pitch or \ the current rate of roll. \ \ The rate of pitch or roll ranges from 1 to 255 with 128 as the centre point. \ This is the amount by which the pitch or roll is currently changing, so 1 \ means it is decreasing at the maximum rate, 128 means it is not changing, \ and 255 means it is increasing at the maximum rate. These values correspond \ to the line on the DC or RL indicators on the dashboard, with 1 meaning full \ left, 128 meaning the middle, and 255 meaning full right. \ \ If bumping up X would push it past 255, then X is set to 255. \ \ If keyboard auto-recentre is configured and the result is less than 128, we \ bump X up to the mid-point, 128. This is the equivalent of having a roll or \ pitch in the left half of the indicator, when increasing the roll or pitch \ should jump us straight to the mid-point. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ RE2+2 Restore A from T and return from the subroutine \ \ ****************************************************************************** .BUMP2 STA T \ Store argument A in T so we can restore it later TXA \ Copy argument X into A CLC \ Clear the C flag so we can do addition without the \ C flag affecting the result ADC T \ Set X = A = argument X + argument A TAX BCC RE2 \ If the C flag is clear, then we didn't overflow, so \ jump to RE2 to auto-recentre and return the result LDX #255 \ We have an overflow, so set X to the maximum possible \ value of 255 .RE2 BPL RE3+2 \ If X has bit 7 clear (i.e. the result < 128), then \ jump to RE3+2 in routine REDU2 to do an auto-recentre, \ if configured, because the result is on the left side \ of the centre point of 128 \ Jumps to RE2+2 end up here LDA T \ Restore the original argument A from T into A RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: REDU2 \ Type: Subroutine \ Category: Dashboard \ Summary: Reduce the value of the pitch or roll dashboard indicator \ \ ------------------------------------------------------------------------------ \ \ Reduce X by A, where X is either the current rate of pitch or the current \ rate of roll. \ \ The rate of pitch or roll ranges from 1 to 255 with 128 as the centre point. \ This is the amount by which the pitch or roll is currently changing, so 1 \ means it is decreasing at the maximum rate, 128 means it is not changing, \ and 255 means it is increasing at the maximum rate. These values correspond \ to the line on the DC or RL indicators on the dashboard, with 1 meaning full \ left, 128 meaning the middle, and 255 meaning full right. \ \ If reducing X would bring it below 1, then X is set to 1. \ \ If keyboard auto-recentre is configured and the result is greater than 128, we \ reduce X down to the mid-point, 128. This is the equivalent of having a roll \ or pitch in the right half of the indicator, when decreasing the roll or pitch \ should jump us straight to the mid-point. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ RE3+2 Auto-recentre the value in X, if keyboard auto-recentre \ is configured \ \ ****************************************************************************** .REDU2 STA T \ Store argument A in T so we can restore it later TXA \ Copy argument X into A SEC \ Set the C flag so we can do subtraction without the \ C flag affecting the result SBC T \ Set X = A = argument X - argument A TAX BCS RE3 \ If the C flag is set, then we didn't underflow, so \ jump to RE3 to auto-recentre and return the result LDX #1 \ We have an underflow, so set X to the minimum possible \ value, 1 .RE3 BPL RE2+2 \ If X has bit 7 clear (i.e. the result < 128), then \ jump to RE2+2 above to return the result as is, \ because the result is on the left side of the centre \ point of 128, so we don't need to auto-centre \ Jumps to RE3+2 end up here \ If we get here, then we need to apply auto-recentre, \ if it is configured LDA DJD \ If keyboard auto-recentre is disabled, then jump to BNE RE2+2 \ RE2+2 to restore A and return LDX #128 \ If we get here then keyboard auto-recentre is enabled, BMI RE2+2 \ so set X to 128 (the middle of our range) and jump to \ RE2+2 to restore A and return from the subroutine \ (this BMI is effectively a JMP as bit 7 of X is always \ set) \ ****************************************************************************** \ \ Name: ARCTAN \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Calculate A = arctan(P / Q) \ Deep dive: The sine, cosine and arctan tables \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ A = arctan(P / Q) \ \ In other words, this finds the angle in the right-angled triangle where the \ opposite side to angle A is length P and the adjacent side to angle A has \ length Q, so: \ \ tan(A) = P / Q \ \ The result in A is an integer representing the angle in radians. The routine \ returns values in the range 0 to 128, which covers 0 to 180 degrees (or 0 to \ PI radians). \ \ ****************************************************************************** .ARCTAN LDA P \ Set T1 = P EOR Q, which will have the sign of P * Q EOR Q \ \AND #%10000000 \ The AND is commented out in the original source STA T1 LDA Q \ If Q = 0, jump to AR2 to return a right angle BEQ AR2 ASL A \ Set Q = |Q| * 2 (this is a quick way of clearing the STA Q \ sign bit, and we don't need to shift right again as we \ only ever use this value in the division with |P| * 2, \ which we set next) LDA P \ Set A = |P| * 2 ASL A CMP Q \ If A >= Q, i.e. |P| > |Q|, jump to AR1 to swap P BCS AR1 \ and Q around, so we can still use the lookup table JSR ARS1 \ Call ARS1 to set the following from the lookup table: \ \ A = arctan(A / Q) \ = arctan(|P / Q|) SEC \ Set the C flag so the SBC instruction in AR3 will be \ correct, should we jump there .AR4 LDX T1 \ If T1 is negative, i.e. P and Q have different signs, BMI AR3 \ jump down to AR3 to return arctan(-|P / Q|) RTS \ Otherwise P and Q have the same sign, so our result is \ correct and we can return from the subroutine .AR1 \ We want to calculate arctan(t) where |t| > 1, so we \ can use the calculation described in the documentation \ for the ACT table, i.e. 64 - arctan(1 / t) LDX Q \ Swap the values in Q and P, using the fact that we STA Q \ called AR1 with A = P STX P \ TXA \ This also sets A = P (which now contains the original \ argument |Q|) JSR ARS1 \ Call ARS1 to set the following from the lookup table: \ \ A = arctan(A / Q) \ = arctan(|Q / P|) \ = arctan(1 / |P / Q|) STA T \ Set T = 64 - T LDA #64 SBC T BCS AR4 \ Jump to AR4 to continue the calculation (this BCS is \ effectively a JMP as the subtraction will never \ underflow, as ARS1 returns values in the range 0-31) .AR2 \ If we get here then Q = 0, so tan(A) = infinity and \ A is a right angle, or 0.25 of a circle. We allocate \ 255 to a full circle, so we should return 63 for a \ right angle LDA #63 \ Set A to 63, to represent a right angle RTS \ Return from the subroutine .AR3 \ A contains arctan(|P / Q|) but P and Q have different \ signs, so we need to return arctan(-|P / Q|), using \ the calculation described in the documentation for the \ ACT table, i.e. 128 - A STA T \ Set A = 128 - A LDA #128 \ \SEC \ The SEC instruction is commented out in the original SBC T \ source, and isn't required as we did a SEC before \ calling AR3 RTS \ Return from the subroutine .ARS1 \ This routine fetches arctan(A / Q) from the ACT table, \ so A will be set to an integer in the range 0 to 31 \ that represents an angle from 0 to 45 degrees (or 0 to \ PI / 4 radians) JSR LL28 \ Call LL28 to calculate: \ \ R = 256 * A / Q LDA R \ Set X = R / 8 LSR A \ = 32 * A / Q LSR A \ LSR A \ so X has the value t * 32 where t = A / Q, which is TAX \ what we need to look up values in the ACT table LDA ACT,X \ Fetch ACT+X from the ACT table into A, so now: \ \ A = value in ACT + X \ = value in ACT + (32 * A / Q) \ = arctan(A / Q) RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: ACT \ Type: Variable \ Category: Maths (Geometry) \ Summary: Arctan table \ Deep dive: The sine, cosine and arctan tables \ \ ------------------------------------------------------------------------------ \ \ This table contains lookup values for arctangent calculations involving angles \ in the range 0 to 45 degrees (or 0 to PI / 4 radians). \ \ To calculate the value of theta in the following: \ \ theta = arctan(t) \ \ where 0 <= t < 1, we look up the value in: \ \ ACT + (t * 32) \ \ The result will be an integer representing the angle in radians, where 256 \ represents a full circle of 360 degrees (2 * PI radians). The result of the \ lookup will therefore be an integer in the range 0 to 31, as this represents \ 0 to 45 degrees (0 to PI / 4 radians). \ \ The table does not support values of t >= 1 or t < 0 directly, so if we need \ to calculate the arctangent for an angle greater than 45 degrees, we can apply \ the following calculation to the result from the table: \ \ * For t > 1, arctan(t) = 64 - arctan(1 / t) \ \ For negative values of t where -1 < t < 0, we can apply the following \ calculation to the result from the table: \ \ * For t < 0, arctan(-t) = 128 - arctan(t) \ \ Finally, if t < -1, we can do the first calculation to get arctan(|t|), and \ the second to get arctan(-|t|). \ \ ****************************************************************************** .ACT FOR I%, 0, 31 EQUB INT((128 / PI) * ATN(I% / 32) + 0.5) NEXT \ ****************************************************************************** \ \ Name: WARP \ Type: Subroutine \ Category: Flight \ Summary: Perform an in-system jump \ Deep dive: A sense of scale \ \ ------------------------------------------------------------------------------ \ \ This is called when we press "J" during flight. The following checks are \ performed: \ \ * Make sure we don't have any ships or space stations in the vicinity \ \ * Make sure we are not in witchspace \ \ * If we are facing the planet, make sure we aren't too close \ \ * If we are facing the sun, make sure we aren't too close \ \ If the above checks are passed, then we perform an in-system jump by moving \ the sun and planet in the opposite direction to travel, so we appear to jump \ in space. This means that any asteroids, cargo canisters or escape pods get \ dragged along for the ride. \ \ ****************************************************************************** .WARP IF _SOURCE_DISC LDA MANY+AST \ Set X to the total number of asteroids, escape pods CLC \ and cargo canisters in the vicinity ADC MANY+ESC CLC \ The second CLC instruction has no effect, as there is ADC MANY+OIL \ no way that adding the number of asteroids and the TAX \ number escape pods will cause a carry ELIF _TEXT_SOURCES OR _STH_CASSETTE LDA MANY+AST \ Set X to the total number of asteroids, escape pods CLC \ and cargo canisters in the vicinity ADC MANY+ESC \ ADC MANY+OIL \ This code saves one byte of memory over the code in TAX \ the source disc version. The second CLC is not needed \ as there is no way that adding the number of asteroids \ and the number of escape pods will cause a carry ENDIF LDA FRIN+2,X \ If the slot at FRIN+2+X is non-zero, then we have \ something else in the vicinity besides asteroids, \ escape pods and cargo canisters, so to check whether \ we can jump, we first grab the slot contents into A ORA SSPR \ If there is a space station nearby, then SSPR will \ be non-zero, so OR'ing with SSPR will produce a \ non-zero result if either A or SSPR are non-zero ORA MJ \ If we are in witchspace, then MJ will be non-zero, so \ OR'ing with MJ will produce a non-zero result if \ either A or SSPR or MJ are non-zero BNE WA1 \ A is non-zero if we have either a ship or a space \ station in the vicinity, or we are in witchspace, in \ which case jump to WA1 to make a low beep to show that \ we can't do an in-system jump LDY K%+8 \ Otherwise we can do an in-system jump, so now we fetch \ the byte at K%+8, which contains the z_sign for the \ first ship slot, i.e. the distance of the planet BMI WA3 \ If the planet's z_sign is negative, then the planet \ is behind us, so jump to WA3 to skip the following TAY \ Set A = Y = 0 (as we didn't BNE above) so the call \ to MAS2 measures the distance to the planet JSR MAS2 \ Call MAS2 to set A to the largest distance to the \ planet in any of the three axes (we could also call \ routine m to do the same thing, as A = 0) IF _SOURCE_DISC CMP #2 \ If A < 2 then jump to WA1 to abort the in-system jump BCC WA1 \ with a low beep, as we are facing the planet and are \ too close to jump in that direction ELIF _TEXT_SOURCES OR _STH_CASSETTE LSR A \ If A < 2 then jump to WA1 to abort the in-system jump BEQ WA1 \ with a low beep, as we are facing the planet and are \ too close to jump in that direction \ \ These instructions between them save one byte of \ memory over the CMP-based code in the source disc \ version, as LSR A is a one-byte opcode, while CMP #2 \ takes up two bytes (though the code does exactly the \ same thing) ENDIF .WA3 LDY K%+NI%+8 \ Fetch the z_sign (byte #8) of the second ship in the \ ship data workspace at K%, which is reserved for the \ sun or the space station (in this case it's the \ former, as we already confirmed there isn't a space \ station in the vicinity) BMI WA2 \ If the sun's z_sign is negative, then the sun is \ behind us, so jump to WA2 to skip the following LDY #NI% \ Set Y to point to the offset of the ship data block \ for the sun, which is NI% (as each block is NI% bytes \ long, and the sun is the second block) JSR m \ Call m to set A to the largest distance to the sun \ in any of the three axes IF _SOURCE_DISC CMP #2 \ If A < 2 then jump to WA1 to abort the in-system jump BCC WA1 \ with a low beep, as we are facing the planet and are \ too close to jump in that direction ELIF _TEXT_SOURCES OR _STH_CASSETTE LSR A \ If A < 2 then jump to WA1 to abort the in-system jump BEQ WA1 \ with a low beep, as we are facing the planet and are \ too close to jump in that direction \ \ These instructions between them save one byte of \ memory over the CMP-based code in the source disc \ version, as LSR A is a one-byte opcode, while CMP #2 \ takes up two bytes (though the code does exactly the \ same thing) ENDIF .WA2 \ If we get here, then we can do an in-system jump, as \ we don't have any ships or space stations in the \ vicinity, we are not in witchspace, and if we are \ facing the planet or the sun, we aren't too close to \ jump towards it \ \ We do an in-system jump by moving the sun and planet, \ rather than moving our own local bubble (this is why \ in-system jumps drag asteroids, cargo canisters and \ escape pods along for the ride). Specifically, we move \ them in the z-axis by a fixed amount in the opposite \ direction to travel, thus performing a jump towards \ our destination LDA #&81 \ Set R = R = P = &81 STA S STA R STA P LDA K%+8 \ Set A = z_sign for the planet JSR ADD \ Set (A X) = (A P) + (S R) \ = (z_sign &81) + &8181 \ = (z_sign &81) - &0181 \ \ This moves the planet against the direction of travel \ by reducing z_sign by 1, as the above maths is: \ \ z_sign 00000000 \ + 00000000 10000001 \ - 00000001 10000001 \ \ or: \ \ z_sign 00000000 \ + 00000000 00000000 \ - 00000001 00000000 \ \ i.e. the high byte is z_sign - 1, making sure the sign \ is preserved STA K%+8 \ Set the planet's z_sign to the high byte of the result LDA K%+NI%+8 \ Set A = z_sign for the sun JSR ADD \ Set (A X) = (A P) + (S R) \ = (z_sign &81) + &8181 \ = (z_sign &81) - &0181 \ \ which moves the sun against the direction of travel \ by reducing z_sign by 1 STA K%+NI%+8 \ Set the planet's z_sign to the high byte of the result LDA #1 \ Temporarily set the view type to a non-zero value, so STA QQ11 \ the call to LOOK1 below clears the screen before \ switching to the space view STA MCNT \ Set the main loop counter to 1, so the next iteration \ through the main loop will potentially spawn ships \ (see part 2 of the main game loop at me3) LSR A \ Set EV, the extra vessels spawning counter, to 0 STA EV \ (the LSR produces a 0 as A was previously 1) LDX VIEW \ Set X to the current view (front, rear, left or right) JMP LOOK1 \ and jump to LOOK1 to initialise that view, returning \ from the subroutine using a tail call .WA1 LDA #40 \ If we get here then we can't do an in-system jump, so JMP NOISE \ call the NOISE routine with A = 40 to make a long, low \ beep and return from the subroutine using a tail call \ ****************************************************************************** \ \ Name: LASLI \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw the laser lines for when we fire our lasers \ \ ------------------------------------------------------------------------------ \ \ Draw the laser lines, aiming them to slightly different place each time so \ they appear to flicker and dance. Also heat up the laser temperature and drain \ some energy. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ LASLI2 Just draw the current laser lines without moving the \ centre point, draining energy or heating up. This has \ the effect of removing the lines from the screen \ \ LASLI-1 Contains an RTS \ \ ****************************************************************************** .LASLI JSR DORND \ Set A and X to random numbers AND #7 \ Restrict A to a random value in the range 0 to 7 ADC #Y-4 \ Set LASY to four pixels above the centre of the STA LASY \ screen (#Y), plus our random number, so the laser \ dances above and below the centre point JSR DORND \ Set A and X to random numbers AND #7 \ Restrict A to a random value in the range 0 to 7 ADC #X-4 \ Set LASX to four pixels left of the centre of the STA LASX \ screen (#X), plus our random number, so the laser \ dances to the left and right of the centre point LDA GNTMP \ Add 8 to the laser temperature in GNTMP ADC #8 STA GNTMP JSR DENGY \ Call DENGY to deplete our energy banks by 1 .LASLI2 LDA QQ11 \ If this is not a space view (i.e. QQ11 is non-zero) BNE PU1-1 \ then jump to MA9 to return from the main flight loop \ (as PU1-1 is an RTS) LDA #32 \ Set A = 32 and Y = 224 for the first set of laser LDY #224 \ lines (the wider pair of lines) JSR las \ Call las below to draw the first set of laser lines LDA #48 \ Fall through into las with A = 48 and Y = 208 to draw LDY #208 \ a second set of lines (the narrower pair) \ The following routine draws two laser lines, one from \ the centre point down to point A on the bottom row, \ and the other from the centre point down to point Y \ on the bottom row. We therefore get lines from the \ centre point to points 32, 48, 208 and 224 along the \ bottom row, giving us the triangular laser effect \ we're after .las STA X2 \ Set X2 = A LDA LASX \ Set (X1, Y1) to the random centre point we set above STA X1 LDA LASY STA Y1 LDA #2*Y-1 \ Set Y2 = 2 * #Y - 1. The constant #Y is 96, the STA Y2 \ 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 JSR LOIN \ Draw a line from (X1, Y1) to (X2, Y2), so that's from \ the centre point to (A, 191) LDA LASX \ Set (X1, Y1) to the random centre point we set above STA X1 LDA LASY STA Y1 STY X2 \ Set X2 = Y LDA #2*Y-1 \ Set Y2 = 2 * #Y - 1, the y-coordinate of the bottom STA Y2 \ pixel row of the space view (as before) JMP LOIN \ Draw a line from (X1, Y1) to (X2, Y2), so that's from \ the centre point to (Y, 191), and return from \ the subroutine using a tail call \ ****************************************************************************** \ \ Name: PLUT \ Type: Subroutine \ Category: Flight \ Summary: Flip the coordinate axes for the four different views \ Deep dive: Flipping axes between space views \ \ ------------------------------------------------------------------------------ \ \ This routine flips the relevant geometric axes in INWK depending on which \ view we are looking through (front, rear, left, right). \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ PU1-1 Contains an RTS \ \ ****************************************************************************** .PLUT LDX VIEW \ Load the current view into X: \ \ 0 = front \ 1 = rear \ 2 = left \ 3 = right BNE PU1 \ If the current view is the front view, return from the RTS \ subroutine, as the geometry in INWK is already correct .PU1 DEX \ Decrement the view, so now: \ \ 0 = rear \ 1 = left \ 2 = right BNE PU2 \ If the current view is left or right, jump to PU2, \ otherwise this is the rear view, so continue on LDA INWK+2 \ Flip the sign of x_sign EOR #%10000000 STA INWK+2 LDA INWK+8 \ Flip the sign of z_sign EOR #%10000000 STA INWK+8 LDA INWK+10 \ Flip the sign of nosev_x_hi EOR #%10000000 STA INWK+10 LDA INWK+14 \ Flip the sign of nosev_z_hi EOR #%10000000 STA INWK+14 LDA INWK+16 \ Flip the sign of roofv_x_hi EOR #%10000000 STA INWK+16 LDA INWK+20 \ Flip the sign of roofv_z_hi EOR #%10000000 STA INWK+20 LDA INWK+22 \ Flip the sign of sidev_x_hi EOR #%10000000 STA INWK+22 LDA INWK+26 \ Flip the sign of roofv_z_hi EOR #%10000000 STA INWK+26 RTS \ Return from the subroutine .PU2 \ We enter this with X set to the view, as follows: \ \ 1 = left \ 2 = right LDA #0 \ Set RAT2 = 0 (left view) or -1 (right view) CPX #2 ROR A STA RAT2 EOR #%10000000 \ Set RAT = -1 (left view) or 0 (right view) STA RAT LDA INWK \ Swap x_lo and z_lo LDX INWK+6 STA INWK+6 STX INWK LDA INWK+1 \ Swap x_hi and z_hi LDX INWK+7 STA INWK+7 STX INWK+1 LDA INWK+2 \ Swap x_sign and z_sign EOR RAT \ If left view, flip sign of new z_sign TAX \ If right view, flip sign of new x_sign LDA INWK+8 EOR RAT2 STA INWK+2 STX INWK+8 LDY #9 \ Swap nosev_x_lo and nosev_z_lo JSR PUS1 \ Swap nosev_x_hi and nosev_z_hi \ If left view, flip sign of new nosev_z_hi \ If right view, flip sign of new nosev_x_hi LDY #15 \ Swap roofv_x_lo and roofv_z_lo JSR PUS1 \ Swap roofv_x_hi and roofv_z_hi \ If left view, flip sign of new roofv_z_hi \ If right view, flip sign of new roofv_x_hi LDY #21 \ Swap sidev_x_lo and sidev_z_lo \ Swap sidev_x_hi and sidev_z_hi \ If left view, flip sign of new sidev_z_hi \ If right view, flip sign of new sidev_x_hi .PUS1 LDA INWK,Y \ Swap the low x and z bytes for the vector in Y: LDX INWK+4,Y \ STA INWK+4,Y \ * For Y = 9 swap nosev_x_lo and nosev_z_lo STX INWK,Y \ * For Y = 15 swap roofv_x_lo and roofv_z_lo \ * For Y = 21 swap sidev_x_lo and sidev_z_lo LDA INWK+1,Y \ Swap the high x and z bytes for the offset in Y: EOR RAT \ TAX \ * If left view, flip sign of new z-coordinate LDA INWK+5,Y \ * If right view, flip sign of new x-coordinate EOR RAT2 STA INWK+1,Y STX INWK+5,Y \ Fall through into LOOK1 to return from the subroutine \ ****************************************************************************** \ \ Name: LOOK1 \ Type: Subroutine \ Category: Flight \ Summary: Initialise the space view \ \ ------------------------------------------------------------------------------ \ \ Initialise the space view, with the direction of view given in X. This clears \ the upper screen and draws the laser crosshairs, if the view in X has lasers \ fitted. It also wipes all the ships from the scanner, so we can recalculate \ ship positions for the new view (they get put back in the main flight loop). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The space view to set: \ \ * 0 = front \ * 1 = rear \ * 2 = left \ * 3 = right \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ LO2 Contains an RTS \ \ ****************************************************************************** .LO2 RTS \ Return from the subroutine .LQ STX VIEW \ Set the current space view to X JSR TT66 \ Clear the top part of the screen, draw a border box, \ and set the current view type in QQ11 to 0 (space \ view) JSR SIGHT \ Draw the laser crosshairs JMP NWSTARS \ Set up a new stardust field and return from the \ subroutine using a tail call .LOOK1 LDA #0 \ Set A = 0, the type number of a space view LDY QQ11 \ If the current view is not a space view, jump up to LQ BNE LQ \ to set up a new space view CPX VIEW \ If the current view is already of type X, jump to LO2 BEQ LO2 \ to return from the subroutine (as LO2 contains an RTS) STX VIEW \ Change the current space view to X JSR TT66 \ Clear the top part of the screen, draw a border box, \ and set the current view type in QQ11 to 0 (space \ view) JSR FLIP \ Swap the x- and y-coordinates of all the stardust \ particles and redraw the stardust field JSR WPSHPS \ Wipe all the ships from the scanner and mark them all \ as not being shown on-screen \ And fall through into SIGHT to draw the laser \ crosshairs \ ****************************************************************************** \ \ Name: SIGHT \ Type: Subroutine \ Category: Flight \ Summary: Draw the laser crosshairs \ \ ****************************************************************************** .SIGHT LDY VIEW \ Fetch the laser power for our new view LDA LASER,Y BEQ LO2 \ If it is zero (i.e. there is no laser fitted to this \ view), jump to LO2 to return from the subroutine (as \ LO2 contains an RTS) LDA #128 \ Set QQ19 to the x-coordinate of the centre of the STA QQ19 \ screen LDA #Y-24 \ Set QQ19+1 to the y-coordinate of the centre of the STA QQ19+1 \ screen, minus 24 (because TT15 will add 24 to the \ coordinate when it draws the crosshairs) LDA #20 \ Set QQ19+2 to size 20 for the crosshairs size STA QQ19+2 JSR TT15 \ Call TT15 to draw crosshairs of size 20 just to the \ left of the middle of the screen LDA #10 \ Set QQ19+2 to size 10 for the crosshairs size STA QQ19+2 JMP TT15 \ Call TT15 to draw crosshairs of size 10 at the same \ location, which will remove the centre part from the \ laser crosshairs, leaving a gap in the middle, and \ return from the subroutine using a tail call \ ****************************************************************************** \ \ Name: TT66 \ Type: Subroutine \ Category: Drawing the screen \ Summary: Clear the screen and set the current view type \ \ ------------------------------------------------------------------------------ \ \ Clear the top part of the screen, draw a border box, and set the current \ view type in QQ11 to A. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The type of the new current view (see QQ11 for a list of \ view types) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT66-2 Call TT66 with A = 1 \ \ ****************************************************************************** LDA #1 \ Set the view type to 1 when this is called via the \ TT66-2 entry point .TT66 STA QQ11 \ Set the current view type in QQ11 to A \ Fall through into TTX66 to clear the screen and draw a \ border box \ ****************************************************************************** \ \ Name: TTX66 \ Type: Subroutine \ Category: Drawing the screen \ Summary: Clear the top part of the screen, draw a border box and configure \ the specified view \ \ ------------------------------------------------------------------------------ \ \ Clear the top part of the screen (the space view) and draw a border box \ along the top and sides. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ BOX Just draw the border and (if this is a space view) the \ view name. This can be used to remove the border and \ view name, as it is drawn using EOR logic \ \ ****************************************************************************** .TTX66 LDA #%10000000 \ Set bit 7 of QQ17 to switch to Sentence Case STA QQ17 IF _SOURCE_DISC ASL A \ Set LASCT to 0, as 128 << 1 = %10000000 << 1 = 0. This STA LASCT \ stops any laser pulsing ELIF _TEXT_SOURCES OR _STH_CASSETTE ASL A \ Set LAS2 to 0, as 128 << 1 = %10000000 << 1 = 0. This STA LAS2 \ stops any laser pulsing ENDIF STA DLY \ Set the delay in DLY to 0, to indicate that we are \ no longer showing an in-flight message, so any new \ in-flight messages will be shown instantly STA de \ Clear de, the flag that appends " DESTROYED" to the \ end of the next text token, so that it doesn't LDX #&60 \ Set X to the screen memory page for the top row of the \ screen (as screen memory starts at &6000) .BOL1 JSR ZES1 \ Call ZES1 to zero-fill the page in X, which clears \ that character row on the screen INX \ Increment X to point to the next page, i.e. the next \ character row CPX #&78 \ Loop back to BOL1 until we have cleared page &7700, BNE BOL1 \ the last character row in the space view part of the \ screen (the top part) LDX QQ22+1 \ Fetch into X the number that's shown on-screen during \ the hyperspace countdown BEQ BOX \ If the counter is zero then we are not counting down \ to hyperspace, so jump to BOX to skip the next \ instruction JSR ee3 \ Print the 8-bit number in X at text location (0, 1), \ i.e. print the hyperspace countdown in the top-left \ corner .BOX LDY #1 \ Move the text cursor to row 1 STY YC LDA QQ11 \ If this is not a space view, jump to tt66 to skip BNE tt66 \ displaying the view name LDY #11 \ Move the text cursor to row 11 STY XC LDA VIEW \ Load the current view into A: \ \ 0 = front \ 1 = rear \ 2 = left \ 3 = right ORA #&60 \ OR with &60 so we get a value of &60 to &63 (96 to 99) JSR TT27 \ Print recursive token 96 to 99, which will be in the \ range "FRONT" to "RIGHT" JSR TT162 \ Print a space LDA #175 \ Print recursive token 15 ("VIEW ") JSR TT27 .tt66 LDX #0 \ Set (X1, Y1) to (0, 0) STX X1 STX Y1 STX QQ17 \ Set QQ17 = 0 to switch to ALL CAPS DEX \ Set X2 = 255 STX X2 JSR HLOIN \ Draw a horizontal line from (X1, Y1) to (X2, Y1), so \ that's (0, 0) to (255, 0), along the very top of the \ screen LDA #2 \ Set X1 = X2 = 2 STA X1 STA X2 JSR BOS2 \ Call BOS2 below, which will call BOS1 twice, and then \ fall through into BOS2 again, so we effectively do \ BOS1 four times, decrementing X1 and X2 each time \ before calling LOIN, so this whole loop-within-a-loop \ mind-bender ends up drawing these four lines: \ \ (1, 0) to (1, 191) \ (0, 0) to (0, 191) \ (255, 0) to (255, 191) \ (254, 0) to (254, 191) \ \ So that's a two-pixel wide vertical border along the \ left edge of the upper part of the screen, and a \ two-pixel wide vertical border along the right edge .BOS2 JSR BOS1 \ Call BOS1 below and then fall through into it, which \ ends up running BOS1 twice. This is all part of the \ loop-the-loop border-drawing mind-bender explained \ above .BOS1 LDA #0 \ Set Y1 = 0 STA Y1 LDA #2*Y-1 \ Set Y2 = 2 * #Y - 1. The constant #Y is 96, the STA Y2 \ 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 DEC X1 \ Decrement X1 and X2 DEC X2 JMP LOIN \ Draw a line from (X1, Y1) to (X2, Y2), and return from \ the subroutine using a tail call \ ****************************************************************************** \ \ Name: DELAY \ Type: Subroutine \ Category: Utility routines \ Summary: Wait for a specified time, in 1/50s of a second \ \ ------------------------------------------------------------------------------ \ \ Wait for the number of vertical syncs given in Y, so this effectively waits \ for Y/50 of a second (as the vertical sync occurs 50 times a second). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ Y The number of vertical sync events to wait for \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ DEL8 Wait for 8/50 of a second (0.16 seconds) \ \ DELAY-5 Wait for 2/50 of a second (0.04 seconds) \ \ ****************************************************************************** LDY #2 \ Set Y to 2 vertical syncs EQUB &2C \ Skip the next instruction by turning it into \ &2C &A0 &08, or BIT &08A0, which does nothing apart \ from affect the flags .DEL8 LDY #8 \ Set Y to 8 vertical syncs and fall through into DELAY \ to wait for this long .DELAY JSR WSCAN \ Call WSCAN to wait for the vertical sync, so the whole \ screen gets drawn DEY \ Decrement the counter in Y BNE DELAY \ If Y isn't yet at zero, jump back to DELAY to wait \ for another vertical sync RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: hm \ Type: Subroutine \ Category: Charts \ Summary: Select the closest system and redraw the chart crosshairs \ \ ------------------------------------------------------------------------------ \ \ Set the system closest to galactic coordinates (QQ9, QQ10) as the selected \ system, redraw the crosshairs on the chart accordingly (if they are being \ shown), and if this is not the space view, clear the bottom three text rows of \ the screen. \ \ ****************************************************************************** .hm JSR TT103 \ Draw small crosshairs at coordinates (QQ9, QQ10), \ which will erase the crosshairs currently there JSR TT111 \ Select the system closest to galactic coordinates \ (QQ9, QQ10) JSR TT103 \ Draw small crosshairs at coordinates (QQ9, QQ10), \ which will draw the crosshairs at our current home \ system LDA QQ11 \ If this is a space view, return from the subroutine BEQ SC5 \ (as SC5 contains an RTS) \ Otherwise fall through into CLYNS to clear space at \ the bottom of the screen \ ****************************************************************************** \ \ Name: CLYNS \ Type: Subroutine \ Category: Drawing the screen \ Summary: Clear the bottom three text rows of the space view \ \ ------------------------------------------------------------------------------ \ \ This routine clears some space at the bottom of the screen and moves the text \ cursor to column 1, row 20. \ \ Specifically, it zeroes the following screen locations: \ \ &7507 to &75F0 \ &7607 to &76F0 \ &7707 to &77F0 \ \ which clears the three bottom text rows of the mode 4 screen (rows 21 to 23), \ clearing each row from text column 1 to 30 (so it doesn't overwrite the box \ border in columns 0 and 32, or the last usable column in column 31). \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A is set to 0 \ \ Y Y is set to 0 \ \ ****************************************************************************** .CLYNS LDA #20 \ Move the text cursor to row 20, near the bottom of STA YC \ the screen LDA #&75 \ Set the two-byte value in SC to &7507 STA SC+1 LDA #7 STA SC JSR TT67 \ Print a newline, which will move the text cursor down \ a line (to row 21) and back to column 1 LDA #0 \ Call LYN to clear the pixels from &7507 to &75F0 JSR LYN INC SC+1 \ Increment SC+1 so SC points to &7607 JSR LYN \ Call LYN to clear the pixels from &7607 to &76F0 INC SC+1 \ Increment SC+1 so SC points to &7707 INY \ Move the text cursor to column 1 (as LYN sets Y to 0) STY XC \ Fall through into LYN to clear the pixels from &7707 \ to &77F0 \ ****************************************************************************** \ \ Name: LYN \ Type: Subroutine \ Category: Drawing the screen \ Summary: Clear most of a row of pixels \ \ ------------------------------------------------------------------------------ \ \ Set pixels 0-233 to the value in A, starting at the pixel pointed to by SC. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The value to store in pixels 1-233 (the only value that \ is actually used is A = 0, which clears those pixels) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Y Y is set to 0 \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ SC5 Contains an RTS \ \ ****************************************************************************** .LYN LDY #233 \ Set up a counter in Y to count down from pixel 233 .EE2 STA (SC),Y \ Store A in the Y-th byte after the address pointed to \ by SC DEY \ Decrement Y BNE EE2 \ Loop back until Y is zero .SC5 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SCAN \ Type: Subroutine \ Category: Dashboard \ Summary: Display the current ship on the scanner \ Deep dive: The 3D scanner \ \ ------------------------------------------------------------------------------ \ \ This is used both to display a ship on the scanner, and to erase it again. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ INWK The ship's data block \ \ ****************************************************************************** .SCAN LDA INWK+31 \ Fetch the ship's scanner flag from byte #31 AND #%00010000 \ If bit 4 is clear then the ship should not be shown BEQ SC5 \ on the scanner, so return from the subroutine (as SC5 \ contains an RTS) LDA TYPE \ Fetch the ship's type from TYPE into A BMI SC5 \ If this is the planet or the sun, then the type will \ have bit 7 set and we don't want to display it on the \ scanner, so return from the subroutine (as SC5 \ contains an RTS) LDX #&FF \ Set X to the default scanner colour of green/cyan \ (a four-pixel mode 5 byte in colour 3) \CMP #TGL \ These instructions are commented out in the original \BEQ SC49 \ source. Along with the block just below, they would \ set X to colour 1 (red) for asteroids, cargo canisters \ and escape pods, rather than green/cyan. Presumably \ they decided it didn't work that well against the red \ ellipse and took this code out for release CMP #MSL \ If this is not a missile, skip the following BNE P%+4 \ instruction LDX #&F0 \ This is a missile, so set X to colour 2 (yellow/white) \CMP #AST \ These instructions are commented out in the original \BCC P%+4 \ source. See above for an explanation of what they do \ \LDX #&0F \ \.SC49 STX COL \ Store X, the colour of this ship on the scanner, in \ COL LDA INWK+1 \ If any of x_hi, y_hi and z_hi have a 1 in bit 6 or 7, ORA INWK+4 \ then the ship is too far away to be shown on the ORA INWK+7 \ scanner, so return from the subroutine (as SC5 AND #%11000000 \ contains an RTS) BNE SC5 \ If we get here, we know x_hi, y_hi and z_hi are all \ 63 (%00111111) or less \ Now, we convert the x_hi coordinate of the ship into \ the screen x-coordinate of the dot on the scanner, \ using the following: \ \ X1 = 123 + (x_sign x_hi) LDA INWK+1 \ Set A = x_hi CLC \ Clear the C flag so we can do addition below LDX INWK+2 \ Set X = x_sign BPL SC2 \ If x_sign is positive, skip the following EOR #%11111111 \ x_sign is negative, so flip the bits in A and add 1 ADC #1 \ to make it a negative number (bit 7 will now be set \ as we confirmed above that bits 6 and 7 are clear). So \ this gives A the sign of x_sign and gives it a value \ range of -63 (%11000001) to 0 .SC2 ADC #123 \ Set X1 = 123 + (x_sign x_hi) STA X1 \ Next, we convert the z_hi coordinate of the ship into \ the y-coordinate of the base of the ship's stick, \ like this: \ \ SC = 220 - (z_sign z_hi) / 4 \ \ though the following code actually does it like this: \ \ SC = 255 - (35 + z_hi / 4) LDA INWK+7 \ Set A = z_hi / 4 LSR A \ LSR A \ So A is in the range 0-15 CLC \ Clear the C flag for the addition below LDX INWK+8 \ Set X = z_sign BPL SC3 \ If z_sign is positive, skip the following EOR #%11111111 \ z_sign is negative, so flip the bits in A and set the SEC \ C flag. As above, this makes A negative, this time \ with a range of -16 (%11110000) to -1 (%11111111). And \ as we are about to do an ADC, the SEC effectively adds \ another 1 to that value, giving a range of -15 to 0 .SC3 ADC #35 \ Set A = 35 + A to give a number in the range 20 to 50 EOR #%11111111 \ Flip all the bits and store in SC, so SC is in the STA SC \ range 205 to 235, with a higher z_hi giving a lower SC \ Now for the stick height, which we calculate using the \ following: \ \ A = - (y_sign y_hi) / 2 LDA INWK+4 \ Set A = y_hi / 2 LSR A CLC \ Clear the C flag LDX INWK+5 \ Set X = y_sign BMI SCD6 \ If y_sign is negative, skip the following, as we \ already have a positive value in A EOR #%11111111 \ y_sign is positive, so flip the bits in A and set the SEC \ C flag. This makes A negative, and as we are about to \ do an ADC below, the SEC effectively adds another 1 to \ that value to implement two's complement negation, so \ we don't need to add another 1 here .SCD6 \ We now have all the information we need to draw this \ ship on the scanner, namely: \ \ X1 = the screen x-coordinate of the ship's dot \ \ SC = the screen y-coordinate of the base of the \ stick \ \ A = the screen height of the ship's stick, with the \ correct sign for adding to the base of the stick \ to get the dot's y-coordinate \ \ First, though, we have to make sure the dot is inside \ the dashboard, by moving it if necessary ADC SC \ Set A = SC + A, so A now contains the y-coordinate of \ the end of the stick, plus the length of the stick, to \ give us the screen y-coordinate of the dot BPL ld246 \ If the result has bit 0 clear, then the result has \ overflowed and is bigger than 256, so jump to ld246 to \ set A to the maximum allowed value of 246 (this \ instruction isn't required as we test both the maximum \ and minimum below, but it might save a few cycles) CMP #194 \ If A >= 194, skip the following instruction, as 194 is BCS P%+4 \ the minimum allowed value of A LDA #194 \ A < 194, so set A to 194, the minimum allowed value \ for the y-coordinate of our ship's dot CMP #247 \ If A < 247, skip the following instruction, as 246 is BCC P%+4 \ the maximum allowed value of A .ld246 LDA #246 \ A >= 247, so set A to 246, the maximum allowed value \ for the y-coordinate of our ship's dot STA Y1 \ Store A in Y1, as it now contains the screen \ y-coordinate for the ship's dot, clipped so that it \ fits within the dashboard SEC \ Set A = A - SC to get the stick length, by reversing SBC SC \ the ADC SC we did above. This clears the C flag if the \ result is negative (i.e. the stick length is negative) \ and sets it if the result is positive (i.e. the stick \ length is negative) \ So now we have the following: \ \ X1 = the screen x-coordinate of the ship's dot, \ clipped to fit into the dashboard \ \ Y1 = the screen y-coordinate of the ship's dot, \ clipped to fit into the dashboard \ \ SC = the screen y-coordinate of the base of the \ stick \ \ A = the screen height of the ship's stick, with the \ correct sign for adding to the base of the stick \ to get the dot's y-coordinate \ \ C = 0 if A is negative, 1 if A is positive \ \ and we can get on with drawing the dot and stick PHP \ Store the flags (specifically the C flag) from the \ above subtraction \BCS SC48 \ These instructions are commented out in the original \EOR #&FF \ source. They would negate A if the C flag were set, \ADC #1 \ which would reverse the direction of all the sticks, \ so you could turn your joystick around. Perhaps one of \ the authors' test sticks were easier to use upside \ down? Who knows... .SC48 PHA \ Store the stick height in A on the stack JSR CPIX4 \ Draw a double-height dot at (X1, Y1). This also leaves \ the following variables set up for the dot's top-right \ pixel, the last pixel to be drawn (as the dot gets \ drawn from the bottom up): \ \ SC(1 0) = screen address of the pixel's character \ block \ \ Y = number of the character row containing the pixel \ \ X = the pixel's number (0-3) in that row \ \ We can use there as the starting point for drawing the \ stick, if there is one LDA CTWOS+1,X \ Load the same mode 5 one-pixel byte that we just used AND COL \ for the top-right pixel, and mask it with the same STA X1 \ colour, storing the result in X1, so we can use it as \ the character row byte for the stick PLA \ Restore the stick height from the stack into A PLP \ Restore the flags from above, so the C flag once again \ reflects the sign of the stick height TAX \ Copy the stick height into X BEQ RTS \ If the stick height is zero, then there is no stick to \ draw, so return from the subroutine (as RTS contains \ an RTS) BCC RTS+1 \ If the C flag is clear then the stick height in A is \ negative, so jump down to RTS+1 .VLL1 \ If we get here then the stick length is positive (so \ the dot is below the ellipse and the stick is above \ the dot, and we need to draw the stick upwards from \ the dot) DEY \ We want to draw the stick upwards, so decrement the \ pixel row in Y BPL VL1 \ If Y is still positive then it correctly points at the \ line above, so jump to VL1 to skip the following LDY #7 \ We just decremented Y up through the top of the \ character block, so we need to move it to the last row \ in the character above, so set Y to 7, the number of \ the last row DEC SC+1 \ Decrement the high byte of the screen address to move \ to the character block above .VL1 LDA X1 \ Set A to the character row byte for the stick, which \ we stored in X1 above, and which has the same pixel \ pattern as the bottom-right pixel of the dot (so the \ stick comes out of the right side of the dot) EOR (SC),Y \ Draw the stick on row Y of the character block using STA (SC),Y \ EOR logic DEX \ Decrement the (positive) stick height in X BNE VLL1 \ If we still have more stick to draw, jump up to VLL1 \ to draw the next pixel .RTS RTS \ Return from the subroutine \ If we get here then the stick length is negative (so \ the dot is above the ellipse and the stick is below \ the dot, and we need to draw the stick downwards from \ the dot) INY \ We want to draw the stick downwards, so we first \ increment the row counter so that it's pointing to the \ bottom-right pixel in the dot (as opposed to the top- \ right pixel that the call to CPIX4 finished on) CPY #8 \ If the row number in Y is less than 8, then it BNE P%+6 \ correctly points at the next line down, so jump to \ VLL2 to skip the following LDY #0 \ We just incremented Y down through the bottom of the \ character block, so we need to move it to the first \ row in the character below, so set Y to 0, the number \ of the first row INC SC+1 \ Increment the high byte of the screen address to move \ to the character block above .VLL2 INY \ We want to draw the stick itself, heading downwards, \ so increment the pixel row in Y CPY #8 \ If the row number in Y is less than 8, then it BNE VL2 \ correctly points at the next line down, so jump to \ VL2 to skip the following LDY #0 \ We just incremented Y down through the bottom of the \ character block, so we need to move it to the first \ row in the character below, so set Y to 0, the number \ of the first row INC SC+1 \ Increment the high byte of the screen address to move \ to the character block above .VL2 LDA X1 \ Set A to the character row byte for the stick, which \ we stored in X1 above, and which has the same pixel \ pattern as the bottom-right pixel of the dot (so the \ stick comes out of the right side of the dot) EOR (SC),Y \ Draw the stick on row Y of the character block using STA (SC),Y \ EOR logic INX \ Increment the (negative) stick height in X BNE VLL2 \ If we still have more stick to draw, jump up to VLL2 \ to draw the next pixel RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: WSCAN \ Type: Subroutine \ Category: Drawing the screen \ Summary: Wait for the vertical sync \ \ ------------------------------------------------------------------------------ \ \ Wait for vertical sync to occur on the video system - in other words, wait \ for the screen to start its refresh cycle, which it does 50 times a second \ (50Hz). \ \ ****************************************************************************** .WSCAN LDA #0 \ Set DL to 0 STA DL LDA DL \ Loop round these two instructions until DL is no BEQ P%-2 \ longer 0 (DL gets set to 30 in the LINSCN routine, \ which is run when vertical sync has occurred on the \ video system, so DL will change to a non-zero value \ at the start of each screen refresh) RTS \ Return from the subroutine \ ****************************************************************************** \ \ Save ELTC.bin \ \ ****************************************************************************** PRINT "ELITE C" PRINT "Assembled at ", ~CODE_C% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_C%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_C% PRINT "S.ELTC ", ~CODE_C%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_C% SAVE "3-assembled-output/ELTC.bin", CODE_C%, P%, LOAD% \ ****************************************************************************** \ \ ELITE D FILE \ \ Produces the binary file ELTD.bin that gets loaded by elite-bcfs.asm. \ \ ****************************************************************************** CODE_D% = P% LOAD_D% = LOAD% + P% - CODE% \ ****************************************************************************** \ \ Name: tnpr \ Type: Subroutine \ Category: Market \ Summary: Work out if we have space for a specific amount of cargo \ \ ------------------------------------------------------------------------------ \ \ Given a market item and an amount, work out whether there is room in the \ cargo hold for this item. \ \ For standard tonne canisters, the limit is given by the type of cargo hold we \ have, with a standard cargo hold having a capacity of 20t and an extended \ cargo bay being 35t. \ \ For items measured in kg (gold, platinum), g (gem-stones) and alien items, \ the individual limit on each of these is 200 units. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The number of units of this market item \ \ QQ29 The type of market item (see QQ23 for a list of market \ item numbers) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A is preserved \ \ C flag Returns the result: \ \ * Set if there is no room for this item \ \ * Clear if there is room for this item \ \ ****************************************************************************** .tnpr PHA \ Store A on the stack LDX #12 \ If QQ29 > 12 then jump to kg below, as this cargo CPX QQ29 \ type is gold, platinum, gem-stones or alien items, BCC kg \ and they have different cargo limits to the standard \ tonne canisters .Tml \ Here we count the tonne canisters we have in the hold \ and add to A to see if we have enough room for A more \ tonnes of cargo, using X as the loop counter, starting \ with X = 12 ADC QQ20,X \ Set A = A + the number of tonnes we have in the hold \ of market item number X. Note that the first time we \ go round this loop, the C flag is set (as we didn't \ branch with the BCC above, so the effect of this loop \ is to count the number of tonne canisters in the hold, \ and add 1 DEX \ Decrement the loop counter BPL Tml \ Loop back to add in the next market item in the hold, \ until we have added up all market items from 12 \ (minerals) down to 0 (food) CMP CRGO \ If A < CRGO then the C flag will be clear (we have \ room in the hold) \ \ If A >= CRGO then the C flag will be set (we do not \ have room in the hold) \ \ This works because A contains the number of canisters \ plus 1, while CRGO contains our cargo capacity plus 2, \ so if we actually have "a" canisters and a capacity \ of "c", then: \ \ A < CRGO means: a+1 < c+2 \ a < c+1 \ a <= c \ \ So this is why the value in CRGO is 2 higher than the \ actual cargo bay size, i.e. it's 22 for the standard \ 20-tonne bay, and 37 for the large 35-tonne bay PLA \ Restore A from the stack RTS \ Return from the subroutine .kg \ Here we count the number of items of this type that \ we already have in the hold, and add to A to see if \ we have enough room for A more units LDY QQ29 \ Set Y to the item number we want to add ADC QQ20,Y \ Set A = A + the number of units of this item that we \ already have in the hold CMP #200 \ Is the result greater than 200 (the limit on \ individual stocks of gold, platinum, gem-stones and \ alien items)? \ \ If so, this sets the C flag (no room) \ \ Otherwise it is clear (we have room) PLA \ Restore A from the stack RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT20 \ Type: Subroutine \ Category: Universe \ Summary: Twist the selected system's seeds four times \ Deep dive: Twisting the system seeds \ Galaxy and system seeds \ \ ------------------------------------------------------------------------------ \ \ Twist the three 16-bit seeds in QQ15 (selected system) four times, to \ generate the next system. \ \ ****************************************************************************** .TT20 JSR P%+3 \ This line calls the line below as a subroutine, which \ does two twists before returning here, and then we \ fall through to the line below for another two \ twists, so the net effect of these two consecutive \ JSR calls is four twists, not counting the ones \ inside your head as you try to follow this process JSR P%+3 \ This line calls TT54 as a subroutine to do a twist, \ and then falls through into TT54 to do another twist \ before returning from the subroutine \ ****************************************************************************** \ \ Name: TT54 \ Type: Subroutine \ Category: Universe \ Summary: Twist the selected system's seeds \ Deep dive: Twisting the system seeds \ Galaxy and system seeds \ \ ------------------------------------------------------------------------------ \ \ This routine twists the three 16-bit seeds in QQ15 once. \ \ If we start with seeds s0, s1 and s2 and we want to work out their new values \ after we perform a twist (let's call the new values s0´, s1´ and s2´), then: \ \ s0´ = s1 \ s1´ = s2 \ s2´ = s0 + s1 + s2 \ \ So given an existing set of seeds in s0, s1 and s2, we can get the new values \ s0´, s1´ and s2´ simply by doing the above sums. And if we want to do the \ above in-place without creating three new s´ variables, then we can do the \ following: \ \ tmp = s0 + s1 \ s0 = s1 \ s1 = s2 \ s2 = tmp + s1 \ \ So this is what we do in this routine, where each seed is a 16-bit number. \ \ ****************************************************************************** .TT54 LDA QQ15 \ X = tmp_lo = s0_lo + s1_lo CLC ADC QQ15+2 TAX LDA QQ15+1 \ Y = tmp_hi = s1_hi + s1_hi + C ADC QQ15+3 TAY LDA QQ15+2 \ s0_lo = s1_lo STA QQ15 LDA QQ15+3 \ s0_hi = s1_hi STA QQ15+1 LDA QQ15+5 \ s1_hi = s2_hi STA QQ15+3 LDA QQ15+4 \ s1_lo = s2_lo STA QQ15+2 CLC \ s2_lo = X + s1_lo TXA ADC QQ15+2 STA QQ15+4 TYA \ s2_hi = Y + s1_hi + C ADC QQ15+3 STA QQ15+5 RTS \ The twist is complete so return from the subroutine \ ****************************************************************************** \ \ Name: TT146 \ Type: Subroutine \ Category: Universe \ Summary: Print the distance to the selected system in light years \ \ ------------------------------------------------------------------------------ \ \ If it is non-zero, print the distance to the selected system in light years. \ If it is zero, just move the text cursor down a line. \ \ Specifically, if the distance in QQ8 is non-zero, print token 31 ("DISTANCE"), \ then a colon, then the distance to one decimal place, then token 35 ("LIGHT \ YEARS"). If the distance is zero, move the cursor down one line. \ \ ****************************************************************************** .TT146 LDA QQ8 \ Take the two bytes of the 16-bit value in QQ8 and ORA QQ8+1 \ OR them together to check whether there are any BNE TT63 \ non-zero bits, and if so, jump to TT63 to print the \ distance INC YC \ The distance is zero, so we just move the text cursor RTS \ in YC down by one line and return from the subroutine .TT63 LDA #191 \ Print recursive token 31 ("DISTANCE") followed by JSR TT68 \ a colon LDX QQ8 \ Load (Y X) from QQ8, which contains the 16-bit LDY QQ8+1 \ distance we want to show SEC \ Set the C flag so that the call to pr5 will include a \ decimal point, and display the value as (Y X) / 10 JSR pr5 \ Print (Y X) to 5 digits, including a decimal point LDA #195 \ Set A to the recursive token 35 (" LIGHT YEARS") and \ fall through into TT60 to print the token followed \ by a paragraph break \ ****************************************************************************** \ \ Name: TT60 \ Type: Subroutine \ Category: Text \ Summary: Print a text token and a paragraph break \ \ ------------------------------------------------------------------------------ \ \ Print a text token (i.e. a character, control code, two-letter token or \ recursive token). Then print a paragraph break (a blank line between \ paragraphs) by moving the cursor down a line, setting Sentence Case, and then \ printing a newline. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ ****************************************************************************** .TT60 JSR TT27 \ Print the text token in A and fall through into TTX69 \ to print the paragraph break \ ****************************************************************************** \ \ Name: TTX69 \ Type: Subroutine \ Category: Text \ Summary: Print a paragraph break \ \ ------------------------------------------------------------------------------ \ \ Print a paragraph break (a blank line between paragraphs) by moving the cursor \ down a line, setting Sentence Case, and then printing a newline. \ \ ****************************************************************************** .TTX69 INC YC \ Move the text cursor down a line \ Fall through into TT69 to set Sentence Case and print \ a newline \ ****************************************************************************** \ \ Name: TT69 \ Type: Subroutine \ Category: Text \ Summary: Set Sentence Case and print a newline \ \ ****************************************************************************** .TT69 LDA #%10000000 \ Set bit 7 of QQ17 to switch to Sentence Case STA QQ17 \ Fall through into TT67 to print a newline \ ****************************************************************************** \ \ Name: TT67 \ Type: Subroutine \ Category: Text \ Summary: Print a newline \ \ ****************************************************************************** .TT67 LDA #13 \ Load a newline character into A JMP TT27 \ Print the text token in A and return from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: TT70 \ Type: Subroutine \ Category: Universe \ Summary: Display "MAINLY " and jump to TT72 \ \ ------------------------------------------------------------------------------ \ \ This subroutine is called by TT25 when displaying a system's economy. \ \ ****************************************************************************** .TT70 LDA #173 \ Print recursive token 13 ("MAINLY ") JSR TT27 JMP TT72 \ Jump to TT72 to continue printing system data as part \ of routine TT25 \ ****************************************************************************** \ \ Name: spc \ Type: Subroutine \ Category: Text \ Summary: Print a text token followed by a space \ \ ------------------------------------------------------------------------------ \ \ Print a text token (i.e. a character, control code, two-letter token or \ recursive token) followed by a space. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ ****************************************************************************** .spc JSR TT27 \ Print the text token in A JMP TT162 \ Print a space and return from the subroutine using a \ tail call \ ****************************************************************************** \ \ Name: TT25 \ Type: Subroutine \ Category: Universe \ Summary: Show the Data on System screen (red key f6) \ Deep dive: Generating system data \ Galaxy and system seeds \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT72 Used by TT70 to re-enter the routine after displaying \ "MAINLY" for the economy type \ \ ****************************************************************************** .TT25 JSR TT66-2 \ Clear the top part of the screen, draw a border box, \ and set the current view type in QQ11 to 1 LDA #9 \ Move the text cursor to column 9 STA XC LDA #163 \ Print recursive token 3 as a title in capitals at JSR TT27 \ the top ("DATA ON {selected system name}") JSR NLIN \ Draw a horizontal line underneath the title JSR TTX69 \ Print a paragraph break and set Sentence Case INC YC \ Move the text cursor down one more line JSR TT146 \ If the distance to this system is non-zero, print \ "DISTANCE", then the distance, "LIGHT YEARS" and a \ paragraph break, otherwise just move the cursor down \ a line LDA #194 \ Print recursive token 34 ("ECONOMY") followed by JSR TT68 \ a colon LDA QQ3 \ The system economy is determined by the value in QQ3, \ so fetch it into A. First we work out the system's \ prosperity as follows: \ \ QQ3 = 0 or 5 = %000 or %101 = Rich \ QQ3 = 1 or 6 = %001 or %110 = Average \ QQ3 = 2 or 7 = %010 or %111 = Poor \ QQ3 = 3 or 4 = %011 or %100 = Mainly CLC \ If (QQ3 + 1) >> 1 = %10, i.e. if QQ3 = %011 or %100 ADC #1 \ (3 or 4), then call TT70, which prints "MAINLY " and LSR A \ jumps down to TT72 to print the type of economy CMP #%00000010 BEQ TT70 LDA QQ3 \ If (QQ3 + 1) >> 1 < %10, i.e. if QQ3 = %000, %001 or BCC TT71 \ %010 (0, 1 or 2), then jump to TT71 with A set to the \ original value of QQ3 SBC #5 \ Here QQ3 = %101, %110 or %111 (5, 6 or 7), so subtract CLC \ 5 to bring it down to 0, 1 or 2 (the C flag is already \ set so the SBC will be correct) .TT71 ADC #170 \ A is now 0, 1 or 2, so print recursive token 10 + A. JSR TT27 \ This means that: \ \ QQ3 = 0 or 5 prints token 10 ("RICH ") \ QQ3 = 1 or 6 prints token 11 ("AVERAGE ") \ QQ3 = 2 or 7 prints token 12 ("POOR ") .TT72 LDA QQ3 \ Now to work out the type of economy, which is LSR A \ determined by bit 2 of QQ3, as follows: LSR A \ \ QQ3 bit 2 = 0 = Industrial \ QQ3 bit 2 = 1 = Agricultural \ \ So we fetch QQ3 into A and set A = bit 2 of QQ3 using \ two right shifts (which will work as QQ3 is only a \ 3-bit number) CLC \ Print recursive token 8 + A, followed by a paragraph ADC #168 \ break and Sentence Case, so: JSR TT60 \ \ QQ3 bit 2 = 0 prints token 8 ("INDUSTRIAL") \ QQ3 bit 2 = 1 prints token 9 ("AGRICULTURAL") LDA #162 \ Print recursive token 2 ("GOVERNMENT") followed by JSR TT68 \ a colon LDA QQ4 \ The system's government is determined by the value in \ QQ4, so fetch it into A CLC \ Print recursive token 17 + A, followed by a paragraph ADC #177 \ break and Sentence Case, so: JSR TT60 \ \ QQ4 = 0 prints token 17 ("ANARCHY") \ QQ4 = 1 prints token 18 ("FEUDAL") \ QQ4 = 2 prints token 19 ("MULTI-GOVERNMENT") \ QQ4 = 3 prints token 20 ("DICTATORSHIP") \ QQ4 = 4 prints token 21 ("COMMUNIST") \ QQ4 = 5 prints token 22 ("CONFEDERACY") \ QQ4 = 6 prints token 23 ("DEMOCRACY") \ QQ4 = 7 prints token 24 ("CORPORATE STATE") LDA #196 \ Print recursive token 36 ("TECH.LEVEL") followed by a JSR TT68 \ colon LDX QQ5 \ Fetch the tech level from QQ5 and increment it, as it INX \ is stored in the range 0-14 but the displayed range \ should be 1-15 CLC \ Call pr2 to print the technology level as a JSR pr2 \ three-digit number without a decimal point (by \ clearing the C flag) JSR TTX69 \ Print a paragraph break and set Sentence Case LDA #192 \ Print recursive token 32 ("POPULATION") followed by a JSR TT68 \ colon SEC \ Call pr2 to print the population as a three-digit LDX QQ6 \ number with a decimal point (by setting the C flag), JSR pr2 \ so the number printed will be population / 10 LDA #198 \ Print recursive token 38 (" BILLION"), followed by a JSR TT60 \ paragraph break and Sentence Case LDA #'(' \ Print an opening bracket JSR TT27 LDA QQ15+4 \ Now to calculate the species, so first check bit 7 of BMI TT75 \ s2_lo, and if it is set, jump to TT75 as this is an \ alien species LDA #188 \ Bit 7 of s2_lo is clear, so print recursive token 28 JSR TT27 \ ("HUMAN COLONIAL") JMP TT76 \ Jump to TT76 to print "S)" and a paragraph break, so \ the whole species string is "(HUMAN COLONIALS)" .TT75 LDA QQ15+5 \ This is an alien species, and we start with the first LSR A \ adjective, so fetch bits 2-7 of s2_hi into A and push LSR A \ onto the stack so we can use this later PHA AND #%00000111 \ Set A = bits 0-2 of A (so that's bits 2-4 of s2_hi) CMP #3 \ If A >= 3, jump to TT205 to skip the first adjective, BCS TT205 ADC #227 \ Otherwise A = 0, 1 or 2, so print recursive token JSR spc \ 67 + A, followed by a space, so: \ \ A = 0 prints token 67 ("LARGE") and a space \ A = 1 prints token 68 ("FIERCE") and a space \ A = 2 prints token 69 ("SMALL") and a space .TT205 PLA \ Now for the second adjective, so restore A to bits LSR A \ 2-7 of s2_hi, and throw away bits 2-4 to leave LSR A \ A = bits 5-7 of s2_hi LSR A CMP #6 \ If A >= 6, jump to TT206 to skip the second adjective BCS TT206 ADC #230 \ Otherwise A = 0 to 5, so print recursive token JSR spc \ 70 + A, followed by a space, so: \ \ A = 0 prints token 70 ("GREEN") and a space \ A = 1 prints token 71 ("RED") and a space \ A = 2 prints token 72 ("YELLOW") and a space \ A = 3 prints token 73 ("BLUE") and a space \ A = 4 prints token 74 ("BLACK") and a space \ A = 5 prints token 75 ("HARMLESS") and a space .TT206 LDA QQ15+3 \ Now for the third adjective, so EOR the high bytes of EOR QQ15+1 \ s0 and s1 and extract bits 0-2 of the result: AND #%00000111 \ STA QQ19 \ A = (s0_hi EOR s1_hi) AND %111 \ \ storing the result in QQ19 so we can use it later CMP #6 \ If A >= 6, jump to TT207 to skip the third adjective BCS TT207 ADC #236 \ Otherwise A = 0 to 5, so print recursive token JSR spc \ 76 + A, followed by a space, so: \ \ A = 0 prints token 76 ("SLIMY") and a space \ A = 1 prints token 77 ("BUG-EYED") and a space \ A = 2 prints token 78 ("HORNED") and a space \ A = 3 prints token 79 ("BONY") and a space \ A = 4 prints token 80 ("FAT") and a space \ A = 5 prints token 81 ("FURRY") and a space .TT207 LDA QQ15+5 \ Now for the actual species, so take bits 0-1 of AND #%00000011 \ s2_hi, add this to the value of A that we used for CLC \ the third adjective, and take bits 0-2 of the result ADC QQ19 AND #%00000111 ADC #242 \ A = 0 to 7, so print recursive token 82 + A, so: JSR TT27 \ \ A = 0 prints token 82 ("RODENT") \ A = 1 prints token 83 ("FROG") \ A = 2 prints token 84 ("LIZARD") \ A = 3 prints token 85 ("LOBSTER") \ A = 4 prints token 86 ("BIRD") \ A = 5 prints token 87 ("HUMANOID") \ A = 6 prints token 88 ("FELINE") \ A = 7 prints token 89 ("INSECT") .TT76 LDA #'S' \ Print an "S" to pluralise the species JSR TT27 LDA #')' \ And finally, print a closing bracket, followed by a JSR TT60 \ paragraph break and Sentence Case, to end the species \ section LDA #193 \ Print recursive token 33 ("GROSS PRODUCTIVITY"), JSR TT68 \ followed by a colon LDX QQ7 \ Fetch the 16-bit productivity value from QQ7 into LDY QQ7+1 \ (Y X) JSR pr6 \ Print (Y X) to 5 digits with no decimal point JSR TT162 \ Print a space LDA #0 \ Set QQ17 = 0 to switch to ALL CAPS STA QQ17 LDA #'M' \ Print "M" JSR TT27 LDA #226 \ Print recursive token 66 (" CR"), followed by a JSR TT60 \ paragraph break and Sentence Case LDA #250 \ Print recursive token 90 ("AVERAGE RADIUS"), followed JSR TT68 \ by a colon \ The average radius is calculated like this: \ \ ((s2_hi AND %1111) + 11) * 256 + s1_hi \ \ or, in terms of memory locations: \ \ ((QQ15+5 AND %1111) + 11) * 256 + QQ15+3 \ \ Because the multiplication is by 256, this is the \ same as saying a 16-bit number, with high byte: \ \ (QQ15+5 AND %1111) + 11 \ \ and low byte: \ \ QQ15+3 \ \ so we can set this up in (Y X) and call the pr5 \ routine to print it out LDA QQ15+5 \ Set A = QQ15+5 LDX QQ15+3 \ Set X = QQ15+3 AND #%00001111 \ Set Y = (A AND %1111) + 11 CLC ADC #11 TAY JSR pr5 \ Print (Y X) to 5 digits, not including a decimal \ point, as the C flag will be clear (as the maximum \ radius will always fit into 16 bits) JSR TT162 \ Print a space LDA #'k' \ Print "km", returning from the subroutine using a JSR TT26 \ tail call LDA #'m' JMP TT26 \ ****************************************************************************** \ \ Name: TT24 \ Type: Subroutine \ Category: Universe \ Summary: Calculate system data from the system seeds \ Deep dive: Generating system data \ Galaxy and system seeds \ \ ------------------------------------------------------------------------------ \ \ Calculate system data from the seeds in QQ15 and store them in the relevant \ locations. Specifically, this routine calculates the following from the three \ 16-bit seeds in QQ15 (using only s0_hi, s1_hi and s1_lo): \ \ QQ3 = economy (0-7) \ QQ4 = government (0-7) \ QQ5 = technology level (0-14) \ QQ6 = population * 10 (1-71) \ QQ7 = productivity (96-62480) \ \ The ranges of the various values are shown in brackets. Note that the radius \ and type of inhabitant are calculated on-the-fly in the TT25 routine when \ the system data gets displayed, so they aren't calculated here. \ \ ****************************************************************************** .TT24 LDA QQ15+1 \ Fetch s0_hi and extract bits 0-2 to determine the AND #%00000111 \ system's economy, and store in QQ3 STA QQ3 LDA QQ15+2 \ Fetch s1_lo and extract bits 3-5 to determine the LSR A \ system's government, and store in QQ4 LSR A LSR A AND #%00000111 STA QQ4 LSR A \ If government isn't anarchy or feudal, skip to TT77, BNE TT77 \ as we need to fix the economy of anarchy and feudal \ systems so they can't be rich LDA QQ3 \ Set bit 1 of the economy in QQ3 to fix the economy ORA #%00000010 \ for anarchy and feudal governments STA QQ3 .TT77 LDA QQ3 \ Now to work out the tech level, which we do like this: EOR #%00000111 \ CLC \ flipped_economy + (s1_hi AND %11) + (government / 2) STA QQ5 \ \ or, in terms of memory locations: \ \ QQ5 = (QQ3 EOR %111) + (QQ15+3 AND %11) + (QQ4 / 2) \ \ We start by setting QQ5 = QQ3 EOR %111 LDA QQ15+3 \ We then take the first 2 bits of s1_hi (QQ15+3) and AND #%00000011 \ add it into QQ5 ADC QQ5 STA QQ5 LDA QQ4 \ And finally we add QQ4 / 2 and store the result in LSR A \ QQ5, using LSR then ADC to divide by 2, which rounds ADC QQ5 \ up the result for odd-numbered government types STA QQ5 ASL A \ Now to work out the population, like so: ASL A \ ADC QQ3 \ (tech level * 4) + economy + government + 1 ADC QQ4 \ ADC #1 \ or, in terms of memory locations: STA QQ6 \ \ QQ6 = (QQ5 * 4) + QQ3 + QQ4 + 1 LDA QQ3 \ Finally, we work out productivity, like this: EOR #%00000111 \ ADC #3 \ (flipped_economy + 3) * (government + 4) STA P \ * population LDA QQ4 \ * 8 ADC #4 \ STA Q \ or, in terms of memory locations: JSR MULTU \ \ QQ7 = (QQ3 EOR %111 + 3) * (QQ4 + 4) * QQ6 * 8 \ \ We do the first step by setting P to the first \ expression in brackets and Q to the second, and \ calling MULTU, so now (A P) = P * Q. The highest this \ can be is 10 * 11 (as the maximum values of economy \ and government are 7), so the high byte of the result \ will always be 0, so we actually have: \ \ P = P * Q \ = (flipped_economy + 3) * (government + 4) LDA QQ6 \ We now take the result in P and multiply by the STA Q \ population to get the productivity, by setting Q to JSR MULTU \ the population from QQ6 and calling MULTU again, so \ now we have: \ \ (A P) = P * population ASL P \ Next we multiply the result by 8, as a 16-bit number, ROL A \ so we shift both bytes to the left three times, using ASL P \ the C flag to carry bits from bit 7 of the low byte ROL A \ into bit 0 of the high byte ASL P ROL A STA QQ7+1 \ Finally, we store the productivity in two bytes, with LDA P \ the low byte in QQ7 and the high byte in QQ7+1 STA QQ7 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT22 \ Type: Subroutine \ Category: Charts \ Summary: Show the Long-range Chart (red key f4) \ Deep dive: A sense of scale \ \ ****************************************************************************** .TT22 LDA #64 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 32 (Long- \ range Chart) LDA #7 \ Move the text cursor to column 7 STA XC JSR TT81 \ Set the seeds in QQ15 to those of system 0 in the \ current galaxy (i.e. copy the seeds from QQ21 to QQ15) LDA #199 \ Print recursive token 39 ("GALACTIC CHART{galaxy JSR TT27 \ number right-aligned to width 3}") JSR NLIN \ Draw a horizontal line at pixel row 23 to box in the \ title and act as the top frame of the chart, and move \ the text cursor down one line LDA #152 \ Draw a screen-wide horizontal line at pixel row 152 JSR NLIN2 \ for the bottom edge of the chart, so the chart itself \ is 128 pixels high, starting on row 24 and ending on \ row 151 JSR TT14 \ Call TT14 to draw a circle with crosshairs at the \ current system's galactic coordinates LDX #0 \ We're now going to plot each of the galaxy's systems, \ so set up a counter in X for each system, starting at \ 0 and looping through to 255 .TT83 STX XSAV \ Store the counter in XSAV LDX QQ15+3 \ Fetch the s1_hi seed into X, which gives us the \ galactic x-coordinate of this system LDY QQ15+4 \ Fetch the s2_lo seed and set bits 4 and 6, storing the TYA \ result in ZZ to give a random number between 80 and ORA #%01010000 \ (but which will always be the same for this system). STA ZZ \ We use this value to determine the size of the point \ for this system on the chart by passing it as the \ distance argument to the PIXEL routine below LDA QQ15+1 \ Fetch the s0_hi seed into A, which gives us the \ galactic y-coordinate of this system LSR A \ We halve the y-coordinate because the galaxy in \ in Elite is rectangular rather than square, and is \ twice as wide (x-axis) as it is high (y-axis), so the \ chart is 256 pixels wide and 128 high CLC \ Add 24 to the halved y-coordinate and store in XX15+1 ADC #24 \ (as the top of the chart is on pixel row 24, just STA XX15+1 \ below the line we drew on row 23 above) JSR PIXEL \ Call PIXEL to draw a point at (X, A), with the size of \ the point dependent on the distance specified in ZZ \ (so a high value of ZZ will produce a one-pixel point, \ a medium value will produce a two-pixel dash, and a \ small value will produce a four-pixel square) JSR TT20 \ We want to move on to the next system, so call TT20 \ to twist the three 16-bit seeds in QQ15 LDX XSAV \ Restore the loop counter from XSAV INX \ Increment the counter BNE TT83 \ If X > 0 then we haven't done all 256 systems yet, so \ loop back up to TT83 LDA QQ9 \ Set QQ19 to the selected system's x-coordinate STA QQ19 LDA QQ10 \ Set QQ19+1 to the selected system's y-coordinate, LSR A \ halved to fit it into the chart STA QQ19+1 LDA #4 \ Set QQ19+2 to size 4 for the crosshairs size STA QQ19+2 \ Fall through into TT15 to draw crosshairs of size 4 at \ the selected system's coordinates \ ****************************************************************************** \ \ Name: TT15 \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a set of crosshairs \ \ ------------------------------------------------------------------------------ \ \ For all views except the Short-range Chart, the centre is drawn 24 pixels to \ the right of the y-coordinate given. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ QQ19 The pixel x-coordinate of the centre of the crosshairs \ \ QQ19+1 The pixel y-coordinate of the centre of the crosshairs \ \ QQ19+2 The size of the crosshairs \ \ ****************************************************************************** .TT15 LDA #24 \ Set A to 24, which we will use as the minimum \ screen indent for the crosshairs (i.e. the minimum \ distance from the top-left corner of the screen) LDX QQ11 \ If the current view is not the Short-range Chart, BPL P%+4 \ which is the only view with bit 7 set, then skip the \ following instruction LDA #0 \ This is the Short-range Chart, so set A to 0, so the \ crosshairs can go right up against the screen edges STA QQ19+5 \ Set QQ19+5 to A, which now contains the correct indent \ for this view LDA QQ19 \ Set A = crosshairs x-coordinate - crosshairs size SEC \ to get the x-coordinate of the left edge of the SBC QQ19+2 \ crosshairs BCS TT84 \ If the above subtraction didn't underflow, then A is \ positive, so skip the next instruction LDA #0 \ The subtraction underflowed, so set A to 0 so the \ crosshairs don't spill out of the left of the screen .TT84 \ In the following, the authors have used XX15 for \ temporary storage. XX15 shares location with X1, Y1, \ X2 and Y2, so in the following, you can consider \ the variables like this: \ \ XX15 is the same as X1 \ XX15+1 is the same as Y1 \ XX15+2 is the same as X2 \ XX15+3 is the same as Y2 \ \ Presumably this routine was written at a different \ time to the line-drawing routine, before the two \ workspaces were merged to save space STA XX15 \ Set XX15 (X1) = A (the x-coordinate of the left edge \ of the crosshairs) LDA QQ19 \ Set A = crosshairs x-coordinate + crosshairs size CLC \ to get the x-coordinate of the right edge of the ADC QQ19+2 \ crosshairs BCC P%+4 \ If the above addition didn't overflow, then A is \ correct, so skip the next instruction LDA #255 \ The addition overflowed, so set A to 255 so the \ crosshairs don't spill out of the right of the screen \ (as 255 is the x-coordinate of the rightmost pixel \ on-screen) STA XX15+2 \ Set XX15+2 (X2) = A (the x-coordinate of the right \ edge of the crosshairs) LDA QQ19+1 \ Set XX15+1 (Y1) = crosshairs y-coordinate + indent CLC \ to get the y-coordinate of the centre of the ADC QQ19+5 \ crosshairs STA XX15+1 JSR HLOIN \ Draw a horizontal line from (X1, Y1) to (X2, Y1), \ which will draw from the left edge of the crosshairs \ to the right edge, through the centre of the \ crosshairs LDA QQ19+1 \ Set A = crosshairs y-coordinate - crosshairs size SEC \ to get the y-coordinate of the top edge of the SBC QQ19+2 \ crosshairs BCS TT86 \ If the above subtraction didn't underflow, then A is \ correct, so skip the next instruction LDA #0 \ The subtraction underflowed, so set A to 0 so the \ crosshairs don't spill out of the top of the screen .TT86 CLC \ Set XX15+1 (Y1) = A + indent to get the y-coordinate ADC QQ19+5 \ of the top edge of the indented crosshairs STA XX15+1 LDA QQ19+1 \ Set A = crosshairs y-coordinate + crosshairs size CLC \ + indent to get the y-coordinate of the bottom edge ADC QQ19+2 \ of the indented crosshairs ADC QQ19+5 CMP #152 \ If A < 152 then skip the following, as the crosshairs BCC TT87 \ won't spill out of the bottom of the screen LDX QQ11 \ A >= 152, so we need to check whether this will fit in \ this view, so fetch the view type BMI TT87 \ If this is the Short-range Chart then the y-coordinate \ is fine, so skip to TT87 LDA #151 \ Otherwise this is the Long-range Chart, so we need to \ clip the crosshairs at a maximum y-coordinate of 151 .TT87 STA XX15+3 \ Set XX15+3 (Y2) = A (the y-coordinate of the bottom \ edge of the crosshairs) LDA QQ19 \ Set XX15 (X1) = the x-coordinate of the centre of the STA XX15 \ crosshairs STA XX15+2 \ Set XX15+2 (X2) = the x-coordinate of the centre of \ the crosshairs JMP LL30 \ Draw a vertical line from (X1, Y1) to (X2, Y2), which \ will draw from the top edge of the crosshairs to the \ bottom edge, through the centre of the crosshairs, \ and returning from the subroutine using a tail call \ ****************************************************************************** \ \ Name: TT14 \ Type: Subroutine \ Category: Drawing circles \ Summary: Draw a circle with crosshairs on a chart \ \ ------------------------------------------------------------------------------ \ \ Draw a circle with crosshairs at the current system's galactic coordinates. \ \ ****************************************************************************** .TT126 LDA #104 \ Set QQ19 = 104, for the x-coordinate of the centre of STA QQ19 \ the fixed circle on the Short-range Chart LDA #90 \ Set QQ19+1 = 90, for the y-coordinate of the centre of STA QQ19+1 \ the fixed circle on the Short-range Chart LDA #16 \ Set QQ19+2 = 16, the size of the crosshairs on the STA QQ19+2 \ Short-range Chart JSR TT15 \ Draw the set of crosshairs defined in QQ19, at the \ exact coordinates as this is the Short-range Chart LDA QQ14 \ Set K to the fuel level from QQ14, so this can act as STA K \ the circle's radius (70 being a full tank) JMP TT128 \ Jump to TT128 to draw a circle with the centre at the \ same coordinates as the crosshairs, (QQ19, QQ19+1), \ and radius K that reflects the current fuel levels, \ returning from the subroutine using a tail call .TT14 LDA QQ11 \ If the current view is the Short-range Chart, which BMI TT126 \ is the only view with bit 7 set, then jump up to TT126 \ to draw the crosshairs and circle for that view \ Otherwise this is the Long-range Chart, so we draw the \ crosshairs and circle for that view instead LDA QQ14 \ Set K to the fuel level from QQ14 divided by 4, so LSR A \ this can act as the circle's radius (70 being a full LSR A \ tank, which divides down to a radius of 17) STA K LDA QQ0 \ Set QQ19 to the x-coordinate of the current system, STA QQ19 \ which will be the centre of the circle and crosshairs \ we draw LDA QQ1 \ Set QQ19+1 to the y-coordinate of the current system, LSR A \ halved because the galactic chart is half as high as STA QQ19+1 \ it is wide, which will again be the centre of the \ circle and crosshairs we draw LDA #7 \ Set QQ19+2 = 7, the size of the crosshairs on the STA QQ19+2 \ Long-range Chart JSR TT15 \ Draw the set of crosshairs defined in QQ19, which will \ be drawn 24 pixels to the right of QQ19+1 LDA QQ19+1 \ Add 24 to the y-coordinate of the crosshairs in QQ19+1 CLC \ so that the centre of the circle matches the centre ADC #24 \ of the crosshairs STA QQ19+1 \ Fall through into TT128 to draw a circle with the \ centre at the same coordinates as the crosshairs, \ (QQ19, QQ19+1), and radius K that reflects the \ current fuel levels \ ****************************************************************************** \ \ Name: TT128 \ Type: Subroutine \ Category: Drawing circles \ Summary: Draw a circle on a chart \ Deep dive: Drawing circles \ \ ------------------------------------------------------------------------------ \ \ Draw a circle with the centre at (QQ19, QQ19+1) and radius K. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ QQ19 The x-coordinate of the centre of the circle \ \ QQ19+1 The y-coordinate of the centre of the circle \ \ K The radius of the circle \ \ ****************************************************************************** .TT128 LDA QQ19 \ Set K3 = the x-coordinate of the centre STA K3 LDA QQ19+1 \ Set K4 = the y-coordinate of the centre STA K4 LDX #0 \ Set the high bytes of K3(1 0) and K4(1 0) to 0 STX K4+1 STX K3+1 \STX LSX \ This instruction is commented out in the original \ source INX \ Set LSP = 1 to reset the ball line heap STX LSP LDX #2 \ Set STP = 2, the step size for the circle STX STP JSR CIRCLE2 \ Call CIRCLE2 to draw a circle with the centre at \ (K3(1 0), K4(1 0)) and radius K \LDA #&FF \ These instructions are commented out in the original \STA LSX \ source RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT219 \ Type: Subroutine \ Category: Market \ Summary: Show the Buy Cargo screen (red key f1) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ BAY2 Jump into the main loop at FRCE, setting the key \ "pressed" to red key f9 (so we show the Inventory \ screen) \ \ ****************************************************************************** .TT219 \LDA #2 \ This instruction is commented out in the original \ source. Perhaps this view originally had a QQ11 value \ of 2, but it turned out not to need its own unique ID, \ so the authors found they could just use a view value \ of 1 and save an instruction at the same time? JSR TT66-2 \ Clear the top part of the screen, draw a border box, \ and set the current view type in QQ11 to 1 JSR TT163 \ Print the column headers for the prices table LDA #%10000000 \ Set bit 7 of QQ17 to switch to Sentence Case, with the STA QQ17 \ next letter in capitals \JSR FLKB \ This instruction is commented out in the original \ source. It calls a routine to flush the keyboard \ buffer (FLKB) that isn't present in the cassette \ version but is in other versions LDA #0 \ We're going to loop through all the available market STA QQ29 \ items, so we set up a counter in QQ29 to denote the \ current item and start it at 0 .TT220 JSR TT151 \ Call TT151 to print the item name, market price and \ availability of the current item, and set QQ24 to the \ item's price / 4, QQ25 to the quantity available and \ QQ19+1 to byte #1 from the market prices table for \ this item LDA QQ25 \ If there are some of the current item available, jump BNE TT224 \ to TT224 below to see if we want to buy any JMP TT222 \ Otherwise there are none available, so jump down to \ TT222 to skip this item .TQ4 LDY #176 \ Set Y to the recursive token 16 ("QUANTITY") .Tc JSR TT162 \ Print a space TYA \ Print the recursive token in Y followed by a question JSR prq \ mark .TTX224 JSR dn2 \ Call dn2 to make a short, high beep and delay for 1 \ second .TT224 JSR CLYNS \ Clear the bottom three text rows of the upper screen, \ and move the text cursor to the first cleared row LDA #204 \ Print recursive token 44 ("QUANTITY OF ") JSR TT27 LDA QQ29 \ Print recursive token 48 + QQ29, which will be in the CLC \ range 48 ("FOOD") to 64 ("ALIEN ITEMS"), so this ADC #208 \ prints the current item's name JSR TT27 LDA #'/' \ Print "/" JSR TT27 JSR TT152 \ Print the unit ("t", "kg" or "g") for the current item \ (as the call to TT151 above set QQ19+1 with the \ appropriate value) LDA #'?' \ Print "?" JSR TT27 JSR TT67 \ Print a newline LDX #0 \ These instructions have no effect, as they are STX R \ repeated at the start of gnum, which we call next. LDX #12 \ Perhaps they were left behind when code was moved from STX T1 \ here into gnum, and weren't deleted? \.TT223 \ This label is commented out in the original source, \ and is a duplicate of a label in gnum, so this could \ also be a remnant if the code in gnum was originally \ here, but got moved into the gnum subroutine JSR gnum \ Call gnum to get a number from the keyboard, which \ will be the quantity of this item we want to purchase, \ returning the number entered in A and R BCS TQ4 \ If gnum set the C flag, the number entered is greater \ than the quantity available, so jump up to TQ4 to \ display a "Quantity?" error, beep, clear the number \ and try again STA P \ Otherwise we have a valid purchase quantity entered, \ so store the amount we want to purchase in P JSR tnpr \ Call tnpr to work out whether there is room in the \ cargo hold for this item LDY #206 \ Set Y to recursive token 46 (" CARGO{sentence case}") \ to pass to the Tc routine if we call it BCS Tc \ If the C flag is set, then there is no room in the \ cargo hold, jump up to Tc to print a "Cargo?" error, \ beep, clear the number and try again LDA QQ24 \ There is room in the cargo hold, so now to check STA Q \ whether we have enough cash, so fetch the item's \ price / 4, which was returned in QQ24 by the call \ to TT151 above and store it in Q JSR GCASH \ Call GCASH to calculate: \ \ (Y X) = P * Q * 4 \ \ which will be the total price of this transaction \ (as P contains the purchase quantity and Q contains \ the item's price / 4) JSR LCASH \ Subtract (Y X) cash from the cash pot in CASH LDY #197 \ If the C flag is clear, we didn't have enough cash, BCC Tc \ so set Y to the recursive token 37 ("CASH") and jump \ up to Tc to print a "Cash?" error, beep, clear the \ number and try again LDY QQ29 \ Fetch the current market item number from QQ29 into Y LDA R \ Set A to the number of items we just purchased (this \ was set by gnum above) PHA \ Store the quantity just purchased on the stack CLC \ Add the number purchased to the Y-th byte of QQ20, ADC QQ20,Y \ which contains the number of items of this type in STA QQ20,Y \ our hold (so this transfers the bought items into our \ cargo hold) LDA AVL,Y \ Subtract the number of items from the Y-th byte of SEC \ AVL, which contains the number of items of this type SBC R \ that are available on the market STA AVL,Y PLA \ Restore the quantity just purchased BEQ TT222 \ If we didn't buy anything, jump to TT222 to skip the \ following instruction JSR dn \ Call dn to print the amount of cash left in the cash \ pot, then make a short, high beep to confirm the \ purchase, and delay for 1 second .TT222 LDA QQ29 \ Move the text cursor to row QQ29 + 5 (where QQ29 is CLC \ the item number, starting from 0) ADC #5 STA YC LDA #0 \ Move the text cursor to column 0 STA XC INC QQ29 \ Increment QQ29 to point to the next item LDA QQ29 \ If QQ29 >= 17 then jump to BAY2 as we have done the CMP #17 \ last item BCS BAY2 JMP TT220 \ Otherwise loop back to TT220 to print the next market \ item .BAY2 LDA #f9 \ Jump into the main loop at FRCE, setting the key JMP FRCE \ "pressed" to red key f9 (so we show the Inventory \ screen) \ ****************************************************************************** \ \ Name: gnum \ Type: Subroutine \ Category: Market \ Summary: Get a number from the keyboard \ \ ------------------------------------------------------------------------------ \ \ Get a number from the keyboard, up to the maximum number in QQ25, for the \ buying and selling of cargo and equipment. \ \ Pressing a key with an ASCII code less than ASCII "0" will return a 0 in A (so \ that includes pressing Space or Return), while pressing a key with an ASCII \ code greater than ASCII "9" will jump to the Inventory screen (so that \ includes all letters and most punctuation). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ QQ25 The maximum number allowed \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A The number entered \ \ R Also contains the number entered \ \ C flag Set if the number is too large (> QQ25), clear otherwise \ \ ****************************************************************************** .gnum LDX #0 \ We will build the number entered in R, so initialise STX R \ it with 0 LDX #12 \ We will check for up to 12 key presses, so set a STX T1 \ counter in T1 .TT223 JSR TT217 \ Scan the keyboard until a key is pressed, and return \ the key's ASCII code in A (and X) STA Q \ Store the key pressed in Q SEC \ Subtract ASCII "0" from the key pressed, to leave the SBC #'0' \ numeric value of the key in A (if it was a number key) BCC OUT \ If A < 0, jump to OUT to load the current number and \ return from the subroutine, as the key pressed was \ RETURN (or some other character with a value less than \ ASCII "0") CMP #10 \ If A >= 10, jump to BAY2 to display the Inventory BCS BAY2 \ screen, as the key pressed was a letter or other \ non-digit and is greater than ASCII "9" STA S \ Store the numeric value of the key pressed in S LDA R \ Fetch the result so far into A CMP #26 \ If A >= 26, where A is the number entered so far, then BCS OUT \ adding a further digit will make it bigger than 256, \ so jump to OUT to return from the subroutine with the \ result in R (i.e. ignore the last key press) ASL A \ Set A = (A * 2) + (A * 8) = A * 10 STA T ASL A ASL A ADC T ADC S \ Add the pressed digit to A and store in R, so R now STA R \ contains its previous value with the new key press \ tacked onto the end CMP QQ25 \ If the result in R = the maximum allowed in QQ25, jump BEQ TT226 \ to TT226 to print the key press and keep looping (the \ BEQ is needed because the BCS below would jump to OUT \ if R >= QQ25, which we don't want) BCS OUT \ If the result in R > QQ25, jump to OUT to return from \ the subroutine with the result in R .TT226 LDA Q \ Print the character in Q (i.e. the key that was JSR TT26 \ pressed, as we stored the ASCII value in Q earlier) DEC T1 \ Decrement the loop counter BNE TT223 \ Loop back to TT223 until we have checked for 12 digits .OUT LDA R \ Set A to the result we have been building in R RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT208 \ Type: Subroutine \ Category: Market \ Summary: Show the Sell Cargo screen (red key f2) \ \ ****************************************************************************** .TT208 LDA #4 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 4 (Sell \ Cargo screen) LDA #4 \ Move the text cursor to row 4, column 4 STA YC STA XC \JSR FLKB \ This instruction is commented out in the original \ source. It calls a routine to flush the keyboard \ buffer (FLKB) that isn't present in the cassette \ version but is in other versions LDA #205 \ Print recursive token 45 ("SELL") JSR TT27 LDA #206 \ Print recursive token 46 (" CARGO{sentence case}") JSR TT68 \ followed by a colon \ Fall through into TT210 to show the Inventory screen \ with the option to sell \ ****************************************************************************** \ \ Name: TT210 \ Type: Subroutine \ Category: Market \ Summary: Show a list of current cargo in our hold, optionally to sell \ \ ------------------------------------------------------------------------------ \ \ Show a list of current cargo in our hold, either with the ability to sell (the \ Sell Cargo screen) or without (the Inventory screen), depending on the current \ view. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ QQ11 The current view: \ \ * 4 = Sell Cargo \ \ * 8 = Inventory \ \ ****************************************************************************** .TT210 LDY #0 \ We're going to loop through all the available market \ items and check whether we have any in the hold (and, \ if we are in the Sell Cargo screen, whether we want \ to sell any items), so we set up a counter in Y to \ denote the current item and start it at 0 .TT211 STY QQ29 \ Store the current item number in QQ29 LDX QQ20,Y \ Fetch into X the amount of the current item that we BEQ TT212 \ have in our cargo hold, which is stored in QQ20+Y, \ and if there are no items of this type in the hold, \ jump down to TT212 to skip to the next item TYA \ Set Y = Y * 4, so this will act as an index into the ASL A \ market prices table at QQ23 for this item (as there ASL A \ are four bytes per item in the table) TAY LDA QQ23+1,Y \ Fetch byte #1 from the market prices table for the STA QQ19+1 \ current item and store it in QQ19+1, for use by the \ call to TT152 below TXA \ Store the amount of item in the hold (in X) on the PHA \ stack JSR TT69 \ Call TT69 to set Sentence Case and print a newline CLC \ Print recursive token 48 + QQ29, which will be in the LDA QQ29 \ range 48 ("FOOD") to 64 ("ALIEN ITEMS"), so this ADC #208 \ prints the current item's name JSR TT27 LDA #14 \ Move the text cursor to column 14, for the item's STA XC \ quantity PLA \ Restore the amount of item in the hold into X TAX CLC \ Print the 8-bit number in X to 3 digits, without a JSR pr2 \ decimal point JSR TT152 \ Print the unit ("t", "kg" or "g") for the market item \ whose byte #1 from the market prices table is in \ QQ19+1 (which we set up above) LDA QQ11 \ If the current view type in QQ11 is not 4 (Sell Cargo CMP #4 \ screen), jump to TT212 to skip the option to sell BNE TT212 \ items LDA #205 \ Set A to recursive token 45 ("SELL") JSR TT214 \ Call TT214 to print "Sell(Y/N)?" and return the \ response in the C flag BCC TT212 \ If the response was "no", jump to TT212 to move on to \ the next item LDA QQ29 \ We are selling this item, so fetch the item number \ from QQ29 LDX #255 \ Set QQ17 = 255 to disable printing STX QQ17 JSR TT151 \ Call TT151 to set QQ24 to the item's price / 4 (the \ routine doesn't print the item details, as we just \ disabled printing) LDY QQ29 \ Set P to the amount of this item we have in our cargo LDA QQ20,Y \ hold (which is the amount to sell) STA P LDA QQ24 \ Set Q to the item's price / 4 STA Q JSR GCASH \ Call GCASH to calculate \ \ (Y X) = P * Q * 4 \ \ which will be the total price we make from this sale \ (as P contains the quantity we're selling and Q \ contains the item's price / 4) JSR MCASH \ Add (Y X) cash to the cash pot in CASH LDA #0 \ We've made the sale, so set the amount LDY QQ29 STA QQ20,Y STA QQ17 \ Set QQ17 = 0, which enables printing again .TT212 LDY QQ29 \ Fetch the item number from QQ29 into Y, and increment INY \ Y to point to the next item CPY #17 \ If Y >= 17 then skip the next instruction as we have BCS P%+5 \ done the last item JMP TT211 \ Otherwise loop back to TT211 to print the next item \ in the hold LDA QQ11 \ If the current view type in QQ11 is not 4 (Sell Cargo CMP #4 \ screen), skip the next two instructions and just BNE P%+8 \ return from the subroutine JSR dn2 \ This is the Sell Cargo screen, so call dn2 to make a \ short, high beep and delay for 1 second JMP BAY2 \ And then jump to BAY2 to display the Inventory \ screen, as we have finished selling cargo RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT213 \ Type: Subroutine \ Category: Market \ Summary: Show the Inventory screen (red key f9) \ \ ****************************************************************************** .TT213 LDA #8 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 8 (Inventory \ screen) LDA #11 \ Move the text cursor to column 11 to print the screen STA XC \ title LDA #164 \ Print recursive token 4 ("INVENTORY{crlf}") followed JSR TT60 \ by a paragraph break and Sentence Case JSR NLIN4 \ Draw a horizontal line at pixel row 19 to box in the \ title. The authors could have used a call to NLIN3 \ instead and saved the above call to TT60, but you \ just can't optimise everything JSR fwl \ Call fwl to print the fuel and cash levels on two \ separate lines LDA CRGO \ If our ship's cargo capacity is < 26 (i.e. we do not CMP #26 \ have a cargo bay extension), skip the following two BCC P%+7 \ instructions LDA #107 \ We do have a cargo bay extension, so print recursive JSR TT27 \ token 107 ("LARGE CARGO{sentence case} BAY") JMP TT210 \ Jump to TT210 to print the contents of our cargo bay \ and return from the subroutine using a tail call \ ****************************************************************************** \ \ Name: TT214 \ Type: Subroutine \ Category: Keyboard \ Summary: Ask a question with a "Y/N?" prompt and return the response \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to print before the "Y/N?" prompt \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Set if the response was "yes", clear otherwise \ \ ****************************************************************************** .TT214 PHA \ Print a space, using the stack to preserve the value JSR TT162 \ of A PLA .TT221 JSR TT27 \ Print the text token in A LDA #225 \ Print recursive token 65 ("(Y/N)?") JSR TT27 JSR TT217 \ Scan the keyboard until a key is pressed, and return \ the key's ASCII code in A and X ORA #%00100000 \ Set bit 5 in the value of the key pressed, which \ converts it to lower case CMP #'y' \ If "y" was pressed, jump to TT218 BEQ TT218 LDA #'n' \ Otherwise jump to TT26 to print "n" and return from JMP TT26 \ the subroutine using a tail call (so all other \ responses apart from "y" indicate a no) .TT218 JSR TT26 \ Print the character in A, i.e. print "y" SEC \ Set the C flag to indicate a "yes" response RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT16 \ Type: Subroutine \ Category: Charts \ Summary: Move the crosshairs on a chart \ \ ------------------------------------------------------------------------------ \ \ Move the chart crosshairs by the amount in X and Y. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The amount to move the crosshairs in the x-axis \ \ Y The amount to move the crosshairs in the y-axis \ \ ****************************************************************************** .TT16 TXA \ Push the change in X onto the stack (let's call this PHA \ the x-delta) DEY \ Negate the change in Y and push it onto the stack TYA \ (let's call this the y-delta) EOR #&FF PHA JSR WSCAN \ Call WSCAN to wait for the vertical sync, so the whole \ screen gets drawn and we can move the crosshairs with \ no screen flicker JSR TT103 \ Draw small crosshairs at coordinates (QQ9, QQ10), \ which will erase the crosshairs currently there PLA \ Store the y-delta in QQ19+3 and fetch the current STA QQ19+3 \ y-coordinate of the crosshairs from QQ10 into A, ready LDA QQ10 \ for the call to TT123 JSR TT123 \ Call TT123 to move the selected system's galactic \ y-coordinate by the y-delta, putting the new value in \ QQ19+4 LDA QQ19+4 \ Store the updated y-coordinate in QQ10 (the current STA QQ10 \ y-coordinate of the crosshairs) STA QQ19+1 \ This instruction has no effect, as QQ19+1 is \ overwritten below, both in TT103 and TT105 PLA \ Store the x-delta in QQ19+3 and fetch the current STA QQ19+3 \ x-coordinate of the crosshairs from QQ10 into A, ready LDA QQ9 \ for the call to TT123 JSR TT123 \ Call TT123 to move the selected system's galactic \ x-coordinate by the x-delta, putting the new value in \ QQ19+4 LDA QQ19+4 \ Store the updated x-coordinate in QQ9 (the current STA QQ9 \ x-coordinate of the crosshairs) STA QQ19 \ This instruction has no effect, as QQ19 is overwritten \ below, both in TT103 and TT105 \ Now we've updated the coordinates of the crosshairs, \ fall through into TT103 to redraw them at their new \ location \ ****************************************************************************** \ \ Name: TT103 \ Type: Subroutine \ Category: Charts \ Summary: Draw a small set of crosshairs on a chart \ \ ------------------------------------------------------------------------------ \ \ Draw a small set of crosshairs on a galactic chart at the coordinates in \ (QQ9, QQ10). \ \ ****************************************************************************** .TT103 LDA QQ11 \ Fetch the current view type into A BEQ TT180 \ If this is a space view, return from the subroutine \ (as TT180 contains an RTS), as there are no moveable \ crosshairs in space BMI TT105 \ If this is the Short-range Chart screen, jump to TT105 LDA QQ9 \ Store the crosshairs x-coordinate in QQ19 STA QQ19 LDA QQ10 \ Halve the crosshairs y-coordinate and store it in QQ19 LSR A \ (we halve it because the Long-range Chart is half as STA QQ19+1 \ high as it is wide) LDA #4 \ Set QQ19+2 to 4 denote crosshairs of size 4 STA QQ19+2 JMP TT15 \ Jump to TT15 to draw crosshairs of size 4 at the \ crosshairs coordinates, returning from the subroutine \ using a tail call \ ****************************************************************************** \ \ Name: TT123 \ Type: Subroutine \ Category: Charts \ Summary: Move galactic coordinates by a signed delta \ \ ------------------------------------------------------------------------------ \ \ Move an 8-bit galactic coordinate by a certain distance in either direction \ (i.e. a signed 8-bit delta), but only if it doesn't cause the coordinate to \ overflow. The coordinate is in a single axis, so it's either an x-coordinate \ or a y-coordinate. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The galactic coordinate to update \ \ QQ19+3 The delta (can be positive or negative) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ QQ19+4 The updated coordinate after moving by the delta (this \ will be the same as A if moving by the delta overflows) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT180 Contains an RTS \ \ ****************************************************************************** .TT123 STA QQ19+4 \ Store the original coordinate in temporary storage at \ QQ19+4 CLC \ Set A = A + QQ19+3, so A now contains the original ADC QQ19+3 \ coordinate, moved by the delta LDX QQ19+3 \ If the delta is negative, jump to TT124 BMI TT124 BCC TT125 \ If the C flag is clear, then the above addition didn't \ overflow, so jump to TT125 to return the updated value RTS \ Otherwise the C flag is set and the above addition \ overflowed, so do not update the return value .TT124 BCC TT180 \ If the C flag is clear, then because the delta is \ negative, this indicates the addition (which is \ effectively a subtraction) underflowed, so jump to \ TT180 to return from the subroutine without updating \ the return value .TT125 STA QQ19+4 \ Store the updated coordinate in QQ19+4 .TT180 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT105 \ Type: Subroutine \ Category: Charts \ Summary: Draw crosshairs on the Short-range Chart, with clipping \ \ ------------------------------------------------------------------------------ \ \ Check whether the crosshairs are close enough to the current system to appear \ on the Short-range Chart, and if so, draw them. \ \ ****************************************************************************** .TT105 LDA QQ9 \ Set A = QQ9 - QQ0, the horizontal distance between the SEC \ crosshairs (QQ9) and the current system (QQ0) SBC QQ0 CMP #38 \ If the horizontal distance in A < 38, then the BCC TT179 \ crosshairs are close enough to the current system to \ appear in the Short-range Chart, so jump to TT179 to \ check the vertical distance CMP #230 \ If the horizontal distance in A < -26, then the BCC TT180 \ crosshairs are too far from the current system to \ appear in the Short-range Chart, so jump to TT180 to \ return from the subroutine (as TT180 contains an RTS) .TT179 ASL A \ Set QQ19 = 104 + A * 4 ASL A \ CLC \ 104 is the x-coordinate of the centre of the chart, ADC #104 \ so this sets QQ19 to the screen pixel x-coordinate STA QQ19 \ of the crosshairs LDA QQ10 \ Set A = QQ10 - QQ1, the vertical distance between the SEC \ crosshairs (QQ10) and the current system (QQ1) SBC QQ1 CMP #38 \ If the vertical distance in A is < 38, then the BCC P%+6 \ crosshairs are close enough to the current system to \ appear in the Short-range Chart, so skip the next two \ instructions CMP #220 \ If the horizontal distance in A is < -36, then the BCC TT180 \ crosshairs are too far from the current system to \ appear in the Short-range Chart, so jump to TT180 to \ return from the subroutine (as TT180 contains an RTS) ASL A \ Set QQ19+1 = 90 + A * 2 CLC \ ADC #90 \ 90 is the y-coordinate of the centre of the chart, STA QQ19+1 \ so this sets QQ19+1 to the screen pixel x-coordinate \ of the crosshairs LDA #8 \ Set QQ19+2 to 8 denote crosshairs of size 8 STA QQ19+2 JMP TT15 \ Jump to TT15 to draw crosshairs of size 8 at the \ crosshairs coordinates, returning from the subroutine \ using a tail call \ ****************************************************************************** \ \ Name: TT23 \ Type: Subroutine \ Category: Charts \ Summary: Show the Short-range Chart (red key f5) \ \ ****************************************************************************** .TT23 LDA #128 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 128 (Short- \ range Chart) LDA #7 \ Move the text cursor to column 7 STA XC LDA #190 \ Print recursive token 30 ("SHORT RANGE CHART") and JSR NLIN3 \ draw a horizontal line at pixel row 19 to box in the \ title JSR TT14 \ Call TT14 to draw a circle with crosshairs at the \ current system's galactic coordinates JSR TT103 \ Draw small crosshairs at coordinates (QQ9, QQ10), \ i.e. at the selected system JSR TT81 \ Set the seeds in QQ15 to those of system 0 in the \ current galaxy (i.e. copy the seeds from QQ21 to QQ15) LDA #0 \ Set A = 0, which we'll use below to zero out the INWK \ workspace STA XX20 \ We're about to start working our way through each of \ the galaxy's systems, so set up a counter in XX20 for \ each system, starting at 0 and looping through to 255 LDX #24 \ First, though, we need to zero out the 25 bytes at \ INWK so we can use them to work out which systems have \ room for a label, so set a counter in X for 25 bytes .EE3 STA INWK,X \ Set the X-th byte of INWK to zero DEX \ Decrement the counter BPL EE3 \ Loop back to EE3 for the next byte until we've zeroed \ all 25 bytes \ We now loop through every single system in the galaxy \ and check the distance from the current system whose \ coordinates are in (QQ0, QQ1). We get the galactic \ coordinates of each system from the system's seeds, \ like this: \ \ x = s1_hi (which is stored in QQ15+3) \ y = s0_hi (which is stored in QQ15+1) \ \ so the following loops through each system in the \ galaxy in turn and calculates the distance between \ (QQ0, QQ1) and (s1_hi, s0_hi) to find the closest one .TT182 LDA QQ15+3 \ Set A = s1_hi - QQ0, the horizontal distance between SEC \ (s1_hi, s0_hi) and (QQ0, QQ1) SBC QQ0 BCS TT184 \ If a borrow didn't occur, i.e. s1_hi >= QQ0, then the \ result is positive, so jump to TT184 and skip the \ following two instructions EOR #&FF \ Otherwise negate the result in A, so A is always ADC #1 \ positive (i.e. A = |s1_hi - QQ0|) .TT184 CMP #20 \ If the horizontal distance in A is >= 20, then this BCS TT187 \ system is too far away from the current system to \ appear in the Short-range Chart, so jump to TT187 to \ move on to the next system LDA QQ15+1 \ Set A = s0_hi - QQ1, the vertical distance between SEC \ (s1_hi, s0_hi) and (QQ0, QQ1) SBC QQ1 BCS TT186 \ If a borrow didn't occur, i.e. s0_hi >= QQ1, then the \ result is positive, so jump to TT186 and skip the \ following two instructions EOR #&FF \ Otherwise negate the result in A, so A is always ADC #1 \ positive (i.e. A = |s0_hi - QQ1|) .TT186 CMP #38 \ If the vertical distance in A is >= 38, then this BCS TT187 \ system is too far away from the current system to \ appear in the Short-range Chart, so jump to TT187 to \ move on to the next system \ This system should be shown on the Short-range Chart, \ so now we need to work out where the label should go, \ and set up the various variables we need to draw the \ system's filled circle on the chart LDA QQ15+3 \ Set A = s1_hi - QQ0, the horizontal distance between SEC \ this system and the current system, where |A| < 20. SBC QQ0 \ Let's call this the x-delta, as it's the horizontal \ difference between the current system at the centre of \ the chart, and this system (and this time we keep the \ sign of A, so it can be negative if it's to the left \ of the chart's centre, or positive if it's to the \ right) ASL A \ Set XX12 = 104 + x-delta * 4 ASL A \ ADC #104 \ 104 is the x-coordinate of the centre of the chart, STA XX12 \ so this sets XX12 to the centre 104 +/- 76, the pixel \ x-coordinate of this system LSR A \ Move the text cursor to column x-delta / 2 + 1 LSR A \ which will be in the range 1-10 LSR A STA XC INC XC LDA QQ15+1 \ Set A = s0_hi - QQ1, the vertical distance between SEC \ this system and the current system, where |A| < 38. SBC QQ1 \ Let's call this the y-delta, as it's the vertical \ difference between the current system at the centre of \ the chart, and this system (and this time we keep the \ sign of A, so it can be negative if it's above the \ chart's centre, or positive if it's below) ASL A \ Set K4 = 90 + y-delta * 2 ADC #90 \ STA K4 \ 90 is the y-coordinate of the centre of the chart, \ so this sets K4 to the centre 90 +/- 74, the pixel \ y-coordinate of this system LSR A \ Set Y = A >> 3 LSR A \ = K4 div 8 LSR A \ TAY \ So Y now contains the number of the character row \ that contains this system \ Now to see if there is room for this system's label. \ Ideally we would print the system name on the same \ text row as the system, but we only want to print one \ label per row, to prevent overlap, so now we check \ this system's row, and if that's already occupied, \ the row above, and if that's already occupied, the \ row below... and if that's already occupied, we give \ up and don't print a label for this system LDX INWK,Y \ If the value in INWK+Y is 0 (i.e. the text row BEQ EE4 \ containing this system does not already have another \ system's label on it), jump to EE4 to store this \ system's label on this row INY \ If the value in INWK+Y+1 is 0 (i.e. the text row below LDX INWK,Y \ the one containing this system does not already have BEQ EE4 \ another system's label on it), jump to EE4 to store \ this system's label on this row DEY \ If the value in INWK+Y-1 is 0 (i.e. the text row above DEY \ the one containing this system does not already have LDX INWK,Y \ another system's label on it), fall through into to BNE ee1 \ EE4 to store this system's label on this row, \ otherwise jump to ee1 to skip printing a label for \ this system (as there simply isn't room) .EE4 STY YC \ Now to print the label, so move the text cursor to row \ Y (which contains the row where we can print this \ system's label) CPY #3 \ If Y < 3, then the system would clash with the chart BCC TT187 \ title, so jump to TT187 to skip showing the system DEX \ We entered the EE4 routine with X = 0, so this stores STX INWK,Y \ &FF in INWK+Y, to denote that this row is now occupied \ so we don't try to print another system's label on \ this row LDA #%10000000 \ Set bit 7 of QQ17 to switch to Sentence Case STA QQ17 JSR cpl \ Call cpl to print out the system name for the seeds \ in QQ15 (which now contains the seeds for the current \ system) .ee1 LDA #0 \ Now to plot the star, so set the high bytes of K, K3 STA K3+1 \ and K4 to 0 STA K4+1 STA K+1 LDA XX12 \ Set the low byte of K3 to XX12, the pixel x-coordinate STA K3 \ of this system LDA QQ15+5 \ Fetch s2_hi for this system from QQ15+5, extract bit 0 AND #1 \ and add 2 to get the size of the star, which we store ADC #2 \ in K. This will be either 2, 3 or 4, depending on the STA K \ value of bit 0, and whether the C flag is set (which \ will vary depending on what happens in the above call \ to cpl). Incidentally, the planet's average radius \ also uses s2_hi, bits 0-3 to be precise, but that \ doesn't mean the two sizes affect each other \ We now have the following: \ \ K(1 0) = radius of star (2, 3 or 4) \ \ K3(1 0) = pixel x-coordinate of system \ \ K4(1 0) = pixel y-coordinate of system \ \ which we can now pass to the SUN routine to draw a \ small "sun" on the Short-range Chart for this system JSR FLFLLS \ Call FLFLLS to reset the LSO block JSR SUN \ Call SUN to plot a sun with radius K at pixel \ coordinate (K3, K4) JSR FLFLLS \ Call FLFLLS to reset the LSO block .TT187 JSR TT20 \ We want to move on to the next system, so call TT20 \ to twist the three 16-bit seeds in QQ15 INC XX20 \ Increment the counter BEQ TT111-1 \ If X = 0 then we have done all 256 systems, so return \ from the subroutine (as TT111-1 contains an RTS) JMP TT182 \ Otherwise jump back up to TT182 to process the next \ system \ ****************************************************************************** \ \ Name: TT81 \ Type: Subroutine \ Category: Universe \ Summary: Set the selected system's seeds to those of system 0 \ \ ------------------------------------------------------------------------------ \ \ Copy the three 16-bit seeds for the current galaxy's system 0 (QQ21) into the \ seeds for the selected system (QQ15) - in other words, set the selected \ system's seeds to those of system 0. \ \ ****************************************************************************** .TT81 LDX #5 \ Set up a counter in X to copy six bytes (for three \ 16-bit numbers) LDA QQ21,X \ Copy the X-th byte in QQ21 to the X-th byte in QQ15 STA QQ15,X DEX \ Decrement the counter BPL TT81+2 \ Loop back up to the LDA instruction if we still have \ more bytes to copy RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT111 \ Type: Subroutine \ Category: Universe \ Summary: Set the current system to the nearest system to a point \ \ ------------------------------------------------------------------------------ \ \ Given a set of galactic coordinates in (QQ9, QQ10), find the nearest system \ to this point in the galaxy, and set this as the currently selected system. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ QQ9 The x-coordinate near which we want to find a system \ \ QQ10 The y-coordinate near which we want to find a system \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ QQ8(1 0) The distance from the current system to the nearest \ system to the original coordinates \ \ QQ9 The x-coordinate of the nearest system to the original \ coordinates \ \ QQ10 The y-coordinate of the nearest system to the original \ coordinates \ \ QQ15 to QQ15+5 The three 16-bit seeds of the nearest system to the \ original coordinates \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT111-1 Contains an RTS \ \ ****************************************************************************** .TT111 JSR TT81 \ Set the seeds in QQ15 to those of system 0 in the \ current galaxy (i.e. copy the seeds from QQ21 to QQ15) \ We now loop through every single system in the galaxy \ and check the distance from (QQ9, QQ10). We get the \ galactic coordinates of each system from the system's \ seeds, like this: \ \ x = s1_hi (which is stored in QQ15+3) \ y = s0_hi (which is stored in QQ15+1) \ \ so the following loops through each system in the \ galaxy in turn and calculates the distance between \ (QQ9, QQ10) and (s1_hi, s0_hi) to find the closest one LDY #127 \ Set Y = T = 127 to hold the shortest distance we've STY T \ found so far, which we initially set to half the \ distance across the galaxy, or 127, as our coordinate \ system ranges from (0,0) to (255, 255) LDA #0 \ Set A = U = 0 to act as a counter for each system in STA U \ the current galaxy, which we start at system 0 and \ loop through to 255, the last system .TT130 LDA QQ15+3 \ Set A = s1_hi - QQ9, the horizontal distance between SEC \ (s1_hi, s0_hi) and (QQ9, QQ10) SBC QQ9 BCS TT132 \ If a borrow didn't occur, i.e. s1_hi >= QQ9, then the \ result is positive, so jump to TT132 and skip the \ following two instructions EOR #&FF \ Otherwise negate the result in A, so A is always ADC #1 \ positive (i.e. A = |s1_hi - QQ9|) .TT132 LSR A \ Set S = A / 2 STA S \ = |s1_hi - QQ9| / 2 LDA QQ15+1 \ Set A = s0_hi - QQ10, the vertical distance between SEC \ (s1_hi, s0_hi) and (QQ9, QQ10) SBC QQ10 BCS TT134 \ If a borrow didn't occur, i.e. s0_hi >= QQ10, then the \ result is positive, so jump to TT134 and skip the \ following two instructions EOR #&FF \ Otherwise negate the result in A, so A is always ADC #1 \ positive (i.e. A = |s0_hi - QQ10|) .TT134 LSR A \ Set A = S + A / 2 CLC \ = |s1_hi - QQ9| / 2 + |s0_hi - QQ10| / 2 ADC S \ \ So A now contains the sum of the horizontal and \ vertical distances, both divided by 2 so the result \ fits into one byte, and although this doesn't contain \ the actual distance between the systems, it's a good \ enough approximation to use for comparing distances CMP T \ If A >= T, then this system's distance is bigger than BCS TT135 \ our "minimum distance so far" stored in T, so it's no \ closer than the systems we have already found, so \ skip to TT135 to move on to the next system STA T \ This system is the closest to (QQ9, QQ10) so far, so \ update T with the new "distance" approximation LDX #5 \ As this system is the closest we have found yet, we \ want to store the system's seeds in case it ends up \ being the closest of all, so we set up a counter in X \ to copy six bytes (for three 16-bit numbers) .TT136 LDA QQ15,X \ Copy the X-th byte in QQ15 to the X-th byte in QQ19, STA QQ19,X \ where QQ15 contains the seeds for the system we just \ found to be the closest so far, and QQ19 is temporary \ storage DEX \ Decrement the counter BPL TT136 \ Loop back to TT136 if we still have more bytes to \ copy .TT135 JSR TT20 \ We want to move on to the next system, so call TT20 \ to twist the three 16-bit seeds in QQ15 INC U \ Increment the system counter in U BNE TT130 \ If U > 0 then we haven't done all 256 systems yet, so \ loop back up to TT130 \ We have now finished checking all the systems in the \ galaxy, and the seeds for the closest system are in \ QQ19, so now we want to copy these seeds to QQ15, \ to set the selected system to this closest system LDX #5 \ So we set up a counter in X to copy six bytes (for \ three 16-bit numbers) .TT137 LDA QQ19,X \ Copy the X-th byte in QQ19 to the X-th byte in QQ15 STA QQ15,X DEX \ Decrement the counter BPL TT137 \ Loop back to TT137 if we still have more bytes to \ copy LDA QQ15+1 \ The y-coordinate of the system described by the seeds STA QQ10 \ in QQ15 is in QQ15+1 (s0_hi), so we copy this to QQ10 \ as this is where we store the selected system's \ y-coordinate LDA QQ15+3 \ The x-coordinate of the system described by the seeds STA QQ9 \ in QQ15 is in QQ15+3 (s1_hi), so we copy this to QQ9 \ as this is where we store the selected system's \ x-coordinate \ We have now found the closest system to (QQ9, QQ10) \ and have set it as the selected system, so now we \ need to work out the distance between the selected \ system and the current system SEC \ Set A = QQ9 - QQ0, the horizontal distance between SBC QQ0 \ the selected system's x-coordinate (QQ9) and the \ current system's x-coordinate (QQ0) BCS TT139 \ If a borrow didn't occur, i.e. QQ9 >= QQ0, then the \ result is positive, so jump to TT139 and skip the \ following two instructions EOR #&FF \ Otherwise negate the result in A, so A is always ADC #1 \ positive (i.e. A = |QQ9 - QQ0|) \ A now contains the difference between the two \ systems' x-coordinates, with the sign removed. We \ will refer to this as the x-delta ("delta" means \ change or difference in maths) .TT139 JSR SQUA2 \ Set (A P) = A * A \ = |QQ9 - QQ0| ^ 2 \ = x_delta ^ 2 STA K+1 \ Store (A P) in K(1 0) LDA P STA K LDA QQ10 \ Set A = QQ10 - QQ1, the vertical distance between the SEC \ selected system's y-coordinate (QQ10) and the current SBC QQ1 \ system's y-coordinate (QQ1) BCS TT141 \ If a borrow didn't occur, i.e. QQ10 >= QQ1, then the \ result is positive, so jump to TT141 and skip the \ following two instructions EOR #&FF \ Otherwise negate the result in A, so A is always ADC #1 \ positive (i.e. A = |QQ10 - QQ1|) .TT141 LSR A \ Set A = A / 2 \ A now contains the difference between the two \ systems' y-coordinates, with the sign removed, and \ halved. We halve the value because the galaxy in \ in Elite is rectangular rather than square, and is \ twice as wide (x-axis) as it is high (y-axis), so to \ get a distance that matches the shape of the \ long-range galaxy chart, we need to halve the \ distance between the vertical y-coordinates. We will \ refer to this as the y-delta JSR SQUA2 \ Set (A P) = A * A \ = (|QQ10 - QQ1| / 2) ^ 2 \ = y_delta ^ 2 \ By this point we have the following results: \ \ K(1 0) = x_delta ^ 2 \ (A P) = y_delta ^ 2 \ \ so to find the distance between the two points, we \ can use Pythagoras - so first we need to add the two \ results together, and then take the square root PHA \ Store the high byte of the y-axis value on the stack, \ so we can use A for another purpose LDA P \ Set Q = P + K, which adds the low bytes of the two CLC \ calculated values ADC K STA Q PLA \ Restore the high byte of the y-axis value from the \ stack into A again ADC K+1 \ Set R = A + K+1, which adds the high bytes of the two STA R \ calculated values, so we now have: \ \ (R Q) = K(1 0) + (A P) \ = (x_delta ^ 2) + (y_delta ^ 2) JSR LL5 \ Set Q = SQRT(R Q), so Q now contains the distance \ between the two systems, in terms of coordinates \ We now store the distance to the selected system * 4 \ in the two-byte location QQ8, by taking (0 Q) and \ shifting it left twice, storing it in QQ8(1 0) LDA Q \ First we shift the low byte left by setting ASL A \ A = Q * 2, with bit 7 of A going into the C flag LDX #0 \ Now we set the high byte in QQ8+1 to 0 and rotate STX QQ8+1 \ the C flag into bit 0 of QQ8+1 ROL QQ8+1 ASL A \ And then we repeat the shift left of (QQ8+1 A) ROL QQ8+1 STA QQ8 \ And store A in the low byte, QQ8, so QQ8(1 0) now \ contains Q * 4. Given that the width of the galaxy is \ 256 in coordinate terms, the width of the galaxy \ would be 1024 in the units we store in QQ8 JMP TT24 \ Call TT24 to calculate system data from the seeds in \ QQ15 and store them in the relevant locations, so our \ new selected system is fully set up, and return from \ the subroutine using a tail call \ ****************************************************************************** \ \ Name: hy6 \ Type: Subroutine \ Category: Flight \ Summary: Print a message to say there is no hyperspacing allowed inside the \ station \ \ ------------------------------------------------------------------------------ \ \ Print "Docked" at the bottom of the screen to indicate we can't hyperspace \ when docked. \ \ ****************************************************************************** .hy6 JSR CLYNS \ Clear the bottom three text rows of the upper screen, \ and move the text cursor to the first cleared row LDA #15 \ Move the text cursor to column 15 (the middle of the STA XC \ screen), setting A to 15 at the same time for the \ following call to TT27 JMP TT27 \ Print recursive token 129 ("{sentence case}DOCKED") \ and return from the subroutine using a tail call \ ****************************************************************************** \ \ Name: hyp \ Type: Subroutine \ Category: Flight \ Summary: Start the hyperspace process \ \ ------------------------------------------------------------------------------ \ \ Called when "H" or CTRL-H is pressed during flight. Checks the following: \ \ * We are in space \ \ * We are not already in a hyperspace countdown \ \ If CTRL is being held down, we jump to Ghy to engage the galactic hyperdrive, \ otherwise we check that: \ \ * The selected system is not the current system \ \ * We have enough fuel to make the jump \ \ and if all the pre-jump checks are passed, we print the destination on-screen \ and start the countdown. \ \ ****************************************************************************** .hyp LDA QQ12 \ If we are docked (QQ12 = &FF) then jump to hy6 to BNE hy6 \ print an error message and return from the subroutine \ using a tail call (as we can't hyperspace when docked) LDA QQ22+1 \ Fetch QQ22+1, which contains the number that's shown \ on-screen during hyperspace countdown BNE zZ+1 \ If it is non-zero, return from the subroutine (as zZ+1 \ contains an RTS), as there is already a countdown in \ progress JSR CTRL \ Scan the keyboard to see if CTRL is currently pressed BMI Ghy \ If it is, then the galactic hyperdrive has been \ activated, so jump to Ghy to process it JSR hm \ This is a chart view, so call hm to redraw the chart \ crosshairs LDA QQ8 \ If both bytes of the distance to the selected system ORA QQ8+1 \ in QQ8 are zero, return from the subroutine (as zZ+1 BEQ zZ+1 \ contains an RTS), as the selected system is the \ current system LDA #7 \ Move the text cursor to column 7, row 23 (in the STA XC \ middle of the bottom text row) LDA #23 STA YC LDA #0 \ Set QQ17 = 0 to switch to ALL CAPS STA QQ17 LDA #189 \ Print recursive token 29 ("HYPERSPACE ") JSR TT27 LDA QQ8+1 \ If the high byte of the distance to the selected BNE TT147 \ system in QQ8 is > 0, then it is definitely too far to \ jump (as our maximum range is 7.0 light years, or a \ value of 70 in QQ8(1 0)), so jump to TT147 to print \ "RANGE?" and return from the subroutine using a tail \ call LDA QQ14 \ Fetch our current fuel level from Q114 into A CMP QQ8 \ If our fuel reserves are less than the distance to the BCC TT147 \ selected system, then we don't have enough fuel for \ this jump, so jump to TT147 to print "RANGE?" and \ return from the subroutine using a tail call LDA #'-' \ Print a hyphen JSR TT27 JSR cpl \ Call cpl to print the name of the selected system \ Fall through into wW to start the hyperspace countdown \ ****************************************************************************** \ \ Name: wW \ Type: Subroutine \ Category: Flight \ Summary: Start a hyperspace countdown \ \ ------------------------------------------------------------------------------ \ \ Start the hyperspace countdown (for both inter-system hyperspace and the \ galactic hyperdrive). \ \ ****************************************************************************** .wW LDA #15 \ The hyperspace countdown starts from 15, so set A to \ 15 so we can set the two hyperspace counters STA QQ22+1 \ Set the number in QQ22+1 to A, which is the number \ that's shown on-screen during the hyperspace countdown STA QQ22 \ Set the number in QQ22 to 15, which is the internal \ counter that counts down by 1 each iteration of the \ main game loop, and each time it reaches zero, the \ on-screen counter gets decremented, and QQ22 gets set \ to 5, so setting QQ22 to 15 here makes the first tick \ of the hyperspace counter longer than subsequent ticks TAX \ Print the 8-bit number in X (i.e. 15) at text location JMP ee3 \ (0, 1), padded to 5 digits, so it appears in the top \ left corner of the screen, and return from the \ subroutine using a tail call \.hy5 \ This instruction and the hy5 label are commented out \ \ in the original - they can actually be found at the \RTS \ end of the jmp routine below, so perhaps this is where \ they were originally, but the authors realised they \ could save a byte by using a tail call instead of an \ RTS? \ ****************************************************************************** \ \ Name: Ghy \ Type: Subroutine \ Category: Flight \ Summary: Perform a galactic hyperspace jump \ Deep dive: Twisting the system seeds \ Galaxy and system seeds \ \ ------------------------------------------------------------------------------ \ \ Engage the galactic hyperdrive. Called from the hyp routine above if CTRL-H is \ being pressed. \ \ This routine also updates the galaxy seeds to point to the next galaxy. Using \ a galactic hyperdrive rotates each seed byte to the left, rolling each byte \ left within itself like this: \ \ 01234567 -> 12345670 \ \ to get the seeds for the next galaxy. So after 8 galactic jumps, the seeds \ roll round to those of the first galaxy again. \ \ We always arrive in a new galaxy at galactic coordinates (96, 96), and then \ find the nearest system and set that as our location. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ zZ+1 Contains an RTS \ \ ****************************************************************************** .Ghy IF _TEXT_SOURCES JSR TT111 \ Call TT111 to set the current system to the nearest \ system to (QQ9, QQ10), and put the seeds of the \ nearest system into QQ15 to QQ15+5 \ \ This appears to be a failed attempt to fix a bug in \ the cassette version, where the galactic hyperdrive \ will take us to coordinates (96, 96) in the new \ galaxy, even if there isn't actually a system there, \ so if we jump when you are low on fuel, it is \ possible to get stuck in the middle of nowhere when \ changing galaxy \ \ All the other versions contain a fix for this bug that \ involves adding an extra JSR TT111 instruction after \ the coordinates are set to (96, 96) below, which finds \ the nearest system to those coordinates and sets that \ as the current system \ \ The cassette version on the original source disc \ doesn't contain this instruction, and although the \ text sources do, it's in the wrong place at the start \ of the Ghy routine, as the fix only works if it's done \ after the new coordinates are set, not before ENDIF LDX GHYP \ Fetch GHYP, which tells us whether we own a galactic BEQ hy5 \ hyperdrive, and if it is zero, which means we don't, \ return from the subroutine (as hy5 contains an RTS) INX \ We own a galactic hyperdrive, so X is &FF, so this \ instruction sets X = 0 IF _SOURCE_DISC OR _TEXT_SOURCES STX QQ8 \ Set the distance to the selected system in QQ8(1 0) STX QQ8+1 \ to 0 ENDIF STX GHYP \ The galactic hyperdrive is a one-use item, so set GHYP \ to 0 so we no longer have one fitted STX FIST \ Changing galaxy also clears our criminal record, so \ set our legal status in FIST to 0 ("clean") JSR wW \ Call wW to start the hyperspace countdown LDX #5 \ To move galaxy, we rotate the galaxy's seeds left, so \ set a counter in X for the 6 seed bytes INC GCNT \ Increment the current galaxy number in GCNT LDA GCNT \ Set GCNT = GCNT mod 8, so we jump from galaxy 7 back AND #7 \ to galaxy 0 (shown in-game as going from galaxy 8 back STA GCNT \ to the starting point in galaxy 1) .G1 LDA QQ21,X \ Load the X-th seed byte into A ASL A \ Set the C flag to bit 7 of the seed ROL QQ21,X \ Rotate the seed in memory, which will add bit 7 back \ in as bit 0, so this rolls the seed around on itself DEX \ Decrement the counter BPL G1 \ Loop back for the next seed byte, until we have \ rotated them all \JSR DORND \ This instruction is commented out in the original \ source, and would set A and X to random numbers, so \ perhaps the original plan was to arrive in each new \ galaxy in a random place? .zZ LDA #96 \ Set (QQ9, QQ10) to (96, 96), which is where we always STA QQ9 \ arrive in a new galaxy (the selected system will be STA QQ10 \ set to the nearest actual system later on) JSR TT110 \ Call TT110 to show the front space view IF _STH_CASSETTE JSR TT111 \ Call TT111 to set the current system to the nearest \ system to (QQ9, QQ10), and put the seeds of the \ nearest system into QQ15 to QQ15+5 \ \ This call fixes a bug in the early cassette versions, \ where the galactic hyperdrive will take us to \ coordinates (96, 96) in the new galaxy, even if there \ isn't actually a system there, so if we jump when we \ are low on fuel, it is possible to get stuck in the \ middle of nowhere when changing galaxy \ \ This call sets the current system correctly, so we \ always arrive at the nearest system to (96, 96) ENDIF IF _STH_CASSETTE LDX #0 \ Set the distance to the selected system in QQ8(1 0) STX QQ8 \ to 0 STX QQ8+1 ENDIF LDA #116 \ Print recursive token 116 (GALACTIC HYPERSPACE ") JSR MESS \ as an in-flight message \ Fall through into jmp to set the system to the \ current system and return from the subroutine there \ ****************************************************************************** \ \ Name: jmp \ Type: Subroutine \ Category: Universe \ Summary: Set the current system to the selected system \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ (QQ0, QQ1) The galactic coordinates of the new system \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ hy5 Contains an RTS \ \ ****************************************************************************** .jmp LDA QQ9 \ Set the current system's galactic x-coordinate to the STA QQ0 \ x-coordinate of the selected system LDA QQ10 \ Set the current system's galactic y-coordinate to the STA QQ1 \ y-coordinate of the selected system .hy5 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: ee3 \ Type: Subroutine \ Category: Flight \ Summary: Print the hyperspace countdown in the top-left of the screen \ \ ------------------------------------------------------------------------------ \ \ Print the 8-bit number in X at text location (0, 1). Print the number to \ 5 digits, left-padding with spaces for numbers with fewer than 3 digits (so \ numbers < 10000 are right-aligned), with no decimal point. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The number to print \ \ ****************************************************************************** .ee3 LDY #1 \ Move the text cursor to row 1 STY YC DEY \ Decrement Y to 0 for the high byte in pr6 STY XC \ Move the text cursor to column 0 \ Fall through into pr6 to print X to 5 digits, as the \ high byte in Y is 0 \ ****************************************************************************** \ \ Name: pr6 \ Type: Subroutine \ Category: Text \ Summary: Print 16-bit number, left-padded to 5 digits, no point \ \ ------------------------------------------------------------------------------ \ \ Print the 16-bit number in (Y X) to 5 digits, left-padding with spaces for \ numbers with fewer than 3 digits (so numbers < 10000 are right-aligned), \ with no decimal point. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The low byte of the number to print \ \ Y The high byte of the number to print \ \ ****************************************************************************** .pr6 CLC \ Do not display a decimal point when printing \ Fall through into pr5 to print X to 5 digits \ ****************************************************************************** \ \ Name: pr5 \ Type: Subroutine \ Category: Text \ Summary: Print a 16-bit number, left-padded to 5 digits, and optional point \ \ ------------------------------------------------------------------------------ \ \ Print the 16-bit number in (Y X) to 5 digits, left-padding with spaces for \ numbers with fewer than 3 digits (so numbers < 10000 are right-aligned). \ Optionally include a decimal point. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The low byte of the number to print \ \ Y The high byte of the number to print \ \ C flag If set, include a decimal point \ \ ****************************************************************************** .pr5 LDA #5 \ Set the number of digits to print to 5 JMP TT11 \ Call TT11 to print (Y X) to 5 digits and return from \ the subroutine using a tail call \ ****************************************************************************** \ \ Name: TT147 \ Type: Subroutine \ Category: Flight \ Summary: Print an error when a system is out of hyperspace range \ \ ------------------------------------------------------------------------------ \ \ Print "RANGE?" for when the hyperspace distance is too far \ \ ****************************************************************************** .TT147 LDA #202 \ Load A with token 42 ("RANGE") and fall through into \ prq to print it, followed by a question mark \ ****************************************************************************** \ \ Name: prq \ Type: Subroutine \ Category: Text \ Summary: Print a text token followed by a question mark \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ prq+3 Print a question mark \ \ ****************************************************************************** .prq JSR TT27 \ Print the text token in A LDA #'?' \ Print a question mark and return from the JMP TT27 \ subroutine using a tail call \ ****************************************************************************** \ \ Name: TT151 \ Type: Subroutine \ Category: Market \ Summary: Print the name, price and availability of a market item \ Deep dive: Market item prices and availability \ Galaxy and system seeds \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The number of the market item to print, 0-16 (see QQ23 \ for details of item numbers) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ QQ19+1 Byte #1 from the market prices table for this item \ \ QQ24 The item's price / 4 \ \ QQ25 The item's availability \ \ ****************************************************************************** .TT151 PHA \ Store the item number on the stack and in QQ19+4 STA QQ19+4 ASL A \ Store the item number * 4 in QQ19, so this will act as ASL A \ an index into the market prices table at QQ23 for this STA QQ19 \ item (as there are four bytes per item in the table) LDA #1 \ Move the text cursor to column 1, for the item's name STA XC PLA \ Restore the item number ADC #208 \ Print recursive token 48 + A, which will be in the JSR TT27 \ range 48 ("FOOD") to 64 ("ALIEN ITEMS"), so this \ prints the item's name LDA #14 \ Move the text cursor to column 14, for the price STA XC LDX QQ19 \ Fetch byte #1 from the market prices table (units and LDA QQ23+1,X \ economic_factor) for this item and store in QQ19+1 STA QQ19+1 LDA QQ26 \ Fetch the random number for this system visit and AND QQ23+3,X \ AND with byte #3 from the market prices table (mask) \ to give: \ \ A = random AND mask CLC \ Add byte #0 from the market prices table (base_price), ADC QQ23,X \ so we now have: STA QQ24 \ \ A = base_price + (random AND mask) JSR TT152 \ Call TT152 to print the item's unit ("t", "kg" or \ "g"), padded to a width of two characters JSR var \ Call var to set QQ19+3 = economy * |economic_factor| \ (and set the availability of alien items to 0) LDA QQ19+1 \ Fetch the byte #1 that we stored above and jump to BMI TT155 \ TT155 if it is negative (i.e. if the economic_factor \ is negative) LDA QQ24 \ Set A = QQ24 + QQ19+3 ADC QQ19+3 \ \ = base_price + (random AND mask) \ + (economy * |economic_factor|) \ \ which is the result we want, as the economic_factor \ is positive JMP TT156 \ Jump to TT156 to multiply the result by 4 .TT155 LDA QQ24 \ Set A = QQ24 - QQ19+3 SEC \ SBC QQ19+3 \ = base_price + (random AND mask) \ - (economy * |economic_factor|) \ \ which is the result we want, as economic_factor \ is negative .TT156 STA QQ24 \ Store the result in QQ24 and P STA P LDA #0 \ Set A = 0 and call GC2 to calculate (Y X) = (A P) * 4, JSR GC2 \ which is the same as (Y X) = P * 4 because A = 0 SEC \ We now have our final price, * 10, so we can call pr5 JSR pr5 \ to print (Y X) to 5 digits, including a decimal \ point, as the C flag is set LDY QQ19+4 \ We now move on to availability, so fetch the market \ item number that we stored in QQ19+4 at the start LDA #5 \ Set A to 5 so we can print the availability to 5 \ digits (right-padded with spaces) LDX AVL,Y \ Set X to the item's availability, which is given in \ the AVL table STX QQ25 \ Store the availability in QQ25 CLC \ Clear the C flag BEQ TT172 \ If none are available, jump to TT172 to print a tab \ and a "-" JSR pr2+2 \ Otherwise print the 8-bit number in X to 5 digits, \ right-aligned with spaces. This works because we set \ A to 5 above, and we jump into the pr2 routine just \ after the first instruction, which would normally \ set the number of digits to 3 JMP TT152 \ Print the unit ("t", "kg" or "g") for the market item, \ with a following space if required to make it two \ characters long, and return from the subroutine using \ a tail call .TT172 LDA XC \ Move the text cursor in XC to the right by 4 columns, ADC #4 \ so the cursor is where the last digit would be if we STA XC \ were printing a five-digit availability number LDA #'-' \ Print a "-" character by jumping to TT162+2, which BNE TT162+2 \ contains JMP TT27 (this BNE is effectively a JMP as A \ will never be zero), and return from the subroutine \ using a tail call \ ****************************************************************************** \ \ Name: TT152 \ Type: Subroutine \ Category: Market \ Summary: Print the unit ("t", "kg" or "g") for a market item \ \ ------------------------------------------------------------------------------ \ \ Print the unit ("t", "kg" or "g") for the market item whose byte #1 from the \ market prices table is in QQ19+1, right-padded with spaces to a width of two \ characters (so that's "t ", "kg" or "g "). \ \ ****************************************************************************** .TT152 LDA QQ19+1 \ Fetch the economic_factor from QQ19+1 AND #96 \ If bits 5 and 6 are both clear, jump to TT160 to BEQ TT160 \ print "t" for tonne, followed by a space, and return \ from the subroutine using a tail call CMP #32 \ If bit 5 is set, jump to TT161 to print "kg" for BEQ TT161 \ kilograms, and return from the subroutine using a tail \ call JSR TT16a \ Otherwise call TT16a to print "g" for grams, and fall \ through into TT162 to print a space and return from \ the subroutine \ ****************************************************************************** \ \ Name: TT162 \ Type: Subroutine \ Category: Text \ Summary: Print a space \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT162+2 Jump to TT27 to print the text token in A \ \ ****************************************************************************** .TT162 LDA #' ' \ Load a space character into A JMP TT27 \ Print the text token in A and return from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: TT160 \ Type: Subroutine \ Category: Market \ Summary: Print "t" (for tonne) and a space \ \ ****************************************************************************** .TT160 LDA #'t' \ Load a "t" character into A JSR TT26 \ Print the character, using TT216 so that it doesn't \ change the character case BCC TT162 \ Jump to TT162 to print a space and return from the \ subroutine using a tail call (this BCC is effectively \ a JMP as the C flag is cleared by TT26) \ ****************************************************************************** \ \ Name: TT161 \ Type: Subroutine \ Category: Market \ Summary: Print "kg" (for kilograms) \ \ ****************************************************************************** .TT161 LDA #'k' \ Load a "k" character into A JSR TT26 \ Print the character, using TT216 so that it doesn't \ change the character case, and fall through into \ TT16a to print a "g" character \ ****************************************************************************** \ \ Name: TT16a \ Type: Subroutine \ Category: Market \ Summary: Print "g" (for grams) \ \ ****************************************************************************** .TT16a LDA #'g' \ Load a "g" character into A JMP TT26 \ Print the character, using TT216 so that it doesn't \ change the character case, and return from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: TT163 \ Type: Subroutine \ Category: Market \ Summary: Print the headers for the table of market prices \ \ ------------------------------------------------------------------------------ \ \ Print the column headers for the prices table in the Buy Cargo and Market \ Price screens. \ \ ****************************************************************************** .TT163 LDA #17 \ Move the text cursor in XC to column 17 STA XC LDA #255 \ Print recursive token 95 token ("UNIT QUANTITY BNE TT162+2 \ {crlf} PRODUCT UNIT PRICE FOR SALE{crlf}{lf}") by \ jumping to TT162+2, which contains JMP TT27 (this BNE \ is effectively a JMP as A will never be zero), and \ return from the subroutine using a tail call \ ****************************************************************************** \ \ Name: TT167 \ Type: Subroutine \ Category: Market \ Summary: Show the Market Price screen (red key f7) \ \ ****************************************************************************** .TT167 LDA #16 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 16 (Market \ Price screen) LDA #5 \ Move the text cursor to column 5 STA XC LDA #167 \ Print recursive token 7 ("{current system name} MARKET JSR NLIN3 \ PRICES") and draw a horizontal line at pixel row 19 \ to box in the title LDA #3 \ Move the text cursor to row 3 STA YC JSR TT163 \ Print the column headers for the prices table LDA #0 \ We're going to loop through all the available market STA QQ29 \ items, so we set up a counter in QQ29 to denote the \ current item and start it at 0 .TT168 LDX #%10000000 \ Set bit 7 of QQ17 to switch to Sentence Case, with the STX QQ17 \ next letter in capitals JSR TT151 \ Call TT151 to print the item name, market price and \ availability of the current item, and set QQ24 to the \ item's price / 4, QQ25 to the quantity available and \ QQ19+1 to byte #1 from the market prices table for \ this item INC YC \ Move the text cursor down one row INC QQ29 \ Increment QQ29 to point to the next item LDA QQ29 \ If QQ29 >= 17 then jump to TT168 as we have done the CMP #17 \ last item BCC TT168 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: var \ Type: Subroutine \ Category: Market \ Summary: Calculate QQ19+3 = economy * |economic_factor| \ \ ------------------------------------------------------------------------------ \ \ Set QQ19+3 = economy * |economic_factor|, given byte #1 of the market prices \ table for an item. Also sets the availability of alien items to 0. \ \ This routine forms part of the calculations for market item prices (TT151) \ and availability (GVL). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ QQ19+1 Byte #1 of the market prices table for this market item \ (which contains the economic_factor in bits 0-5, and the \ sign of the economic_factor in bit 7) \ \ ****************************************************************************** .var LDA QQ19+1 \ Extract bits 0-5 from QQ19+1 into A, to get the AND #31 \ economic_factor without its sign, in other words: \ \ A = |economic_factor| LDY QQ28 \ Set Y to the economy byte of the current system STA QQ19+2 \ Store A in QQ19+2 CLC \ Clear the C flag so we can do additions below LDA #0 \ Set AVL+16 (availability of alien items) to 0, STA AVL+16 \ setting A to 0 in the process .TT153 \ We now do the multiplication by doing a series of \ additions in a loop, building the result in A. Each \ loop adds QQ19+2 (|economic_factor|) to A, and it \ loops the number of times given by the economy byte; \ in other words, because A starts at 0, this sets: \ \ A = economy * |economic_factor| DEY \ Decrement the economy in Y, exiting the loop when it BMI TT154 \ becomes negative ADC QQ19+2 \ Add QQ19+2 to A JMP TT153 \ Loop back to TT153 to do another addition .TT154 STA QQ19+3 \ Store the result in QQ19+3 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: hyp1 \ Type: Subroutine \ Category: Universe \ Summary: Process a jump to the system closest to (QQ9, QQ10) \ \ ------------------------------------------------------------------------------ \ \ Do a hyperspace jump to the system closest to galactic coordinates \ (QQ9, QQ10), and set up the current system's state to those of the new system. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ (QQ0, QQ1) The galactic coordinates of the new system \ \ QQ2 to QQ2+6 The seeds of the new system \ \ EV Set to 0 \ \ QQ28 The new system's economy \ \ tek The new system's tech level \ \ gov The new system's government \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ hyp1+3 Jump straight to the system at (QQ9, QQ10) without \ first calculating which system is closest. We do this \ if we already know that (QQ9, QQ10) points to a system \ \ ****************************************************************************** .hyp1 JSR TT111 \ Select the system closest to galactic coordinates \ (QQ9, QQ10) JSR jmp \ Set the current system to the selected system LDX #5 \ We now want to copy the seeds for the selected system \ in QQ15 into QQ2, where we store the seeds for the \ current system, so set up a counter in X for copying \ 6 bytes (for three 16-bit seeds) .TT112 LDA QQ15,X \ Copy the X-th byte in QQ15 to the X-th byte in QQ2, to STA QQ2,X \ update the selected system to the new one. Note that \ this approach has a minor bug associated with it: if \ your hyperspace counter hits 0 just as you're docking, \ then you will magically appear in the station in your \ hyperspace destination, without having to go to the \ effort of actually flying there. This bug was fixed in \ later versions by saving the destination seeds in a \ separate location called safehouse, and using those \ instead... but that isn't the case in this version DEX \ Decrement the counter BPL TT112 \ Loop back to TT112 if we still have more bytes to \ copy INX \ Set X = 0 (as we ended the above loop with X = &FF) STX EV \ Set EV, the extra vessels spawning counter, to 0, as \ we are entering a new system with no extra vessels \ spawned LDA QQ3 \ Set the current system's economy in QQ28 to the STA QQ28 \ selected system's economy from QQ3 LDA QQ5 \ Set the current system's tech level in tek to the STA tek \ selected system's economy from QQ5 LDA QQ4 \ Set the current system's government in gov to the STA gov \ selected system's government from QQ4 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: GVL \ Type: Subroutine \ Category: Universe \ Summary: Calculate the availability of market items \ Deep dive: Market item prices and availability \ Galaxy and system seeds \ \ ------------------------------------------------------------------------------ \ \ Calculate the availability for each market item and store it in AVL. This is \ called on arrival in a new system. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ hyR Contains an RTS \ \ ****************************************************************************** .GVL JSR DORND \ Set A and X to random numbers STA QQ26 \ Set QQ26 to the random byte that's used in the market \ calculations LDX #0 \ We are now going to loop through the market item STX XX4 \ availability table in AVL, so set a counter in XX4 \ (and X) for the market item number, starting with 0 .hy9 LDA QQ23+1,X \ Fetch byte #1 from the market prices table (units and STA QQ19+1 \ economic_factor) for item number X and store it in \ QQ19+1 JSR var \ Call var to set QQ19+3 = economy * |economic_factor| \ (and set the availability of alien items to 0) LDA QQ23+3,X \ Fetch byte #3 from the market prices table (mask) and AND QQ26 \ AND with the random number for this system visit \ to give: \ \ A = random AND mask CLC \ Add byte #2 from the market prices table ADC QQ23+2,X \ (base_quantity) so we now have: \ \ A = base_quantity + (random AND mask) LDY QQ19+1 \ Fetch the byte #1 that we stored above and jump to BMI TT157 \ TT157 if it is negative (i.e. if the economic_factor \ is negative) SEC \ Set A = A - QQ19+3 SBC QQ19+3 \ \ = base_quantity + (random AND mask) \ - (economy * |economic_factor|) \ \ which is the result we want, as the economic_factor \ is positive JMP TT158 \ Jump to TT158 to skip TT157 .TT157 CLC \ Set A = A + QQ19+3 ADC QQ19+3 \ \ = base_quantity + (random AND mask) \ + (economy * |economic_factor|) \ \ which is the result we want, as the economic_factor \ is negative .TT158 BPL TT159 \ If A < 0, then set A = 0, so we don't have negative LDA #0 \ availability .TT159 LDY XX4 \ Fetch the counter (the market item number) into Y AND #%00111111 \ Take bits 0-5 of A, i.e. A mod 64, and store this as STA AVL,Y \ this item's availability in the Y=th byte of AVL, so \ each item has a maximum availability of 63t INY \ Increment the counter into XX44, Y and A TYA STA XX4 ASL A \ Set X = counter * 4, so that X points to the next ASL A \ item's entry in the four-byte market prices table, TAX \ ready for the next loop CMP #63 \ If A < 63, jump back up to hy9 to set the availability BCC hy9 \ for the next market item .hyR RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: GTHG \ Type: Subroutine \ Category: Universe \ Summary: Spawn a Thargoid ship and a Thargon companion \ Deep dive: Fixing ship positions \ Aggression and hostility in ship tactics \ \ ****************************************************************************** .GTHG JSR Ze \ Call Ze to initialise INWK to a fairly aggressive \ ship (though we increase this below) \ \ Note that because Ze uses the value of X returned by \ DORND, and X contains the value of A returned by the \ previous call to DORND, this does not set the new ship \ to a totally random location LDA #%11111111 \ Set the AI flag in byte #32 so that the ship has AI, STA INWK+32 \ an aggression level of 63 out of 63, and E.C.M. LDA #THG \ Call NWSHP to add a new Thargoid ship to our local JSR NWSHP \ bubble of universe LDA #TGL \ Call NWSHP to add a new Thargon ship to our local JMP NWSHP \ bubble of universe, and return from the subroutine \ using a tail call \ ****************************************************************************** \ \ Name: MJP \ Type: Subroutine \ Category: Flight \ Summary: Process a mis-jump into witchspace \ \ ------------------------------------------------------------------------------ \ \ Process a mis-jump into witchspace (which happens very rarely). Witchspace has \ a strange, almost dust-free aspect to it, and it is populated by aggressive \ Thargoids. Using our escape pod will be fatal, and our position on the \ galactic chart is in-between systems. It is a scary place... \ \ There is a 0.78% chance that this routine is called from TT18 instead of doing \ a normal hyperspace, or we can manually trigger a mis-jump by holding down \ CTRL after first enabling the "author display" configuration option ("X") when \ paused. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ ptg Called when the user manually forces a mis-jump \ \ ****************************************************************************** .ptg LSR COK \ Set bit 0 of the competition flags in COK, so that the SEC \ competition code will include the fact that we have ROL COK \ manually forced a mis-jump into witchspace .MJP \LDA #1 \ This instruction is commented out in the original \ source - it is not required as a call to TT66-2 sets \ A to 1 for us. This is presumably an example of the \ authors saving a couple of bytes by calling TT66-2 \ instead of TT66, while leaving the original LDA \ instruction in place JSR TT66-2 \ Clear the top part of the screen, draw a border box, \ and set the current view type in QQ11 to 1 JSR LL164 \ Call LL164 to show the hyperspace tunnel and make the \ hyperspace sound for a second time (as we already \ called LL164 in TT18) JSR RES2 \ Reset a number of flight variables and workspaces, as \ well as setting Y to &FF STY MJ \ Set the mis-jump flag in MJ to &FF, to indicate that \ we are now in witchspace .MJP1 JSR GTHG \ Call GTHG to spawn a Thargoid ship and a Thargon \ companion LDA #3 \ Fetch the number of Thargoid ships from MANY+THG, and CMP MANY+THG \ if it is less than or equal to 3, loop back to MJP1 to BCS MJP1 \ spawn another one, until we have four Thargoids STA NOSTM \ Set NOSTM (the maximum number of stardust particles) \ to 3, so there are fewer bits of stardust in \ witchspace (normal space has a maximum of 18) LDX #0 \ Initialise the front space view JSR LOOK1 LDA QQ1 \ Fetch the current system's galactic y-coordinate in EOR #%00011111 \ QQ1 and flip bits 0-5, so we end up somewhere in the STA QQ1 \ vicinity of our original destination, but above or \ below it in the galactic chart RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT18 \ Type: Subroutine \ Category: Flight \ Summary: Try to initiate a jump into hyperspace \ \ ------------------------------------------------------------------------------ \ \ Try to go through hyperspace. Called from TT102 in the main loop when the \ hyperspace countdown has finished. \ \ ****************************************************************************** .TT18 LDA QQ14 \ Subtract the distance to the selected system (in QQ8) SEC \ from the amount of fuel in our tank (in QQ14) into A SBC QQ8 STA QQ14 \ Store the updated fuel amount in QQ14 LDA QQ11 \ If the current view is not a space view, jump to ee5 BNE ee5 \ to skip the following JSR TT66 \ Clear the top part of the screen, draw a border box, \ and set the current view type in QQ11 to 0 (space \ view) JSR LL164 \ Call LL164 to show the hyperspace tunnel and make the \ hyperspace sound .ee5 JSR CTRL \ Scan the keyboard to see if CTRL is currently pressed, \ returning a negative value in A if it is AND PATG \ If the game is configured to show the author's names \ on the start-up screen, then PATG will contain &FF, \ otherwise it will be 0 BMI ptg \ By now, A will be negative if we are holding down CTRL \ and author names are configured, which is what we have \ to do in order to trigger a manual mis-jump, so jump \ to ptg to do a mis-jump (ptg not only mis-jumps, but \ updates the competition flags, so Acornsoft could tell \ from the competition code whether this feature had \ been used) JSR DORND \ Set A and X to random numbers CMP #253 \ If A >= 253 (0.78% chance) then jump to MJP to trigger BCS MJP \ a mis-jump into witchspace \JSR TT111 \ This instruction is commented out in the original \ source. It finds the closest system to coordinates \ (QQ9, QQ10), but we don't need to do this as the \ crosshairs will already be on a system by this point JSR hyp1+3 \ Jump straight to the system at (QQ9, QQ10) without \ first calculating which system is closest JSR GVL \ Calculate the availability for each market item in the \ new system JSR RES2 \ Reset a number of flight variables and workspaces JSR SOLAR \ Halve our legal status, update the missile indicators, \ and set up data blocks and slots for the planet and \ sun LDA QQ11 \ If the current view in QQ11 is not a space view (0) or AND #%00111111 \ one of the charts (64 or 128), return from the BNE hyR \ subroutine (as hyR contains an RTS) JSR TTX66 \ Otherwise clear the screen and draw a border box LDA QQ11 \ If the current view is one of the charts, jump to BNE TT114 \ TT114 (from which we jump to the correct routine to \ display the chart) INC QQ11 \ This is a space view, so increment QQ11 to 1 \ Fall through into TT110 to show the front space view \ ****************************************************************************** \ \ Name: TT110 \ Type: Subroutine \ Category: Flight \ Summary: Launch from a station or show the front space view \ \ ------------------------------------------------------------------------------ \ \ Launch the ship (if we are docked), or show the front space view (if we are \ already in space). \ \ Called when red key f0 is pressed while docked (launch), after we arrive in a \ new galaxy, or after a hyperspace if the current view is a space view. \ \ ****************************************************************************** .TT110 LDX QQ12 \ If we are not docked (QQ12 = 0) then jump to NLUNCH BEQ NLUNCH \ to skip the launch tunnel and setup process JSR LAUN \ Show the space station launch tunnel JSR RES2 \ Reset a number of flight variables and workspaces JSR TT111 \ Select the system closest to galactic coordinates \ (QQ9, QQ10) INC INWK+8 \ Increment z_sign ready for the call to SOS, so the \ planet appears at a z_sign of 1 in front of us when \ we launch JSR SOS1 \ Call SOS1 to set up the planet's data block and add it \ to FRIN, where it will get put in the first slot as \ it's the first one to be added to our local bubble of \ universe following the call to RES2 above LDA #128 \ For the space station, set z_sign to &80, so it's STA INWK+8 \ behind us (&80 is negative) INC INWK+7 \ And increment z_hi, so it's only just behind us JSR NWSPS \ Add a new space station to our local bubble of \ universe LDA #12 \ Set our launch speed in DELTA to 12 STA DELTA JSR BAD \ Call BAD to work out how much illegal contraband we \ are carrying in our hold (A is up to 40 for a \ standard hold crammed with contraband, up to 70 for \ an extended cargo hold full of narcotics and slaves) ORA FIST \ OR the value in A with our legal status in FIST to \ get a new value that is at least as high as both \ values, to reflect the fact that launching with a \ hold full of contraband can only make matters worse STA FIST \ Update our legal status with the new value .NLUNCH LDX #0 \ Set QQ12 to 0 to indicate we are not docked STX QQ12 JMP LOOK1 \ Jump to LOOK1 to switch to the front view (X = 0), \ returning from the subroutine using a tail call \ ****************************************************************************** \ \ Name: TT114 \ Type: Subroutine \ Category: Charts \ Summary: Display either the Long-range or Short-range Chart \ \ ------------------------------------------------------------------------------ \ \ Display either the Long-range or Short-range Chart, depending on the current \ view setting. Called from TT18 once we know the current view is one of the \ charts. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The current view, loaded from QQ11 \ \ ****************************************************************************** .TT114 BMI TT115 \ If bit 7 of the current view is set (i.e. the view is \ the Short-range Chart, 128), skip to TT115 below to \ jump to TT23 to display the chart JMP TT22 \ Otherwise the current view is the Long-range Chart, so \ jump to TT22 to display it .TT115 JMP TT23 \ Jump to TT23 to display the Short-range Chart \ ****************************************************************************** \ \ Name: LCASH \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Subtract an amount of cash from the cash pot \ \ ------------------------------------------------------------------------------ \ \ Subtract (Y X) cash from the cash pot in CASH, but only if there is enough \ cash in the pot. As CASH is a four-byte number, this calculates: \ \ CASH(0 1 2 3) = CASH(0 1 2 3) - (0 0 Y X) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag If set, there was enough cash to do the subtraction \ \ If clear, there was not enough cash to do the \ subtraction \ \ ****************************************************************************** .LCASH STX T1 \ Subtract the least significant bytes: LDA CASH+3 \ SEC \ CASH+3 = CASH+3 - X SBC T1 STA CASH+3 STY T1 \ Then the second most significant bytes: LDA CASH+2 \ SBC T1 \ CASH+2 = CASH+2 - Y STA CASH+2 LDA CASH+1 \ Then the third most significant bytes (which are 0): SBC #0 \ STA CASH+1 \ CASH+1 = CASH+1 - 0 LDA CASH \ And finally the most significant bytes (which are 0): SBC #0 \ STA CASH \ CASH = CASH - 0 BCS TT113 \ If the C flag is set then the subtraction didn't \ underflow, so the value in CASH is correct and we can \ jump to TT113 to return from the subroutine with the \ C flag set to indicate success (as TT113 contains an \ RTS) \ Otherwise we didn't have enough cash in CASH to \ subtract (Y X) from it, so fall through into \ MCASH to reverse the sum and restore the original \ value in CASH, and returning with the C flag clear \ ****************************************************************************** \ \ Name: MCASH \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Add an amount of cash to the cash pot \ \ ------------------------------------------------------------------------------ \ \ Add (Y X) cash to the cash pot in CASH. As CASH is a four-byte number, this \ calculates: \ \ CASH(0 1 2 3) = CASH(0 1 2 3) + (Y X) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT113 Contains an RTS \ \ ****************************************************************************** .MCASH TXA \ Add the least significant bytes: CLC \ ADC CASH+3 \ CASH+3 = CASH+3 + X STA CASH+3 TYA \ Then the second most significant bytes: ADC CASH+2 \ STA CASH+2 \ CASH+2 = CASH+2 + Y LDA CASH+1 \ Then the third most significant bytes (which are 0): ADC #0 \ STA CASH+1 \ CASH+1 = CASH+1 + 0 LDA CASH \ And finally the most significant bytes (which are 0): ADC #0 \ STA CASH \ CASH = CASH + 0 CLC \ Clear the C flag, so if the above was done following \ a failed LCASH call, the C flag correctly indicates \ failure .TT113 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: GCASH \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (Y X) = P * Q * 4 \ \ ------------------------------------------------------------------------------ \ \ Calculate the following multiplication of unsigned 8-bit numbers: \ \ (Y X) = P * Q * 4 \ \ ****************************************************************************** .GCASH JSR MULTU \ Call MULTU to calculate (A P) = P * Q \ ****************************************************************************** \ \ Name: GC2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (Y X) = (A P) * 4 \ \ ------------------------------------------------------------------------------ \ \ Calculate the following multiplication of unsigned 16-bit numbers: \ \ (Y X) = (A P) * 4 \ \ ****************************************************************************** .GC2 ASL P \ Set (A P) = (A P) * 4 ROL A ASL P ROL A TAY \ Set (Y X) = (A P) LDX P RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: EQSHP \ Type: Subroutine \ Category: Equipment \ Summary: Show the Equip Ship screen (red key f3) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ err Beep, pause and go to the docking bay (i.e. show the \ Status Mode screen) \ \ pres Given an item number A with the item name in recursive \ token Y, show an error to say that the item is already \ present, refund the cost of the item, and then beep and \ exit to the docking bay (i.e. show the Status Mode \ screen) \ \ ****************************************************************************** .bay JMP BAY \ Go to the docking bay (i.e. show the Status Mode \ screen) .EQSHP JSR DIALS \ Call DIALS to update the dashboard LDA #32 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 32 (Equip \ Ship screen) LDA #12 \ Move the text cursor to column 12 STA XC LDA #207 \ Print recursive token 47 ("EQUIP") followed by a space JSR spc LDA #185 \ Print recursive token 25 ("SHIP") and draw a JSR NLIN3 \ horizontal line at pixel row 19 to box in the title LDA #%10000000 \ Set bit 7 of QQ17 to switch to Sentence Case, with the STA QQ17 \ next letter in capitals INC YC \ Move the text cursor down one line LDA tek \ Fetch the tech level of the current system from tek CLC \ and add 3 (the tech level is stored as 0-14, so A is ADC #3 \ now set to between 3 and 17) CMP #12 \ If A >= 12 then set A = 12, so A is now set to between BCC P%+4 \ 3 and 12 LDA #12 STA Q \ Set QQ25 = A (so QQ25 is in the range 3-12 and STA QQ25 \ represents the number of the most advanced item INC Q \ available in this system, which we can pass to gnum \ below when asking which item we want to buy) \ \ Set Q = A + 1 (so Q is in the range 4-13 and contains \ QQ25 + 1, i.e. the highest item number on sale + 1) LDA #70 \ Set A = 70 - QQ14, where QQ14 contains the current SEC \ fuel in light years * 10, so this leaves the amount SBC QQ14 \ of fuel we need to fill 'er up (in light years * 10) ASL A \ The price of fuel is always 2 Cr per light year, so we STA PRXS \ double A and store it in PRXS, as the first price in \ the price list (which is reserved for fuel), and \ because the table contains prices as price * 10, it's \ in the right format (so tank containing 7.0 light \ years of fuel would be 14.0 Cr, or a PRXS value of \ 140) LDX #1 \ We are now going to work our way through the equipment \ price list at PRXS, printing out the equipment that is \ available at this station, so set a counter in X, \ starting at 1, to hold the number of the current item \ plus 1 (so the item number in X loops through 1-13) .EQL1 STX XX13 \ Store the current item number + 1 in XX13 JSR TT67 \ Print a newline LDX XX13 \ Print the current item number + 1 to 3 digits, left- CLC \ padding with spaces, and with no decimal point, so the JSR pr2 \ items are numbered from 1 JSR TT162 \ Print a space LDA XX13 \ Print recursive token 104 + XX13, which will be in the CLC \ range 105 ("FUEL") to 116 ("GALACTIC HYPERSPACE ") ADC #104 \ so this prints the current item's name JSR TT27 LDA XX13 \ Call prx-3 to set (Y X) to the price of the item with JSR prx-3 \ number XX13 - 1 (as XX13 contains the item number + 1) SEC \ Set the C flag so we will print a decimal point when \ we print the price LDA #25 \ Move the text cursor to column 25 STA XC LDA #6 \ Print the number in (Y X) to 6 digits, left-padding JSR TT11 \ with spaces and including a decimal point, which will \ be the correct price for this item as (Y X) contains \ the price * 10, so the trailing zero will go after the \ decimal point (i.e. 5250 will be printed as 525.0) LDX XX13 \ Increment the current item number in XX13 INX CPX Q \ If X < Q, loop back up to print the next item on the BCC EQL1 \ list of equipment available at this station JSR CLYNS \ Clear the bottom three text rows of the upper screen, \ and move the text cursor to the first cleared row LDA #127 \ Print recursive token 127 ("ITEM") followed by a JSR prq \ question mark JSR gnum \ Call gnum to get a number from the keyboard, which \ will be the number of the item we want to purchase, \ returning the number entered in A and R, and setting \ the C flag if the number is bigger than the highest \ item number in QQ25 BEQ bay \ If no number was entered, jump up to bay to go to the \ docking bay (i.e. show the Status Mode screen) BCS bay \ If the number entered was too big, jump up to bay to \ go to the docking bay (i.e. show the Status Mode \ screen) SBC #0 \ Set A to the number entered - 1 (because the C flag is \ clear), which will be the actual item number we want \ to buy LDX #2 \ Move the text cursor to column 2 STX XC INC YC \ Move the text cursor down one line PHA \ While preserving the value in A, call eq to subtract JSR eq \ the price of the item we want to buy (which is in A) PLA \ from our cash pot, but only if we have enough cash in \ the pot. If we don't have enough cash, exit to the \ docking bay (i.e. show the Status Mode screen) BNE et0 \ If A is not 0 (i.e. the item we've just bought is not \ fuel), skip to et0 STA MCNT \ We just bought fuel, so we zero the main loop counter LDX #70 \ Set the current fuel level * 10 in QQ14 to 70, or 7.0 STX QQ14 \ light years (a full tank) .et0 CMP #1 \ If A is not 1 (i.e. the item we've just bought is not BNE et1 \ a missile), skip to et1 LDX NOMSL \ Fetch the current number of missiles from NOMSL into X INX \ Increment X to the new number of missiles LDY #117 \ Set Y to recursive token 117 ("ALL") CPX #5 \ If buying this missile would give us 5 missiles, this BCS pres \ is more than the maximum of 4 missiles that we can \ fit, so jump to pres to show the error "All Present", \ beep and exit to the docking bay (i.e. show the Status \ Mode screen) STX NOMSL \ Otherwise update the number of missiles in NOMSL JSR msblob \ Reset the dashboard's missile indicators so none of \ them are targeted .et1 LDY #107 \ Set Y to recursive token 107 ("LARGE CARGO{sentence \ case} BAY") CMP #2 \ If A is not 2 (i.e. the item we've just bought is not BNE et2 \ a large cargo bay), skip to et2 LDX #37 \ If our current cargo capacity in CRGO is 37, then we CPX CRGO \ already have a large cargo bay fitted, so jump to pres BEQ pres \ to show the error "Large Cargo Bay Present", beep and \ exit to the docking bay (i.e. show the Status Mode \ screen) STX CRGO \ Otherwise we just scored ourselves a large cargo bay, \ so update our current cargo capacity in CRGO to 37 .et2 CMP #3 \ If A is not 3 (i.e. the item we've just bought is not BNE et3 \ an E.C.M. system), skip to et3 INY \ Increment Y to recursive token 108 ("E.C.M.SYSTEM") LDX ECM \ If we already have an E.C.M. fitted (i.e. ECM is BNE pres \ non-zero), jump to pres to show the error "E.C.M. \ System Present", beep and exit to the docking bay \ (i.e. show the Status Mode screen) DEC ECM \ Otherwise we just took delivery of a brand new E.C.M. \ system, so set ECM to &FF (as ECM was 0 before the DEC \ instruction) .et3 CMP #4 \ If A is not 4 (i.e. the item we've just bought is not BNE et4 \ an extra pulse laser), skip to et4 JSR qv \ Print a menu listing the four views, with a "View ?" \ prompt, and ask for a view number, which is returned \ in X (which now contains 0-3) LDA #4 \ This instruction doesn't appear to do anything, as we \ either don't need it (if we already have this laser) \ or we set A to 4 below (if we buy it) LDY LASER,X \ If there is no laser mounted in the chosen view (i.e. BEQ ed4 \ LASER+X, which contains the laser power for view X, is \ zero), jump to ed4 to buy a pulse laser .ed7 LDY #187 \ Otherwise we already have a laser mounted in this BNE pres \ view, so jump to pres with Y set to token 27 \ (" LASER") to show the error "Laser Present", beep \ and exit to the docking bay (i.e. show the Status \ Mode screen) .ed4 LDA #POW \ We just bought a pulse laser for view X, so we need STA LASER,X \ to fit it by storing the laser power for a pulse laser \ (given in POW) in LASER+X LDA #4 \ Set A to 4 as we just overwrote the original value, \ and we still need it set correctly so we can continue \ through the conditional statements for all the other \ equipment .et4 CMP #5 \ If A is not 5 (i.e. the item we've just bought is not BNE et5 \ an extra beam laser), skip to et5 JSR qv \ Print a menu listing the four views, with a "View ?" \ prompt, and ask for a view number, which is returned \ in X (which now contains 0-3) STX T1 \ Store the view in T1 so we can retrieve it below LDA #5 \ Set A to 5 as the call to qv will have overwritten \ the original value, and we still need it set \ correctly so we can continue through the conditional \ statements for all the other equipment LDY LASER,X \ If there is no laser mounted in the chosen view (i.e. BEQ ed5 \ LASER+X, which contains the laser power for view X, \ is zero), jump to ed5 to buy a beam laser \BPL P%+4 \ This instruction is commented out in the original \ source, though it would have no effect (it would \ simply skip the BMI if A is positive, which is what \ BMI does anyway) BMI ed7 \ If there is a beam laser already mounted in the chosen \ view (i.e. LASER+X has bit 7 set, which indicates a \ beam laser rather than a pulse laser), skip back to \ ed7 to print a "Laser Present" error, beep and exit \ to the docking bay (i.e. show the Status Mode screen) LDA #4 \ If we get here then we already have a pulse laser in JSR prx \ the selected view, so we call prx to set (Y X) to the \ price of equipment item number 4 (extra pulse laser) \ so we can give a refund of the pulse laser JSR MCASH \ Add (Y X) cash to the cash pot in CASH, so we refund \ the price of the pulse laser we are exchanging for a \ new beam laser .ed5 LDA #POW+128 \ We just bought a beam laser for view X, so we need LDX T1 \ to fit it by storing the laser power for a beam laser STA LASER,X \ (given in POW+128) in LASER+X, using the view number \ we stored in T1 earlier, as the call to prx will have \ overwritten the original value in X .et5 LDY #111 \ Set Y to recursive token 111 ("FUEL SCOOPS") CMP #6 \ If A is not 6 (i.e. the item we've just bought is not BNE et6 \ a fuel scoop), skip to et6 LDX BST \ If we already have fuel scoops fitted (i.e. BST is BEQ ed9 \ zero), jump to ed9, otherwise fall through into pres \ to show the error "Fuel Scoops Present", beep and \ exit to the docking bay (i.e. show the Status Mode \ screen) .pres \ If we get here we need to show an error to say that \ the item whose name is in recursive token Y is already \ present, and then process a refund for the cost of \ item number A STY K \ Store the item's name in K JSR prx \ Call prx to set (Y X) to the price of equipment item \ number A JSR MCASH \ Add (Y X) cash to the cash pot in CASH, as the station \ already took the money for this item in the JSR eq \ instruction above, but we can't fit the item, so need \ our money back LDA K \ Print the recursive token in K (the item's name) JSR spc \ followed by a space LDA #31 \ Print recursive token 145 ("PRESENT") JSR TT27 .err 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) .ed9 DEC BST \ We just bought a shiny new fuel scoop, so set BST to \ &FF (as BST was 0 before the jump to ed9 above) .et6 INY \ Increment Y to recursive token 112 ("E.C.M.SYSTEM") CMP #7 \ If A is not 7 (i.e. the item we've just bought is not BNE et7 \ an escape pod), skip to et7 LDX ESCP \ If we already have an escape pod fitted (i.e. ESCP is BNE pres \ non-zero), jump to pres to show the error "Escape Pod \ Present", beep and exit to the docking bay (i.e. show \ the Status Mode screen) DEC ESCP \ Otherwise we just bought an escape pod, so set ESCP \ to &FF (as ESCP was 0 before the DEC instruction) .et7 INY \ Increment Y to recursive token 113 ("ENERGY BOMB") CMP #8 \ If A is not 8 (i.e. the item we've just bought is not BNE et8 \ an energy bomb), skip to et8 LDX BOMB \ If we already have an energy bomb fitted (i.e. BOMB BNE pres \ is non-zero), jump to pres to show the error "Energy \ Bomb Present", beep and exit to the docking bay (i.e. \ show the Status Mode screen) LDX #&7F \ Otherwise we just bought an energy bomb, so set BOMB STX BOMB \ to &7F .et8 INY \ Increment Y to recursive token 114 ("ENERGY UNIT") CMP #9 \ If A is not 9 (i.e. the item we've just bought is not BNE etA \ an energy unit), skip to etA LDX ENGY \ If we already have an energy unit fitted (i.e. ENGY is BNE pres \ non-zero), jump to pres to show the error "Energy Unit \ Present", beep and exit to the docking bay (i.e. show \ the Status Mode screen) INC ENGY \ Otherwise we just picked up an energy unit, so set \ ENGY to 1 (as ENGY was 0 before the INC instruction) .etA INY \ Increment Y to recursive token 115 ("DOCKING \ COMPUTERS") CMP #10 \ If A is not 10 (i.e. the item we've just bought is not BNE etB \ a docking computer), skip to etB LDX DKCMP \ If we already have a docking computer fitted (i.e. BNE pres \ DKCMP is non-zero), jump to pres to show the error \ "Docking Computer Present", beep and exit to the \ docking bay (i.e. show the Status Mode screen) DEC DKCMP \ Otherwise we just got hold of a docking computer, so \ set DKCMP to &FF (as DKCMP was 0 before the DEC \ instruction) .etB INY \ Increment Y to recursive token 116 ("GALACTIC \ HYPERSPACE ") CMP #11 \ If A is not 11 (i.e. the item we've just bought is not BNE et9 \ a galactic hyperdrive), skip to et9 LDX GHYP \ If we already have a galactic hyperdrive fitted (i.e. BNE pres \ GHYP is non-zero), jump to pres to show the error \ "Galactic Hyperspace Present", beep and exit to the \ docking bay (i.e. show the Status Mode screen) DEC GHYP \ Otherwise we just splashed out on a galactic \ hyperdrive, so set GHYP to &FF (as GHYP was 0 before \ the DEC instruction) .et9 JSR dn \ We are done buying equipment, so print the amount of \ cash left in the cash pot, then make a short, high \ beep to confirm the purchase, and delay for 1 second JMP EQSHP \ Jump back up to EQSHP to show the Equip Ship screen \ again and see if we can't track down another bargain \ ****************************************************************************** \ \ Name: dn \ Type: Subroutine \ Category: Market \ Summary: Print the amount of money we have left in the cash pot, then make \ a short, high beep and delay for 1 second \ \ ****************************************************************************** .dn JSR TT162 \ Print a space LDA #119 \ Print recursive token 119 ("CASH:{cash} CR{crlf}") JSR spc \ followed by a space \ Fall through into dn2 to make a beep and delay for \ 1 second before returning from the subroutine \ ****************************************************************************** \ \ Name: dn2 \ Type: Subroutine \ Category: Text \ Summary: Make a short, high beep and delay for 1 second \ \ ****************************************************************************** .dn2 JSR BEEP \ Call the BEEP subroutine to make a short, high beep LDY #50 \ Wait for 50/50 of a second (1 second) and return JMP DELAY \ from the subroutine using a tail call \ ****************************************************************************** \ \ Name: eq \ Type: Subroutine \ Category: Equipment \ Summary: Subtract the price of equipment from the cash pot \ \ ------------------------------------------------------------------------------ \ \ If we have enough cash, subtract the price of a specified piece of equipment \ from our cash pot and return from the subroutine. If we don't have enough \ cash, exit to the docking bay (i.e. show the Status Mode screen). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The item number of the piece of equipment (0-11) as \ shown in the table at PRXS \ \ ****************************************************************************** .eq JSR prx \ Call prx to set (Y X) to the price of equipment item \ number A JSR LCASH \ Subtract (Y X) cash from the cash pot, but only if \ we have enough cash BCS c \ If the C flag is set then we did have enough cash for \ the transaction, so jump to c to return from the \ subroutine (as c contains an RTS) LDA #197 \ Otherwise we don't have enough cash to buy this piece JSR prq \ of equipment, so print recursive token 37 ("CASH") \ followed by a question mark JMP err \ Jump to err to beep, pause and go to the docking bay \ (i.e. show the Status Mode screen) \ ****************************************************************************** \ \ Name: prx \ Type: Subroutine \ Category: Equipment \ Summary: Return the price of a piece of equipment \ \ ------------------------------------------------------------------------------ \ \ This routine returns the price of equipment as listed in the table at PRXS. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The item number of the piece of equipment (0-11) as \ shown in the table at PRXS \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ (Y X) The item price in Cr * 10 (Y = high byte, X = low byte) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ prx-3 Return the price of the item with number A - 1 \ \ c Contains an RTS \ \ ****************************************************************************** SEC \ Decrement A (for when this routine is called via SBC #1 \ prx-3) .prx ASL A \ Set Y = A * 2, so it can act as an index into the TAY \ PRXS table, which has two bytes per entry LDX PRXS,Y \ Fetch the low byte of the price into X LDA PRXS+1,Y \ Fetch the high byte of the price into A and transfer TAY \ it to X, so the price is now in (Y X) .c RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: qv \ Type: Subroutine \ Category: Equipment \ Summary: Print a menu of the four space views, for buying lasers \ \ ------------------------------------------------------------------------------ \ \ Print a menu in the bottom-middle of the screen, at row 16, column 12, that \ lists the four available space views, like this: \ \ 0 Front \ 1 Rear \ 2 Left \ 3 Right \ \ Also print a "View ?" prompt and ask for a view number. The menu is shown \ when we choose to buy a new laser in the Equip Ship screen. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ X The chosen view number (0-3) \ \ ****************************************************************************** .qv LDY #16 \ Move the text cursor to row 16, and at the same time STY YC \ set Y to a counter going from 16 to 19 in the loop \ below .qv1 LDX #12 \ Move the text cursor to column 12 STX XC TYA \ Transfer the counter value from Y to A CLC \ Print ASCII character "0" - 16 + A, so as A goes from ADC #'0'-16 \ 16 to 19, this prints "0" through "3" followed by a JSR spc \ space LDA YC \ Print recursive text token 80 + YC, so as YC goes from CLC \ 16 to 19, this prints "FRONT", "REAR", "LEFT" and ADC #80 \ "RIGHT" JSR TT27 INC YC \ Move the text cursor down a row, and increment the \ counter in YC at the same time LDY YC \ Update Y with the incremented counter in YC CPY #20 \ If Y < 20 then loop back up to qv1 to print the next BCC qv1 \ view in the menu .qv3 JSR CLYNS \ Clear the bottom three text rows of the upper screen, \ and move the text cursor to the first cleared row .qv2 LDA #175 \ Print recursive text token 15 ("VIEW ") followed by JSR prq \ a question mark JSR TT217 \ Scan the keyboard until a key is pressed, and return \ the key's ASCII code in A (and X) SEC \ Subtract ASCII "0" from the key pressed, to leave the SBC #'0' \ numeric value of the key in A (if it was a number key) CMP #4 \ If the number entered in A >= 4, then it is not a BCS qv3 \ valid view number, so jump back to qv3 to try again TAX \ We have a valid view number, so transfer it to X RTS \ Return from the subroutine \ ****************************************************************************** \ \ Save ELTD.bin \ \ ****************************************************************************** PRINT "ELITE D" PRINT "Assembled at ", ~CODE_D% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_D%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_D% PRINT "S.ELTD ", ~CODE_D%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_D% SAVE "3-assembled-output/ELTD.bin", CODE_D%, P%, LOAD% \ ****************************************************************************** \ \ ELITE E FILE \ \ Produces the binary file ELTE.bin that gets loaded by elite-bcfs.asm. \ \ ****************************************************************************** CODE_E% = P% LOAD_E% = LOAD% + P% - CODE% \ ****************************************************************************** \ \ Name: Authors' names \ Type: Variable \ Category: Copy protection \ Summary: The authors' names and a copyright notice, buried in the code \ \ ------------------------------------------------------------------------------ \ \ This copyright notice is not used anywhere and it is obfuscated by EOR'ing \ each character with 164, but presumably the authors wanted their names buried \ in the code somewhere. Though they do also have recursive token 94, which \ reads "BY D.BRABEN & I.BELL" and can be displayed on the title screen using \ the "X" configuration option, so this isn't the only author name easter egg \ in the game. It contains the following text: \ \ (C)Bell/Braben1984 \ \ ****************************************************************************** EQUB '(' EOR 164 EQUB 'C' EOR 164 EQUB ')' EOR 164 EQUB 'B' EOR 164 EQUB 'e' EOR 164 EQUB 'l' EOR 164 EQUB 'l' EOR 164 EQUB '/' EOR 164 EQUB 'B' EOR 164 EQUB 'r' EOR 164 EQUB 'a' EOR 164 EQUB 'b' EOR 164 EQUB 'e' EOR 164 EQUB 'n' EOR 164 EQUB '1' EOR 164 EQUB '9' EOR 164 EQUB '8' EOR 164 EQUB '4' EOR 164 \ ****************************************************************************** \ \ Name: cpl \ Type: Subroutine \ Category: Universe \ Summary: Print the selected system name \ Deep dive: Generating system names \ Galaxy and system seeds \ \ ------------------------------------------------------------------------------ \ \ Print control code 3 (the selected system name, i.e. the one in the crosshairs \ in the Short-range Chart). \ \ ****************************************************************************** .cpl LDX #5 \ First we need to back up the seeds in QQ15, so set up \ a counter in X to cover three 16-bit seeds (i.e. \ 6 bytes) .TT53 LDA QQ15,X \ Copy byte X from QQ15 to QQ19 STA QQ19,X DEX \ Decrement the loop counter BPL TT53 \ Loop back for the next byte to back up LDY #3 \ Step 1: Now that the seeds are backed up, we can \ start the name-generation process. We will either \ need to loop three or four times, so for now set \ up a counter in Y to loop four times BIT QQ15 \ Check bit 6 of s0_lo, which is stored in QQ15 BVS P%+3 \ If bit 6 is set then skip over the next instruction DEY \ Bit 6 is clear, so we only want to loop three times, \ so decrement the loop counter in Y STY T \ Store the loop counter in T .TT55 LDA QQ15+5 \ Step 2: Load s2_hi, which is stored in QQ15+5, and AND #%00011111 \ extract bits 0-4 by AND'ing with %11111 BEQ P%+7 \ If all those bits are zero, then skip the following \ two instructions to go to step 3 ORA #%10000000 \ We now have a number in the range 1-31, which we can \ easily convert into a two-letter token, but first we \ need to add 128 (or set bit 7) to get a range of \ 129-159 JSR TT27 \ Print the two-letter token in A JSR TT54 \ Step 3: twist the seeds in QQ15 DEC T \ Decrement the loop counter BPL TT55 \ Loop back for the next two letters LDX #5 \ We have printed the system name, so we can now \ restore the seeds we backed up earlier. Set up a \ counter in X to cover three 16-bit seeds (i.e. 6 \ bytes) .TT56 LDA QQ19,X \ Copy byte X from QQ19 to QQ15 STA QQ15,X DEX \ Decrement the loop counter BPL TT56 \ Loop back for the next byte to restore RTS \ Once all the seeds are restored, return from the \ subroutine \ ****************************************************************************** \ \ Name: cmn \ Type: Subroutine \ Category: Status \ Summary: Print the commander's name \ \ ------------------------------------------------------------------------------ \ \ Print control code 4 (the commander's name). \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ cmn-1 Contains an RTS \ \ ****************************************************************************** .cmn LDY #0 \ Set up a counter in Y, starting from 0 .QUL4 LDA NA%,Y \ The commander's name is stored at NA%, so load the \ Y-th character from NA% CMP #13 \ If we have reached the end of the name, return from BEQ ypl-1 \ the subroutine (ypl-1 points to the RTS below) JSR TT26 \ Print the character we just loaded INY \ Increment the loop counter BNE QUL4 \ Loop back for the next character RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: ypl \ Type: Subroutine \ Category: Universe \ Summary: Print the current system name \ \ ------------------------------------------------------------------------------ \ \ Print control code 2 (the current system name). \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ ypl-1 Contains an RTS \ \ ****************************************************************************** .ypl LDA MJ \ Check the mis-jump flag at MJ, and if it is non-zero BNE cmn-1 \ then we are in witchspace, and witchspace doesn't have \ a system name, so return from the subroutine (cmn-1 \ contains an RTS) JSR TT62 \ Call TT62 below to swap the three 16-bit seeds in \ QQ2 and QQ15 (before the swap, QQ2 contains the seeds \ for the current system, while QQ15 contains the seeds \ for the selected system) JSR cpl \ Call cpl to print out the system name for the seeds \ in QQ15 (which now contains the seeds for the current \ system) \ Now we fall through into the TT62 subroutine, which \ will swap QQ2 and QQ15 once again, so everything goes \ back into the right place, and the RTS at the end of \ TT62 will return from the subroutine .TT62 LDX #5 \ Set up a counter in X for the three 16-bit seeds we \ want to swap (i.e. 6 bytes) .TT78 LDA QQ15,X \ Swap byte X between QQ2 and QQ15 LDY QQ2,X STA QQ2,X STY QQ15,X DEX \ Decrement the loop counter BPL TT78 \ Loop back for the next byte to swap RTS \ Once all bytes are swapped, return from the \ subroutine \ ****************************************************************************** \ \ Name: tal \ Type: Subroutine \ Category: Universe \ Summary: Print the current galaxy number \ \ ------------------------------------------------------------------------------ \ \ Print control code 1 (the current galaxy number, right-aligned to width 3). \ \ ****************************************************************************** .tal CLC \ We don't want to print the galaxy number with a \ decimal point, so clear the C flag for pr2 to take as \ an argument LDX GCNT \ Load the current galaxy number from GCNT into X INX \ Add 1 to the galaxy number, as the galaxy numbers \ are 0-7 internally, but we want to display them as \ galaxy 1 through 8 JMP pr2 \ Jump to pr2, which prints the number in X to a width \ of 3 figures, left-padding with spaces to a width of \ 3, and return from the subroutine using a tail call \ ****************************************************************************** \ \ Name: fwl \ Type: Subroutine \ Category: Status \ Summary: Print fuel and cash levels \ \ ------------------------------------------------------------------------------ \ \ Print control code 5 ("FUEL: ", fuel level, " LIGHT YEARS", newline, "CASH:", \ control code 0). \ \ ****************************************************************************** .fwl LDA #105 \ Print recursive token 105 ("FUEL") followed by a JSR TT68 \ colon LDX QQ14 \ Load the current fuel level from QQ14 SEC \ We want to print the fuel level with a decimal point, \ so set the C flag for pr2 to take as an argument JSR pr2 \ Call pr2, which prints the number in X to a width of \ 3 figures (i.e. in the format x.x, which will always \ be exactly 3 characters as the maximum fuel is 7.0) LDA #195 \ Print recursive token 35 ("LIGHT YEARS") followed by JSR plf \ a newline .PCASH LDA #119 \ Print recursive token 119 ("CASH:" then control code BNE TT27 \ 0, which prints cash levels, then " CR" and newline) \ ****************************************************************************** \ \ Name: csh \ Type: Subroutine \ Category: Status \ Summary: Print the current amount of cash \ \ ------------------------------------------------------------------------------ \ \ Print control code 0 (the current amount of cash, right-aligned to width 9, \ followed by " CR" and a newline). \ \ ****************************************************************************** .csh LDX #3 \ We are going to use the BPRNT routine to print out \ the current amount of cash, which is stored as a \ 32-bit number at location CASH. BPRNT prints out \ the 32-bit number stored in K, so before we call \ BPRNT, we need to copy the four bytes from CASH into \ K, so first we set up a counter in X for the 4 bytes .pc1 LDA CASH,X \ Copy byte X from CASH to K STA K,X DEX \ Decrement the loop counter BPL pc1 \ Loop back for the next byte to copy LDA #9 \ We want to print the cash amount 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 cash amount 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 LDA #226 \ Print recursive token 66 (" CR") followed by a \ newline by falling through into plf \ ****************************************************************************** \ \ Name: plf \ Type: Subroutine \ Category: Text \ Summary: Print a text token followed by a newline \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ ****************************************************************************** .plf JSR TT27 \ Print the text token in A JMP TT67 \ Jump to TT67 to print a newline and return from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: TT68 \ Type: Subroutine \ Category: Text \ Summary: Print a text token followed by a colon \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ ****************************************************************************** .TT68 JSR TT27 \ Print the text token in A and fall through into TT73 \ to print a colon \ ****************************************************************************** \ \ Name: TT73 \ Type: Subroutine \ Category: Text \ Summary: Print a colon \ \ ****************************************************************************** .TT73 LDA #':' \ Set A to ASCII ":" and fall through into TT27 to \ actually print the colon \ ****************************************************************************** \ \ Name: TT27 \ Type: Subroutine \ Category: Text \ Summary: Print a text token \ Deep dive: Printing text tokens \ \ ------------------------------------------------------------------------------ \ \ Print a text token (i.e. a character, control code, two-letter token or \ recursive token). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ ****************************************************************************** .TT27 TAX \ Copy the token number from A to X. We can then keep \ decrementing X and testing it against zero, while \ keeping the original token number intact in A; this \ effectively implements a switch statement on the \ value of the token BEQ csh \ If token = 0, this is control code 0 (current amount \ of cash and newline), so jump to csh to print the \ amount of cash and return from the subroutine using \ a tail call BMI TT43 \ If token > 127, this is either a two-letter token \ (128-159) or a recursive token (160-255), so jump \ to TT43 to process tokens DEX \ If token = 1, this is control code 1 (current galaxy BEQ tal \ number), so jump to tal to print the galaxy number and \ return from the subroutine using a tail call DEX \ If token = 2, this is control code 2 (current system BEQ ypl \ name), so jump to ypl to print the current system name \ and return from the subroutine using a tail call DEX \ If token > 3, skip the following instruction BNE P%+5 JMP cpl \ This token is control code 3 (selected system name) \ so jump to cpl to print the selected system name \ and return from the subroutine using a tail call DEX \ If token = 4, this is control code 4 (commander BEQ cmn \ name), so jump to cmn to print the commander name \ and return from the subroutine using a tail call DEX \ If token = 5, this is control code 5 (fuel, newline, BEQ fwl \ cash, newline), so jump to fwl to print the fuel level \ and return from the subroutine using a tail call DEX \ If token > 6, skip the following three instructions BNE P%+7 LDA #%10000000 \ This token is control code 6 (switch to Sentence STA QQ17 \ Case), so set bit 7 of QQ17 to switch to Sentence Case RTS \ and return from the subroutine as we are done DEX \ If token > 8, skip the following two instructions DEX BNE P%+5 STX QQ17 \ This token is control code 8 (switch to ALL CAPS), so RTS \ set QQ17 to 0 to switch to ALL CAPS and return from \ the subroutine as we are done DEX \ If token = 9, this is control code 9 (tab to column BEQ crlf \ 21 and print a colon), so jump to crlf CMP #96 \ By this point, token is either 7, or in 10-127. BCS ex \ Check token number in A and if token >= 96, then the \ token is in 96-127, which is a recursive token, so \ jump to ex, which prints recursive tokens in this \ range (i.e. where the recursive token number is \ correct and doesn't need correcting) CMP #14 \ If token < 14, skip the following two instructions BCC P%+6 CMP #32 \ If token < 32, then this means token is in 14-31, so BCC qw \ this is a recursive token that needs 114 adding to it \ to get the recursive token number, so jump to qw \ which will do this \ By this point, token is either 7 (beep) or in 10-13 \ (line feeds and carriage returns), or in 32-95 \ (ASCII letters, numbers and punctuation) LDX QQ17 \ Fetch QQ17, which controls letter case, into X BEQ TT74 \ If QQ17 = 0, then ALL CAPS is set, so jump to TT74 \ to print this character as is (i.e. as a capital) BMI TT41 \ If QQ17 has bit 7 set, then we are using Sentence \ Case, so jump to TT41, which will print the \ character in upper or lower case, depending on \ whether this is the first letter in a word BIT QQ17 \ If we get here, QQ17 is not 0 and bit 7 is clear, so BVS TT46 \ either it is bit 6 that is set, or some other flag in \ QQ17 is set (bits 0-5). So check whether bit 6 is set. \ If it is, then ALL CAPS has been set (as bit 7 is \ clear) but bit 6 is still indicating that the next \ character should be printed in lower case, so we need \ to fix this. We do this with a jump to TT46, which \ will print this character in upper case and clear bit \ 6, so the flags are consistent with ALL CAPS going \ forward \ If we get here, some other flag is set in QQ17 (one \ of bits 0-5 is set), which shouldn't happen in this \ version of Elite. If this were the case, then we \ would fall through into TT42 to print in lower case, \ which is how printing all words in lower case could \ be supported (by setting QQ17 to 1, say) \ ****************************************************************************** \ \ Name: TT42 \ Type: Subroutine \ Category: Text \ Summary: Print a letter in lower case \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The character to be printed. Can be one of the \ following: \ \ * 7 (beep) \ \ * 10-13 (line feeds and carriage returns) \ \ * 32-95 (ASCII capital letters, numbers and \ punctuation) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT44 Jumps to TT26 to print the character in A (used to \ enable us to use a branch instruction to jump to TT26) \ \ ****************************************************************************** .TT42 CMP #'A' \ If A < ASCII "A", then this is punctuation, so jump BCC TT44 \ to TT26 (via TT44) to print the character as is, as \ we don't care about the character's case CMP #'Z'+1 \ If A >= (ASCII "Z" + 1), then this is also BCS TT44 \ punctuation, so jump to TT26 (via TT44) to print the \ character as is, as we don't care about the \ character's case ADC #32 \ Add 32 to the character, to convert it from upper to \ lower case .TT44 JMP TT26 \ Print the character in A \ ****************************************************************************** \ \ Name: TT41 \ Type: Subroutine \ Category: Text \ Summary: Print a letter according to Sentence Case \ \ ------------------------------------------------------------------------------ \ \ The rules for printing in Sentence Case are as follows: \ \ * If QQ17 bit 6 is set, print lower case (via TT45) \ \ * If QQ17 bit 6 is clear, then: \ \ * If character is punctuation, just print it \ \ * If character is a letter, set QQ17 bit 6 and print letter as a capital \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The character to be printed. Can be one of the \ following: \ \ * 7 (beep) \ \ * 10-13 (line feeds and carriage returns) \ \ * 32-95 (ASCII capital letters, numbers and \ punctuation) \ \ X Contains the current value of QQ17 \ \ QQ17 Bit 7 is set \ \ ****************************************************************************** .TT41 \ If we get here, then QQ17 has bit 7 set, so we are in \ Sentence Case BIT QQ17 \ If QQ17 also has bit 6 set, jump to TT45 to print BVS TT45 \ this character in lower case \ If we get here, then QQ17 has bit 6 clear and bit 7 \ set, so we are in Sentence Case and we need to print \ the next letter in upper case CMP #'A' \ If A < ASCII "A", then this is punctuation, so jump BCC TT74 \ to TT26 (via TT44) to print the character as is, as \ we don't care about the character's case PHA \ Otherwise this is a letter, so store the token number TXA \ Set bit 6 in QQ17 (X contains the current QQ17) ORA #%1000000 \ so the next letter after this one is printed in lower STA QQ17 \ case PLA \ Restore the token number into A BNE TT44 \ Jump to TT26 (via TT44) to print the character in A \ (this BNE is effectively a JMP as A will never be \ zero) \ ****************************************************************************** \ \ Name: qw \ Type: Subroutine \ Category: Text \ Summary: Print a recursive token in the range 128-145 \ \ ------------------------------------------------------------------------------ \ \ Print a recursive token where the token number is in 128-145 (so the value \ passed to TT27 is in the range 14-31). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A A value from 128-145, which refers to a recursive token \ in the range 14-31 \ \ ****************************************************************************** .qw ADC #114 \ This is a recursive token in the range 0-95, so add BNE ex \ 114 to the argument to get the token number 128-145 \ and jump to ex to print it \ ****************************************************************************** \ \ Name: crlf \ Type: Subroutine \ Category: Text \ Summary: Tab to column 21 and print a colon \ \ ------------------------------------------------------------------------------ \ \ Print control code 9 (tab to column 21 and print a colon). The subroutine \ name is pretty misleading, as it doesn't have anything to do with carriage \ returns or line feeds. \ \ ****************************************************************************** .crlf LDA #21 \ Set the X-column in XC to 21 STA XC BNE TT73 \ Jump to TT73, which prints a colon (this BNE is \ effectively a JMP as A will never be zero) \ ****************************************************************************** \ \ Name: TT45 \ Type: Subroutine \ Category: Text \ Summary: Print a letter in lower case \ \ ------------------------------------------------------------------------------ \ \ This routine prints a letter in lower case. Specifically: \ \ * If QQ17 = 255, abort printing this character as printing is disabled \ \ * If this is a letter then print in lower case \ \ * Otherwise this is punctuation, so clear bit 6 in QQ17 and print \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The character to be printed. Can be one of the \ following: \ \ * 7 (beep) \ \ * 10-13 (line feeds and carriage returns) \ \ * 32-95 (ASCII capital letters, numbers and \ punctuation) \ \ X Contains the current value of QQ17 \ \ QQ17 Bits 6 and 7 are set \ \ ****************************************************************************** .TT45 \ If we get here, then QQ17 has bit 6 and 7 set, so we \ are in Sentence Case and we need to print the next \ letter in lower case CPX #255 \ If QQ17 = 255 then printing is disabled, so return BEQ TT48 \ from the subroutine (as TT48 contains an RTS) CMP #'A' \ If A >= ASCII "A", then jump to TT42, which will BCS TT42 \ print the letter in lowercase \ Otherwise this is not a letter, it's punctuation, so \ this is effectively a word break. We therefore fall \ through to TT46 to print the character and set QQ17 \ to ensure the next word starts with a capital letter \ ****************************************************************************** \ \ Name: TT46 \ Type: Subroutine \ Category: Text \ Summary: Print a character and switch to capitals \ \ ------------------------------------------------------------------------------ \ \ Print a character and clear bit 6 in QQ17, so that the next letter that gets \ printed after this will start with a capital letter. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The character to be printed. Can be one of the \ following: \ \ * 7 (beep) \ \ * 10-13 (line feeds and carriage returns) \ \ * 32-95 (ASCII capital letters, numbers and \ punctuation) \ \ X Contains the current value of QQ17 \ \ QQ17 Bits 6 and 7 are set \ \ ****************************************************************************** .TT46 PHA \ Store the token number TXA \ Clear bit 6 in QQ17 (X contains the current QQ17) so AND #%10111111 \ the next letter after this one is printed in upper STA QQ17 \ case PLA \ Restore the token number into A \ Now fall through into TT74 to print the character \ ****************************************************************************** \ \ Name: TT74 \ Type: Subroutine \ Category: Text \ Summary: Print a character \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The character to be printed \ \ ****************************************************************************** .TT74 JMP TT26 \ Print the character in A \ ****************************************************************************** \ \ Name: TT43 \ Type: Subroutine \ Category: Text \ Summary: Print a two-letter token or recursive token 0-95 \ \ ------------------------------------------------------------------------------ \ \ Print a two-letter token, or a recursive token where the token number is in \ 0-95 (so the value passed to TT27 is in the range 160-255). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A One of the following: \ \ * 128-159 (two-letter token) \ \ * 160-255 (the argument to TT27 that refers to a \ recursive token in the range 0-95) \ \ ****************************************************************************** .TT43 CMP #160 \ If token >= 160, then this is a recursive token, so BCS TT47 \ jump to TT47 below to process it AND #127 \ This is a two-letter token with number 128-159. The ASL A \ set of two-letter tokens is stored in a lookup table \ at QQ16, with each token taking up two bytes, so to \ convert this into the token's position in the table, \ we subtract 128 (or just clear bit 7) and multiply \ by 2 (or shift left) TAY \ Transfer the token's position into Y so we can look \ up the token using absolute indexed mode LDA QQ16,Y \ Get the first letter of the token and print it JSR TT27 LDA QQ16+1,Y \ Get the second letter of the token CMP #'?' \ If the second letter of the token is a question mark BEQ TT48 \ then this is a one-letter token, so just return from \ the subroutine without printing (as TT48 contains an \ RTS) JMP TT27 \ Print the second letter and return from the \ subroutine .TT47 SBC #160 \ This is a recursive token in the range 160-255, so \ subtract 160 from the argument to get the token \ number 0-95 and fall through into ex to print it \ ****************************************************************************** \ \ Name: ex \ Type: Subroutine \ Category: Text \ Summary: Print a recursive token \ Deep dive: Printing text tokens \ \ ------------------------------------------------------------------------------ \ \ This routine works its way through the recursive text tokens that are stored \ in tokenised form in the table at QQ18, and when it finds token number A, \ it prints it. Tokens are null-terminated in memory and fill three pages, \ but there is no lookup table as that would consume too much memory, so the \ only way to find the correct token is to start at the beginning and look \ through the table byte by byte, counting tokens as we go until we are in the \ right place. This approach might not be terribly speed efficient, but it is \ certainly memory-efficient. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The recursive token to be printed, in the range 0-148 \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT48 Contains an RTS \ \ ****************************************************************************** .ex TAX \ Copy the token number into X LDA #LO(QQ18) \ Set V(1 0) to point to the recursive token table at STA V \ location QQ18 LDA #HI(QQ18) STA V+1 LDY #0 \ Set a counter Y to point to the character offset \ as we scan through the table TXA \ Copy the token number back into A, so both A and X \ now contain the token number we want to print BEQ TT50 \ If the token number we want is 0, then we have \ already found the token we are looking for, so jump \ to TT50, otherwise start working our way through the \ null-terminated token table until we find the X-th \ token .TT51 LDA (V),Y \ Fetch the Y-th character from the token table page \ we are currently scanning BEQ TT49 \ If the character is null, we've reached the end of \ this token, so jump to TT49 INY \ Increment character pointer and loop back around for BNE TT51 \ the next character in this token, assuming Y hasn't \ yet wrapped around to 0 INC V+1 \ If it has wrapped round to 0, we have just crossed BNE TT51 \ into a new page, so increment V+1 so that V points \ to the start of the new page .TT49 INY \ Increment the character pointer BNE TT59 \ 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 .TT59 DEX \ We have just reached a new token, so decrement the \ token number we are looking for BNE TT51 \ Assuming we haven't yet reached the token number in \ X, look back up to keep fetching characters .TT50 \ We have now reached the correct token in the token \ table, with Y pointing to the start of the token as \ an offset within the page pointed to by V, so let's \ print the recursive token. Because recursive tokens \ can contain other recursive tokens, we need to store \ our current state on the stack, so we can retrieve \ it after printing each character in this token TYA \ Store the offset in Y on the stack PHA LDA V+1 \ Store the high byte of V (the page containing the PHA \ token we have found) on the stack, so the stack now \ contains the address of the start of this token LDA (V),Y \ Load the character at offset Y in the token table, \ which is the next character of this token that we \ want to print EOR #RE \ Tokens are stored in memory having been EOR'd with the \ value of RE - which is 35 for all versions of Elite \ except for NES, where RE is 62 - so we repeat the \ EOR to get the actual character to print JSR TT27 \ Print the text token in A, which could be a letter, \ number, control code, two-letter token or another \ recursive token PLA \ Restore the high byte of V (the page containing the STA V+1 \ token we have found) into V+1 PLA \ Restore the offset into Y TAY INY \ Increment Y to point to the next character in the \ token we are printing BNE P%+4 \ If Y is zero then we have just crossed into a new INC V+1 \ page, so increment V+1 so that V points to the start \ of the new page LDA (V),Y \ Load the next character we want to print into A BNE TT50 \ If this is not the null character at the end of the \ token, jump back up to TT50 to print the next \ character, otherwise we are done printing .TT48 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DOEXP \ Type: Subroutine \ Category: Drawing ships \ Summary: Draw an exploding ship \ Deep dive: Drawing explosion clouds \ Generating random numbers \ \ ****************************************************************************** .EX2 LDA INWK+31 \ Set bits 5 and 7 of the ship's byte #31 to denote that ORA #%10100000 \ the ship is exploding and has been killed STA INWK+31 RTS \ Return from the subroutine .DOEXP LDA INWK+31 \ If bit 6 of the ship's byte #31 is clear, then the AND #%01000000 \ ship is not already exploding so there is no existing BEQ P%+5 \ explosion cloud to remove, so skip the following \ instruction JSR PTCLS \ Call PTCLS to remove the existing cloud by drawing it \ again LDA INWK+6 \ Set T = z_lo STA T LDA INWK+7 \ Set A = z_hi, so (A T) = z CMP #32 \ If z_hi < 32, skip the next two instructions BCC P%+6 LDA #&FE \ Set A = 254 and jump to yy (this BNE is effectively a BNE yy \ JMP, as A is never zero) ASL T \ Shift (A T) left twice ROL A ASL T ROL A SEC \ And then shift A left once more, inserting a 1 into ROL A \ bit 0 \ Overall, the above multiplies A by 8 and makes sure it \ is at least 1, to leave a one-byte distance in A. We \ can use this as the distance for our cloud, to ensure \ that the explosion cloud is visible even for ships \ that blow up a long way away .yy STA Q \ Store the distance to the explosion in Q LDY #1 \ Fetch byte #1 of the ship line heap, which contains LDA (XX19),Y \ the cloud counter ADC #4 \ Add 4 to the cloud counter, so it ticks onwards every \ we redraw it BCS EX2 \ If the addition overflowed, jump up to EX2 to update \ the explosion flags and return from the subroutine STA (XX19),Y \ Store the updated cloud counter in byte #1 of the ship \ line heap JSR DVID4 \ Calculate the following: \ \ (P R) = 256 * A / Q \ = 256 * cloud counter / distance \ \ We are going to use this as our cloud size, so the \ further away the cloud, the smaller it is, and as the \ cloud counter ticks onward, the cloud expands LDA P \ Set A = P, so we now have: \ \ (A R) = 256 * cloud counter / distance CMP #&1C \ If A < 28, skip the next two instructions BCC P%+6 LDA #&FE \ Set A = 254 and skip the following (this BNE is BNE LABEL_1 \ effectively a JMP as A is never zero) ASL R \ Shift (A R) left three times to multiply by 8 ROL A ASL R ROL A ASL R ROL A \ Overall, the above multiplies (A R) by 8 to leave a \ one-byte cloud size in A, given by the following: \ \ A = 8 * cloud counter / distance .LABEL_1 DEY \ Decrement Y to 0 STA (XX19),Y \ Store the cloud size in byte #0 of the ship line heap LDA INWK+31 \ Clear bit 6 of the ship's byte #31 to denote that the AND #%10111111 \ explosion has not yet been drawn STA INWK+31 AND #%00001000 \ If bit 3 of the ship's byte #31 is clear, then nothing BEQ TT48 \ is being drawn on-screen for this ship anyway, so \ return from the subroutine (as TT48 contains an RTS) LDY #2 \ Otherwise it's time to draw an explosion cloud, so LDA (XX19),Y \ fetch byte #2 of the ship line heap into Y, which we TAY \ set to the explosion count for this ship (i.e. the \ number of vertices used as origins for explosion \ clouds) \ \ The explosion count is stored as 4 * n + 6, where n is \ the number of vertices, so the following loop copies \ the coordinates of the first n vertices from the heap \ at XX3, which is where we stored all the visible \ vertex coordinates in part 8 of the LL9 routine, and \ sticks them in the ship line heap pointed to by XX19, \ starting at byte #7 (so it leaves the first 6 bytes of \ the ship line heap alone) .EXL1 LDA XX3-7,Y \ Copy byte Y-7 from the XX3 heap, into the Y-th byte of STA (XX19),Y \ the ship line heap DEY \ Decrement the loop counter CPY #6 \ Keep copying vertex coordinates into the ship line BNE EXL1 \ heap until Y = 6 (which will copy n vertices, where n \ is the number of vertices we should be exploding) LDA INWK+31 \ Set bit 6 of the ship's byte #31 to denote that the ORA #%01000000 \ explosion has been drawn (as it's about to be) STA INWK+31 .PTCLS \ This part of the routine actually draws the explosion \ cloud LDY #0 \ Fetch byte #0 of the ship line heap, which contains LDA (XX19),Y \ the cloud size we stored above, and store it in Q STA Q INY \ Increment the index in Y to point to byte #1 LDA (XX19),Y \ Fetch byte #1 of the ship line heap, which contains \ the cloud counter. We are now going to process this \ into the number of particles in each vertex's cloud BPL P%+4 \ If the cloud counter < 128, then we are in the first \ half of the cloud's existence, so skip the next \ instruction EOR #&FF \ Flip the value of A so that in the second half of the \ cloud's existence, A counts down instead of up LSR A \ Divide A by 8 so that is has a maximum value of 15 LSR A LSR A ORA #1 \ Make sure A is at least 1 and store it in U, to STA U \ give us the number of particles in the explosion for \ each vertex INY \ Increment the index in Y to point to byte #2 LDA (XX19),Y \ Fetch byte #2 of the ship line heap, which contains STA TGT \ the explosion count for this ship (i.e. the number of \ vertices used as origins for explosion clouds) and \ store it in TGT LDA RAND+1 \ Fetch the current random number seed in RAND+1 and PHA \ store it on the stack, so we can re-randomise the \ seeds when we are done LDY #6 \ Set Y = 6 to point to the byte before the first vertex \ coordinate we stored on the ship line heap above (we \ increment it below so it points to the first vertex) .EXL5 LDX #3 \ We are about to fetch a pair of coordinates from the \ ship line heap, so set a counter in X for 4 bytes .EXL3 INY \ Increment the index in Y so it points to the next byte \ from the coordinate we are copying LDA (XX19),Y \ Copy the Y-th byte from the ship line heap to the X-th STA K3,X \ byte of K3 DEX \ Decrement the X index BPL EXL3 \ Loop back to EXL3 until we have copied all four bytes \ The above loop copies the vertex coordinates from the \ ship line heap to K3, reversing them as we go, so it \ sets the following: \ \ K3+3 = x_lo \ K3+2 = x_hi \ K3+1 = y_lo \ K3+0 = y_hi STY CNT \ Set CNT to the index that points to the next vertex on \ the ship line heap LDY #2 \ Set Y = 2, which we will use to point to bytes #3 to \ #6, after incrementing it \ This next loop copies bytes #3 to #6 from the ship \ line heap into the four random number seeds in RAND to \ RAND+3, EOR'ing them with the vertex index so they are \ different for every vertex. This enables us to \ generate random numbers for drawing each vertex that \ are random but repeatable, which we need when we \ redraw the cloud to remove it \ \ Note that we haven't actually set the values of bytes \ #3 to #6 in the ship line heap, so we have no idea \ what they are, we just use what's already there. But \ the fact that those bytes are stored for this ship \ means we can repeat the random generation of the \ cloud, which is the important bit .EXL2 INY \ Increment the index in Y so it points to the next \ random number seed to copy LDA (XX19),Y \ Fetch the Y-th byte from the ship line heap EOR CNT \ EOR with the vertex index, so the seeds are different \ for each vertex STA &FFFD,Y \ Y is going from 3 to 6, so this stores the four bytes \ in memory locations &00, &01, &02 and &03, which are \ the memory locations of RAND through RAND+3 CPY #6 \ Loop back to EXL2 until Y = 6, which means we have BNE EXL2 \ copied four bytes LDY U \ Set Y to the number of particles in the explosion for \ each vertex, which we stored in U above. We will now \ use this as a loop counter to iterate through all the \ particles in the explosion .EXL4 JSR DORND2 \ Set ZZ to a random number, making sure the C flag STA ZZ \ doesn't affect the outcome LDA K3+1 \ Set (A R) = (y_hi y_lo) STA R \ = y LDA K3 JSR EXS1 \ Set (A X) = (A R) +/- random * cloud size \ = y +/- random * cloud size BNE EX11 \ If A is non-zero, the particle is off-screen as the \ coordinate is bigger than 255), so jump to EX11 to do \ the next particle CPX #2*Y-1 \ If X > the y-coordinate of the bottom of the screen, BCS EX11 \ the particle is off the bottom of the screen, so jump \ to EX11 to do the next particle \ Otherwise X contains a random y-coordinate within the \ cloud STX Y1 \ Set Y1 = our random y-coordinate within the cloud LDA K3+3 \ Set (A R) = (x_hi x_lo) STA R LDA K3+2 JSR EXS1 \ Set (A X) = (A R) +/- random * cloud size \ = x +/- random * cloud size BNE EX4 \ If A is non-zero, the particle is off-screen as the \ coordinate is bigger than 255), so jump to EX4 to do \ the next particle \ Otherwise X contains a random x-coordinate within the \ cloud LDA Y1 \ Set A = our random y-coordinate within the cloud JSR PIXEL \ Draw a point at screen coordinate (X, A) with the \ point size determined by the distance in ZZ .EX4 DEY \ Decrement the loop counter for the next particle BPL EXL4 \ Loop back to EXL4 until we have done all the particles \ in the cloud LDY CNT \ Set Y to the index that points to the next vertex on \ the ship line heap CPY TGT \ If Y < TGT, which we set to the explosion count for BCC EXL5 \ this ship (i.e. the number of vertices used as origins \ for explosion clouds), loop back to EXL5 to do a cloud \ for the next vertex PLA \ Restore the current random number seed to RAND+1 that STA RAND+1 \ we stored at the start of the routine LDA K%+6 \ Store the z_lo coordinate for the planet (which will STA RAND+3 \ be pretty random) in the RAND+3 seed RTS \ Return from the subroutine .EX11 JSR DORND2 \ Set A and X to random numbers, making sure the C flag \ doesn't affect the outcome JMP EX4 \ We just skipped a particle, so jump up to EX4 to do \ the next one .EXS1 \ This routine calculates the following: \ \ (A X) = (A R) +/- random * cloud size \ \ returning with the flags set for the high byte in A STA S \ Store A in S so we can use it later JSR DORND2 \ Set A and X to random numbers, making sure the C flag \ doesn't affect the outcome ROL A \ Set A = A * 2 BCS EX5 \ If bit 7 of A was set (50% chance), jump to EX5 JSR FMLTU \ Set A = A * Q / 256 \ = random << 1 * projected cloud size / 256 ADC R \ Set (A X) = (S R) + A TAX \ = (S R) + random * projected cloud size \ \ where S contains the argument A, starting with the low \ bytes LDA S \ And then the high bytes ADC #0 RTS \ Return from the subroutine .EX5 JSR FMLTU \ Set T = A * Q / 256 STA T \ = random << 1 * projected cloud size / 256 LDA R \ Set (A X) = (S R) - T SBC T \ TAX \ where S contains the argument A, starting with the low \ bytes LDA S \ And then the high bytes SBC #0 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SOS1 \ Type: Subroutine \ Category: Universe \ Summary: Update the missile indicators, set up the planet data block \ \ ------------------------------------------------------------------------------ \ \ Update the missile indicators, and set up a data block for the planet, but \ only setting the pitch and roll counters to 127 (no damping). \ \ ****************************************************************************** .SOS1 JSR msblob \ Reset the dashboard's missile indicators so none of \ them are targeted LDA #127 \ Set the pitch and roll counters to 127, so that's a STA INWK+29 \ clockwise roll and a diving pitch with no damping, so STA INWK+30 \ the planet's rotation doesn't slow down LDA tek \ Set A = 128 or 130 depending on bit 1 of the system's AND #%00000010 \ tech level in tek ORA #%10000000 JMP NWSHP \ Add a new planet to our local bubble of universe, \ with the planet type defined by A (128 is a planet \ with an equator and meridian, 130 is a planet with \ a crater) \ ****************************************************************************** \ \ Name: SOLAR \ Type: Subroutine \ Category: Universe \ Summary: Set up various aspects of arriving in a new system \ Deep dive: A sense of scale \ \ ------------------------------------------------------------------------------ \ \ Halve our legal status, update the missile indicators, and set up data blocks \ and slots for the planet and sun. \ \ ****************************************************************************** .SOLAR LSR FIST \ Halve our legal status in FIST, making us less bad, \ and moving bit 0 into the C flag (so every time we \ arrive in a new system, our legal status improves a \ bit) JSR ZINF \ Call ZINF to reset the INWK ship workspace, which \ doesn't affect the C flag LDA QQ15+1 \ Fetch s0_hi AND #%00000111 \ Extract bits 0-2 (which also happen to determine the \ economy), which will be between 0 and 7 ADC #6 \ Add 6 + C, and divide by 2, to get a result between 3 LSR A \ and 7, at the same time shifting bit 0 of the result \ of the addition into the C flag STA INWK+8 \ Store the result in z_sign in byte #6 ROR A \ Halve A, rotating in the C flag, which was previously STA INWK+2 \ bit 0 of s0_hi + 6 + C, so when this is stored in both STA INWK+5 \ x_sign and y_sign, it moves the planet to the upper \ right or lower left JSR SOS1 \ Call SOS1 to set up the planet's data block and add it \ to FRIN, where it will get put in the first slot as \ it's the first one to be added to our local bubble of \ this new system's universe LDA QQ15+3 \ Fetch s1_hi, extract bits 0-2, set bits 0 and 7 and AND #%00000111 \ store in z_sign, so the sun is behind us at a distance ORA #%10000001 \ of 1 to 7 STA INWK+8 LDA QQ15+5 \ Fetch s2_hi, extract bits 0-1 and store in x_sign and AND #%00000011 \ y_sign, so the sun is either dead centre in our rear STA INWK+2 \ laser crosshairs, or off to the top left by a distance STA INWK+1 \ of 1 or 2 when we look out the back LDA #0 \ Set the pitch and roll counters to 0 (no rotation) STA INWK+29 STA INWK+30 LDA #129 \ Set A = 129, the ship type for the sun JSR NWSHP \ Call NWSHP to set up the sun's data block and add it \ to FRIN, where it will get put in the second slot as \ it's the second one to be added to our local bubble \ of this new system's universe \ ****************************************************************************** \ \ Name: NWSTARS \ Type: Subroutine \ Category: Stardust \ Summary: Initialise the stardust field \ \ ------------------------------------------------------------------------------ \ \ This routine is called when the space view is initialised in routine LOOK1. \ \ ****************************************************************************** .NWSTARS LDA QQ11 \ If this is not a space view, jump to WPSHPS to skip \ORA MJ \ the initialisation of the SX, SY and SZ tables. The OR BNE WPSHPS \ instruction is commented out in the original source, \ but it would have the effect of also skipping the \ initialisation if we had mis-jumped into witchspace \ ****************************************************************************** \ \ Name: nWq \ Type: Subroutine \ Category: Stardust \ Summary: Create a random cloud of stardust \ \ ------------------------------------------------------------------------------ \ \ Create a random cloud of stardust containing the correct number of dust \ particles, i.e. NOSTM of them, which is 3 in witchspace and 18 (#NOST) in \ normal space. Also clears the scanner and initialises the LSO block. \ \ This is called by the DEATH routine when it displays our untimely demise. \ \ ****************************************************************************** .nWq LDY NOSTM \ Set Y to the current number of stardust particles, so \ we can use it as a counter through all the stardust .SAL4 JSR DORND \ Set A and X to random numbers ORA #8 \ Set A so that it's at least 8 STA SZ,Y \ Store A in the Y-th particle's z_hi coordinate at \ SZ+Y, so the particle appears in front of us STA ZZ \ Set ZZ to the particle's z_hi coordinate JSR DORND \ Set A and X to random numbers STA SX,Y \ Store A in the Y-th particle's x_hi coordinate at \ SX+Y, so the particle appears in front of us STA X1 \ Set X1 to the particle's x_hi coordinate JSR DORND \ Set A and X to random numbers STA SY,Y \ Store A in the Y-th particle's y_hi coordinate at \ SY+Y, so the particle appears in front of us STA Y1 \ Set Y1 to the particle's y_hi coordinate JSR PIXEL2 \ Draw a stardust particle at (X1,Y1) with distance ZZ DEY \ Decrement the counter to point to the next particle of \ stardust BNE SAL4 \ Loop back to SAL4 until we have randomised all the \ stardust particles \ Fall through into WPSHPS to clear the scanner and \ reset the LSO block \ ****************************************************************************** \ \ Name: WPSHPS \ Type: Subroutine \ Category: Dashboard \ Summary: Clear the scanner, reset the ball line and sun line heaps \ \ ------------------------------------------------------------------------------ \ \ Remove all ships from the scanner, reset the sun line heap at LSO, and reset \ the ball line heap at LSX2 and LSY2. \ \ ****************************************************************************** .WPSHPS LDX #0 \ Set up a counter in X to work our way through all the \ ship slots in FRIN .WSL1 LDA FRIN,X \ Fetch the ship type in slot X BEQ WS2 \ If the slot contains 0 then it is empty and we have \ checked all the slots (as they are always shuffled \ down in the main loop to close up and gaps), so jump \ to WS2 as we are done BMI WS1 \ If the slot contains a ship type with bit 7 set, then \ it contains the planet or the sun, so jump down to WS1 \ to skip this slot, as the planet and sun don't appear \ on the scanner STA TYPE \ Store the ship type in TYPE JSR GINF \ Call GINF to get the address of the data block for \ ship slot X and store it in INF LDY #31 \ We now want to copy the first 32 bytes from the ship's \ data block into INWK, so set a counter in Y .WSL2 LDA (INF),Y \ Copy the Y-th byte from the data block pointed to by STA INWK,Y \ INF into the Y-th byte of INWK workspace DEY \ Decrement the counter to point at the next byte BPL WSL2 \ Loop back to WSL2 until we have copied all 32 bytes STX XSAV \ Store the ship slot number in XSAV while we call SCAN JSR SCAN \ Call SCAN to plot this ship on the scanner, which will \ remove it as it's plotted with EOR logic LDX XSAV \ Restore the ship slot number from XSAV into X LDY #31 \ Clear bits 3, 4 and 6 in the ship's byte #31, which LDA (INF),Y \ stops drawing the ship on-screen (bit 3), hides it AND #%10100111 \ from the scanner (bit 4) and stops any lasers firing STA (INF),Y \ (bit 6) .WS1 INX \ Increment X to point to the next ship slot BNE WSL1 \ Loop back up to process the next slot (this BNE is \ effectively a JMP as X will never be zero) .WS2 LDX #&FF \ Set LSX2 = LSY2 = &FF to clear the ball line heap STX LSX2 STX LSY2 \ Fall through into FLFLLS to reset the LSO block \ ****************************************************************************** \ \ Name: FLFLLS \ Type: Subroutine \ Category: Drawing suns \ Summary: Reset the sun line heap \ \ ------------------------------------------------------------------------------ \ \ Reset the sun line heap at LSO by zero-filling it and setting the first byte \ to &FF. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A is set to 0 \ \ ****************************************************************************** .FLFLLS LDY #2*Y-1 \ #Y is the y-coordinate of the centre of the space \ view, so this sets Y as a counter for the number of \ lines in the space view (i.e. 191), which is also the \ number of lines in the LSO block LDA #0 \ Set A to 0 so we can zero-fill the LSO block .SAL6 STA LSO,Y \ Set the Y-th byte of the LSO block to 0 DEY \ Decrement the counter BNE SAL6 \ Loop back until we have filled all the way to LSO+1 DEY \ Decrement Y to value of &FF (as we exit the above loop \ with Y = 0) STY LSX \ Set the first byte of the LSO block, which has its own \ label LSX, to &FF, to indicate that the sun line heap \ is empty RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DET1 \ Type: Subroutine \ Category: Drawing the screen \ Summary: Show or hide the dashboard (for when we die) \ \ ------------------------------------------------------------------------------ \ \ This routine sets the screen to show the number of text rows given in X. \ \ It is used when we are killed, as reducing the number of rows from the usual \ 31 to 24 has the effect of hiding the dashboard, leaving a monochrome image \ of ship debris and explosion clouds. Increasing the rows back up to 31 makes \ the dashboard reappear, as the dashboard's screen memory doesn't get touched \ by this process. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The number of text rows to display on the screen (24 \ will hide the dashboard, 31 will make it reappear) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A is set to 6 \ \ ****************************************************************************** .DET1 LDA #6 \ Set A to 6 so we can update 6845 register R6 below SEI \ Disable interrupts so we can update the 6845 STA VIA+&00 \ Set 6845 register R6 to the value in X. Register R6 STX VIA+&01 \ is the "vertical displayed" register, which sets the \ number of rows shown on the screen CLI \ Re-enable interrupts RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SHD \ Type: Subroutine \ Category: Flight \ Summary: Charge a shield and drain some energy from the energy banks \ \ ------------------------------------------------------------------------------ \ \ Charge up a shield, and if it needs charging, drain some energy from the \ energy banks. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The value of the shield to recharge \ \ ****************************************************************************** DEX \ If we get here then we just incremented the shield \ value back around to zero, so decrement it back down \ to 255 so it stays at the maximum value of 255 RTS \ Return from the subroutine .SHD INX \ Increment the shield value BEQ SHD-2 \ If the shield value is 0 then this means it was 255 \ before, which is the maximum value, so jump to SHD-2 \ to bring it back down to 255 and return without \ draining our energy banks \ Otherwise fall through into DENGY to drain our energy \ to pay for all this shield charging \ ****************************************************************************** \ \ Name: DENGY \ Type: Subroutine \ Category: Flight \ Summary: Drain some energy from the energy banks \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Z flag Set if we have no energy left, clear otherwise \ \ ****************************************************************************** .DENGY DEC ENERGY \ Decrement the energy banks in ENERGY PHP \ Save the flags on the stack BNE P%+5 \ If the energy levels are not yet zero, skip the \ following instruction INC ENERGY \ The minimum allowed energy level is 1, and we just \ reached 0, so increment ENERGY back to 1 PLP \ Restore the flags from the stack, so we return with \ the Z flag from the DEC instruction above RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: COMPAS \ Type: Subroutine \ Category: Dashboard \ Summary: Update the compass \ \ ****************************************************************************** .COMPAS JSR DOT \ Call DOT to redraw (i.e. remove) the current compass \ dot LDA SSPR \ If we are inside the space station safe zone, jump to BNE SP1 \ SP1 to draw the space station on the compass JSR SPS1 \ Otherwise we need to draw the planet on the compass, \ so first call SPS1 to calculate the vector to the \ planet and store it in XX15 JMP SP2 \ Jump to SP2 to draw XX15 on the compass, returning \ from the subroutine using a tail call \ ****************************************************************************** \ \ Name: SPS2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (Y X) = A / 10 \ \ ------------------------------------------------------------------------------ \ \ Calculate the following, where A is a sign-magnitude 8-bit integer and the \ result is a signed 16-bit integer: \ \ (Y X) = A / 10 \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag The C flag is cleared \ \ ****************************************************************************** .SPS2 ASL A \ Set X = |A| * 2, and set the C flag to the sign bit of TAX \ A LDA #0 \ Set Y to have the sign bit from A in bit 7, with the ROR A \ rest of its bits zeroed, so Y now contains the sign of TAY \ the original argument LDA #20 \ Set Q = 20 STA Q TXA \ Copy X into A, so A now contains the argument A * 2 JSR DVID4 \ Calculate the following: \ \ P = A / Q \ = |argument A| * 2 / 20 \ = |argument A| / 10 LDX P \ Set X to the result TYA \ If the sign of the original argument A is negative, BMI LL163 \ jump to LL163 to flip the sign of the result LDY #0 \ Set the high byte of the result to 0, as the result is \ positive RTS \ Return from the subroutine .LL163 LDY #&FF \ The result is negative, so set the high byte to &FF TXA \ Flip the low byte and add 1 to get the negated low EOR #&FF \ byte, using two's complement TAX INX RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SPS4 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Calculate the vector to the space station \ \ ------------------------------------------------------------------------------ \ \ Calculate the vector between our ship and the space station and store it in \ XX15. \ \ ****************************************************************************** .SPS4 LDX #8 \ First we need to copy the space station's coordinates \ into K3, so set a counter to copy the first 9 bytes \ (the three-byte x, y and z coordinates) from the \ station's data block at K% + NI% into K3 .SPL1 LDA K%+NI%,X \ Copy the X-th byte from the station's data block at STA K3,X \ K% + NI% to the X-th byte of K3 DEX \ Decrement the loop counter BPL SPL1 \ Loop back to SPL1 until we have copied all 9 bytes JMP TAS2 \ Call TAS2 to build XX15 from K3, returning from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: SP1 \ Type: Subroutine \ Category: Dashboard \ Summary: Draw the space station on the compass \ \ ****************************************************************************** .SP1 JSR SPS4 \ Call SPS4 to calculate the vector to the space station \ and store it in XX15 \ Fall through into SP2 to draw XX15 on the compass \ ****************************************************************************** \ \ Name: SP2 \ Type: Subroutine \ Category: Dashboard \ Summary: Draw a dot on the compass, given the planet/station vector \ \ ------------------------------------------------------------------------------ \ \ Draw a dot on the compass to represent the planet or station, whose normalised \ vector is in XX15. \ \ XX15 to XX15+2 The normalised vector to the planet or space station, \ stored as x in XX15, y in XX15+1 and z in XX15+2 \ \ ****************************************************************************** .SP2 LDA XX15 \ Set A to the x-coordinate of the planet or station to \ show on the compass, which will be in the range -96 to \ +96 as the vector has been normalised JSR SPS2 \ Set (Y X) = A / 10, so X will be from -9 to +9, which \ is the x-offset from the centre of the compass of the \ dot we want to draw. Returns with the C flag clear TXA \ Set COMX = 195 + X, as 186 is the pixel x-coordinate ADC #195 \ of the leftmost dot possible on the compass, and X can STA COMX \ be -9, which would be 195 - 9 = 186. This also means \ that the highest value for COMX is 195 + 9 = 204, \ which is the pixel x-coordinate of the rightmost dot \ in the compass... but the compass dot is actually two \ pixels wide, so the compass dot can overlap the right \ edge of the compass, but not the left edge LDA XX15+1 \ Set A to the y-coordinate of the planet or station to \ show on the compass, which will be in the range -96 to \ +96 as the vector has been normalised JSR SPS2 \ Set (Y X) = A / 10, so X will be from -9 to +9, which \ is the x-offset from the centre of the compass of the \ dot we want to draw. Returns with the C flag clear STX T \ Set COMY = 204 - X, as 203 is the pixel y-coordinate LDA #204 \ of the centre of the compass, the C flag is clear, SBC T \ and the y-axis needs to be flipped around (because STA COMY \ when the planet or station is above us, and the \ vector is therefore positive, we want to show the dot \ higher up on the compass, which has a smaller pixel \ y-coordinate). So this calculation does this: \ \ COMY = 204 - X - (1 - 0) = 203 - X LDA #&F0 \ Set A to a four-pixel mode 5 byte row in colour 2 \ (yellow/white), the colour for when the planet or \ station in the compass is in front of us LDX XX15+2 \ If the z-coordinate of the XX15 vector is positive, BPL P%+4 \ skip the following instruction LDA #&FF \ The z-coordinate of XX15 is negative, so the planet or \ station is behind us and the compass dot should be in \ green/cyan, so set A to a four-pixel mode 5 byte row \ in colour 3 STA COMC \ Store the compass colour in COMC \ Fall through into DOT to draw the dot on the compass \ ****************************************************************************** \ \ Name: DOT \ Type: Subroutine \ Category: Dashboard \ Summary: Draw a dash on the compass \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ COMX The screen pixel x-coordinate of the dash \ \ COMY The screen pixel y-coordinate of the dash \ \ COMC The colour and thickness of the dash: \ \ * &F0 = a double-height dash in yellow/white, for when \ the object in the compass is in front of us \ \ * &FF = a single-height dash in green/cyan, for when \ the object in the compass is behind us \ \ ****************************************************************************** .DOT LDA COMY \ Set Y1 = COMY, the y-coordinate of the dash STA Y1 LDA COMX \ Set X1 = COMX, the x-coordinate of the dash STA X1 LDA COMC \ Set COL = COMC, the mode 5 colour byte for the dash STA COL CMP #&F0 \ If COL is &F0 then the planet/station is in front of BNE CPIX2 \ us and we want to draw a double-height dash, so if it \ isn't &F0 jump to CPIX2 to draw a single-height dash \ Otherwise fall through into CPIX4 to draw a double- \ height dash \ ****************************************************************************** \ \ Name: CPIX4 \ Type: Subroutine \ Category: Drawing pixels \ Summary: Draw a double-height dot on the dashboard \ \ ------------------------------------------------------------------------------ \ \ Draw a double-height mode 5 dot (2 pixels high, 2 pixels wide). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X1 The screen pixel x-coordinate of the bottom-left corner \ of the dot \ \ Y1 The screen pixel y-coordinate of the bottom-left corner \ of the dot \ \ COL The colour of the dot as a mode 5 character row byte \ \ ****************************************************************************** .CPIX4 JSR CPIX2 \ Call CPIX2 to draw a single-height dash at (X1, Y1) DEC Y1 \ Decrement Y1 \ Fall through into CPIX2 to draw a second single-height \ dash on the pixel row above the first one, to create a \ double-height dot \ ****************************************************************************** \ \ Name: CPIX2 \ Type: Subroutine \ Category: Drawing pixels \ Summary: Draw a single-height dash on the dashboard \ Deep dive: Drawing colour pixels on the BBC Micro \ \ ------------------------------------------------------------------------------ \ \ Draw a single-height mode 5 dash (1 pixel high, 2 pixels wide). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X1 The screen pixel x-coordinate of the dash \ \ Y1 The screen pixel y-coordinate of the dash \ \ COL The colour of the dash as a mode 5 character row byte \ \ ****************************************************************************** .CPIX2 LDA Y1 \ Fetch the y-coordinate into A \.CPIX \ This label is commented out in the original source. It \ would provide a new entry point with A specifying the \ y-coordinate instead of Y1, but it isn't used anywhere TAY \ Store the y-coordinate in Y LSR A \ Set A = A / 8, so A now contains the character row we LSR A \ need to draw in (as each character row contains 8 LSR A \ pixel rows) ORA #&60 \ Each character row in Elite's screen mode takes up one \ page in memory (256 bytes), so we now OR with &60 to \ get the page containing the dash (see the comments in \ routine TT26 for more discussion about calculating \ screen memory addresses) STA SCH \ Store the screen page in the high byte of SC(1 0) LDA X1 \ Each character block contains 8 pixel rows, so to get AND #%11111000 \ the address of the first byte in the character block \ that we need to draw into, as an offset from the start \ of the row, we clear bits 0-2 STA SC \ Store the address of the character block in the low \ byte of SC(1 0), so now SC(1 0) points to the \ character block we need to draw into TYA \ Set Y to the y-coordinate mod 8, which will be the AND #7 \ number of the pixel row we need to draw within the TAY \ character block LDA X1 \ Copy bits 0-1 of X1 to bits 1-2 of X, and clear the C AND #%00000110 \ flag in the process (using the LSR). X will now be LSR A \ a value between 0 and 3, and will be the pixel number TAX \ in the character row for the left pixel in the dash. \ This is because each character row is one byte that \ contains 4 pixels, but covers 8 screen coordinates, so \ this effectively does the division by 2 that we need LDA CTWOS,X \ Fetch a mode 5 one-pixel byte with the pixel position AND COL \ at X, and AND with the colour byte so that pixel takes \ on the colour we want to draw (i.e. A is acting as a \ mask on the colour byte) EOR (SC),Y \ Draw the pixel on-screen using EOR logic, so we can STA (SC),Y \ remove it later without ruining the background that's \ already on-screen LDA CTWOS+1,X \ Fetch a mode 5 one-pixel byte with the pixel position \ at X+1, so we can draw the right pixel of the dash BPL CP1 \ The CTWOS table has an extra row at the end of it that \ repeats the first value, %10001000, so if we have not \ fetched that value, then the right pixel of the dash \ is in the same character block as the left pixel, so \ jump to CP1 to draw it LDA SC \ Otherwise the left pixel we drew was at the last ADC #8 \ position of four in this character block, so we add STA SC \ 8 to the screen address to move onto the next block \ along (as there are 8 bytes in a character block). \ The C flag was cleared above, so this ADC is correct LDA CTWOS+1,X \ Re-fetch the mode 5 one-pixel byte, as we just \ overwrote A (the byte will still be the fifth byte \ from the table, which is correct as we want to draw \ the leftmost pixel in the next character along as the \ dash's right pixel) .CP1 AND COL \ Apply the colour mask to the pixel byte, as above EOR (SC),Y \ Draw the dash's right pixel according to the mask in STA (SC),Y \ A, with the colour in COL, using EOR logic, just as \ above RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: OOPS \ Type: Subroutine \ Category: Flight \ Summary: Take some damage \ \ ------------------------------------------------------------------------------ \ \ We just took some damage, so reduce the shields if we have any, or reduce the \ energy levels and potentially take some damage to the cargo if we don't. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The amount of damage to take \ \ INF The address of the ship block for the ship that attacked \ us, or the ship that we just ran into \ \ ****************************************************************************** .OOPS STA T \ Store the amount of damage in T LDY #8 \ Fetch byte #8 (z_sign) for the ship attacking us, and LDX #0 \ set X = 0 LDA (INF),Y BMI OO1 \ If A is negative, then we got hit in the rear, so jump \ to OO1 to process damage to the aft shield LDA FSH \ Otherwise the forward shield was damaged, so fetch the SBC T \ shield strength from FSH and subtract the damage in T BCC OO2 \ If the C flag is clear then this amount of damage was \ too much for the shields, so jump to OO2 to set the \ shield level to 0 and start taking damage directly \ from the energy banks STA FSH \ Store the new value of the forward shield in FSH RTS \ Return from the subroutine .OO2 \LDX #0 \ This instruction is commented out in the original \ source, and isn't required as X is set to 0 above STX FSH \ Set the forward shield to 0 BCC OO3 \ Jump to OO3 to start taking damage directly from the \ energy banks (this BCC is effectively a JMP as the C \ flag is clear, as we jumped to OO2 with a BCC) .OO1 LDA ASH \ The aft shield was damaged, so fetch the shield SBC T \ strength from ASH and subtract the damage in T BCC OO5 \ If the C flag is clear then this amount of damage was \ too much for the shields, so jump to OO5 to set the \ shield level to 0 and start taking damage directly \ from the energy banks STA ASH \ Store the new value of the aft shield in ASH RTS \ Return from the subroutine .OO5 \LDX #0 \ This instruction is commented out in the original \ source, and isn't required as X is set to 0 above STX ASH \ Set the aft shield to 0 .OO3 ADC ENERGY \ A is negative and contains the amount by which the STA ENERGY \ damage overwhelmed the shields, so this drains the \ energy banks by that amount (and because the energy \ banks are shown over four indicators rather than one, \ but with the same value range of 0-255, energy will \ appear to drain away four times faster than the \ shields did) BEQ P%+4 \ If we have just run out of energy, skip the next \ instruction to jump straight to our death BCS P%+5 \ If the C flag is set, then subtracting the damage from \ the energy banks didn't underflow, so we had enough \ energy to survive, and we can skip the next \ instruction to make a sound and take some damage JMP DEATH \ Otherwise our energy levels are either 0 or negative, \ and in either case that means we jump to our DEATH, \ returning from the subroutine using a tail call JSR EXNO3 \ We didn't die, so call EXNO3 to make the sound of a \ collision JMP OUCH \ And jump to OUCH to take damage and return from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: SPS3 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Copy a space coordinate from the K% block into K3 \ \ ------------------------------------------------------------------------------ \ \ Copy one of the planet's coordinates into the corresponding location in the \ temporary variable K3. The high byte and absolute value of the sign byte are \ copied into the first two K3 bytes, and the sign of the sign byte is copied \ into the highest K3 byte. \ \ The comments below are written for copying the planet's x-coordinate into \ K3(2 1 0). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X Determines which coordinate to copy, and to where: \ \ * X = 0 copies (x_sign, x_hi) into K3(2 1 0) \ \ * X = 3 copies (y_sign, y_hi) into K3(5 4 3) \ \ * X = 6 copies (z_sign, z_hi) into K3(8 7 6) \ \ ****************************************************************************** .SPS3 LDA K%+1,X \ Copy x_hi into K3+X STA K3,X LDA K%+2,X \ Set A = Y = x_sign TAY AND #%01111111 \ Set K3+1 = |x_sign| STA K3+1,X TYA \ Set K3+2 = the sign of x_sign AND #%10000000 STA K3+2,X RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: GINF \ Type: Subroutine \ Category: Universe \ Summary: Fetch the address of a ship's data block into INF \ \ ------------------------------------------------------------------------------ \ \ Get the address of the data block for ship slot X and store it in INF. This \ address is fetched from the UNIV table, which stores the addresses of the 13 \ ship data blocks in workspace K%. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The ship slot number for which we want the data block \ address \ \ ****************************************************************************** .GINF TXA \ Set Y = X * 2 ASL A TAY LDA UNIV,Y \ Get the high byte of the address of the X-th ship STA INF \ from UNIV and store it in INF LDA UNIV+1,Y \ Get the low byte of the address of the X-th ship STA INF+1 \ from UNIV and store it in INF RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: NWSPS \ Type: Subroutine \ Category: Universe \ Summary: Add a new space station to our local bubble of universe \ \ ****************************************************************************** .NWSPS JSR SPBLB \ Light up the space station bulb on the dashboard LDX #%00000001 \ Set the AI flag in byte #32 to %00000001 (friendly, STX INWK+32 \ has an E.C.M.) DEX \ Set pitch counter to 0 (no pitch, roll only) STX INWK+30 \STX INWK+31 \ This instruction is commented out in the original \ source. It would set the exploding state and missile \ count to 0 STX FRIN+1 \ Set the second slot in the FRIN table to 0, so when we \ fall through into NWSHP below, the new station that \ gets created will go into slot FRIN+1, as this will be \ the first empty slot that the routine finds DEX \ Set the roll counter to 255 (maximum anti-clockwise STX INWK+29 \ roll with no damping) LDX #10 \ Call NwS1 to flip the sign of nosev_x_hi (byte #10) JSR NwS1 JSR NwS1 \ And again to flip the sign of nosev_y_hi (byte #12) JSR NwS1 \ And again to flip the sign of nosev_z_hi (byte #14) LDA #LO(LSO) \ Set bytes #33 and #34 to point to LSO for the ship STA INWK+33 \ line heap for the space station LDA #HI(LSO) STA INWK+34 LDA #SST \ Set A to the space station type, and fall through \ into NWSHP to finish adding the space station to the \ universe \ ****************************************************************************** \ \ Name: NWSHP \ Type: Subroutine \ Category: Universe \ Summary: Add a new ship to our local bubble of universe \ \ ------------------------------------------------------------------------------ \ \ This creates a new block of ship data in the K% workspace, allocates a new \ block in the ship line heap at WP, adds the new ship's type into the first \ empty slot in FRIN, and adds a pointer to the ship data into UNIV. If there \ isn't enough free memory for the new ship, it isn't added. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The type of the ship to add (see variable XX21 for a \ list of ship types) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Set if the ship was successfully added, clear if it \ wasn't (as there wasn't enough free memory) \ \ INF Points to the new ship's data block in K% \ \ ****************************************************************************** .NWSHP STA T \ Store the ship type in location T LDX #0 \ Before we can add a new ship, we need to check \ whether we have an empty slot we can put it in. To do \ this, we need to loop through all the slots to look \ for an empty one, so set a counter in X that starts \ from the first slot at 0. When ships are killed, then \ the slots are shuffled down by the KILLSHP routine, so \ the first empty slot will always come after the last \ filled slot. This allows us to tack the new ship's \ data block and ship line heap onto the end of the \ existing ship data and heap, as shown in the memory \ map below .NWL1 LDA FRIN,X \ Load the ship type for the X-th slot BEQ NW1 \ If it is zero, then this slot is empty and we can use \ it for our new ship, so jump down to NW1 INX \ Otherwise increment X to point to the next slot CPX #NOSH \ If we haven't reached the last slot yet, loop back up BCC NWL1 \ to NWL1 to check the next slot (note that this means \ only slots from 0 to #NOSH - 1 are populated by this \ routine, but there is one more slot reserved in FRIN, \ which is used to identify the end of the slot list \ when shuffling the slots down in the KILLSHP routine) .NW3 CLC \ Otherwise we don't have an empty slot, so we can't RTS \ add a new ship, so clear the C flag to indicate that \ we have not managed to create the new ship, and return \ from the subroutine .NW1 \ If we get here, then we have found an empty slot at \ index X, so we can go ahead and create our new ship. \ We do that by creating a ship data block at INWK and, \ when we are done, copying the block from INWK into \ the K% workspace (specifically, to INF) JSR GINF \ Get the address of the data block for ship slot X \ (which is in workspace K%) and store it in INF LDA T \ If the type of ship that we want to create is BMI NW2 \ negative, then this indicates a planet or sun, so \ jump down to NW2, as the next section sets up a ship \ data block, which doesn't apply to planets and suns, \ as they don't have things like shields, missiles, \ vertices and edges \ This is a ship, so first we need to set up various \ pointers to the ship blueprint we will need. The \ blueprints for each ship type in Elite are stored \ in a table at location XX21, so refer to the comments \ on that variable for more details on the data we're \ about to access ASL A \ Set Y = ship type * 2 TAY LDA XX21-2,Y \ The ship blueprints at XX21 start with a lookup STA XX0 \ table that points to the individual ship blueprints, \ so this fetches the low byte of this particular ship \ type's blueprint and stores it in XX0 LDA XX21-1,Y \ Fetch the high byte of this particular ship type's STA XX0+1 \ blueprint and store it in XX0+1, so XX0(1 0) now \ contains the address of this ship's blueprint CPY #2*SST \ If the ship type is a space station (SST), then jump BEQ NW6 \ to NW6, skipping the heap space steps below, as the \ space station has its own line heap at LSO (which it \ shares with the sun) \ We now want to allocate space for a heap that we can \ use to store the lines we draw for our new ship (so it \ can easily be erased from the screen again). SLSP \ points to the start of the current heap space, and we \ can extend it downwards with the heap for our new ship \ (as the heap space always ends just before the WP \ workspace) LDY #5 \ Fetch ship blueprint byte #5, which contains the LDA (XX0),Y \ maximum heap size required for plotting the new ship, STA T1 \ and store it in T1 LDA SLSP \ Take the 16-bit address in SLSP and subtract T1, SEC \ storing the 16-bit result in INWK(34 33), so this now SBC T1 \ points to the start of the line heap for our new ship STA INWK+33 LDA SLSP+1 SBC #0 STA INWK+34 \ We now need to check that there is enough free space \ for both this new line heap and the new data block \ for our ship. In memory, this is the layout of the \ ship data blocks and ship line heaps: \ \ +-----------------------------------+ &0F34 \ | | \ | WP workspace | \ | | \ +-----------------------------------+ &0D40 = WP \ | | \ | Current ship line heap | \ | | \ +-----------------------------------+ SLSP \ | | \ | Proposed heap for new ship | \ | | \ +-----------------------------------+ INWK(34 33) \ | | \ . . \ . . \ . . \ . . \ . . \ | | \ +-----------------------------------+ INF + NI% \ | | \ | Proposed data block for new ship | \ | | \ +-----------------------------------+ INF \ | | \ | Existing ship data blocks | \ | | \ +-----------------------------------+ &0900 = K% \ \ So, to work out if we have enough space, we have to \ make sure there is room between the end of our new \ ship data block at INF + NI%, and the start of the \ proposed heap for our new ship at the address we \ stored in INWK(34 33). Or, to put it another way, we \ and to make sure that: \ \ INWK(34 33) > INF + NI% \ \ which is the same as saying: \ \ INWK+33 - INF > NI% \ \ because INWK is in zero page, so INWK+34 = 0 LDA INWK+33 \ Calculate INWK+33 - INF, again using 16-bit \SEC \ arithmetic, and put the result in (A Y), so the high SBC INF \ byte is in A and the low byte in Y. The SEC TAY \ instruction is commented out in the original source; LDA INWK+34 \ as the previous subtraction will never underflow, it SBC INF+1 \ is superfluous BCC NW3+1 \ If we have an underflow from the subtraction, then \ INF > INWK+33 and we definitely don't have enough \ room for this ship, so jump to NW3+1, which returns \ from the subroutine (with the C flag already cleared) BNE NW4 \ If the subtraction of the high bytes in A is not \ zero, and we don't have underflow, then we definitely \ have enough space, so jump to NW4 to continue setting \ up the new ship CPY #NI% \ Otherwise the high bytes are the same in our BCC NW3+1 \ subtraction, so now we compare the low byte of the \ result (which is in Y) with NI%. This is the same as \ doing INWK+33 - INF > NI% (see above). If this isn't \ true, the C flag will be clear and we don't have \ enough space, so we jump to NW3+1, which returns \ from the subroutine (with the C flag already cleared) .NW4 LDA INWK+33 \ If we get here then we do have enough space for our STA SLSP \ new ship, so store the new bottom of the ship line LDA INWK+34 \ heap (i.e. INWK+33) in SLSP, doing both the high and STA SLSP+1 \ low bytes .NW6 LDY #14 \ Fetch ship blueprint byte #14, which contains the LDA (XX0),Y \ ship's energy, and store it in byte #35 STA INWK+35 LDY #19 \ Fetch ship blueprint byte #19, which contains the LDA (XX0),Y \ number of missiles and laser power, and AND with %111 AND #%00000111 \ to extract the number of missiles before storing in STA INWK+31 \ byte #31 LDA T \ Restore the ship type we stored above .NW2 STA FRIN,X \ Store the ship type in the X-th byte of FRIN, so the \ slot is now shown as occupied in the index table TAX \ Copy the ship type into X BMI P%+5 \ If the ship type is negative (planet or sun), then \ skip the following instruction INC MANY,X \ Increment the total number of ships of type X LDY #NI%-1 \ The final step is to copy the new ship's data block \ from INWK to INF, so set up a counter for NI% bytes \ in Y .NWL3 LDA INWK,Y \ Load the Y-th byte of INWK and store in the Y-th byte STA (INF),Y \ of the workspace pointed to by INF DEY \ Decrement the loop counter BPL NWL3 \ Loop back for the next byte until we have copied them \ all over SEC \ We have successfully created our new ship, so set the \ C flag to indicate success RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: NwS1 \ Type: Subroutine \ Category: Universe \ Summary: Flip the sign and double an INWK byte \ \ ------------------------------------------------------------------------------ \ \ Flip the sign of the INWK byte at offset X, and increment X by 2. This is \ used by the space station creation routine at NWSPS. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The offset of the INWK byte to be flipped \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ X X is incremented by 2 \ \ ****************************************************************************** .NwS1 LDA INWK,X \ Load the X-th byte of INWK into A and flip bit 7, EOR #%10000000 \ storing the result back in the X-th byte of INWK STA INWK,X INX \ Add 2 to X INX RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: ABORT \ Type: Subroutine \ Category: Dashboard \ Summary: Disarm missiles and update the dashboard indicators \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ Y The new colour of the missile indicator: \ \ * &00 = black (no missile) \ \ * &0E = red (armed and locked) \ \ * &E0 = yellow/white (armed) \ \ * &EE = green/cyan (disarmed) \ \ ****************************************************************************** .ABORT LDX #&FF \ Set X to &FF, which is the value of MSTG when we have \ no target lock for our missile \ Fall through into ABORT2 to set the missile lock to \ the value in X, which effectively disarms the missile \ ****************************************************************************** \ \ Name: ABORT2 \ Type: Subroutine \ Category: Dashboard \ Summary: Set/unset the lock target for a missile and update the dashboard \ \ ------------------------------------------------------------------------------ \ \ Set the lock target for the leftmost missile and update the dashboard. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The slot number of the ship to lock our missile onto, or \ &FF to remove missile lock \ \ Y The new colour of the missile indicator: \ \ * &00 = black (no missile) \ \ * &0E = red (armed and locked) \ \ * &E0 = yellow/white (armed) \ \ * &EE = green/cyan (disarmed) \ \ ****************************************************************************** .ABORT2 STX MSTG \ Store the target of our missile lock in MSTG LDX NOMSL \ Call MSBAR to update the leftmost indicator in the JSR MSBAR \ dashboard's missile bar, which returns with Y = 0 STY MSAR \ Set MSAR = 0 to indicate that the leftmost missile \ is no longer seeking a target lock RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: ECBLB2 \ Type: Subroutine \ Category: Dashboard \ Summary: Start up the E.C.M. (light up the indicator, start the countdown \ and make the E.C.M. sound) \ \ ****************************************************************************** .ECBLB2 LDA #32 \ Set the E.C.M. countdown timer in ECMA to 32 STA ECMA ASL A \ Call the NOISE routine with A = 64 to make the sound JSR NOISE \ of the E.C.M. being switched on \ Fall through into ECBLB to light up the E.C.M. bulb \ ****************************************************************************** \ \ Name: ECBLB \ Type: Subroutine \ Category: Dashboard \ Summary: Light up the E.C.M. indicator bulb ("E") on the dashboard \ \ ****************************************************************************** .ECBLB LDA #7*8 \ The E.C.M. bulb is in character block number 7 \ with each character taking 8 bytes, so this sets the \ low byte of the screen address of the character block \ we want to draw to LDX #LO(ECBT) \ Set (Y X) to point to the character definition in LDY #HI(ECBT) \ ECBT. The LDY has no effect, as we overwrite Y with \ the jump to BULB-2, which writes the high byte of SPBT \ into Y. This works as long as ECBT and SPBT are in \ the same page of memory, so perhaps the BNE below got \ changed from BULB to BULB-2 so they could remove the \ LDY, but for some reason it didn't get culled? Who \ knows... BNE BULB-2 \ Jump down to BULB-2 (this BNE is effectively a JMP as \ A will never be zero) \ ****************************************************************************** \ \ Name: SPBLB \ Type: Subroutine \ Category: Dashboard \ Summary: Light up the space station indicator ("S") on the dashboard \ \ ****************************************************************************** .SPBLB LDA #24*8 \ The space station bulb is in character block number 24 \ with each character taking 8 bytes, so this sets the \ low byte of the screen address of the character block \ we want to draw to LDX #LO(SPBT) \ Set (Y X) to point to the character definition in SPBT LDY #HI(SPBT) \ Fall through into BULB to draw the space station bulb \ ****************************************************************************** \ \ Name: BULB \ Type: Subroutine \ Category: Dashboard \ Summary: Draw an indicator bulb on the dashboard \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The y-coordinate of the bulb as a low-byte screen \ address offset within screen page &7D (as both bulbs \ are on this character row in the dashboard) \ \ (Y X) The address of the character definition of the bulb to \ be drawn (i.e. ECBT for the E.C.M. bulb, or SPBT for the \ space station bulb) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ BULB-2 Set the Y screen address \ \ ****************************************************************************** .BULB STA SC \ Store the low byte of the screen address in SC STX P+1 \ Set P(2 1) = (Y X) STY P+2 LDA #&7D \ Set A to the high byte of the screen address, which is \ &7D as the bulbs are both in the character row from \ &7D00 to &7DFF JMP RREN \ Call RREN to print the character definition pointed to \ by P(2 1) at the screen address pointed to by (A SC), \ returning from the subroutine using a tail call \ ****************************************************************************** \ \ Name: ECBT \ Type: Variable \ Category: Dashboard \ Summary: The character bitmap for the E.C.M. indicator bulb \ \ ------------------------------------------------------------------------------ \ \ The character bitmap for the E.C.M. indicator's "E" bulb that gets displayed \ on the dashboard. \ \ The E.C.M. indicator uses the first 5 rows of the space station's "S" bulb \ below, as the bottom 5 rows of the "E" match the top 5 rows of the "S". \ \ Each pixel is in mode 5 colour 2 (%10), which is yellow/white. \ \ ****************************************************************************** .ECBT EQUB %11100000 \ x x x . EQUB %11100000 \ x x x . EQUB %10000000 \ x . . . \ x x x . \ x x x . \ x . . . \ x x x . \ x x x . \ ****************************************************************************** \ \ Name: SPBT \ Type: Variable \ Category: Dashboard \ Summary: The bitmap definition for the space station indicator bulb \ \ ------------------------------------------------------------------------------ \ \ The bitmap definition for the space station indicator's "S" bulb that gets \ displayed on the dashboard. \ \ Each pixel is in mode 5 colour 2 (%10), which is yellow/white. \ \ ****************************************************************************** .SPBT EQUB %11100000 \ x x x . EQUB %11100000 \ x x x . EQUB %10000000 \ x . . . EQUB %11100000 \ x x x . EQUB %11100000 \ x x x . EQUB %00100000 \ . . x . EQUB %11100000 \ x x x . EQUB %11100000 \ x x x . \ ****************************************************************************** \ \ Name: MSBAR \ Type: Subroutine \ Category: Dashboard \ Summary: Draw a specific indicator in the dashboard's missile bar \ \ ------------------------------------------------------------------------------ \ \ Each indicator is a rectangle that's 3 pixels wide and 5 pixels high. If the \ indicator is set to black, this effectively removes a missile. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The number of the missile indicator to update (counting \ from right to left, so indicator NOMSL is the leftmost \ indicator) \ \ Y The colour of the missile indicator: \ \ * &00 = black (no missile) \ \ * &0E = red (armed and locked) \ \ * &E0 = yellow/white (armed) \ \ * &EE = green/cyan (disarmed) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ X X is preserved \ \ Y Y is set to 0 \ \ ****************************************************************************** .MSBAR TXA \ Set T = X * 8 ASL A ASL A ASL A STA T LDA #49 \ Set SC = 49 - T SBC T \ = 48 + 1 - (X * 8) STA SC \ So the low byte of SC(1 0) contains the row address \ for the rightmost missile indicator, made up as \ follows: \ \ * 48 (character block 7, as byte #7 * 8 = 48), the \ character block of the rightmost missile \ \ * 1 (so we start drawing on the second row of the \ character block) \ \ * Move left one character (8 bytes) for each count \ of X, so when X = 0 we are drawing the rightmost \ missile, for X = 1 we hop to the left by one \ character, and so on LDA #&7E \ Set the high byte of SC(1 0) to &7E, the character row STA SCH \ that contains the missile indicators (i.e. the bottom \ row of the screen) TYA \ Set A to the correct colour, which is a three-pixel \ wide mode 5 character row in the correct colour (for \ example, a green block has Y = &EE, or %11101110, so \ the missile blocks are 3 pixels wide, with the \ fourth pixel on the character row being empty) LDY #5 \ We now want to draw this line five times, so set a \ counter in Y .MBL1 STA (SC),Y \ Draw the three-pixel row, and as we do not use EOR \ logic, this will overwrite anything that is already \ there (so drawing a black missile will delete what's \ there) DEY \ Decrement the counter for the next row BNE MBL1 \ Loop back to MBL1 if have more rows to draw RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PROJ \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Project the current ship or planet onto the screen \ Deep dive: Extended screen coordinates \ \ ------------------------------------------------------------------------------ \ \ Project the current ship's location or the planet onto the screen, either \ returning the screen coordinates of the projection (if it's on-screen), or \ returning an error via the C flag. \ \ In this context, "on-screen" means that the point is projected into the \ following range: \ \ centre of screen - 1024 < x < centre of screen + 1024 \ centre of screen - 1024 < y < centre of screen + 1024 \ \ This is to cater for ships (and, more likely, planets and suns) whose centres \ are off-screen but whose edges may still be visible. \ \ The projection calculation is: \ \ K3(1 0) = #X + x / z \ K4(1 0) = #Y + y / z \ \ where #X and #Y are the pixel x-coordinate and y-coordinate of the centre of \ the screen. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ INWK The ship data block for the ship to project on-screen \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ K3(1 0) The x-coordinate of the ship's projection on-screen \ \ K4(1 0) The y-coordinate of the ship's projection on-screen \ \ C flag Set if the ship's projection doesn't fit on the screen, \ clear if it does project onto the screen \ \ A Contains K4+1, the high byte of the y-coordinate \ \ ****************************************************************************** .PROJ LDA INWK \ Set P(1 0) = (x_hi x_lo) STA P \ = x LDA INWK+1 STA P+1 LDA INWK+2 \ Set A = x_sign JSR PLS6 \ Call PLS6 to calculate: \ \ (X K) = (A P+1 P) / (z_sign z_hi z_lo) \ = (x_sign x_hi x_lo) / (z_sign z_hi z_lo) \ = x / z BCS PL2-1 \ If the C flag is set then the result overflowed and \ the coordinate doesn't fit on the screen, so return \ from the subroutine with the C flag set (as PL2-1 \ contains an RTS) LDA K \ Set K3(1 0) = (X K) + #X ADC #X \ = #X + x / z STA K3 \ \ first doing the low bytes TXA \ And then the high bytes. #X is the x-coordinate of ADC #0 \ the centre of the space view, so this converts the STA K3+1 \ space x-coordinate into a screen x-coordinate LDA INWK+3 \ Set P(1 0) = (y_hi y_lo) STA P LDA INWK+4 STA P+1 LDA INWK+5 \ Set A = -y_sign EOR #%10000000 JSR PLS6 \ Call PLS6 to calculate: \ \ (X K) = (A P+1 P) / (z_sign z_hi z_lo) \ = -(y_sign y_hi y_lo) / (z_sign z_hi z_lo) \ = -y / z BCS PL2-1 \ If the C flag is set then the result overflowed and \ the coordinate doesn't fit on the screen, so return \ from the subroutine with the C flag set (as PL2-1 \ contains an RTS) LDA K \ Set K4(1 0) = (X K) + #Y ADC #Y \ = #Y - y / z STA K4 \ \ first doing the low bytes TXA \ And then the high bytes. #Y is the y-coordinate of ADC #0 \ the centre of the space view, so this converts the STA K4+1 \ space y-coordinate into a screen y-coordinate CLC \ Clear the C flag to indicate success RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PL2 \ Type: Subroutine \ Category: Drawing planets \ Summary: Remove the planet or sun from the screen \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ PL2-1 Contains an RTS \ \ ****************************************************************************** .PL2 LDA TYPE \ Shift bit 0 of the planet/sun's type into the C flag LSR A BCS P%+5 \ If the planet/sun's type has bit 0 clear, then it's \ either 128 or 130, which is a planet; meanwhile, the \ sun has type 129, which has bit 0 set. So if this is \ the sun, skip the following instruction JMP WPLS2 \ This is the planet, so jump to WPLS2 to remove it from \ screen, returning from the subroutine using a tail \ call JMP WPLS \ This is the sun, so jump to WPLS to remove it from \ screen, returning from the subroutine using a tail \ call \ ****************************************************************************** \ \ Name: PLANET \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw the planet or sun \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ INWK The planet or sun's ship data block \ \ ****************************************************************************** .PLANET LDA INWK+8 \ Set A = z_sign (the highest byte in the planet/sun's \ coordinates) BMI PL2 \ If A is negative then the planet/sun is behind us, so \ jump to PL2 to remove it from the screen, returning \ from the subroutine using a tail call CMP #48 \ If A >= 48 then the planet/sun is too far away to be BCS PL2 \ seen, so jump to PL2 to remove it from the screen, \ returning from the subroutine using a tail call ORA INWK+7 \ Set A to 0 if both z_sign and z_hi are 0 BEQ PL2 \ If both z_sign and z_hi are 0, then the planet/sun is \ too close to be shown, so jump to PL2 to remove it \ from the screen, returning from the subroutine using a \ tail call JSR PROJ \ Project the planet/sun onto the screen, returning the \ centre's coordinates in K3(1 0) and K4(1 0) BCS PL2 \ If the C flag is set by PROJ then the planet/sun is \ not visible on-screen, so jump to PL2 to remove it \ from the screen, returning from the subroutine using \ a tail call LDA #96 \ Set (A P+1 P) = (0 96 0) = 24576 STA P+1 \ LDA #0 \ This represents the planet/sun's radius at a distance STA P \ of z = 1 JSR DVID3B2 \ Call DVID3B2 to calculate: \ \ K(3 2 1 0) = (A P+1 P) / (z_sign z_hi z_lo) \ = (0 96 0) / z \ = 24576 / z \ \ so K now contains the planet/sun's radius, reduced by \ the actual distance to the planet/sun. We know that \ K+3 and K+2 will be 0, as the number we are dividing, \ (0 96 0), fits into the two bottom bytes, so the \ result is actually in K(1 0) LDA K+1 \ If the high byte of the reduced radius is zero, jump BEQ PL82 \ to PL82, as K contains the radius on its own LDA #248 \ Otherwise set K = 248, to round up the radius in STA K \ K(1 0) to the nearest integer (if we consider the low \ byte to be the fractional part) .PL82 LDA TYPE \ If the planet/sun's type has bit 0 clear, then it's LSR A \ either 128 or 130, which is a planet (the sun has type BCC PL9 \ 129, which has bit 0 set). So jump to PL9 to draw the \ planet with radius K, returning from the subroutine \ using a tail call JMP SUN \ Otherwise jump to SUN to draw the sun with radius K, \ returning from the subroutine using a tail call \ ****************************************************************************** \ \ Name: PL9 (Part 1 of 3) \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw the planet, with either an equator and meridian, or a crater \ \ ------------------------------------------------------------------------------ \ \ Draw the planet with radius K at pixel coordinate (K3, K4), and with either an \ equator and meridian, or a crater. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K(1 0) The planet's radius \ \ K3(1 0) Pixel x-coordinate of the centre of the planet \ \ K4(1 0) Pixel y-coordinate of the centre of the planet \ \ INWK The planet's ship data block \ \ ****************************************************************************** .PL9 JSR WPLS2 \ Call WPLS2 to remove the planet from the screen JSR CIRCLE \ Call CIRCLE to draw the planet's new circle BCS PL20 \ If the call to CIRCLE returned with the C flag set, \ then the circle does not fit on-screen, so jump to \ PL20 to return from the subroutine LDA K+1 \ If K+1 is zero, jump to PL25 as K(1 0) < 256, so the BEQ PL25 \ planet fits on the screen and we can draw meridians or \ craters .PL20 RTS \ The planet doesn't fit on-screen, so return from the \ subroutine .PL25 LDA TYPE \ If the planet type is 128 then it has an equator and CMP #128 \ a meridian, so this jumps to PL26 if this is not a BNE PL26 \ planet with an equator - in other words, if it is a \ planet with a crater \ Otherwise this is a planet with an equator and \ meridian, so fall through into the following to draw \ them \ ****************************************************************************** \ \ Name: PL9 (Part 2 of 3) \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw the planet's equator and meridian \ Deep dive: Drawing meridians and equators \ \ ------------------------------------------------------------------------------ \ \ Draw the planet's equator and meridian. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K(1 0) The planet's radius \ \ K3(1 0) Pixel x-coordinate of the centre of the planet \ \ K4(1 0) Pixel y-coordinate of the centre of the planet \ \ INWK The planet's ship data block \ \ ****************************************************************************** LDA K \ If the planet's radius is less than 6, the planet is CMP #6 \ too small to show a meridian, so jump to PL20 to BCC PL20 \ return from the subroutine LDA INWK+14 \ Set P = -nosev_z_hi EOR #%10000000 STA P LDA INWK+20 \ Set A = roofv_z_hi JSR PLS4 \ Call PLS4 to calculate the following: \ \ CNT2 = arctan(P / A) / 4 \ = arctan(-nosev_z_hi / roofv_z_hi) / 4 \ \ and do the following if nosev_z_hi >= 0: \ \ CNT2 = CNT2 + PI LDX #9 \ Set X to 9 so the call to PLS1 divides nosev_x JSR PLS1 \ Call PLS1 to calculate the following: STA K2 \ STY XX16 \ (XX16 K2) = nosev_x / z \ \ and increment X to point to nosev_y for the next call JSR PLS1 \ Call PLS1 to calculate the following: STA K2+1 \ STY XX16+1 \ (XX16+1 K2+1) = nosev_y / z LDX #15 \ Set X to 15 so the call to PLS5 divides roofv_x JSR PLS5 \ Call PLS5 to calculate the following: \ \ (XX16+2 K2+2) = roofv_x / z \ \ (XX16+3 K2+3) = roofv_y / z JSR PLS2 \ Call PLS2 to draw the first meridian LDA INWK+14 \ Set P = -nosev_z_hi EOR #%10000000 STA P LDA INWK+26 \ Set A = sidev_z_hi, so the second meridian will be at \ 90 degrees to the first JSR PLS4 \ Call PLS4 to calculate the following: \ \ CNT2 = arctan(P / A) / 4 \ = arctan(-nosev_z_hi / sidev_z_hi) / 4 \ \ and do the following if nosev_z_hi >= 0: \ \ CNT2 = CNT2 + PI LDX #21 \ Set X to 21 so the call to PLS5 divides sidev_x JSR PLS5 \ Call PLS5 to calculate the following: \ \ (XX16+2 K2+2) = sidev_x / z \ \ (XX16+3 K2+3) = sidev_y / z JMP PLS2 \ Jump to PLS2 to draw the second meridian, returning \ from the subroutine using a tail call \ ****************************************************************************** \ \ Name: PL9 (Part 3 of 3) \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw the planet's crater \ Deep dive: Drawing craters \ \ ------------------------------------------------------------------------------ \ \ Draw the planet's crater. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K(1 0) The planet's radius \ \ K3(1 0) Pixel x-coordinate of the centre of the planet \ \ K4(1 0) Pixel y-coordinate of the centre of the planet \ \ INWK The planet's ship data block \ \ ****************************************************************************** .PL26 LDA INWK+20 \ Set A = roofv_z_hi BMI PL20 \ If A is negative, the crater is on the far side of the \ planet, so return from the subroutine (as PL2 \ contains an RTS) LDX #15 \ Set X = 15, so the following call to PLS3 operates on \ roofv JSR PLS3 \ Call PLS3 to calculate: \ \ (Y A P) = 222 * roofv_x / z \ \ to give the x-coordinate of the crater offset and \ increment X to point to roofv_y for the next call CLC \ Calculate: ADC K3 \ STA K3 \ K3(1 0) = (Y A) + K3(1 0) \ = 222 * roofv_x / z + x-coordinate of planet \ centre \ \ starting with the high bytes TYA \ And then doing the low bytes, so now K3(1 0) contains ADC K3+1 \ the x-coordinate of the crater offset plus the planet STA K3+1 \ centre to give the x-coordinate of the crater's centre JSR PLS3 \ Call PLS3 to calculate: \ \ (Y A P) = 222 * roofv_y / z \ \ to give the y-coordinate of the crater offset STA P \ Calculate: LDA K4 \ SEC \ K4(1 0) = K4(1 0) - (Y A) SBC P \ = 222 * roofv_y / z - y-coordinate of planet STA K4 \ centre \ \ starting with the low bytes STY P \ And then doing the low bytes, so now K4(1 0) contains LDA K4+1 \ the y-coordinate of the crater offset plus the planet SBC P \ centre to give the y-coordinate of the crater's centre STA K4+1 LDX #9 \ Set X = 9, so the following call to PLS1 operates on \ nosev JSR PLS1 \ Call PLS1 to calculate the following: \ \ (Y A) = nosev_x / z \ \ and increment X to point to nosev_y for the next call LSR A \ Set (XX16 K2) = (Y A) / 2 STA K2 STY XX16 JSR PLS1 \ Call PLS1 to calculate the following: \ \ (Y A) = nosev_y / z \ \ and increment X to point to nosev_z for the next call LSR A \ Set (XX16+1 K2+1) = (Y A) / 2 STA K2+1 STY XX16+1 LDX #21 \ Set X = 21, so the following call to PLS1 operates on \ sidev JSR PLS1 \ Call PLS1 to calculate the following: \ \ (Y A) = sidev_x / z \ \ and increment X to point to sidev_y for the next call LSR A \ Set (XX16+2 K2+2) = (Y A) / 2 STA K2+2 STY XX16+2 JSR PLS1 \ Call PLS1 to calculate the following: \ \ (Y A) = sidev_y / z \ \ and increment X to point to sidev_z for the next call LSR A \ Set (XX16+3 K2+3) = (Y A) / 2 STA K2+3 STY XX16+3 LDA #64 \ Set TGT = 64, so we draw a full ellipse in the call to STA TGT \ PLS22 below LDA #0 \ Set CNT2 = 0 as we are drawing a full ellipse, so we STA CNT2 \ don't need to apply an offset JMP PLS22 \ Jump to PLS22 to draw the crater, returning from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: PLS1 \ Type: Subroutine \ Category: Drawing planets \ Summary: Calculate (Y A) = nosev_x / z \ \ ------------------------------------------------------------------------------ \ \ Calculate the following division of a specified value from one of the \ orientation vectors (in this example, nosev_x): \ \ (Y A) = nosev_x / z \ \ where z is the z-coordinate of the planet from INWK. The result is an 8-bit \ magnitude in A, with maximum value 254, and just a sign bit (bit 7) in Y. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X Determines which of the INWK orientation vectors to \ divide: \ \ * X = 9, 11, 13: divides nosev_x, nosev_y, nosev_z \ \ * X = 15, 17, 19: divides roofv_x, roofv_y, roofv_z \ \ * X = 21, 23, 25: divides sidev_x, sidev_y, sidev_z \ \ INWK The planet's ship data block \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A The result as an 8-bit magnitude with maximum value 254 \ \ Y The sign of the result in bit 7 \ \ K+3 Also the sign of the result in bit 7 \ \ X X gets incremented by 2 so it points to the next \ coordinate in this orientation vector (so consecutive \ calls to the routine will start with x, then move onto y \ and then z) \ \ ****************************************************************************** .PLS1 LDA INWK,X \ Set P = nosev_x_lo STA P LDA INWK+1,X \ Set P+1 = |nosev_x_hi| AND #%01111111 STA P+1 LDA INWK+1,X \ Set A = sign bit of nosev_x_lo AND #%10000000 JSR DVID3B2 \ Call DVID3B2 to calculate: \ \ K(3 2 1 0) = (A P+1 P) / (z_sign z_hi z_lo) LDA K \ Fetch the lowest byte of the result into A LDY K+1 \ Fetch the second byte of the result into Y BEQ P%+4 \ If the second byte is 0, skip the next instruction LDA #254 \ The second byte is non-zero, so the result won't fit \ into one byte, so set A = 254 as our maximum one-byte \ value to return LDY K+3 \ Fetch the sign of the result from K+3 into Y INX \ Add 2 to X so the index points to the next coordinate INX \ in this orientation vector (so consecutive calls to \ the routine will start with x, then move onto y and z) RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PLS2 \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw a half-ellipse \ Deep dive: Drawing ellipses \ Drawing meridians and equators \ \ ------------------------------------------------------------------------------ \ \ Draw a half-ellipse, used for the planet's equator and meridian. \ \ ****************************************************************************** .PLS2 LDA #31 \ Set TGT = 31, so we only draw half an ellipse STA TGT \ Fall through into PLS22 to draw the half-ellipse \ ****************************************************************************** \ \ Name: PLS22 \ Type: Subroutine \ Category: Drawing planets \ Summary: Draw an ellipse or half-ellipse \ Deep dive: Drawing ellipses \ Drawing meridians and equators \ Drawing craters \ \ ------------------------------------------------------------------------------ \ \ Draw an ellipse or half-ellipse, to be used for the planet's equator and \ meridian (in which case we draw half an ellipse), or crater (in which case we \ draw a full ellipse). \ \ The ellipse is defined by a centre point, plus two conjugate radius vectors, \ u and v, where: \ \ u = [ u_x ] v = [ v_x ] \ [ u_y ] [ v_y ] \ \ The individual components of these 2D vectors (i.e. u_x, u_y etc.) are 16-bit \ sign-magnitude numbers, where the high bytes contain only the sign bit (in \ bit 7), with bits 0 to 6 being clear. This means that as we store u_x as \ (XX16 K2), for example, we know that |u_x| = K2. \ \ This routine calls BLINE to draw each line segment in the ellipse, passing the \ coordinates as follows: \ \ K6(1 0) = K3(1 0) + u_x * cos(CNT2) + v_x * sin(CNT2) \ \ K6(3 2) = K4(1 0) - u_y * cos(CNT2) - v_y * sin(CNT2) \ \ The y-coordinates are negated because BLINE expects pixel coordinates but the \ u and v vectors are extracted from the orientation vector. The y-axis runs \ in the opposite direction in 3D space to that on the screen, so we need to \ negate the 3D space coordinates before we can combine them with the ellipse's \ centre coordinates. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K(1 0) The planet's radius \ \ K3(1 0) The pixel x-coordinate of the centre of the ellipse \ \ K4(1 0) The pixel y-coordinate of the centre of the ellipse \ \ (XX16 K2) The x-component of u (i.e. u_x), where XX16 contains \ just the sign of the sign-magnitude number \ \ (XX16+1 K2+1) The y-component of u (i.e. u_y), where XX16+1 contains \ just the sign of the sign-magnitude number \ \ (XX16+2 K2+2) The x-component of v (i.e. v_x), where XX16+2 contains \ just the sign of the sign-magnitude number \ \ (XX16+3 K2+3) The y-component of v (i.e. v_y), where XX16+3 contains \ just the sign of the sign-magnitude number \ \ TGT The number of segments to draw: \ \ * 32 for a half ellipse (a meridian) \ \ * 64 for a full ellipse (a crater) \ \ CNT2 The starting segment for drawing the half-ellipse \ \ ****************************************************************************** .PLS22 LDX #0 \ Set CNT = 0 STX CNT DEX \ Set FLAG = &FF to start a new line in the ball line STX FLAG \ heap when calling BLIN below, so the crater or \ meridian is separate from any previous ellipses .PLL4 LDA CNT2 \ Set X = CNT2 mod 32 AND #31 \ TAX \ So X is the starting segment, reduced to the range 0 \ to 32, so as there are 64 segments in the circle, this \ reduces the starting angle to 0 to 180 degrees, so we \ can use X as an index into the sine table (which only \ contains values for segments 0 to 31) \ \ Also, because CNT2 mod 32 is in the range 0 to 180 \ degrees, we know that sin(CNT2 mod 32) is always \ positive, or to put it another way: \ \ sin(CNT2 mod 32) = |sin(CNT2)| LDA SNE,X \ Set Q = sin(X) STA Q \ = sin(CNT2 mod 32) \ = |sin(CNT2)| LDA K2+2 \ Set A = K2+2 \ = |v_x| JSR FMLTU \ Set R = A * Q / 256 STA R \ = |v_x| * |sin(CNT2)| LDA K2+3 \ Set A = K2+3 \ = |v_y| JSR FMLTU \ Set K = A * Q / 256 STA K \ = |v_y| * |sin(CNT2)| LDX CNT2 \ If CNT2 >= 33 then this sets the C flag, otherwise CPX #33 \ it's clear, so this means that: \ \ * C is clear if the segment starts in the first half \ of the circle, 0 to 180 degrees \ \ * C is set if the segment starts in the second half \ of the circle, 180 to 360 degrees \ \ In other words, the C flag contains the sign bit for \ sin(CNT2), which is positive for 0 to 180 degrees \ and negative for 180 to 360 degrees LDA #0 \ Shift the C flag into the sign bit of XX16+5, so ROR A \ XX16+5 has the correct sign for sin(CNT2) STA XX16+5 \ \ Because we set the following above: \ \ K = |v_y| * |sin(CNT2)| \ R = |v_x| * |sin(CNT2)| \ \ we can add XX16+5 as the high byte to give us the \ following: \ \ (XX16+5 K) = |v_y| * sin(CNT2) \ (XX16+5 R) = |v_x| * sin(CNT2) LDA CNT2 \ Set X = (CNT2 + 16) mod 32 CLC \ ADC #16 \ So we can use X as a lookup index into the SNE table AND #31 \ to get the cosine (as there are 16 segments in a TAX \ quarter-circle) \ \ Also, because the sine table only contains positive \ values, we know that sin((CNT2 + 16) mod 32) will \ always be positive, or to put it another way: \ \ sin((CNT2 + 16) mod 32) = |cos(CNT2)| LDA SNE,X \ Set Q = sin(X) STA Q \ = sin((CNT2 + 16) mod 32) \ = |cos(CNT2)| LDA K2+1 \ Set A = K2+1 \ = |u_y| JSR FMLTU \ Set K+2 = A * Q / 256 STA K+2 \ = |u_y| * |cos(CNT2)| LDA K2 \ Set A = K2 \ = |u_x| JSR FMLTU \ Set P = A * Q / 256 STA P \ = |u_x| * |cos(CNT2)| \ \ The call to FMLTU also sets the C flag, so in the \ following, ADC #15 adds 16 rather than 15 LDA CNT2 \ If (CNT2 + 16) mod 64 >= 33 then this sets the C flag, ADC #15 \ otherwise it's clear, so this means that: AND #63 \ CMP #33 \ * C is clear if the segment starts in the first or \ last quarter of the circle, 0 to 90 degrees or 270 \ to 360 degrees \ \ * C is set if the segment starts in the second or \ third quarter of the circle, 90 to 270 degrees \ \ In other words, the C flag contains the sign bit for \ cos(CNT2), which is positive for 0 to 90 degrees or \ 270 to 360 degrees, and negative for 90 to 270 degrees LDA #0 \ Shift the C flag into the sign bit of XX16+4, so: ROR A \ XX16+4 has the correct sign for cos(CNT2) STA XX16+4 \ \ Because we set the following above: \ \ K+2 = |u_y| * |cos(CNT2)| \ P = |u_x| * |cos(CNT2)| \ \ we can add XX16+4 as the high byte to give us the \ following: \ \ (XX16+4 K+2) = |u_y| * cos(CNT2) \ (XX16+4 P) = |u_x| * cos(CNT2) LDA XX16+5 \ Set S = the sign of XX16+2 * XX16+5 EOR XX16+2 \ = the sign of v_x * XX16+5 STA S \ \ So because we set this above: \ \ (XX16+5 R) = |v_x| * sin(CNT2) \ \ we now have this: \ \ (S R) = v_x * sin(CNT2) LDA XX16+4 \ Set A = the sign of XX16 * XX16+4 EOR XX16 \ = the sign of u_x * XX16+4 \ \ So because we set this above: \ \ (XX16+4 P) = |u_x| * cos(CNT2) \ \ we now have this: \ \ (A P) = u_x * cos(CNT2) JSR ADD \ Set (A X) = (A P) + (S R) \ = u_x * cos(CNT2) + v_x * sin(CNT2) STA T \ Store the high byte in T, so the result is now: \ \ (T X) = u_x * cos(CNT2) + v_x * sin(CNT2) BPL PL42 \ If the result is positive, jump down to PL42 TXA \ The result is negative, so we need to negate the EOR #%11111111 \ magnitude using two's complement, first doing the low CLC \ byte in X ADC #1 TAX LDA T \ And then the high byte in T, making sure to leave the EOR #%01111111 \ sign bit alone ADC #0 STA T .PL42 TXA \ Set K6(1 0) = K3(1 0) + (T X) ADC K3 \ STA K6 \ starting with the low bytes LDA T \ And then doing the high bytes, so we now get: ADC K3+1 \ STA K6+1 \ K6(1 0) = K3(1 0) + (T X) \ = K3(1 0) + u_x * cos(CNT2) \ + v_x * sin(CNT2) \ \ K3(1 0) is the x-coordinate of the centre of the \ ellipse, so we now have the correct x-coordinate for \ our ellipse segment that we can pass to BLINE below LDA K \ Set R = K = |v_y| * sin(CNT2) STA R LDA XX16+5 \ Set S = the sign of XX16+3 * XX16+5 EOR XX16+3 \ = the sign of v_y * XX16+5 STA S \ \ So because we set this above: \ \ (XX16+5 K) = |v_y| * sin(CNT2) \ \ and we just set R = K, we now have this: \ \ (S R) = v_y * sin(CNT2) LDA K+2 \ Set P = K+2 = |u_y| * cos(CNT2) STA P LDA XX16+4 \ Set A = the sign of XX16+1 * XX16+4 EOR XX16+1 \ = the sign of u_y * XX16+4 \ \ So because we set this above: \ \ (XX16+4 K+2) = |u_y| * cos(CNT2) \ \ and we just set P = K+2, we now have this: \ \ (A P) = u_y * cos(CNT2) JSR ADD \ Set (A X) = (A P) + (S R) \ = u_y * cos(CNT2) + v_y * sin(CNT2) EOR #%10000000 \ Store the negated high byte in T, so the result is STA T \ now: \ \ (T X) = - u_y * cos(CNT2) - v_y * sin(CNT2) \ \ This negation is necessary because BLINE expects us \ to pass pixel coordinates, where y-coordinates get \ larger as we go down the screen; u_y and v_y, on the \ other hand, are extracted from the orientation \ vectors, where y-coordinates get larger as we go up \ in space, so to rectify this we need to negate the \ result in (T X) before we can add it to the \ y-coordinate of the ellipse's centre in BLINE BPL PL43 \ If the result is positive, jump down to PL43 TXA \ The result is negative, so we need to negate the EOR #%11111111 \ magnitude using two's complement, first doing the low CLC \ byte in X ADC #1 TAX LDA T \ And then the high byte in T, making sure to leave the EOR #%01111111 \ sign bit alone ADC #0 STA T .PL43 \ We now call BLINE to draw the ellipse line segment \ \ The first few instructions of BLINE do the following: \ \ K6(3 2) = K4(1 0) + (T X) \ \ which gives: \ \ K6(3 2) = K4(1 0) - u_y * cos(CNT2) \ - v_y * sin(CNT2) \ \ K4(1 0) is the pixel y-coordinate of the centre of the \ ellipse, so this gives us the correct y-coordinate for \ our ellipse segment (we already calculated the \ x-coordinate in K3(1 0) above) JSR BLINE \ Call BLINE to draw this segment, which also returns \ the updated value of CNT in A CMP TGT \ If CNT > TGT then jump to PL40 to stop drawing the BEQ P%+4 \ ellipse (which is how we draw half-ellipses) BCS PL40 LDA CNT2 \ Set CNT2 = (CNT2 + STP) mod 64 CLC ADC STP AND #63 STA CNT2 JMP PLL4 \ Jump back to PLL4 to draw the next segment .PL40 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SUN (Part 1 of 4) \ Type: Subroutine \ Category: Drawing suns \ Summary: Draw the sun: Set up all the variables needed to draw the sun \ Deep dive: Drawing the sun \ \ ------------------------------------------------------------------------------ \ \ Draw a new sun with radius K at pixel coordinate (K3, K4), removing the old \ sun if there is one. This routine is used to draw the sun, as well as the \ star systems on the Short-range Chart. \ \ The first part sets up all the variables needed to draw the new sun. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K The new sun's radius \ \ K3(1 0) Pixel x-coordinate of the centre of the new sun \ \ K4(1 0) Pixel y-coordinate of the centre of the new sun \ \ SUNX(1 0) The x-coordinate of the vertical centre axis of the old \ sun (the one currently on-screen) \ \ ****************************************************************************** JMP WPLS \ Jump to WPLS to remove the old sun from the screen. We \ only get here via the BCS just after the SUN entry \ point below, when there is no new sun to draw .PLF3 \ This is called from below to negate X and set A to \ &FF, for when the new sun's centre is off the bottom \ of the screen (so we don't need to draw its bottom \ half) \ \ This happens when the y-coordinate of the centre of \ the sun is bigger than the y-coordinate of the bottom \ of the space view TXA \ Negate X using two's complement, so X = ~X + 1 EOR #%11111111 CLC ADC #1 TAX .PLF17 \ This is called from below to set A to &FF, for when \ the new sun's centre is right on the bottom of the \ screen (so we don't need to draw its bottom half) LDA #&FF \ Set A = &FF JMP PLF5 \ Jump to PLF5 .SUN LDA #1 \ Set LSX = 1 to indicate the sun line heap is about to STA LSX \ be filled up JSR CHKON \ Call CHKON to check whether any part of the new sun's \ circle appears on-screen, and if it does, set P(2 1) \ to the maximum y-coordinate of the new sun on-screen BCS PLF3-3 \ If CHKON set the C flag then the new sun's circle does \ not appear on-screen, so jump to WPLS (via the JMP at \ the top of this routine) to remove the sun from the \ screen, returning from the subroutine using a tail \ call LDA #0 \ Set A = 0 LDX K \ Set X = K = radius of the new sun CPX #96 \ If X >= 96, set the C flag and rotate it into bit 0 ROL A \ of A, otherwise rotate a 0 into bit 0 CPX #40 \ If X >= 40, set the C flag and rotate it into bit 0 ROL A \ of A, otherwise rotate a 0 into bit 0 CPX #16 \ If X >= 16, set the C flag and rotate it into bit 0 ROL A \ of A, otherwise rotate a 0 into bit 0 \ By now, A contains the following: \ \ * If radius is 96-255 then A = %111 = 7 \ \ * If radius is 40-95 then A = %11 = 3 \ \ * If radius is 16-39 then A = %1 = 1 \ \ * If radius is 0-15 then A = %0 = 0 \ \ The value of A determines the size of the new sun's \ ragged fringes - the bigger the sun, the bigger the \ fringes .PLF18 STA CNT \ Store the fringe size in CNT \ We now calculate the highest pixel y-coordinate of the \ new sun, given that P(2 1) contains the 16-bit maximum \ y-coordinate of the new sun on-screen LDA #2*Y-1 \ #Y is the y-coordinate of the centre of the space \ view, so this sets Y to the y-coordinate of the bottom \ of the space view LDX P+2 \ If P+2 is non-zero, the maximum y-coordinate is off BNE PLF2 \ the bottom of the screen, so skip to PLF2 with A set \ to the y-coordinate of the bottom of the space view CMP P+1 \ If A < P+1, the maximum y-coordinate is underneath the BCC PLF2 \ dashboard, so skip to PLF2 with A set to the \ y-coordinate of the bottom of the space view LDA P+1 \ Set A = P+1, the low byte of the maximum y-coordinate \ of the sun on-screen BNE PLF2 \ If A is non-zero, skip to PLF2 as it contains the \ value we are after LDA #1 \ Otherwise set A = 1, the top line of the screen .PLF2 STA TGT \ Set TGT to A, the maximum y-coordinate of the sun on \ screen \ We now calculate the number of lines we need to draw \ and the direction in which we need to draw them, both \ from the centre of the new sun LDA #2*Y-1 \ Set (A X) = y-coordinate of bottom of screen - K4(1 0) SEC \ SBC K4 \ Starting with the low bytes TAX LDA #0 \ And then doing the high bytes, so (A X) now contains SBC K4+1 \ the number of lines between the centre of the sun and \ the bottom of the screen. If it is positive then the \ centre of the sun is above the bottom of the screen, \ if it is negative then the centre of the sun is below \ the bottom of the screen BMI PLF3 \ If A < 0, then this means the new sun's centre is off \ the bottom of the screen, so jump up to PLF3 to negate \ the height in X (so it becomes positive), set A to &FF \ and jump down to PLF5 BNE PLF4 \ If A > 0, then the new sun's centre is at least a full \ screen above the bottom of the space view, so jump \ down to PLF4 to set X = radius and A = 0 INX \ Set the flags depending on the value of X DEX BEQ PLF17 \ If X = 0 (we already know A = 0 by this point) then \ jump up to PLF17 to set A to &FF before jumping down \ to PLF5 CPX K \ If X < the radius in K, jump down to PLF5, so if BCC PLF5 \ X >= the radius in K, we set X = radius and A = 0 .PLF4 LDX K \ Set X to the radius LDA #0 \ Set A = 0 .PLF5 STX V \ Store the height in V STA V+1 \ Store the direction in V+1 LDA K \ Set (A P) = K * K JSR SQUA2 STA K2+1 \ Set K2(1 0) = (A P) = K * K LDA P STA K2 \ By the time we get here, the variables should be set \ up as shown in the header for part 3 below \ ****************************************************************************** \ \ Name: SUN (Part 2 of 4) \ Type: Subroutine \ Category: Drawing suns \ Summary: Draw the sun: Start from the bottom of the screen and erase the \ old sun line by line \ Deep dive: Drawing the sun \ \ ------------------------------------------------------------------------------ \ \ This part erases the old sun, starting at the bottom of the screen and working \ upwards until we reach the bottom of the new sun. \ \ ****************************************************************************** LDY #2*Y-1 \ Set Y = y-coordinate of the bottom of the screen, \ which we use as a counter in the following routine to \ redraw the old sun LDA SUNX \ Set YY(1 0) = SUNX(1 0), the x-coordinate of the STA YY \ vertical centre axis of the old sun that's currently LDA SUNX+1 \ on-screen STA YY+1 .PLFL2 CPY TGT \ If Y = TGT, we have reached the line where we will BEQ PLFL \ start drawing the new sun, so there is no need to \ keep erasing the old one, so jump down to PLFL LDA LSO,Y \ Fetch the Y-th point from the sun line heap, which \ gives us the half-width of the old sun's line on this \ line of the screen BEQ PLF13 \ If A = 0, skip the following call to HLOIN2 as there \ is no sun line on this line of the screen JSR HLOIN2 \ Call HLOIN2 to draw a horizontal line on pixel line Y, \ with centre point YY(1 0) and half-width A, and remove \ the line from the sun line heap once done .PLF13 DEY \ Decrement the loop counter BNE PLFL2 \ Loop back for the next line in the line heap until \ we have either gone through the entire heap, or \ reached the bottom row of the new sun \ ****************************************************************************** \ \ Name: SUN (Part 3 of 4) \ Type: Subroutine \ Category: Drawing suns \ Summary: Draw the sun: Continue to move up the screen, drawing the new sun \ line by line \ Deep dive: Drawing the sun \ \ ------------------------------------------------------------------------------ \ \ This part draws the new sun. By the time we get to this point, the following \ variables should have been set up by parts 1 and 2: \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ V As we draw lines for the new sun, V contains the \ vertical distance between the line we're drawing and the \ centre of the new sun. As we draw lines and move up the \ screen, we either decrement (bottom half) or increment \ (top half) this value \ \ V+1 This determines which half of the new sun we are drawing \ as we work our way up the screen, line by line: \ \ * 0 means we are drawing the bottom half, so the lines \ get wider as we work our way up towards the centre, \ at which point we will move into the top half, and \ V+1 will switch to &FF \ \ * &FF means we are drawing the top half, so the lines \ get smaller as we work our way up, away from the \ centre \ \ TGT The maximum y-coordinate of the new sun on-screen (i.e. \ the screen y-coordinate of the bottom row of the new \ sun) \ \ CNT The fringe size of the new sun \ \ K2(1 0) The new sun's radius squared, i.e. K^2 \ \ Y The y-coordinate of the bottom row of the new sun \ \ ****************************************************************************** .PLFL LDA V \ Set (T P) = V * V JSR SQUA2 \ = V^2 STA T LDA K2 \ Set (R Q) = K^2 - V^2 SEC \ SBC P \ First calculating the low bytes STA Q LDA K2+1 \ And then doing the high bytes SBC T STA R STY Y1 \ Store Y in Y1, so we can restore it after the call to \ LL5 JSR LL5 \ Set Q = SQRT(R Q) \ = SQRT(K^2 - V^2) \ \ So Q contains the half-width of the new sun's line at \ height V from the sun's centre - in other words, it \ contains the half-width of the sun's line on the \ current pixel row Y LDY Y1 \ Restore Y from Y1 JSR DORND \ Set A and X to random numbers AND CNT \ Reduce A to a random number in the range 0 to CNT, \ where CNT is the fringe size of the new sun CLC \ Set A = A + Q ADC Q \ \ So A now contains the half-width of the sun on row \ V, plus a random variation based on the fringe size BCC PLF44 \ If the above addition did not overflow, skip the \ following instruction LDA #255 \ The above overflowed, so set the value of A to 255 \ So A contains the half-width of the new sun on pixel \ line Y, changed by a random amount within the size of \ the sun's fringe .PLF44 LDX LSO,Y \ Set X to the line heap value for the old sun's line \ at row Y STA LSO,Y \ Store the half-width of the new row Y line in the line \ heap BEQ PLF11 \ If X = 0 then there was no sun line on pixel row Y, so \ jump to PLF11 LDA SUNX \ Set YY(1 0) = SUNX(1 0), the x-coordinate of the STA YY \ vertical centre axis of the old sun that's currently LDA SUNX+1 \ on-screen STA YY+1 TXA \ Transfer the line heap value for the old sun's line \ from X into A JSR EDGES \ Call EDGES to calculate X1 and X2 for the horizontal \ line centred on YY(1 0) and with half-width A, i.e. \ the line for the old sun LDA X1 \ Store X1 and X2, the ends of the line for the old sun, STA XX \ in XX and XX+1 LDA X2 STA XX+1 LDA K3 \ Set YY(1 0) = K3(1 0), the x-coordinate of the centre STA YY \ of the new sun LDA K3+1 STA YY+1 LDA LSO,Y \ Fetch the half-width of the new row Y line from the \ line heap (which we stored above) JSR EDGES \ Call EDGES to calculate X1 and X2 for the horizontal \ line centred on YY(1 0) and with half-width A, i.e. \ the line for the new sun BCS PLF23 \ If the C flag is set, the new line doesn't fit on the \ screen, so jump to PLF23 to just draw the old line \ without drawing the new one \ At this point the old line is from XX to XX+1 and the \ new line is from X1 to X2, and both fit on-screen. We \ now want to remove the old line and draw the new one. \ We could do this by simply drawing the old one then \ drawing the new one, but instead Elite does this by \ drawing first from X1 to XX and then from X2 to XX+1, \ which you can see in action by looking at all the \ permutations below of the four points on the line and \ imagining what happens if you draw from X1 to XX and \ X2 to XX+1 using EOR logic. The six possible \ permutations are as follows, along with the result of \ drawing X1 to XX and then X2 to XX+1: \ \ X1 X2 XX____XX+1 -> +__+ + + \ \ X1 XX____X2____XX+1 -> +__+__+ + \ \ X1 XX____XX+1 X2 -> +__+__+__+ \ \ XX____X1____XX+1 X2 -> + +__+__+ \ \ XX____XX+1 X1 X2 -> + + +__+ \ \ XX____X1____X2____XX+1 -> + +__+ + \ \ They all end up with a line between X1 and X2, which \ is what we want. There's probably a mathematical proof \ of why this works somewhere, but the above is probably \ easier to follow. \ \ We can draw from X1 to XX and X2 to XX+1 by swapping \ XX and X2 and drawing from X1 to X2, and then drawing \ from XX to XX+1, so let's do this now LDA X2 \ Swap XX and X2 LDX XX STX X2 STA XX JSR HLOIN \ Draw a horizontal line from (X1, Y1) to (X2, Y1) .PLF23 \ If we jump here from the BCS above when there is no \ new line this will just draw the old line LDA XX \ Set X1 = XX STA X1 LDA XX+1 \ Set X2 = XX+1 STA X2 .PLF16 JSR HLOIN \ Draw a horizontal line from (X1, Y1) to (X2, Y1) .PLF6 DEY \ Decrement the line number in Y to move to the line \ above BEQ PLF8 \ If we have reached the top of the screen, jump to PLF8 \ as we are done drawing (the top line of the screen is \ the border, so we don't draw there) LDA V+1 \ If V+1 is non-zero then we are doing the top half of BNE PLF10 \ the new sun, so jump down to PLF10 to increment V and \ decrease the width of the line we draw DEC V \ Decrement V, the height of the sun that we use to work \ out the width, so this makes the line get wider, as we \ move up towards the sun's centre BNE PLFL \ If V is non-zero, jump back up to PLFL to do the next \ screen line up DEC V+1 \ Otherwise V is 0 and we have reached the centre of the \ sun, so decrement V+1 to -1 so we start incrementing V \ each time, thus doing the top half of the new sun .PLFLS JMP PLFL \ Jump back up to PLFL to do the next screen line up .PLF11 \ If we get here then there is no old sun line on this \ line, so we can just draw the new sun's line LDX K3 \ Set YY(1 0) = K3(1 0), the x-coordinate of the centre STX YY \ of the new sun's line LDX K3+1 STX YY+1 JSR EDGES \ Call EDGES to calculate X1 and X2 for the horizontal \ line centred on YY(1 0) and with half-width A, i.e. \ the line for the new sun BCC PLF16 \ If the line is on-screen, jump up to PLF16 to draw the \ line and loop round for the next line up LDA #0 \ The line is not on-screen, so set the line heap for STA LSO,Y \ line Y to 0, which means there is no sun line here BEQ PLF6 \ Jump up to PLF6 to loop round for the next line up \ (this BEQ is effectively a JMP as A is always zero) .PLF10 LDX V \ Increment V, the height of the sun that we use to work INX \ out the width, so this makes the line get narrower, as STX V \ we move up and away from the sun's centre CPX K \ If V <= the radius of the sun, we still have lines to BCC PLFLS \ draw, so jump up to PLFL (via PLFLS) to do the next BEQ PLFLS \ screen line up \ ****************************************************************************** \ \ Name: SUN (Part 4 of 4) \ Type: Subroutine \ Category: Drawing suns \ Summary: Draw the sun: Continue to the top of the screen, erasing the old \ sun line by line \ Deep dive: Drawing the sun \ \ ------------------------------------------------------------------------------ \ \ This part erases any remaining traces of the old sun, now that we have drawn \ all the way to the top of the new sun. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ RTS2 Contains an RTS \ \ ****************************************************************************** LDA SUNX \ Set YY(1 0) = SUNX(1 0), the x-coordinate of the STA YY \ vertical centre axis of the old sun that's currently LDA SUNX+1 \ on-screen STA YY+1 .PLFL3 LDA LSO,Y \ Fetch the Y-th point from the sun line heap, which \ gives us the half-width of the old sun's line on this \ line of the screen BEQ PLF9 \ If A = 0, skip the following call to HLOIN2 as there \ is no sun line on this line of the screen JSR HLOIN2 \ Call HLOIN2 to draw a horizontal line on pixel line Y, \ with centre point YY(1 0) and half-width A, and remove \ the line from the sun line heap once done .PLF9 DEY \ Decrement the line number in Y to move to the line \ above BNE PLFL3 \ Jump up to PLFL3 to redraw the next line up, until we \ have reached the top of the screen .PLF8 \ If we get here, we have successfully made it from the \ bottom line of the screen to the top, and the old sun \ has been replaced by the new one CLC \ Clear the C flag to indicate success in drawing the \ sun LDA K3 \ Set SUNX(1 0) = K3(1 0) STA SUNX LDA K3+1 STA SUNX+1 .RTS2 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: CIRCLE \ Type: Subroutine \ Category: Drawing circles \ Summary: Draw a circle for the planet \ Deep dive: Drawing circles \ \ ------------------------------------------------------------------------------ \ \ Draw a circle with the centre at (K3, K4) and radius K. Used to draw the \ planet's main outline. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K The planet's radius \ \ K3(1 0) Pixel x-coordinate of the centre of the planet \ \ K4(1 0) Pixel y-coordinate of the centre of the planet \ \ ****************************************************************************** .CIRCLE JSR CHKON \ Call CHKON to check whether the circle fits on-screen BCS RTS2 \ If CHKON set the C flag then the circle does not fit \ on-screen, so return from the subroutine (as RTS2 \ contains an RTS) LDA #0 \ Set LSX2 = 0 to indicate that the ball line heap is STA LSX2 \ not empty, as we are about to fill it LDX K \ Set X = K = radius LDA #8 \ Set A = 8 CPX #8 \ If the radius < 8, skip to PL89 BCC PL89 LSR A \ Halve A so A = 4 CPX #60 \ If the radius < 60, skip to PL89 BCC PL89 LSR A \ Halve A so A = 2 .PL89 STA STP \ Set STP = A. STP is the step size for the circle, so \ the above sets a smaller step size for bigger circles \ Fall through into CIRCLE2 to draw the circle with the \ correct step size \ ****************************************************************************** \ \ Name: CIRCLE2 \ Type: Subroutine \ Category: Drawing circles \ Summary: Draw a circle (for the planet or chart) \ Deep dive: Drawing circles \ \ ------------------------------------------------------------------------------ \ \ Draw a circle with the centre at (K3, K4) and radius K. Used to draw the \ planet and the chart circles. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ STP The step size for the circle \ \ K The circle's radius \ \ K3(1 0) Pixel x-coordinate of the centre of the circle \ \ K4(1 0) Pixel y-coordinate of the centre of the circle \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag The C flag is cleared \ \ ****************************************************************************** .CIRCLE2 LDX #&FF \ Set FLAG = &FF to reset the ball line heap in the call STX FLAG \ to the BLINE routine below INX \ Set CNT = 0, our counter that goes up to 64, counting STX CNT \ segments in our circle .PLL3 LDA CNT \ Set A = CNT JSR FMLTU2 \ Call FMLTU2 to calculate: \ \ A = K * sin(A) \ = K * sin(CNT) LDX #0 \ Set T = 0, so we have the following: STX T \ \ (T A) = K * sin(CNT) \ \ which is the x-coordinate of the circle for this count LDX CNT \ If CNT < 33 then jump to PL37, as this is the right CPX #33 \ half of the circle and the sign of the x-coordinate is BCC PL37 \ correct EOR #%11111111 \ This is the left half of the circle, so we want to ADC #0 \ flip the sign of the x-coordinate in (T A) using two's TAX \ complement, so we start with the low byte and store it \ in X (the ADC adds 1 as we know the C flag is set) LDA #&FF \ And then we flip the high byte in T ADC #0 STA T TXA \ Finally, we restore the low byte from X, so we have \ now negated the x-coordinate in (T A) CLC \ Clear the C flag so we can do some more addition below .PL37 ADC K3 \ We now calculate the following: STA K6 \ \ K6(1 0) = (T A) + K3(1 0) \ \ to add the coordinates of the centre to our circle \ point, starting with the low bytes LDA K3+1 \ And then doing the high bytes, so we now have: ADC T \ STA K6+1 \ K6(1 0) = K * sin(CNT) + K3(1 0) \ \ which is the result we want for the x-coordinate LDA CNT \ Set A = CNT + 16 CLC ADC #16 JSR FMLTU2 \ Call FMLTU2 to calculate: \ \ A = K * sin(A) \ = K * sin(CNT + 16) \ = K * cos(CNT) TAX \ Set X = A \ = K * cos(CNT) LDA #0 \ Set T = 0, so we have the following: STA T \ \ (T X) = K * cos(CNT) \ \ which is the y-coordinate of the circle for this count LDA CNT \ Set A = (CNT + 15) mod 64 ADC #15 AND #63 CMP #33 \ If A < 33 (i.e. CNT is 0-16 or 48-64) then jump to BCC PL38 \ PL38, as this is the bottom half of the circle and the \ sign of the y-coordinate is correct TXA \ This is the top half of the circle, so we want to EOR #%11111111 \ flip the sign of the y-coordinate in (T X) using two's ADC #0 \ complement, so we start with the low byte in X (the TAX \ ADC adds 1 as we know the C flag is set) LDA #&FF \ And then we flip the high byte in T, so we have ADC #0 \ now negated the y-coordinate in (T X) STA T CLC \ Clear the C flag so the addition at the start of BLINE \ will work .PL38 JSR BLINE \ Call BLINE to draw this segment, which also increases \ CNT by STP, the step size CMP #65 \ If CNT >= 65 then skip the next instruction BCS P%+5 JMP PLL3 \ Jump back for the next segment CLC \ Clear the C flag to indicate success RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: WPLS2 \ Type: Subroutine \ Category: Drawing planets \ Summary: Remove the planet from the screen \ Deep dive: The ball line heap \ \ ------------------------------------------------------------------------------ \ \ We do this by redrawing it using the lines stored in the ball line heap when \ the planet was originally drawn by the BLINE routine. \ \ ****************************************************************************** .WPLS2 LDY LSX2 \ If LSX2 is non-zero (which indicates the ball line BNE WP1 \ heap is empty), jump to WP1 to reset the line heap \ without redrawing the planet \ Otherwise Y is now 0, so we can use it as a counter to \ loop through the lines in the line heap, redrawing \ each one to remove the planet from the screen, before \ resetting the line heap once we are done .WPL1 CPY LSP \ If Y >= LSP then we have reached the end of the line BCS WP1 \ heap and have finished redrawing the planet (as LSP \ points to the end of the heap), so jump to WP1 to \ reset the line heap, returning from the subroutine \ using a tail call LDA LSY2,Y \ Set A to the y-coordinate of the current heap entry CMP #&FF \ If the y-coordinate is &FF, this indicates that the BEQ WP2 \ next point in the heap denotes the start of a line \ segment, so jump to WP2 to put it into (X1, Y1) STA Y2 \ Set (X2, Y2) to the x- and y-coordinates from the LDA LSX2,Y \ heap STA X2 JSR LOIN \ Draw a line from (X1, Y1) to (X2, Y2) INY \ Increment the loop counter to point to the next point LDA SWAP \ If SWAP is non-zero then we swapped the coordinates BNE WPL1 \ when filling the heap in BLINE, so loop back WPL1 \ for the next point in the heap LDA X2 \ Swap (X1, Y1) and (X2, Y2), so the next segment will STA X1 \ be drawn from the current (X2, Y2) to the next point LDA Y2 \ in the heap STA Y1 JMP WPL1 \ Loop back to WPL1 for the next point in the heap .WP2 INY \ Increment the loop counter to point to the next point LDA LSX2,Y \ Set (X1, Y1) to the x- and y-coordinates from the STA X1 \ heap LDA LSY2,Y STA Y1 INY \ Increment the loop counter to point to the next point JMP WPL1 \ Loop back to WPL1 for the next point in the heap \ ****************************************************************************** \ \ Name: WP1 \ Type: Subroutine \ Category: Drawing planets \ Summary: Reset the ball line heap \ \ ****************************************************************************** .WP1 LDA #1 \ Set LSP = 1 to reset the ball line heap pointer STA LSP LDA #&FF \ Set LSX2 = &FF to indicate the ball line heap is empty STA LSX2 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: WPLS \ Type: Subroutine \ Category: Drawing suns \ Summary: Remove the sun from the screen \ Deep dive: Drawing the sun \ \ ------------------------------------------------------------------------------ \ \ We do this by redrawing it using the lines stored in the sun line heap when \ the sun was originally drawn by the SUN routine. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ SUNX(1 0) The x-coordinate of the vertical centre axis of the sun \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ WPLS-1 Contains an RTS \ \ ****************************************************************************** .WPLS LDA LSX \ If LSX < 0, the sun line heap is empty, so return from BMI WPLS-1 \ the subroutine (as WPLS-1 contains an RTS) LDA SUNX \ Set YY(1 0) = SUNX(1 0), the x-coordinate of the STA YY \ vertical centre axis of the sun that's currently on LDA SUNX+1 \ screen STA YY+1 LDY #2*Y-1 \ #Y is the y-coordinate of the centre of the space \ view, so this sets Y as a counter for the number of \ lines in the space view (i.e. 191), which is also the \ number of lines in the LSO block .WPL2 LDA LSO,Y \ Fetch the Y-th point from the sun line heap, which \ gives us the half-width of the sun's line on this line \ of the screen BEQ P%+5 \ If A = 0, skip the following call to HLOIN2 as there \ is no sun line on this line of the screen JSR HLOIN2 \ Call HLOIN2 to draw a horizontal line on pixel line Y, \ with centre point YY(1 0) and half-width A, and remove \ the line from the sun line heap once done DEY \ Decrement the loop counter BNE WPL2 \ Loop back for the next line in the line heap until \ we have gone through the entire heap DEY \ This sets Y to &FF, as we end the loop with Y = 0 STY LSX \ Set LSX to &FF to indicate the sun line heap is empty RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: EDGES \ Type: Subroutine \ Category: Drawing lines \ Summary: Draw a horizontal line given a centre and a half-width \ \ ------------------------------------------------------------------------------ \ \ Set X1 and X2 to the x-coordinates of the ends of the horizontal line with \ centre x-coordinate YY(1 0), and length A in either direction from the centre \ (so a total line length of 2 * A). In other words, this line: \ \ X1 YY(1 0) X2 \ +-----------------+-----------------+ \ <- A -> <- A -> \ \ The resulting line gets clipped to the edges of the screen, if needed. If the \ calculation doesn't overflow, we return with the C flag clear, otherwise the C \ flag gets set to indicate failure and the Y-th LSO entry gets set to 0. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The half-length of the line \ \ YY(1 0) The centre x-coordinate \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Clear if the line fits on-screen, set if it doesn't \ \ X1, X2 The x-coordinates of the clipped line \ \ LSO+Y If the line doesn't fit, LSO+Y is set to 0 \ \ Y Y is preserved \ \ ****************************************************************************** .EDGES STA T \ Set T to the line's half-length in argument A CLC \ We now calculate: ADC YY \ STA X2 \ (A X2) = YY(1 0) + A \ \ to set X2 to the x-coordinate of the right end of the \ line, starting with the low bytes LDA YY+1 \ And then adding the high bytes ADC #0 BMI ED1 \ If the addition is negative then the calculation has \ overflowed, so jump to ED1 to return a failure BEQ P%+6 \ If the high byte A from the result is 0, skip the \ next two instructions, as the result already fits on \ the screen LDA #254 \ The high byte is positive and non-zero, so we went STA X2 \ past the right edge of the screen, so clip X2 to the \ x-coordinate of the right edge of the screen LDA YY \ We now calculate: SEC \ SBC T \ (A X1) = YY(1 0) - argument A STA X1 \ \ to set X1 to the x-coordinate of the left end of the \ line, starting with the low bytes LDA YY+1 \ And then subtracting the high bytes SBC #0 BNE ED3 \ If the high byte subtraction is non-zero, then skip \ to ED3 CLC \ Otherwise the high byte of the subtraction was zero, \ so the line fits on-screen and we clear the C flag to \ indicate success RTS \ Return from the subroutine .ED3 BPL ED1 \ If the addition is positive then the calculation has \ underflowed, so jump to ED1 to return a failure LDA #2 \ The high byte is negative and non-zero, so we went STA X1 \ past the left edge of the screen, so clip X1 to the \ x-coordinate of the left edge of the screen CLC \ The line does fit on-screen, so clear the C flag to \ indicate success RTS \ Return from the subroutine .ED1 LDA #0 \ Set the Y-th byte of the LSO block to 0 STA LSO,Y SEC \ The line does not fit on the screen, so set the C flag \ to indicate this result RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: CHKON \ Type: Subroutine \ Category: Drawing circles \ Summary: Check whether any part of a circle appears on the extended screen \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K The circle's radius \ \ K3(1 0) Pixel x-coordinate of the centre of the circle \ \ K4(1 0) Pixel y-coordinate of the centre of the circle \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Clear if any part of the circle appears on-screen, set \ if none of the circle appears on-screen \ \ (A X) Minimum y-coordinate of the circle on-screen (i.e. the \ y-coordinate of the top edge of the circle) \ \ P(2 1) Maximum y-coordinate of the circle on-screen (i.e. the \ y-coordinate of the bottom edge of the circle) \ \ ****************************************************************************** .CHKON LDA K3 \ Set A = K3 + K CLC ADC K LDA K3+1 \ Set A = K3+1 + 0 + any carry from above, so this ADC #0 \ effectively sets A to the high byte of K3(1 0) + K: \ \ (A ?) = K3(1 0) + K \ \ so A is the high byte of the x-coordinate of the right \ edge of the circle BMI PL21 \ If A is negative then the right edge of the circle is \ to the left of the screen, so jump to PL21 to set the \ C flag and return from the subroutine, as the whole \ circle is off-screen to the left LDA K3 \ Set A = K3 - K SEC SBC K LDA K3+1 \ Set A = K3+1 - 0 - any carry from above, so this SBC #0 \ effectively sets A to the high byte of K3(1 0) - K: \ \ (A ?) = K3(1 0) - K \ \ so A is the high byte of the x-coordinate of the left \ edge of the circle BMI PL31 \ If A is negative then the left edge of the circle is \ to the left of the screen, and we already know the \ right edge is either on-screen or off-screen to the \ right, so skip to PL31 to move on to the y-coordinate \ checks, as at least part of the circle is on-screen in \ terms of the x-axis BNE PL21 \ If A is non-zero, then the left edge of the circle is \ to the right of the screen, so jump to PL21 to set the \ C flag and return from the subroutine, as the whole \ circle is off-screen to the right .PL31 LDA K4 \ Set P+1 = K4 + K CLC ADC K STA P+1 LDA K4+1 \ Set A = K4+1 + 0 + any carry from above, so this ADC #0 \ does the following: \ \ (A P+1) = K4(1 0) + K \ \ so A is the high byte of the y-coordinate of the \ bottom edge of the circle BMI PL21 \ If A is negative then the bottom edge of the circle is \ above the top of the screen, so jump to PL21 to set \ the C flag and return from the subroutine, as the \ whole circle is off-screen to the top STA P+2 \ Store the high byte in P+2, so now we have: \ \ P(2 1) = K4(1 0) + K \ \ i.e. the maximum y-coordinate of the circle on-screen \ (which we return) LDA K4 \ Set X = K4 - K SEC SBC K TAX LDA K4+1 \ Set A = K4+1 - 0 - any carry from above, so this SBC #0 \ does the following: \ \ (A X) = K4(1 0) - K \ \ so A is the high byte of the y-coordinate of the top \ edge of the circle BMI PL44 \ If A is negative then the top edge of the circle is \ above the top of the screen, and we already know the \ bottom edge is either on-screen or below the bottom \ of the screen, so skip to PL44 to clear the C flag and \ return from the subroutine using a tail call, as part \ of the circle definitely appears on-screen BNE PL21 \ If A is non-zero, then the top edge of the circle is \ below the bottom of the screen, so jump to PL21 to set \ the C flag and return from the subroutine, as the \ whole circle is off-screen to the bottom CPX #2*Y-1 \ If we get here then A is zero, which means the top \ edge of the circle is within the screen boundary, so \ now we need to check whether it is in the space view \ (in which case it is on-screen) or the dashboard (in \ which case the top of the circle is hidden by the \ dashboard, so the circle isn't on-screen). We do this \ by checking the low byte of the result in X against \ 2 * #Y - 1, and returning the C flag from this \ comparison. The constant #Y is the y-coordinate of the \ mid-point of the space view, so 2 * #Y - 1, the \ y-coordinate of the bottom pixel row of the space \ view. So this does the following: \ \ * The C flag is set if coordinate (A X) is below the \ bottom row of the space view, i.e. the top edge of \ the circle is hidden by the dashboard \ \ * The C flag is clear if coordinate (A X) is above \ the bottom row of the space view, i.e. the top \ edge of the circle is on-screen RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PL21 \ Type: Subroutine \ Category: Drawing planets \ Summary: Return from a planet/sun-drawing routine with a failure flag \ \ ------------------------------------------------------------------------------ \ \ Set the C flag and return from the subroutine. This is used to return from a \ planet- or sun-drawing routine with the C flag indicating an overflow in the \ calculation. \ \ ****************************************************************************** .PL21 SEC \ Set the C flag to indicate an overflow RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PLS3 \ Type: Subroutine \ Category: Drawing planets \ Summary: Calculate (Y A P) = 222 * roofv_x / z \ \ ------------------------------------------------------------------------------ \ \ Calculate the following, with X determining the vector to use: \ \ (Y A P) = 222 * roofv_x / z \ \ though in reality only (Y A) is used. \ \ Although the code below supports a range of values of X, in practice the \ routine is only called with X = 15, and then again after X has been \ incremented to 17. So the values calculated by PLS1 use roofv_x first, then \ roofv_y. The comments below refer to roofv_x, for the first call. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X Determines which of the INWK orientation vectors to \ divide: \ \ * X = 15: divides roofv_x \ \ * X = 17: divides roofv_y \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ X X gets incremented by 2 so it points to the next \ coordinate in this orientation vector (so consecutive \ calls to the routine will start with x, then move onto y \ and then z) \ \ ****************************************************************************** .PLS3 JSR PLS1 \ Call PLS1 to calculate the following: STA P \ \ P = |roofv_x / z| \ K+3 = sign of roofv_x / z \ \ and increment X to point to roofv_y for the next call LDA #222 \ Set Q = 222, the offset to the crater STA Q STX U \ Store the vector index X in U for retrieval after the \ call to MULTU JSR MULTU \ Call MULTU to calculate \ \ (A P) = P * Q \ = 222 * |roofv_x / z| LDX U \ Restore the vector index from U into X LDY K+3 \ If the sign of the result in K+3 is positive, skip to BPL PL12 \ PL12 to return with Y = 0 EOR #&FF \ Otherwise the result should be negative, so negate the CLC \ high byte of the result using two's complement with ADC #1 \ A = ~A + 1 BEQ PL12 \ If A = 0, jump to PL12 to return with (Y A) = 0 LDY #&FF \ Set Y = &FF to be a negative high byte RTS \ Return from the subroutine .PL12 LDY #0 \ Set Y = 0 to be a positive high byte RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PLS4 \ Type: Subroutine \ Category: Drawing planets \ Summary: Calculate CNT2 = arctan(P / A) / 4 \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ CNT2 = arctan(P / A) / 4 \ \ and do the following if nosev_z_hi >= 0: \ \ CNT2 = CNT2 + 32 \ \ which is the equivalent of adding 180 degrees to the result (or PI radians), \ as there are 64 segments in a full circle. \ \ This routine is called with the following arguments when calculating the \ equator and meridian for planets: \ \ * A = roofv_z_hi, P = -nosev_z_hi \ \ * A = sidev_z_hi, P = -nosev_z_hi \ \ So it calculates the angle between the planet's orientation vectors, in the \ z-axis. \ \ ****************************************************************************** .PLS4 STA Q \ Set Q = A JSR ARCTAN \ Call ARCTAN to calculate: \ \ A = arctan(P / Q) \ arctan(P / A) \ \ The result in A will be in the range 0 to 128, which \ represents an angle of 0 to 180 degrees (or 0 to PI \ radians) LDX INWK+14 \ If nosev_z_hi is negative, skip the following BMI P%+4 \ instruction to leave the angle in A as a positive \ integer in the range 0 to 128 (so when we calculate \ CNT2 below, it will be in the right half of the \ anti-clockwise arc that we describe when drawing \ circles, i.e. from 6 o'clock, through 3 o'clock and \ on to 12 o'clock) EOR #%10000000 \ If we get here then nosev_z_hi is positive, so flip \ bit 7 of the angle in A, which is the same as adding \ 128 to give a result in the range 129 to 256 (i.e. 129 \ to 0), or 180 to 360 degrees (so when we calculate \ CNT2 below, it will be in the left half of the \ anti-clockwise arc that we describe when drawing \ circles, i.e. from 12 o'clock, through 9 o'clock and \ on to 6 o'clock) LSR A \ Set CNT2 = A / 4 LSR A STA CNT2 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PLS5 \ Type: Subroutine \ Category: Drawing planets \ Summary: Calculate roofv_x / z and roofv_y / z \ \ ------------------------------------------------------------------------------ \ \ Calculate the following divisions of a specified value from one of the \ orientation vectors (in this example, roofv): \ \ (XX16+2 K2+2) = roofv_x / z \ \ (XX16+3 K2+3) = roofv_y / z \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X Determines which of the INWK orientation vectors to \ divide: \ \ * X = 15: divides roofv_x and roofv_y \ \ * X = 21: divides sidev_x and sidev_y \ \ INWK The planet's ship data block \ \ ****************************************************************************** .PLS5 JSR PLS1 \ Call PLS1 to calculate the following: STA K2+2 \ STY XX16+2 \ K+2 = |roofv_x / z| \ XX16+2 = sign of roofv_x / z \ \ i.e. (XX16+2 K2+2) = roofv_x / z \ \ and increment X to point to roofv_y for the next call JSR PLS1 \ Call PLS1 to calculate the following: STA K2+3 \ STY XX16+3 \ K+3 = |roofv_y / z| \ XX16+3 = sign of roofv_y / z \ \ i.e. (XX16+3 K2+3) = roofv_y / z \ \ and increment X to point to roofv_z for the next call RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: PLS6 \ Type: Subroutine \ Category: Drawing planets \ Summary: Calculate (X K) = (A P+1 P) / (z_sign z_hi z_lo) \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ (X K) = (A P+1 P) / (z_sign z_hi z_lo) \ \ returning an overflow in the C flag if the result is >= 1024. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ INWK The planet or sun's ship data block \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Set if the result >= 1024, clear otherwise \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ PL44 Clear the C flag and return from the subroutine \ \ ****************************************************************************** .PLS6 JSR DVID3B2 \ Call DVID3B2 to calculate: \ \ K(3 2 1 0) = (A P+1 P) / (z_sign z_hi z_lo) LDA K+3 \ Set A = |K+3| OR K+2 AND #%01111111 ORA K+2 BNE PL21 \ If A is non-zero then the two high bytes of K(3 2 1 0) \ are non-zero, so jump to PL21 to set the C flag and \ return from the subroutine \ We can now just consider K(1 0), as we know the top \ two bytes of K(3 2 1 0) are both 0 LDX K+1 \ Set X = K+1, so now (X K) contains the result in \ K(1 0), which is the format we want to return the \ result in CPX #4 \ If the high byte of K(1 0) >= 4 then the result is BCS PL6 \ >= 1024, so return from the subroutine with the C flag \ set to indicate an overflow (as PL6 contains an RTS) LDA K+3 \ Fetch the sign of the result from K+3 (which we know \ has zeroes in bits 0-6, so this just fetches the sign) \CLC \ This instruction is commented out in the original \ source. It would have no effect as we know the C flag \ is already clear, as we skipped past the BCS above BPL PL6 \ If the sign bit is clear and the result is positive, \ then the result is already correct, so return from \ the subroutine with the C flag clear to indicate \ success (as PL6 contains an RTS) LDA K \ Otherwise we need to negate the result, which we do EOR #%11111111 \ using two's complement, starting with the low byte: ADC #1 \ STA K \ K = ~K + 1 TXA \ And then the high byte: EOR #%11111111 \ ADC #0 \ X = ~X TAX .PL44 CLC \ Clear the C flag to indicate success .PL6 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT17 \ Type: Subroutine \ Category: Keyboard \ Summary: Scan the keyboard for cursor key or joystick movement \ \ ------------------------------------------------------------------------------ \ \ Scan the keyboard and joystick for cursor key or stick movement, and return \ the result as deltas (changes) in x- and y-coordinates as follows: \ \ * For joystick, X and Y are integers between -2 and +2 depending on how far \ the stick has moved \ \ * For keyboard, X and Y are integers between -1 and +1 depending on which \ keys are pressed \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A The key pressed, if the arrow keys were used \ \ X Change in the x-coordinate according to the cursor keys \ being pressed or joystick movement, as an integer (see \ above) \ \ Y Change in the y-coordinate according to the cursor keys \ being pressed or joystick movement, as an integer (see \ above) \ \ ****************************************************************************** .TT17 JSR DOKEY \ Scan the keyboard for flight controls and pause keys, \ (or the equivalent on joystick) and update the key \ logger, setting KL to the key pressed LDA JSTK \ If the joystick is not configured, jump down to TJ1, BEQ TJ1 \ otherwise we move the cursor with the joystick LDA JSTX \ Fetch the joystick roll, ranging from 1 to 255 with \ 128 as the centre point EOR #&FF \ Flip the sign so A = -JSTX, because the joystick roll \ works in the opposite way to moving a cursor on-screen \ in terms of left and right JSR TJS1 \ Call TJS1 just below to set A to a value between -2 \ and +2 depending on the joystick roll value (moving \ the stick sideways) TYA \ Copy Y to A TAX \ Copy A to X, so X contains the joystick roll value LDA JSTY \ Fetch the joystick pitch, ranging from 1 to 255 with \ 128 as the centre point, and fall through into TJS1 to \ set Y to the joystick pitch value (moving the stick up \ and down) .TJS1 TAY \ Store A in Y LDA #0 \ Set the result, A = 0 CPY #16 \ If Y >= 16 set the C flag, so A = A - 1 SBC #0 \CPY #&20 \ These instructions are commented out in the original \SBC #0 \ source, but they would make the joystick move the \ cursor faster by increasing the range of Y by -1 to +1 CPY #64 \ If Y >= 64 set the C flag, so A = A - 1 SBC #0 CPY #192 \ If Y >= 192 set the C flag, so A = A + 1 ADC #0 CPY #224 \ If Y >= 224 set the C flag, so A = A + 1 ADC #0 \CPY #&F0 \ These instructions are commented out in the original \ADC #0 \ source, but they would make the joystick move the \ cursor faster by increasing the range of Y by -1 to +1 TAY \ Copy the value of A into Y LDA KL \ Set A to the value of KL (the key pressed) RTS \ Return from the subroutine .TJ1 LDA KL \ Set A to the value of KL (the key pressed) LDX #0 \ Set the initial values for the results, X = Y = 0, LDY #0 \ which we now increase or decrease appropriately CMP #&19 \ If left arrow was pressed, set X = X - 1 BNE P%+3 DEX CMP #&79 \ If right arrow was pressed, set X = X + 1 BNE P%+3 INX CMP #&39 \ If up arrow was pressed, set Y = Y + 1 BNE P%+3 INY CMP #&29 \ If down arrow was pressed, set Y = Y - 1 BNE P%+3 DEY RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: ping \ Type: Subroutine \ Category: Universe \ Summary: Set the selected system to the current system \ \ ****************************************************************************** .ping LDX #1 \ We want to copy the X- and Y-coordinates of the \ current system in (QQ0, QQ1) to the selected system's \ coordinates in (QQ9, QQ10), so set up a counter to \ copy two bytes .pl1 LDA QQ0,X \ Load byte X from the current system in QQ0/QQ1 STA QQ9,X \ Store byte X in the selected system in QQ9/QQ10 DEX \ Decrement the loop counter BPL pl1 \ Loop back for the next byte to copy RTS \ Return from the subroutine \ ****************************************************************************** \ \ Save ELTE.bin \ \ ****************************************************************************** PRINT "ELITE E" PRINT "Assembled at ", ~CODE_E% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_E%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_E% PRINT "S.ELTE ", ~CODE_E%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_E% SAVE "3-assembled-output/ELTE.bin", CODE_E%, P%, LOAD% \ ****************************************************************************** \ \ ELITE F FILE \ \ Produces the binary file ELTF.bin that gets loaded by elite-bcfs.asm. \ \ ****************************************************************************** CODE_F% = P% LOAD_F% = LOAD% + P% - CODE% \ ****************************************************************************** \ \ Name: KS3 \ Type: Subroutine \ Category: Universe \ Summary: Set the SLSP ship line heap pointer after shuffling ship slots \ \ ------------------------------------------------------------------------------ \ \ The final part of the KILLSHP routine, called after we have shuffled the ship \ slots and sorted out our missiles. This simply sets SLSP to the new bottom of \ the ship line heap. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ P(1 0) Points to the ship line heap of the ship in the last \ occupied slot (i.e. it points to the bottom of the \ descending heap) \ \ ****************************************************************************** .KS3 LDA P \ After shuffling the ship slots, P(1 0) will point to STA SLSP \ the new bottom of the ship line heap, so store this in LDA P+1 \ SLSP(1 0), which stores the bottom of the heap STA SLSP+1 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: KS1 \ Type: Subroutine \ Category: Universe \ Summary: Remove the current ship from our local bubble of universe \ \ ------------------------------------------------------------------------------ \ \ Part 12 of the main flight loop calls this routine to remove the ship that is \ currently being analysed by the flight loop. Once the ship is removed, it \ jumps back to MAL1 to rejoin the main flight loop, with X pointing to the \ same slot that we just cleared (and which now contains the next ship in the \ local bubble of universe). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ XX0 The address of the blueprint for this ship \ \ INF The address of the data block for this ship \ \ ****************************************************************************** .KS1 LDX XSAV \ Fetch the current ship's slot number from XSAV JSR KILLSHP \ Call KILLSHP to remove the ship in slot X from our \ local bubble of universe LDX XSAV \ Restore the current ship's slot number from XSAV, \ which now points to the next ship in the bubble JMP MAL1 \ Jump to MAL1 to rejoin the main flight loop at the \ start of the ship analysis loop \ ****************************************************************************** \ \ Name: KS4 \ Type: Subroutine \ Category: Universe \ Summary: Remove the space station and replace it with the sun \ \ ****************************************************************************** .KS4 JSR ZINF \ Call ZINF to reset the INWK ship workspace JSR FLFLLS \ Reset the LSO block, returns with A = 0 STA FRIN+1 \ Set the second slot in the FRIN table to 0, which \ sets this slot to empty, so when we call NWSHP below \ the new sun that gets created will go into FRIN+1 STA SSPR \ Set the "space station present" flag to 0, as we are \ no longer in the space station's safe zone JSR SPBLB \ Call SPBLB to redraw the space station bulb, which \ will erase it from the dashboard LDA #6 \ Set the sun's y_sign to 6 STA INWK+5 LDA #129 \ Set A = 129, the ship type for the sun JMP NWSHP \ Call NWSHP to set up the sun's data block and add it \ to FRIN, where it will get put in the second slot as \ we just cleared out the second slot, and the first \ slot is already taken by the planet \ ****************************************************************************** \ \ Name: KS2 \ Type: Subroutine \ Category: Universe \ Summary: Check the local bubble for missiles with target lock \ \ ------------------------------------------------------------------------------ \ \ Check the local bubble of universe to see if there are any missiles with \ target lock in the vicinity. If there are, then check their targets; if we \ just removed their target in the KILLSHP routine, then switch off their AI so \ they just drift in space, otherwise update their targets to reflect the newly \ shuffled slot numbers. \ \ This is called from KILLSHP once the slots have been shuffled down, following \ the removal of a ship. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ XX4 The slot number of the ship we removed just before \ calling this routine \ \ ****************************************************************************** .KS2 LDX #&FF \ We want to go through the ships in our local bubble \ and pick out all the missiles, so set X to &FF to \ use as a counter .KSL4 INX \ Increment the counter (so it starts at 0 on the first \ iteration) LDA FRIN,X \ If slot X is empty then we have worked our way through BEQ KS3 \ all the slots, so jump to KS3 to stop looking CMP #MSL \ If the slot does not contain a missile, loop back to BNE KSL4 \ KSL4 to check the next slot \ We have found a slot containing a missile, so now we \ want to check whether it has target lock TXA \ Set Y = X * 2 and fetch the Y-th address from UNIV ASL A \ and store it in SC and SC+1 - in other words, set TAY \ SC(1 0) to point to the missile's ship data block LDA UNIV,Y STA SC LDA UNIV+1,Y STA SC+1 LDY #32 \ Fetch byte #32 from the missile's ship data (AI) LDA (SC),Y BPL KSL4 \ If bit 7 of byte #32 is clear, then the missile is \ dumb and has no AI, so loop back to KSL4 to move on \ to the next slot AND #%01111111 \ Otherwise this missile has AI, so clear bit 7 and LSR A \ shift right to set the C flag to the missile's "is \ locked" flag, and A to the target's slot number CMP XX4 \ If this missile's target is less than XX4, then the BCC KSL4 \ target's slot isn't being shuffled down, so jump to \ KSL4 to move on to the next slot BEQ KS6 \ If this missile was locked onto the ship that we just \ removed in KILLSHP, jump to KS6 to stop the missile \ from continuing to hunt it down SBC #1 \ Otherwise this missile is locked and has AI enabled, \ and its target will have moved down a slot, so \ subtract 1 from the target number (we know C is set \ from the BCC above) ASL A \ Shift the target number left by 1, so it's in bits \ 1-6 once again, and also set bit 0 to 1, as the C \ flag is still set, so this makes sure the missile is \ still set to being locked ORA #%10000000 \ Set bit 7, so the missile's AI is enabled STA (SC),Y \ Update the missile's AI flag to the value in A BNE KSL4 \ Loop back to KSL4 to move on to the next slot (this \ BNE is effectively a JMP as A will never be zero) .KS6 LDA #0 \ The missile's target lock just got removed, so set the STA (SC),Y \ AI flag to 0 to make it dumb and not locked BEQ KSL4 \ Loop back to KSL4 to move on to the next slot (this \ BEQ is effectively a JMP as A is always zero) \ ****************************************************************************** \ \ Name: KILLSHP \ Type: Subroutine \ Category: Universe \ Summary: Remove a ship from our local bubble of universe \ \ ------------------------------------------------------------------------------ \ \ Remove the ship in slot X from our local bubble of universe. This happens \ when we kill a ship, collide with a ship and destroy it, or when a ship moves \ outside our local bubble. \ \ We also use this routine when we move out of range of the space station, in \ which case we replace it with the sun. \ \ When removing a ship, this creates a gap in the ship slots at FRIN, so we \ shuffle all the later slots down to close the gap. We also shuffle the ship \ data blocks at K% and ship line heap at WP, to reclaim all the memory that \ the removed ship used to occupy. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The slot number of the ship to remove \ \ XX0 The address of the blueprint for the ship to remove \ \ INF The address of the data block for the ship to remove \ \ ****************************************************************************** .KILLSHP STX XX4 \ Store the slot number of the ship to remove in XX4 IF _SOURCE_DISC LDA MSTG \ Check whether this slot matches the slot number in CMP XX4 \ MSTG, which is the target of our missile lock ELIF _TEXT_SOURCES OR _STH_CASSETTE CPX MSTG \ Check whether this slot matches the slot number in \ MSTG, which is the target of our missile lock \ \ This instructions saves two bytes of memory over the \ LDA and CMP-based code in the source disc version, as \ CPX MSTG is a two-byte opcode, while LDA MSTG and \ CMP XX4 take up four bytes between them (the code does \ the same thing) ENDIF BNE KS5 \ If our missile is not locked on this ship, jump to KS5 LDY #&EE \ Otherwise we need to remove our missile lock, so call JSR ABORT \ ABORT to disarm the missile and update the missile \ indicators on the dashboard to green/cyan (Y = &EE) LDA #200 \ Print recursive token 40 ("TARGET LOST") as an JSR MESS \ in-flight message .KS5 LDY XX4 \ Restore the slot number of the ship to remove into Y LDX FRIN,Y \ Fetch the contents of the slot, which contains the \ ship type CPX #SST \ If this is the space station, then jump to KS4 to BEQ KS4 \ replace the space station with the sun DEC MANY,X \ Decrease the number of this type of ship in our little \ bubble, which is stored in MANY+X (where X is the ship \ type) LDX XX4 \ Restore the slot number of the ship to remove into X \ We now want to remove this ship and reclaim all the \ memory that it uses. Removing the ship will leave a \ gap in three places, which we need to close up: \ \ * The ship slots in FRIN \ \ * The ship data blocks in K% \ \ * The descending ship line heap at WP down \ \ The rest of this routine closes up these gaps by \ looping through all the occupied ship slots after the \ slot we are removing, one by one, and shuffling each \ ship's slot, data block and line heap down to close \ up the gaps left by the removed ship. As part of this, \ we have to make sure we update any address pointers \ so they point to the newly shuffled data blocks and \ line heaps \ \ In the following, when shuffling a ship's data down \ into the preceding empty slot, we call the ship that \ we are shuffling down the "source", and we call the \ empty slot we are shuffling it into the "destination" \ \ Before we start looping through the ships we need to \ shuffle down, we need to set up some variables to \ point to the source and destination line heaps LDY #5 \ Fetch byte #5 of the removed ship's blueprint into A, LDA (XX0),Y \ which gives the ship's maximum heap size for the ship \ we are removing (i.e. the size of the gap in the heap \ created by the ship removal) \ INF currently contains the ship data for the ship we \ are removing, and INF(34 33) contains the address of \ the bottom of the ship's heap, so we can calculate \ the address of the top of the heap by adding the heap \ size to this address LDY #33 \ First we add A and the address in INF+33, to get the CLC \ low byte of the top of the heap, which we store in P ADC (INF),Y STA P INY \ And next we add A and the address in INF+34, with any LDA (INF),Y \ carry from the previous addition, to get the high byte ADC #0 \ of the top of the heap, which we store in P+1, so STA P+1 \ P(1 0) points to the top of this ship's heap \ Now, we're ready to start looping through the ships \ we want to move, moving the slots, data blocks and \ line heap from the source to the destination. In the \ following, we set up SC to point to the source data, \ and INF (which currently points to the removed ship's \ data that we can now overwrite) points to the \ destination \ \ So P(1 0) now points to the top of the line heap for \ the destination .KSL1 INX \ On entry, X points to the empty slot we want to \ shuffle the next ship into (the destination), so \ this increment points X to the next slot - i.e. the \ source slot we want to shuffle down LDA FRIN,X \ Copy the contents of the source slot into the STA FRIN-1,X \ destination slot BEQ KS2 \ If the slot we just shuffled down contains 0, then \ the source slot is empty and we are done shuffling, \ so jump to KS2 to move on to processing missiles ASL A \ Otherwise we have a source ship to shuffle down into TAY \ the destination, so set Y = A * 2 so it can act as an \ index into the two-byte ship blueprint lookup table \ at XX21 for the source ship LDA XX21-2,Y \ Set SC(0 1) to point to the blueprint data for the STA SC \ source ship LDA XX21-1,Y STA SC+1 LDY #5 \ Fetch blueprint byte #5 for the source ship, which LDA (SC),Y \ gives us its maximum heap size, and store it in T STA T \ We now subtract T from P(1 0), so P(1 0) will point to \ the bottom of the line heap for the destination \ (which we will use later when closing up the gap in \ the heap space) LDA P \ First, we subtract the low bytes SEC SBC T STA P LDA P+1 \ And then we do the high bytes, for which we subtract SBC #0 \ 0 to include any carry, so this is effectively doing STA P+1 \ P(1 0) = P(1 0) - (0 T) \ Next, we want to set SC(1 0) to point to the source \ ship's data block TXA \ Set Y = X * 2 so it can act as an index into the ASL A \ two-byte lookup table at UNIV, which contains the TAY \ addresses of the ship data blocks. In this case we are \ multiplying X by 2, and X contains the source ship's \ slot number so Y is now an index for the source ship's \ entry in UNIV LDA UNIV,Y \ Set SC(1 0) to the address of the data block for the STA SC \ source ship LDA UNIV+1,Y STA SC+1 \ We have now set up our variables as follows: \ \ SC(1 0) points to the source's ship data block \ \ INF(1 0) points to the destination's ship data block \ \ P(1 0) points to the destination's line heap \ \ so let's start copying data from the source to the \ destination LDY #35 \ We are going to be using Y as a counter for the 36 \ bytes of ship data we want to copy from the source \ to the destination, so we set it to 35 to start things \ off, and will decrement Y for each byte we copy LDA (SC),Y \ Fetch byte #35 of the source's ship data block at SC, STA (INF),Y \ and store it in byte #35 of the destination's block \ at INF, so that's the ship's energy copied from the \ source to the destination. One down, quite a few to \ go... DEY \ Fetch byte #34 of the source ship, which is the LDA (SC),Y \ high byte of the source ship's line heap, and store STA K+1 \ in K+1 LDA P+1 \ Set the low byte of the destination's heap pointer STA (INF),Y \ to P+1 DEY \ Fetch byte #33 of the source ship, which is the LDA (SC),Y \ low byte of the source ship's heap, and store in K STA K \ so now we have the following: \ \ K(1 0) points to the source's line heap LDA P \ Set the low byte of the destination's heap pointer STA (INF),Y \ to P, so now the destination's heap pointer is to \ P(1 0), so that's the heap pointer in bytes #33 and \ #34 done DEY \ Luckily, we can just copy the rest of the source's \ ship data block into the destination, as there are no \ more address pointers, so first we decrement our \ counter in Y to point to the next byte (the AI flag) \ in byte #32) and then start looping .KSL2 LDA (SC),Y \ Copy the Y-th byte of the source to the Y-th byte of STA (INF),Y \ the destination DEY \ Decrement the counter BPL KSL2 \ Loop back to KSL2 to copy the next byte until we have \ copied the whole block \ We have now shuffled the ship's slot and the ship's \ data block, so we only have the heap data itself to do LDA SC \ First, we copy SC into INF, so when we loop round STA INF \ again, INF will correctly point to the destination for LDA SC+1 \ the next iteration STA INF+1 LDY T \ Now we want to move the contents of the heap, as all \ we did above was to update the pointers, so first \ we set a counter in Y that is initially set to T \ (which we set above to the maximum heap size for the \ source ship) \ \ As a reminder, we have already set the following: \ \ K(1 0) points to the source's line heap \ \ P(1 0) points to the destination's line heap \ \ so we can move the heap data by simply copying the \ correct number of bytes from K(1 0) to P(1 0) .KSL3 DEY \ Decrement the counter LDA (K),Y \ Copy the Y-th byte of the source heap at K(1 0) to STA (P),Y \ the destination heap at P(1 0) TYA \ Loop back to KSL3 to copy the next byte, until we BNE KSL3 \ have done them all BEQ KSL1 \ We have now shuffled everything down one slot, so \ jump back up to KSL1 to see if there is another slot \ that needs shuffling down (this BEQ is effectively a \ JMP as A will always be zero) \ ****************************************************************************** \ \ Name: SFX \ Type: Variable \ Category: Sound \ Summary: Sound data \ \ ------------------------------------------------------------------------------ \ \ Sound data. To make a sound, the NOS1 routine copies the four relevant sound \ bytes to XX16, and NO3 then makes the sound. The sound numbers are shown in \ the table, and are always multiples of 8. Generally, sounds are made by \ calling the NOISE routine with the sound number in A. \ \ These bytes are passed to OSWORD 7, and are the equivalents to the parameters \ passed to the SOUND keyword in BASIC. The parameters therefore have these \ meanings: \ \ channel/flush, amplitude (or envelope number if 1-4), pitch, duration \ \ For the channel/flush parameter, the high nibble of the low byte is the flush \ control (where a flush control of 0 queues the sound, and a flush control of \ 1 makes the sound instantly), while the low nibble of the low byte is the \ channel number. When written in hexadecimal, the first figure gives the flush \ control, while the second is the channel (so &13 indicates flush control = 1 \ and channel = 3). \ \ So when we call NOISE with A = 40 to make a long, low beep, then this is \ effectively what the NOISE routine does: \ \ SOUND &13, &F4, &0C, &08 \ \ which makes a sound with flush control 1 on channel 3, and with amplitude &F4 \ (-12), pitch &0C (2) and duration &08 (8). Meanwhile, to make the hyperspace \ sound, the NOISE routine does this: \ \ SOUND &10, &02, &60, &10 \ \ which makes a sound with flush control 1 on channel 0, using envelope 2, \ and with pitch &60 (96) and duration &10 (16). The four sound envelopes (1-4) \ are set up by the loading process. \ \ ****************************************************************************** .SFX EQUB &12, &01, &00, &10 \ 0 - Lasers fired by us EQUB &12, &02, &2C, &08 \ 8 - We're being hit by lasers EQUB &11, &03, &F0, &18 \ 16 - We died 1 / We made a hit or kill 2 EQUB &10, &F1, &07, &1A \ 24 - We died 2 / We made a hit or kill 1 EQUB &03, &F1, &BC, &01 \ 32 - Short, high beep EQUB &13, &F4, &0C, &08 \ 40 - Long, low beep EQUB &10, &F1, &06, &0C \ 48 - Missile launched / Ship launched from station EQUB &10, &02, &60, &10 \ 56 - Hyperspace drive engaged EQUB &13, &04, &C2, &FF \ 64 - E.C.M. on EQUB &13, &00, &00, &00 \ 72 - E.C.M. off \ ****************************************************************************** \ \ Name: RESET \ Type: Subroutine \ Category: Start and end \ Summary: Reset most variables \ \ ------------------------------------------------------------------------------ \ \ Reset our ship and various controls, recharge shields and energy, and then \ fall through into RES2 to reset the stardust and the ship workspace at INWK. \ \ In this subroutine, this means zero-filling the following locations: \ \ * Pages &9, &A, &B, &C and &D \ \ * BETA to BETA+6, which covers the following: \ \ * BETA, BET1 - Set pitch to 0 \ \ * XC, YC - Set text cursor to (0, 0) \ \ * QQ22 - Set hyperspace counters to 0 \ \ * ECMA - Turn E.C.M. off \ \ It also sets QQ12 to &FF, to indicate we are docked, recharges the shields and \ energy banks, and then falls through into RES2. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ RES4 Reset the shields and energy banks, then fall through \ into RES2 to reset the stardust and the ship workspace \ at INWK \ \ ****************************************************************************** .RESET JSR ZERO \ Zero-fill pages &9, &A, &B, &C and &D, which clears \ the ship data blocks, the ship line heap, the ship \ slots for the local bubble of universe, and various \ flight and ship status variables LDX #6 \ Set up a counter for zeroing BETA through BETA+6 .SAL3 STA BETA,X \ Zero the X-th byte after BETA DEX \ Decrement the loop counter BPL SAL3 \ Loop back for the next byte to zero STX QQ12 \ X is now negative - i.e. &FF - so this sets QQ12 to \ &FF to indicate we are docked \ We now fall through into RES4 to restore shields and \ energy, and reset the stardust and ship workspace at \ INWK .RES4 LDA #&FF \ Set A to &FF so we can fill up the shields and energy \ bars with a full charge LDX #2 \ We're now going to recharge both shields and the \ energy bank, which live in the three bytes at FSH, \ ASH (FSH+1) and ENERGY (FSH+2), so set a loop counter \ in X for 3 bytes .REL5 STA FSH,X \ Set the X-th byte of FSH to &FF to charge up that \ shield/bank DEX \ Decrement the loop counter BPL REL5 \ Loop back to REL5 until we have recharged both shields \ and the energy bank \ Fall through into RES2 to reset the stardust and ship \ workspace at INWK \ ****************************************************************************** \ \ Name: RES2 \ Type: Subroutine \ Category: Start and end \ Summary: Reset a number of flight variables and workspaces \ \ ------------------------------------------------------------------------------ \ \ This is called after we launch from a space station, arrive in a new system \ after hyperspace, launch an escape pod, or die a cold, lonely death in the \ depths of space. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Y Y is set to &FF \ \ ****************************************************************************** .RES2 LDA #NOST \ Reset NOSTM, the number of stardust particles, to the STA NOSTM \ maximum allowed (18) LDX #&FF \ Reset LSX2 and LSY2, the ball line heaps used by the STX LSX2 \ BLINE routine for drawing circles, to &FF, to set the STX LSY2 \ heap to empty STX MSTG \ Reset MSTG, the missile target, to &FF (no target) LDA #128 \ Set the current pitch rate to the mid-point, 128 STA JSTY STA ALP2 \ Reset ALP2 (roll sign) and BET2 (pitch sign) STA BET2 \ to negative, i.e. pitch and roll negative ASL A \ This sets A to 0 STA ALP2+1 \ Reset ALP2+1 (flipped roll sign) and BET2+1 (flipped STA BET2+1 \ pitch sign) to positive, i.e. pitch and roll negative STA MCNT \ Reset MCNT (the main loop counter) to 0 LDA #3 \ Reset DELTA (speed) to 3 STA DELTA STA ALPHA \ Reset ALPHA (roll angle alpha) to 3 STA ALP1 \ Reset ALP1 (magnitude of roll angle alpha) to 3 LDA SSPR \ Fetch the "space station present" flag, and if we are BEQ P%+5 \ not inside the safe zone, skip the next instruction JSR SPBLB \ Light up the space station bulb on the dashboard LDA ECMA \ Fetch the E.C.M. status flag, and if E.C.M. is off, BEQ yu \ skip the next instruction JSR ECMOF \ Turn off the E.C.M. sound .yu JSR WPSHPS \ Wipe all ships from the scanner JSR ZERO \ Zero-fill pages &9, &A, &B, &C and &D, which clears \ the ship data blocks, the ship line heap, the ship \ slots for the local bubble of universe, and various \ flight and ship status variables LDA #LO(WP-1) \ We have reset the ship line heap, so we now point STA SLSP \ SLSP to the byte before the WP workspace to indicate LDA #HI(WP-1) \ that the heap is empty STA SLSP+1 JSR DIALS \ Update the dashboard \ Finally, fall through into ZINF to reset the INWK \ ship workspace \ ****************************************************************************** \ \ Name: ZINF \ Type: Subroutine \ Category: Universe \ Summary: Reset the INWK workspace and orientation vectors \ Deep dive: Orientation vectors \ \ ------------------------------------------------------------------------------ \ \ Zero-fill the INWK ship workspace and reset the orientation vectors, with \ nosev pointing out of the screen, towards us. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Y Y is set to &FF \ \ ****************************************************************************** .ZINF LDY #NI%-1 \ There are NI% bytes in the INWK workspace, so set a \ counter in Y so we can loop through them LDA #0 \ Set A to 0 so we can zero-fill the workspace .ZI1 STA INWK,Y \ Zero the Y-th byte of the INWK workspace DEY \ Decrement the loop counter BPL ZI1 \ Loop back for the next byte, ending when we have \ zero-filled the last byte at INWK, which leaves Y \ with a value of &FF \ Finally, we reset the orientation vectors as follows: \ \ sidev = (1, 0, 0) \ roofv = (0, 1, 0) \ nosev = (0, 0, -1) \ \ 96 * 256 (&6000) represents 1 in the orientation \ vectors, while -96 * 256 (&E000) represents -1. We \ already set the vectors to zero above, so we just \ need to set up the high bytes of the diagonal values \ and we're done. The negative nosev makes the ship \ point towards us, as the z-axis points into the screen LDA #96 \ Set A to represent a 1 (in vector terms) STA INWK+18 \ Set byte #18 = roofv_y_hi = 96 = 1 STA INWK+22 \ Set byte #22 = sidev_x_hi = 96 = 1 ORA #%10000000 \ Flip the sign of A to represent a -1 STA INWK+14 \ Set byte #14 = nosev_z_hi = -96 = -1 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: msblob \ Type: Subroutine \ Category: Dashboard \ Summary: Display the dashboard's missile indicators in green \ \ ------------------------------------------------------------------------------ \ \ Display the dashboard's missile indicators, with all the missiles reset to \ green/cyan (i.e. not armed or locked). \ \ ****************************************************************************** .msblob LDX #4 \ Set up a loop counter in X to count through all four \ missile indicators .ss CPX NOMSL \ If the counter is equal to the number of missiles, BEQ SAL8 \ jump down to SAL8 to draw the remaining missiles, as \ the rest of them are present and should be drawn in \ green/cyan LDY #0 \ Draw the missile indicator at position X in black JSR MSBAR DEX \ Decrement the counter to point to the next missile BNE ss \ Loop back to ss if we still have missiles to draw RTS \ Return from the subroutine .SAL8 LDY #&EE \ Draw the missile indicator at position X in green/cyan JSR MSBAR DEX \ Decrement the counter to point to the next missile BNE SAL8 \ Loop back to SAL8 if we still have missiles to draw RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: me2 \ Type: Subroutine \ Category: Flight \ Summary: Remove an in-flight message from the space view \ \ ****************************************************************************** .me2 LDA MCH \ Fetch the token number of the current message into A JSR MESS \ Call MESS to print the token, which will remove it \ from the screen as printing uses EOR logic LDA #0 \ Set the delay in DLY to 0, so any new in-flight STA DLY \ messages will be shown instantly JMP me3 \ Jump back into the main spawning loop at me3 \ ****************************************************************************** \ \ Name: Ze \ Type: Subroutine \ Category: Universe \ Summary: Initialise the INWK workspace to a fairly aggressive ship \ Deep dive: Fixing ship positions \ Aggression and hostility in ship tactics \ \ ------------------------------------------------------------------------------ \ \ Specifically, this routine does the following: \ \ * Reset the INWK ship workspace \ \ * Set the ship to a fair distance away in all axes, in front of us but \ randomly up or down, left or right \ \ * Give the ship a 4% chance of having E.C.M. \ \ * Set the ship's aggression level to at least 32 out of 63, with AI enabled \ \ This routine also sets A, X, T1 and the C flag to random values. \ \ Note that because this routine uses the value of X returned by DORND, and X \ contains the value of A returned by the previous call to DORND, this routine \ does not necessarily set the new ship to a totally random location. \ \ ****************************************************************************** .Ze JSR ZINF \ Call ZINF to reset the INWK ship workspace JSR DORND \ Set A and X to random numbers STA T1 \ Store A in T1 AND #%10000000 \ Extract the sign of A and store in x_sign STA INWK+2 TXA \ Extract the sign of X and store in y_sign AND #%10000000 STA INWK+5 LDA #32 \ Set x_hi = y_hi = z_hi = 32, a fair distance away STA INWK+1 STA INWK+4 STA INWK+7 TXA \ Set the C flag if X >= 245 (4% chance) CMP #245 ROL A \ Set bit 0 of A to the C flag (i.e. there's a 4% \ chance of this ship having E.C.M.) ORA #%11000000 \ Set bits 6 and 7 of A, so the ship has AI (bit 7) and \ an aggression level of at least 32 out of 63 STA INWK+32 \ Store A in the AI flag of this ship \ Fall through into DORND2 to set A, X and the C flag \ randomly \ ****************************************************************************** \ \ Name: DORND \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Generate random numbers \ Deep dive: Generating random numbers \ Fixing ship positions \ \ ------------------------------------------------------------------------------ \ \ Set A and X to random numbers (though note that X is set to the random number \ that was returned in A the last time DORND was called). \ \ The C and V flags are also set randomly. \ \ If we want to generate a repeatable sequence of random numbers, when \ generating explosion clouds, for example, then we call DORND2 to ensure that \ the value of the C flag on entry doesn't affect the outcome, as otherwise we \ might not get the same sequence of numbers if the C flag changes. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ DORND2 Make sure the C flag doesn't affect the outcome \ \ ****************************************************************************** .DORND2 CLC \ Clear the C flag so the value of the C flag on entry \ doesn't affect the outcome .DORND LDA RAND \ Calculate the next two values f2 and f3 in the feeder ROL A \ sequence: TAX \ ADC RAND+2 \ * f2 = (f1 << 1) mod 256 + C flag on entry STA RAND \ * f3 = f0 + f2 + (1 if bit 7 of f1 is set) STX RAND+2 \ * C flag is set according to the f3 calculation LDA RAND+1 \ Calculate the next value m2 in the main sequence: TAX \ ADC RAND+3 \ * A = m2 = m0 + m1 + C flag from feeder calculation STA RAND+1 \ * X = m1 STX RAND+3 \ * C and V flags set according to the m2 calculation RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: Main game loop (Part 1 of 6) \ Type: Subroutine \ Category: Main loop \ Summary: Spawn a trader (a peaceful Cobra Mk III) \ Deep dive: Program flow of the main game loop \ Ship data blocks \ Aggression and hostility in ship tactics \ \ ------------------------------------------------------------------------------ \ \ This is part of the main game loop. This is where the core loop of the game \ lives, and it's in two parts. The shorter loop (just parts 5 and 6) is \ iterated when we are docked, while the entire loop from part 1 to 6 iterates \ if we are in space. \ \ This section covers the following: \ \ * Spawn a trader, i.e. a Cobra Mk III with AI disabled, a 50% chance of it \ having an E.C.M., a speed between 16 and 31, a random aggression level \ and a gentle clockwise roll \ \ We call this from within the main loop, with A set to a random number. \ \ ****************************************************************************** .MTT4 LSR A \ Clear bit 7 of our random number in A and set the C \ flag to bit 0 of A, which is random STA INWK+32 \ Store this in the ship's AI flag, so this ship does \ not have AI STA INWK+29 \ Store A in the ship's roll counter, giving it a \ clockwise roll (as bit 7 is clear), and a 1 in 127 \ chance of it having no damping ROL INWK+31 \ This instruction would appear to set bit 0 of the \ ship's missile count randomly (as the C flag was set), \ giving the ship either no missiles or one missile \ \ However, INWK+31 is overwritten in the call to the \ NWSHP routine below, where it is set to the number of \ missiles from the ship blueprint, and the value of the \ C flag is not used, so this instruction actually has \ no effect \ \ Interestingly, the original source code for the NWSPS \ routine also has an instruction that sets INWK+31 and \ which gets overwritten when it falls through into \ NWSHP, but in this case the instruction is commented \ out in the source. Perhaps the original version of \ NWSHP didn't set the missile count and instead relied \ on the calling code to set it, and when the authors \ changed it, they commented out the INWK+31 instruction \ in NWSPS and forgot about this one. Who knows? AND #31 \ Set the ship speed to our random number, set to a ORA #16 \ minimum of 16 and a maximum of 31 STA INWK+27 LDA #CYL \ Add a new Cobra Mk III to the local bubble and fall JSR NWSHP \ through into the main game loop again \ ****************************************************************************** \ \ Name: Main game loop (Part 2 of 6) \ Type: Subroutine \ Category: Main loop \ Summary: Call the main flight loop, and potentially spawn a trader, an \ asteroid, or a cargo canister \ Deep dive: Program flow of the main game loop \ Ship data blocks \ Fixing ship positions \ \ ------------------------------------------------------------------------------ \ \ This section covers the following: \ \ * Call M% to do the main flight loop \ \ * Potentially spawn a trader, asteroid or cargo canister \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TT100 The entry point for the start of the main game loop, \ which calls the main flight loop and the moves into the \ spawning routine \ \ me3 Used by me2 to jump back into the main game loop after \ printing an in-flight message \ \ ****************************************************************************** .TT100 JSR M% \ Call M% to iterate through the main flight loop DEC DLY \ Decrement the delay counter in DLY, so any in-flight \ messages get removed once the counter reaches zero BEQ me2 \ If DLY is now 0, jump to me2 to remove any in-flight \ message from the space view, and once done, return to \ me3 below, skipping the following two instructions BPL me3 \ If DLY is positive, jump to me3 to skip the next \ instruction INC DLY \ If we get here, DLY is negative, so we have gone too \ and need to increment DLY back to 0 .me3 DEC MCNT \ Decrement the main loop counter in MCNT BEQ P%+5 \ If the counter has reached zero, which it will do \ every 256 main loops, skip the next JMP instruction \ (or to put it another way, if the counter hasn't \ reached zero, jump down to MLOOP, skipping all the \ following checks) .ytq JMP MLOOP \ Jump down to MLOOP to do some end-of-loop tidying and \ restart the main loop \ We only get here once every 256 iterations of the \ main loop. If we aren't in witchspace and don't \ already have 3 or more asteroids in our local bubble, \ then this section has a 13% chance of spawning \ something benign (the other 87% of the time we jump \ down to consider spawning cops, pirates and bounty \ hunters) \ \ If we are in that 13%, then 50% of the time this will \ be a trader, and the other 50% of the time it will \ either be an asteroid (98.5% chance) or, very rarely, \ a cargo canister (1.5% chance) LDA MJ \ If we are in witchspace following a mis-jump, skip the BNE ytq \ following by jumping down to MLOOP (via ytq above) JSR DORND \ Set A and X to random numbers CMP #35 \ If A >= 35 (87% chance), jump down to MTT1 to skip BCS MTT1 \ the spawning of an asteroid or cargo canister and \ potentially spawn something else LDA MANY+AST \ If we already have 3 or more asteroids in the local CMP #3 \ bubble, jump down to MTT1 to skip the following and BCS MTT1 \ potentially spawn something else JSR ZINF \ Call ZINF to reset the INWK ship workspace LDA #38 \ Set z_hi = 38 (far away) STA INWK+7 JSR DORND \ Set A, X and C flag to random numbers STA INWK \ Set x_lo = random STX INWK+3 \ Set y_lo = random \ \ Note that because we use the value of X returned by \ DORND, and X contains the value of A returned by the \ previous call to DORND, this does not set the new ship \ to a totally random location AND #%10000000 \ Set x_sign = bit 7 of x_lo STA INWK+2 TXA \ Set y_sign = bit 7 of y_lo AND #%10000000 STA INWK+5 ROL INWK+1 \ Set bit 1 of x_hi to the C flag, which is random, so ROL INWK+1 \ this randomly moves us off-centre by 512 (as if x_hi \ is %00000010, then (x_hi x_lo) is 512 + x_lo) JSR DORND \ Set A, X and V flag to random numbers BVS MTT4 \ If V flag is set (50% chance), jump up to MTT4 to \ spawn a trader ORA #%01101111 \ Take the random number in A and set bits 0-3 and 5-6, STA INWK+29 \ so the result has a 50% chance of being positive or \ negative, and a 50% chance of bits 0-6 being 127. \ Storing this number in the roll counter therefore \ gives our new ship a fast roll speed with a 50% \ chance of having no damping, plus a 50% chance of \ rolling clockwise or anti-clockwise LDA SSPR \ If we are inside the space station safe zone, jump BNE MTT1 \ down to MTT1 to skip the following and potentially \ spawn something else TXA \ Set A to the random X we set above, which we haven't BCS MTT2 \ used yet, and if the C flag is set (50% chance) jump \ down to MTT2 to skip the following AND #31 \ Set the ship speed to our random number, set to a ORA #16 \ minimum of 16 and a maximum of 31 STA INWK+27 BCC MTT3 \ Jump down to MTT3, skipping the following (this BCC \ is effectively a JMP as we know the C flag is clear, \ having passed through the BCS above) .MTT2 ORA #%01111111 \ Set bits 0-6 of A to 127, leaving bit 7 as random, so STA INWK+30 \ storing this number in the pitch counter means we have \ full pitch with no damping, with a 50% chance of \ pitching up or down .MTT3 JSR DORND \ Set A and X to random numbers CMP #5 \ Set A to the ship number of an asteroid, and keep LDA #AST \ this value for 98.5% of the time (i.e. if random BCS P%+4 \ A >= 5 then skip the following instruction) LDA #OIL \ Set A to the ship number of a cargo canister JSR NWSHP \ Add our new asteroid or canister to the universe \ ****************************************************************************** \ \ Name: Main game loop (Part 3 of 6) \ Type: Subroutine \ Category: Main loop \ Summary: Potentially spawn a cop, particularly if we've been bad \ Deep dive: Program flow of the main game loop \ Ship data blocks \ Fixing ship positions \ \ ------------------------------------------------------------------------------ \ \ This section covers the following: \ \ * Potentially spawn a cop (in a Viper), very rarely if we have been good, \ more often if have been naughty, and very often if we have been properly \ bad \ \ ****************************************************************************** .MTT1 LDA SSPR \ If we are inside the space station's safe zone, jump BNE MLOOP \ to MLOOP to skip the following JSR BAD \ Call BAD to work out how much illegal contraband we \ are carrying in our hold (A is up to 40 for a \ standard hold crammed with contraband, up to 70 for \ an extended cargo hold full of narcotics and slaves) ASL A \ Double A to a maximum of 80 or 140 LDX MANY+COPS \ If there are no cops in the local bubble, skip the BEQ P%+5 \ next instruction ORA FIST \ There are cops in the vicinity and we've got a hold \ full of jail time, so OR the value in A with FIST to \ get a new value that is at least as high as both \ values, to reflect the fact that they have almost \ certainly scanned our ship STA T \ Store our badness level in T JSR Ze \ Call Ze to initialise INWK to a fairly aggressive \ ship, and set A and X to random values \ \ Note that because Ze uses the value of X returned by \ DORND, and X contains the value of A returned by the \ previous call to DORND, this does not set the new ship \ to a totally random location CMP T \ If the random value in A >= our badness level, which BCS P%+7 \ will be the case unless we have been really, really \ bad, then skip the following two instructions (so \ if we are really bad, there's a higher chance of \ spawning a cop, otherwise we got away with it, for \ now) LDA #COPS \ Add a new police ship to the local bubble JSR NWSHP LDA MANY+COPS \ If we now have at least one cop in the local bubble, BNE MLOOP \ jump down to MLOOP, otherwise fall through into the \ next part to look at spawning something else \ ****************************************************************************** \ \ Name: Main game loop (Part 4 of 6) \ Type: Subroutine \ Category: Main loop \ Summary: Potentially spawn a lone bounty hunter, a Thargoid, or up to four \ pirates \ Deep dive: Program flow of the main game loop \ Ship data blocks \ Fixing ship positions \ Aggression and hostility in ship tactics \ \ ------------------------------------------------------------------------------ \ \ This section covers the following: \ \ * Potentially spawn (35% chance) either a lone bounty hunter (a Mamba, \ Python or Cobra Mk III), a Thargoid, or a group of up to 4 pirates \ (Sidewinders and/or Mambas) \ \ ****************************************************************************** DEC EV \ Decrement EV, the extra vessels spawning delay, and BPL MLOOP \ jump to MLOOP if it is still positive, so we only \ do the following when the EV counter runs down INC EV \ EV is negative, so bump it up again, setting it back \ to 0 JSR DORND \ Set A and X to random numbers LDY gov \ If the government of this system is 0 (anarchy), jump BEQ LABEL_2 \ straight to LABEL_2 to start spawning pirates or a \ lone bounty hunter CMP #90 \ If the random number in A >= 90 (65% chance), jump to BCS MLOOP \ MLOOP to stop spawning (so there's a 35% chance of \ spawning pirates or a lone bounty hunter) AND #7 \ Reduce the random number in A to the range 0-7, and CMP gov \ if A is less than government of this system, jump BCC MLOOP \ to MLOOP to stop spawning (so safer governments with \ larger gov numbers have a greater chance of jumping \ out, which is another way of saying that more \ dangerous systems spawn pirates and bounty hunters \ more often) .LABEL_2 \ Now to spawn a lone bounty hunter, a Thargoid or a \ group of pirates JSR Ze \ Call Ze to initialise INWK to a fairly aggressive \ ship, and set A and X to random values \ \ Note that because Ze uses the value of X returned by \ DORND, and X contains the value of A returned by the \ previous call to DORND, this does not set the new ship \ to a totally random location CMP #200 \ If the random number in A >= 200 (13% chance), jump BCS mt1 \ to mt1 to spawn pirates, otherwise keep going to \ spawn a lone bounty hunter or a Thargoid INC EV \ Increase the extra vessels spawning counter, to \ prevent the next attempt to spawn extra vessels AND #3 \ Set A = Y = random number in the range 3-6, which ADC #3 \ we will use to determine the type of ship TAY \ We now build the AI flag for this ship in A TXA \ First, copy the random number in X to A CMP #200 \ First, set the C flag if X >= 200 (22% chance) ROL A \ Set bit 0 of A to the C flag (i.e. there's a 22% \ chance of this ship having E.C.M.) ORA #%11000000 \ Set bits 6 and 7 of A, so the ship has AI (bit 7) and \ an aggression level of at least 32 out of 63 CPY #6 \ If Y = 6 (i.e. a Thargoid), jump down to the tha BEQ tha \ routine in part 6 to decide whether or not to spawn it \ (where there's a 22% chance of this happening) STA INWK+32 \ Store A in the AI flag of this ship TYA \ Add a new ship of type Y to the local bubble, so JSR NWSHP \ that's a Mamba, Cobra Mk III or Python .mj1 JMP MLOOP \ Jump down to MLOOP, as we are done spawning ships .mt1 AND #3 \ It's time to spawn a group of pirates, so set A to a \ random number in the range 0-3, which will be the \ loop counter for spawning pirates below (so we will \ spawn 1-4 pirates) STA EV \ Delay further spawnings by this number STA XX13 \ Store the number in XX13, the pirate counter .mt3 JSR DORND \ Set A and X to random numbers AND #3 \ Set A to a random number in the range 0-3 ORA #1 \ Set A to %01 or %11 (Sidewinder or Mamba) JSR NWSHP \ Try adding a new ship of type A to the local bubble DEC XX13 \ Decrement the pirate counter BPL mt3 \ If we need more pirates, loop back up to mt3, \ otherwise we are done spawning, so fall through into \ the end of the main loop at MLOOP \ ****************************************************************************** \ \ Name: Main game loop (Part 5 of 6) \ Type: Subroutine \ Category: Main loop \ Summary: Cool down lasers, make calls to update the dashboard \ Deep dive: Program flow of the main game loop \ The dashboard indicators \ \ ------------------------------------------------------------------------------ \ \ This is the first half of the minimal game loop, which we iterate when we are \ docked. This section covers the following: \ \ * Cool down lasers \ \ * Make calls to update the dashboard \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ MLOOP The entry point for the main game loop. This entry point \ comes after the call to the main flight loop and \ spawning routines, so it marks the start of the main \ game loop for when we are docked (as we don't need to \ call the main flight loop or spawning routines if we \ aren't in space) \ \ ****************************************************************************** .MLOOP LDA #%00000001 \ Set 6522 System VIA interrupt enable register IER STA VIA+&4E \ (SHEILA &4E) bit 1 (i.e. disable the CA2 interrupt, \ which comes from the keyboard) LDX #&FF \ Set the stack pointer to &01FF, which is the standard TXS \ location for the 6502 stack, so this instruction \ effectively resets the stack LDX GNTMP \ If the laser temperature in GNTMP is non-zero, BEQ EE20 \ decrement it (i.e. cool it down a bit) DEC GNTMP .EE20 JSR DIALS \ Call DIALS to update the dashboard LDA QQ11 \ If this is a space view, skip the following four BEQ P%+11 \ instructions (i.e. jump to JSR TT17 below) AND PATG \ If PATG = &FF (author names are shown on start-up) LSR A \ and bit 0 of QQ11 is 1 (the current view is type 1), BCS P%+5 \ then skip the following instruction JSR DELAY-5 \ Wait for 8/50 of a second (0.16 seconds), to slow the \ main loop down a bit JSR TT17 \ Scan the keyboard for the cursor keys or joystick, \ returning the cursor's delta values in X and Y and \ the key pressed in A \ ****************************************************************************** \ \ Name: Main game loop (Part 6 of 6) \ Type: Subroutine \ Category: Main loop \ Summary: Process non-flight key presses (red function keys, docked keys) \ Deep dive: Program flow of the main game loop \ \ ------------------------------------------------------------------------------ \ \ This is the second half of the minimal game loop, which we iterate when we are \ docked. This section covers the following: \ \ * Process more key presses (red function keys, docked keys etc.) \ \ It also supports joining the main loop with a key already "pressed", so we can \ jump into the main game loop to perform a specific action. In practice, this \ is used when we enter the docking bay in BAY to display Status Mode (red key \ f8), and when we finish buying or selling cargo in BAY2 to jump to the \ Inventory (red key f9). \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ FRCE The entry point for the main game loop if we want to \ jump straight to a specific screen, by pretending to \ "press" a key, in which case A contains the internal key \ number of the key we want to "press" \ \ tha Consider spawning a Thargoid (22% chance) \ \ ****************************************************************************** .FRCE JSR TT102 \ Call TT102 to process the key pressed in A LDA QQ12 \ Fetch the docked flag from QQ12 into A BNE MLOOP \ If we are docked, loop back up to MLOOP just above \ to restart the main loop, but skipping all the flight \ and spawning code in the top part of the main loop JMP TT100 \ Otherwise jump to TT100 to restart the main loop from \ the start .tha JSR DORND \ Set A and X to random numbers CMP #200 \ If A < 200 (78% chance), skip the next instruction BCC P%+5 JSR GTHG \ Call GTHG to spawn a Thargoid ship and a Thargon \ companion JMP MLOOP \ Jump back into the main loop at MLOOP, which is just \ after the ship-spawning section \ ****************************************************************************** \ \ Name: TT102 \ Type: Subroutine \ Category: Keyboard \ Summary: Process function key, save key, hyperspace and chart key presses \ and update the hyperspace counter \ \ ------------------------------------------------------------------------------ \ \ Process function key presses, plus "@" (save commander), "H" (hyperspace), \ "D" (show distance to system) and "O" (move chart cursor back to current \ system). We can also pass cursor position deltas in X and Y to indicate that \ the cursor keys or joystick have been used (i.e. the values that are returned \ by routine TT17). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The internal key number of the key pressed (see page 142 \ of the "Advanced User Guide for the BBC Micro" by Bray, \ Dickens and Holmes for a list of internal key numbers) \ \ X The amount to move the crosshairs in the x-axis \ \ Y The amount to move the crosshairs in the y-axis \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ T95 Print the distance to the selected system \ \ ****************************************************************************** .TT102 CMP #f8 \ If red key f8 was pressed, jump to STATUS to show the BNE P%+5 \ Status Mode screen, returning from the subroutine JMP STATUS \ using a tail call CMP #f4 \ If red key f4 was pressed, jump to TT22 to show the BNE P%+5 \ Long-range Chart, returning from the subroutine using JMP TT22 \ a tail call CMP #f5 \ If red key f5 was pressed, jump to TT23 to show the BNE P%+5 \ Short-range Chart, returning from the subroutine using JMP TT23 \ a tail call CMP #f6 \ If red key f6 was pressed, call TT111 to select the BNE TT92 \ system nearest to galactic coordinates (QQ9, QQ10) JSR TT111 \ (the location of the chart crosshairs) and jump to JMP TT25 \ TT25 to show the Data on System screen, returning \ from the subroutine using a tail call .TT92 CMP #f9 \ If red key f9 was pressed, jump to TT213 to show the BNE P%+5 \ Inventory screen, returning from the subroutine JMP TT213 \ using a tail call CMP #f7 \ If red key f7 was pressed, jump to TT167 to show the BNE P%+5 \ Market Price screen, returning from the subroutine JMP TT167 \ using a tail call CMP #f0 \ If red key f0 was pressed, jump to TT110 to launch our BNE fvw \ ship (if docked), returning from the subroutine using JMP TT110 \ a tail call .fvw BIT QQ12 \ If bit 7 of QQ12 is clear (i.e. we are not docked, but BPL INSP \ in space), jump to INSP to skip the following checks \ for f1-f3 and "@" (save commander file) key presses CMP #f3 \ If red key f3 was pressed, jump to EQSHP to show the BNE P%+5 \ Equip Ship screen, returning from the subroutine using JMP EQSHP \ a tail call CMP #f1 \ If red key f1 was pressed, jump to TT219 to show the BNE P%+5 \ Buy Cargo screen, returning from the subroutine using JMP TT219 \ a tail call CMP #&47 \ If "@" was pressed, jump to SVE to save the commander BNE P%+5 \ file, returning from the subroutine using a tail call JMP SVE CMP #f2 \ If red key f2 was pressed, jump to TT208 to show the BNE LABEL_3 \ Sell Cargo screen, returning from the subroutine using JMP TT208 \ a tail call .INSP CMP #f1 \ If the key pressed is < red key f1 or > red key f3, BCC LABEL_3 \ jump to LABEL_3 (so only do the following if the key CMP #f3+1 \ pressed is f1, f2 or f3) BCS LABEL_3 AND #3 \ If we get here then we are either in space, or we are TAX \ docked and none of f1-f3 were pressed, so we can now JMP LOOK1 \ process f1-f3 with their in-flight functions, i.e. \ switching space views \ \ A will contain &71, &72 or &73 (for f1, f2 or f3), so \ set X to the last digit (1, 2 or 3) and jump to LOOK1 \ to switch to view X (rear, left or right), returning \ from the subroutine using a tail call .LABEL_3 CMP #&54 \ If "H" was pressed, jump to hyp to do a hyperspace BNE P%+5 \ jump (if we are in space), returning from the JMP hyp \ subroutine using a tail call CMP #&32 \ If "D" was pressed, jump to T95 to print the distance BEQ T95 \ to a system (if we are in one of the chart screens) STA T1 \ Store A (the key that's been pressed) in T1 LDA QQ11 \ If the current view is a chart (QQ11 = 64 or 128), AND #%11000000 \ keep going, otherwise jump down to TT107 to skip the BEQ TT107 \ following LDA QQ22+1 \ If the on-screen hyperspace counter is non-zero, BNE TT107 \ then we are already counting down, so jump to TT107 \ to skip the following LDA T1 \ Restore the original value of A (the key that's been \ pressed) from T1 CMP #&36 \ If "O" was pressed, do the following three jumps, BNE ee2 \ otherwise skip to ee2 to continue JSR TT103 \ Draw small crosshairs at coordinates (QQ9, QQ10), \ which will erase the crosshairs currently there JSR ping \ Set the target system to the current system (which \ will move the location in (QQ9, QQ10) to the current \ home system JSR TT103 \ Draw small crosshairs at coordinates (QQ9, QQ10), \ which will draw the crosshairs at our current home \ system .ee2 JSR TT16 \ Call TT16 to move the crosshairs by the amount in X \ and Y, which were passed to this subroutine as \ arguments .TT107 LDA QQ22+1 \ If the on-screen hyperspace counter is zero, return BEQ t95 \ from the subroutine (as t95 contains an RTS), as we \ are not currently counting down to a hyperspace jump DEC QQ22 \ Decrement the internal hyperspace counter BNE t95 \ If the internal hyperspace counter is still non-zero, \ then we are still counting down, so return from the \ subroutine (as t95 contains an RTS) \ If we get here then the internal hyperspace counter \ has just reached zero and it wasn't zero before, so \ we need to reduce the on-screen counter and update \ the screen. We do this by first printing the next \ number in the countdown sequence, and then printing \ the old number, which will erase the old number \ and display the new one because printing uses EOR \ logic LDX QQ22+1 \ Set X = the on-screen hyperspace counter - 1 DEX \ (i.e. the next number in the sequence) JSR ee3 \ Print the 8-bit number in X at text location (0, 1) LDA #5 \ Reset the internal hyperspace counter to 5 STA QQ22 LDX QQ22+1 \ Set X = the on-screen hyperspace counter (i.e. the \ current number in the sequence, which is already \ shown on-screen) JSR ee3 \ Print the 8-bit number in X at text location (0, 1), \ i.e. print the hyperspace countdown in the top-left \ corner DEC QQ22+1 \ Decrement the on-screen hyperspace countdown BNE t95 \ If the countdown is not yet at zero, return from the \ subroutine (as t95 contains an RTS) JMP TT18 \ Otherwise the countdown has finished, so jump to TT18 \ to do a hyperspace jump, returning from the subroutine \ using a tail call .t95 RTS \ Return from the subroutine .T95 \ If we get here, "D" was pressed, so we need to show \ the distance to the selected system (if we are in a \ chart view) LDA QQ11 \ If the current view is a chart (QQ11 = 64 or 128), AND #%11000000 \ keep going, otherwise return from the subroutine (as BEQ t95 \ t95 contains an RTS) JSR hm \ Call hm to move the crosshairs to the target system \ in (QQ9, QQ10), returning with A = 0 STA QQ17 \ Set QQ17 = 0 to switch to ALL CAPS JSR cpl \ Print control code 3 (the selected system name) LDA #%10000000 \ Set bit 7 of QQ17 to switch to Sentence Case, with the STA QQ17 \ next letter in capitals LDA #1 \ Move the text cursor to column 1 and down one line STA XC \ (in other words, to the start of the next line) INC YC JMP TT146 \ Print the distance to the selected system and return \ from the subroutine using a tail call \ ****************************************************************************** \ \ Name: BAD \ Type: Subroutine \ Category: Status \ Summary: Calculate how bad we have been \ \ ------------------------------------------------------------------------------ \ \ Work out how bad we are from the amount of contraband in our hold. The \ formula is: \ \ (slaves + narcotics) * 2 + firearms \ \ so slaves and narcotics are twice as illegal as firearms. The value in FIST \ (our legal status) is set to at least this value whenever we launch from a \ space station, and a FIST of 50 or more gives us fugitive status, so leaving a \ station carrying 25 tonnes of slaves/narcotics, or 50 tonnes of firearms \ across multiple trips, is enough to make us a fugitive. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A value that determines how bad we are from the amount \ of contraband in our hold \ \ ****************************************************************************** .BAD LDA QQ20+3 \ Set A to the number of tonnes of slaves in the hold CLC \ Clear the C flag so we can do addition without the \ C flag affecting the result ADC QQ20+6 \ Add the number of tonnes of narcotics in the hold ASL A \ Double the result and add the number of tonnes of ADC QQ20+10 \ firearms in the hold RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: FAROF \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Compare x_hi, y_hi and z_hi with 224 \ Deep dive: A sense of scale \ \ ------------------------------------------------------------------------------ \ \ Compare x_hi, y_hi and z_hi with 224, and set the C flag if all three <= 224, \ otherwise clear the C flag. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Set if x_hi <= 224 and y_hi <= 224 and z_hi <= 224 \ \ Clear otherwise (i.e. if any one of them are bigger than \ 224) \ \ ****************************************************************************** .FAROF LDA #224 \ Set A = 224 and fall through into FAROF2 to do the \ comparison \ ****************************************************************************** \ \ Name: FAROF2 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Compare x_hi, y_hi and z_hi with A \ \ ------------------------------------------------------------------------------ \ \ Compare x_hi, y_hi and z_hi with A, and set the C flag if all three <= A, \ otherwise clear the C flag. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ C flag Set if x_hi <= A and y_hi <= A and z_hi <= A \ \ Clear otherwise (i.e. if any one of them are bigger than \ A) \ \ ****************************************************************************** .FAROF2 CMP INWK+1 \ If A < x_hi, C will be clear so jump to MA34 to BCC MA34 \ return from the subroutine with C clear, otherwise \ C will be set so move on to the next one CMP INWK+4 \ If A < y_hi, C will be clear so jump to MA34 to BCC MA34 \ return from the subroutine with C clear, otherwise \ C will be set so move on to the next one CMP INWK+7 \ If A < z_hi, C will be clear, otherwise C will be set .MA34 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: MAS4 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Calculate a cap on the maximum distance to a ship \ \ ------------------------------------------------------------------------------ \ \ Logical OR the value in A with the high bytes of the ship's position (x_hi, \ y_hi and z_hi). \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A OR x_hi OR y_hi OR z_hi \ \ ****************************************************************************** .MAS4 ORA INWK+1 \ OR A with x_hi, y_hi and z_hi ORA INWK+4 ORA INWK+7 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DEATH \ Type: Subroutine \ Category: Start and end \ Summary: Display the death screen \ \ ------------------------------------------------------------------------------ \ \ We have been killed, so display the chaos of our destruction above a "GAME \ OVER" sign, and clean up the mess ready for the next attempt. \ \ ****************************************************************************** .DEATH JSR EXNO3 \ Make the sound of us dying JSR RES2 \ Reset a number of flight variables and workspaces ASL DELTA \ Divide our speed in DELTA by 4 ASL DELTA LDX #24 \ Set the screen to only show 24 text rows, which hides JSR DET1 \ the dashboard, setting A to 6 in the process JSR TT66 \ Clear the top part of the screen, draw a border box, \ and set the current view type in QQ11 to 6 (death \ screen) JSR BOX \ Call BOX to redraw the same border box (BOX is part \ of TT66), which removes the border as it is drawn \ using EOR logic JSR nWq \ Create a cloud of stardust containing the correct \ number of dust particles (i.e. NOSTM of them) LDA #12 \ Move the text cursor to column 12 on row 12 STA YC STA XC LDA #146 \ Print recursive token 146 ("{all caps}GAME OVER") JSR ex .D1 JSR Ze \ Call Ze to initialise INWK to a fairly aggressive \ ship, and set A and X to random values LSR A \ Set A = A / 4, so A is now between 0 and 63, and LSR A \ store in byte #0 (x_lo) STA INWK LDY #0 \ Set the following to 0: the current view in QQ11 STY QQ11 \ (space view), x_hi, y_hi, z_hi and the AI flag (no AI STY INWK+1 \ or E.C.M. and zero aggression) STY INWK+4 STY INWK+7 STY INWK+32 DEY \ Set Y = 255 STY MCNT \ Reset the main loop counter to 255, so all timer-based \ calls will be stopped STY LASCT \ Set the laser count to 255 to act as a counter in the \ D2 loop below, so this setting determines how long the \ death animation lasts (it's 5.1 seconds, as LASCT is \ decremented every vertical sync, or 50 times a second, \ and 255 / 50 = 5.1) EOR #%00101010 \ Flip bits 1, 3 and 5 in A (x_lo) to get another number STA INWK+3 \ between 48 and 63, and store in byte #3 (y_lo) ORA #%01010000 \ Set bits 4 and 6 of A to bump it up to between 112 and STA INWK+6 \ 127, and store in byte #6 (z_lo) TXA \ Set A to the random number in X and keep bits 0-3 and AND #%10001111 \ the sign in bit 7 to get a number between -15 and +15, STA INWK+29 \ and store in byte #29 (roll counter) to give our ship \ a gentle roll with damping ROR A \ The C flag is randomly set from the above call to Ze, AND #%10000111 \ so this sets A to a number between -7 and +7, which STA INWK+30 \ we store in byte #30 (the pitch counter) to give our \ ship a very gentle pitch with damping PHP \ Store the processor flags LDX #OIL \ Call fq1 with X set to #OIL, which adds a new cargo JSR fq1 \ canister to our local bubble of universe and points it \ away from us with double DELTA speed (i.e. 6, as DELTA \ was set to 3 by the call to RES2 above). INF is set to \ point to the canister's ship data block in K% PLP \ Restore the processor flags, including our random C \ flag from before LDA #0 \ Set bit 7 of A to our random C flag and store in byte ROR A \ #31 of the ship's data block, so this has a 50% chance LDY #31 \ of marking our new canister as being killed (so it STA (INF),Y \ will explode) LDA FRIN+3 \ The call we made to RES2 before we entered the loop at BEQ D1 \ D1 will have reset all the ship slots at FRIN, so this \ checks to see if the fourth slot is empty, and if it \ is we loop back to D1 to add another canister, until \ we have added four of them JSR U% \ Clear the key logger, which also sets A = 0 STA DELTA \ Set our speed in DELTA to 0, as we aren't going \ anywhere any more .D2 JSR M% \ Call the M% routine to do the main flight loop once, \ which will display our exploding canister scene and \ move everything about LDA LASCT \ Loop back to D2 to run the main flight loop until BNE D2 \ LASCT reaches zero (which will take 5.1 seconds, as \ explained above) LDX #31 \ Set the screen to show all 31 text rows, which shows JSR DET1 \ the dashboard \ Fall through into DEATH2 to reset and restart the game \ ****************************************************************************** \ \ Name: DEATH2 \ Type: Subroutine \ Category: Start and end \ Summary: Reset most of the game and restart from the title screen \ \ ------------------------------------------------------------------------------ \ \ This routine is called following death, and when the game is quit by pressing \ ESCAPE when paused. \ \ ****************************************************************************** .DEATH2 JSR RES2 \ Reset a number of flight variables and workspaces \ and fall through into the entry code for the game \ to restart from the title screen \ ****************************************************************************** \ \ Name: TT170 \ Type: Subroutine \ Category: Start and end \ Summary: Main entry point for the Elite game code \ Deep dive: Program flow of the main game loop \ \ ------------------------------------------------------------------------------ \ \ This is the main entry point for the main game code. \ \ ****************************************************************************** .TT170 LDX #&FF \ Set the stack pointer to &01FF, which is the standard TXS \ location for the 6502 stack, so this instruction \ effectively resets the stack. We need to do this \ because the loader code in elite-loader.asm pushes \ code onto the stack, and this effectively removes that \ code so we start afresh \ Fall through into BR1 to start the game \ ****************************************************************************** \ \ Name: BR1 (Part 1 of 2) \ Type: Subroutine \ Category: Start and end \ Summary: Show the "Load New Commander (Y/N)?" screen and start the game \ \ ------------------------------------------------------------------------------ \ \ BRKV is set to point to BR1 by the loading process. \ \ ****************************************************************************** .BR1 LDX #3 \ Set XC = 3 (set text cursor to column 3) STX XC JSR FX200 \ Disable the ESCAPE key and clear memory if the BREAK \ key is pressed (*FX 200,3) LDX #CYL \ Call TITLE to show a rotating Cobra Mk III (#CYL) and LDA #128 \ token 128 (" LOAD NEW COMMANDER (Y/N)?{crlf}{crlf}"), JSR TITLE \ returning with the internal number of the key pressed \ in A CMP #&44 \ Did we press "Y"? If not, jump to QU5, otherwise BNE QU5 \ continue on to load a new commander \.BR1 \ These instructions are commented out in the original \ \LDX #3 \ source. This block starts with the same *FX call as \STX XC \ above, then clears the screen, calls a routine to \ \ flush the keyboard buffer (FLKB) that isn't present \JSR FX200 \ in the cassette version but is in other versions, \ \ and then it displays "LOAD NEW COMMANDER (Y/N)?" and \LDA #1 \ lists the current cargo, before falling straight into \JSR TT66 \ the load routine below, whether or not we have \ \ pressed "Y". This may be a bit of testing code, as the \JSR FLKB \ first line is a commented label, BR1, which is where \ \ BRKV points, so when this is uncommented, any BRK \LDA #14 \ instructions will jump straight to the load screen \JSR TT214 \ \BCC QU5 JSR GTNME \ We want to load a new commander, so we need to get \ the commander name to load JSR LOD \ We then call the LOD subroutine to load the commander \ file to address NA%+8, which is where we store the \ commander save file JSR TRNME \ Once loaded, we copy the commander name to NA% JSR TTX66 \ And we clear the top part of the screen and draw a \ border box \ ****************************************************************************** \ \ Name: QU5 \ Type: Subroutine \ Category: Start and end \ Summary: Reset the current commander data block to the last saved commander \ \ ****************************************************************************** .QU5 \ By the time we get here, the correct commander name \ is at NA% and the correct commander data is at NA%+8. \ Specifically: \ \ * If we loaded a commander file, then the name and \ data from that file will be at NA% and NA%+8 \ \ * If this is a brand new game, then NA% will contain \ the default starting commander name ("JAMESON") \ and NA%+8 will contain the default commander data \ \ * If this is not a new game (because they died or \ quit) and we didn't want to load a commander file, \ then NA% will contain the last saved commander \ name, and NA%+8 the last saved commander data. If \ the game has never been saved, this will still be \ the default commander \JSR TTX66 \ This instruction is commented out in the original \ source; it clears the screen and draws a border LDX #NT% \ The size of the commander data block is NT% bytes, \ and it starts at NA%+8, so we need to copy the data \ from the "last saved" buffer at NA%+8 to the current \ commander workspace at TP. So we set up a counter in X \ for the NT% bytes that we want to copy .QUL1 LDA NA%+7,X \ Copy the X-th byte of NA%+7 to the X-th byte of TP-1, STA TP-1,X \ (the -1 is because X is counting down from NT% to 1) DEX \ Decrement the loop counter BNE QUL1 \ Loop back for the next byte of the commander data \ block STX QQ11 \ X is 0 by the end of the above loop, so this sets QQ11 \ to 0, which means we will be showing a view without a \ boxed title at the top (i.e. we're going to use the \ screen layout of a space view in the following) \ If the commander check below fails, we keep jumping \ back to here to crash the game with an infinite loop JSR CHECK \ Call the CHECK subroutine to calculate the checksum \ for the current commander block at NA%+8 and put it \ in A CMP CHK \ Test the calculated checksum against CHK IF _REMOVE_CHECKSUMS NOP \ If we have disabled checksums, then ignore the result NOP \ of the comparison and fall through into the next part ELSE BNE P%-6 \ If the calculated checksum does not match CHK, then \ loop back to repeat the check - in other words, we \ enter an infinite loop here, as the checksum routine \ will keep returning the same incorrect value ENDIF \ The checksum CHK is correct, so now we check whether \ CHK2 = CHK EOR A9, and if this check fails, bit 7 of \ the competition flags at COK gets set, to indicate \ to Acornsoft via the competition code that there has \ been some hacking going on with this competition entry EOR #&A9 \ X = checksum EOR &A9 TAX LDA COK \ Set A to the competition flags in COK CPX CHK2 \ If X = CHK2, then skip the next instruction BEQ tZ ORA #%10000000 \ Set bit 7 of A to indicate this commander file has \ been tampered with .tZ ORA #%00000010 \ Set bit 1 of A to denote that this is the cassette \ version STA COK \ Store the updated competition flags in COK \ ****************************************************************************** \ \ Name: BR1 (Part 2 of 2) \ Type: Subroutine \ Category: Start and end \ Summary: Show the "Press Fire or Space, Commander" screen and start the \ game \ \ ------------------------------------------------------------------------------ \ \ BRKV is set to point to BR1 by the loading process. \ \ ****************************************************************************** JSR msblob \ Reset the dashboard's missile indicators so none of \ them are targeted LDA #147 \ Call TITLE to show a rotating Mamba (#3) and token LDX #3 \ 147 ("PRESS FIRE OR SPACE,COMMANDER.{crlf}{crlf}"), JSR TITLE \ returning with the internal number of the key pressed \ in A JSR ping \ Set the target system coordinates (QQ9, QQ10) to the \ current system coordinates (QQ0, QQ1) we just loaded JSR hyp1 \ Arrive in the system closest to (QQ9, QQ10) \ Fall through into the docking bay routine below \ ****************************************************************************** \ \ Name: BAY \ Type: Subroutine \ Category: Status \ Summary: Go to the docking bay (i.e. show the Status Mode screen) \ \ ------------------------------------------------------------------------------ \ \ We end up here after the start-up process (load commander etc.), as well as \ after a successful save, an escape pod launch, a successful docking, the end \ of a cargo sell, and various errors (such as not having enough cash, entering \ too many items when buying, trying to fit an item to your ship when you \ already have it, running out of cargo space, and so on). \ \ ****************************************************************************** .BAY LDA #&FF \ Set QQ12 = &FF (the docked flag) to indicate that we STA QQ12 \ are docked LDA #f8 \ Jump into the main loop at FRCE, setting the key JMP FRCE \ that's "pressed" to red key f8 (so we show the Status \ Mode screen) \ ****************************************************************************** \ \ Name: TITLE \ Type: Subroutine \ Category: Start and end \ Summary: Display a title screen with a rotating ship and prompt \ \ ------------------------------------------------------------------------------ \ \ Display the title screen, with a rotating ship and a text token at the bottom \ of the screen. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The number of the recursive token to show below the \ rotating ship (see variable QQ18 for details of \ recursive tokens) \ \ X The type of the ship to show (see variable XX21 for a \ list of ship types) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ X If a key is being pressed, X contains the internal key \ number, otherwise it contains 0 \ \ ****************************************************************************** .TITLE PHA \ Store the token number on the stack for later STX TYPE \ Store the ship type in location TYPE JSR RESET \ Reset our ship so we can use it for the rotating \ title ship LDA #1 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 1 DEC QQ11 \ Decrement QQ11 to 0, so from here on we are using a \ space view LDA #96 \ Set nosev_z hi = 96 (96 is the value of unity in the STA INWK+14 \ rotation vector) \LSR A \ This instruction is commented out in the original \ source. It would halve the value of z_hi to 48, so the \ ship would start off closer to the viewer STA INWK+7 \ Set z_hi, the high byte of the ship's z-coordinate, \ to 96, which is the distance at which the rotating \ ship starts out before coming towards us LDX #127 \ Set roll counter = 127, so don't dampen the roll and STX INWK+29 \ make the roll direction clockwise STX INWK+30 \ Set pitch counter = 127, so don't dampen the pitch and \ set the pitch direction to dive INX \ Set QQ17 to 128 (so bit 7 is set) to switch to STX QQ17 \ Sentence Case, with the next letter printing in upper \ case LDA TYPE \ Set up a new ship, using the ship type in TYPE JSR NWSHP LDY #6 \ Move the text cursor to column 6 STY XC JSR DELAY \ Wait for 6/50 of a second (0.12 seconds) LDA #30 \ Print recursive token 144 ("---- E L I T E ----") JSR plf \ followed by a newline LDY #6 \ Move the text cursor to column 6 again STY XC INC YC \ Move the text cursor down a row LDA PATG \ If PATG = 0, skip the following two lines, which BEQ awe \ print the author credits (PATG can be toggled by \ pausing the game and pressing "X") LDA #254 \ Print recursive token 94 ("BY D.BRABEN & I.BELL") JSR TT27 .awe JSR CLYNS \ Clear the bottom three text rows of the upper screen, \ and move the text cursor to the first cleared row. \ It also returns with Y = 0 STY DELTA \ Set DELTA = 0 (i.e. ship speed = 0) STY JSTK \ Set JSTK = 0 (i.e. keyboard, not joystick) PLA \ Restore the recursive token number we stored on the JSR ex \ stack at the start of this subroutine, and print that \ token LDA #148 \ Set A to recursive token 148 LDX #7 \ Move the text cursor to column 7 STX XC JSR ex \ Print recursive token 148 ("(C) ACORNSOFT 1984") .TLL2 LDA INWK+7 \ If z_hi (the ship's distance) is 1, jump to TL1 to CMP #1 \ skip the following decrement BEQ TL1 DEC INWK+7 \ Decrement the ship's distance, to bring the ship \ a bit closer to us .TL1 JSR MVEIT \ Move the ship in space according to the orientation \ vectors and the new value in z_hi LDA #128 \ Set z_lo = 128, so the closest the ship gets to us is STA INWK+6 \ z_hi = 1, z_lo = 128, or 256 + 128 = 384 ASL A \ Set A = 0 STA INWK \ Set x_lo = 0, so the ship remains in the screen centre STA INWK+3 \ Set y_lo = 0, so the ship remains in the screen centre JSR LL9 \ Call LL9 to display the ship DEC MCNT \ Decrement the main loop counter LDA VIA+&40 \ Read 6522 System VIA input register IRB (SHEILA &40) AND #%00010000 \ Bit 4 of IRB (PB4) is clear if joystick 1's fire \ button is pressed, otherwise it is set, so AND'ing \ the value of IRB with %10000 extracts this bit \TAX \ This instruction is commented out in the original \ source; it would have no effect, as the comparison \ flags are already set by the AND, and the value of X \ is not used anywhere BEQ TL2 \ If the joystick fire button is pressed, jump to TL2 JSR RDKEY \ Scan the keyboard for a key press and return the \ internal key number in A and X (or 0 for no key press) BEQ TLL2 \ If no key was pressed, loop back up to move/rotate \ the ship and check again for a key press RTS \ Return from the subroutine .TL2 DEC JSTK \ Joystick fire button was pressed, so set JSTK to &FF \ (it was set to 0 above), to disable keyboard and \ enable joysticks RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: CHECK \ Type: Subroutine \ Category: Save and load \ Summary: Calculate the checksum for the last saved commander data block \ Deep dive: Commander save files \ \ ------------------------------------------------------------------------------ \ \ The checksum for the last saved commander data block is saved as part of the \ commander file, in two places (CHK AND CHK2), to protect against file \ tampering. This routine calculates the checksum and returns it in A. \ \ This algorithm is also implemented in elite-checksum.py. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A The checksum for the last saved commander data block \ \ ****************************************************************************** .CHECK LDX #NT%-2 \ Set X to the size of the commander data block, less \ 2 (to omit the checksum bytes and the save count) CLC \ Clear the C flag so we can do addition without the \ C flag affecting the result TXA \ Seed the checksum calculation by setting A to the \ size of the commander data block, less 2 \ We now loop through the commander data block, \ starting at the end and looping down to the start \ (so at the start of this loop, the X-th byte is the \ last byte of the commander data block, i.e. the save \ count) .QUL2 ADC NA%+7,X \ Add the X-1-th byte of the data block to A, plus the \ C flag EOR NA%+8,X \ EOR A with the X-th byte of the data block DEX \ Decrement the loop counter BNE QUL2 \ Loop back for the next byte in the calculation, until \ we have added byte #0 and EOR'd with byte #1 of the \ data block RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TRNME \ Type: Subroutine \ Category: Save and load \ Summary: Copy the last saved commander's name from INWK to NA% \ \ ****************************************************************************** .TRNME LDX #7 \ The commander's name can contain a maximum of 7 \ characters, and is terminated by a carriage return, \ so set up a counter in X to copy 8 characters .GTL1 LDA INWK,X \ Copy the X-th byte of INWK to the X-th byte of NA% STA NA%,X DEX \ Decrement the loop counter BPL GTL1 \ Loop back until we have copied all 8 bytes \ Fall through into TR1 to copy the name back from NA% \ to INWK. This isn't necessary as the name is already \ there, but it does save one byte, as we don't need an \ RTS here \ ****************************************************************************** \ \ Name: TR1 \ Type: Subroutine \ Category: Save and load \ Summary: Copy the last saved commander's name from NA% to INWK \ \ ****************************************************************************** .TR1 LDX #7 \ The commander's name can contain a maximum of 7 \ characters, and is terminated by a carriage return, \ so set up a counter in X to copy 8 characters .GTL2 LDA NA%,X \ Copy the X-th byte of NA% to the X-th byte of INWK STA INWK,X DEX \ Decrement the loop counter BPL GTL2 \ Loop back until we have copied all 8 bytes RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: GTNME \ Type: Subroutine \ Category: Save and load \ Summary: Fetch the name of a commander file to save or load \ \ ------------------------------------------------------------------------------ \ \ Get the commander's name for loading or saving a commander file. The name is \ stored in the INWK workspace and is terminated by a return character (13). \ \ If ESCAPE is pressed or a blank name is entered, then the name stored is set \ to the name from the last saved commander block. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ INWK The commander name entered, terminated by a return \ character (13) \ \ ****************************************************************************** .GTNME LDA #1 \ Clear the top part of the screen, draw a border box, JSR TT66 \ and set the current view type in QQ11 to 1 LDA #123 \ Print recursive token 123 ("{crlf}COMMANDER'S NAME? ") JSR TT27 JSR DEL8 \ Wait for 8/50 of a second (0.16 seconds) LDA #%10000001 \ Clear 6522 System VIA interrupt enable register IER STA VIA+&4E \ (SHEILA &4E) bit 1 (i.e. enable the CA2 interrupt, \ which comes from the keyboard) LDA #15 \ Call OSBYTE with A = 15 (flush all buffers) TAX JSR OSBYTE LDX #LO(RLINE) \ Set (Y X) to point to the RLINE parameter block LDY #HI(RLINE) \ configuration block below LDA #0 \ Call OSWORD with A = 0 to read a line from the current JSR OSWORD \ input stream (i.e. the keyboard) \LDA #%00000001 \ These instructions are commented out in the original \STA VIA+&4E \ source, but they would set 6522 System VIA interrupt \ enable register IER (SHEILA &4E) bit 1 (i.e. disable \ the CA2 interrupt, which comes from the keyboard) BCS TR1 \ The C flag will be set if we pressed ESCAPE when \ entering the name, in which case jump to TR1 to copy \ the last saved commander's name from NA% to INWK \ and return from the subroutine there TYA \ The OSWORD call returns the length of the commander's \ name in Y, so transfer this to A BEQ TR1 \ If A = 0, no name was entered, so jump to TR1 to copy \ the last saved commander's name from NA% to INWK \ and return from the subroutine there JMP TT67 \ We have a name, so jump to TT67 to print a newline \ and return from the subroutine using a tail call \ ****************************************************************************** \ \ Name: RLINE \ Type: Variable \ Category: Text \ Summary: The OSWORD configuration block used to fetch a line of text from \ the keyboard \ \ ****************************************************************************** .RLINE EQUW INWK \ The address to store the input, so the commander's \ name will be stored in INWK as it is typed EQUB 7 \ Maximum line length = 7, as that's the maximum size \ for a commander's name EQUB '!' \ Allow ASCII characters from "!" through to "z" in EQUB 'z' \ the name \ ****************************************************************************** \ \ Name: ZERO \ Type: Subroutine \ Category: Utility routines \ Summary: Zero-fill pages &9, &A, &B, &C and &D \ \ ------------------------------------------------------------------------------ \ \ This resets the following workspaces to zero: \ \ * The ship data blocks ascending from K% at &0900 \ \ * The ship line heap descending from WP at &0D40 \ \ * WP workspace variables from FRIN to de, which include the ship slots for \ the local bubble of universe, and various flight and ship status variables \ (only a portion of the LSX/LSO sun line heap is cleared) \ \ ****************************************************************************** .ZERO LDX #&D \ Point X to page &D .ZEL JSR ZES1 \ Call ZES1 to zero-fill the page in X DEX \ Decrement X to point to the next page CPX #9 \ If X is > 9 (i.e. is &A, &B or &C), then loop back BNE ZEL \ up to clear the next page \ Then fall through into ZES1 with X set to 9, so we \ clear page &9 too \ ****************************************************************************** \ \ Name: ZES1 \ Type: Subroutine \ Category: Utility routines \ Summary: Zero-fill the page whose number is in X \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The page we want to zero-fill \ \ ****************************************************************************** .ZES1 LDY #0 \ If we set Y = SC = 0 and fall through into ZES2 STY SC \ below, then we will zero-fill 255 bytes starting from \ SC - in other words, we will zero-fill the whole of \ page X \ ****************************************************************************** \ \ Name: ZES2 \ Type: Subroutine \ Category: Utility routines \ Summary: Zero-fill a specific page \ \ ------------------------------------------------------------------------------ \ \ Zero-fill from address (X SC) + Y to (X SC) + &FF. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The high byte (i.e. the page) of the starting point of \ the zero-fill \ \ Y The offset from (X SC) where we start zeroing, counting \ up to &FF \ \ SC The low byte (i.e. the offset into the page) of the \ starting point of the zero-fill \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ Z flag Z flag is set \ \ ****************************************************************************** .ZES2 LDA #0 \ Load A with the byte we want to fill the memory block \ with - i.e. zero STX SC+1 \ We want to zero-fill page X, so store this in the \ high byte of SC, so the 16-bit address in SC and \ SC+1 is now pointing to the SC-th byte of page X .ZEL1 STA (SC),Y \ Zero the Y-th byte of the block pointed to by SC, \ so that's effectively the Y-th byte before SC INY \ Increment the loop counter BNE ZEL1 \ Loop back to zero the next byte RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: SVE \ Type: Subroutine \ Category: Save and load \ Summary: Save the commander file \ Deep dive: Commander save files \ The competition code \ \ ****************************************************************************** .SVE JSR GTNME \ Clear the screen and ask for the commander filename \ to save, storing the name at INWK JSR TRNME \ Transfer the commander filename from INWK to NA% JSR ZERO \ Zero-fill pages &9, &A, &B, &C and &D, which clears \ the ship data blocks, the ship line heap, the ship \ slots for the local bubble of universe, and various \ flight and ship status variables LSR SVC \ Halve the save count value in SVC LDX #NT% \ We now want to copy the current commander data block \ from location TP to the last saved commander block at \ NA%+8, so set a counter in X to copy the NT% bytes in \ the commander data block \ \ We also want to copy the data block to another \ location &0B00, which is normally used for the ship \ lines heap .SVL1 LDA TP,X \ Copy the X-th byte of TP to the X-th byte of &0B00 STA &0B00,X \ and NA%+8 STA NA%+8,X DEX \ Decrement the loop counter BPL SVL1 \ Loop back until we have copied all the bytes in the \ commander data block JSR CHECK \ Call CHECK to calculate the checksum for the last \ saved commander and return it in A STA CHK \ Store the checksum in CHK, which is at the end of the \ last saved commander block PHA \ Store the checksum on the stack ORA #%10000000 \ Set K = checksum with bit 7 set STA K EOR COK \ Set K+2 = K EOR COK (the competition flags) STA K+2 EOR CASH+2 \ Set K+1 = K+2 EOR CASH+2 (the third cash byte) STA K+1 EOR #&5A \ Set K+3 = K+1 EOR &5A EOR TALLY+1 (the high byte of EOR TALLY+1 \ the kill tally) STA K+3 JSR BPRNT \ Print the competition number stored in K to K+3. The \ value of U might affect how this is printed, and as \ it's a temporary variable in zero page that isn't \ reset by ZERO, it might have any value, but as the \ competition code is a 10-digit number, this just means \ it may or may not have an extra space of padding JSR TT67 \ Call TT67 twice to print two newlines JSR TT67 PLA \ Restore the checksum from the stack STA &0B00+NT% \ Store the checksum in the last byte of the save file \ at &0B00 (the equivalent of CHK in the last saved \ block) EOR #&A9 \ Store the checksum EOR &A9 in CHK2, the penultimate STA CHK2 \ byte of the last saved commander block STA &0AFF+NT% \ Store the checksum EOR &A9 in the penultimate byte of \ the save file at &0B00 (the equivalent of CHK2 in the \ last saved block) LDY #&B \ Set up an OSFILE block at &0C00, containing: STY &0C0B \ INY \ Start address for save = &00000B00 in &0C0A to &0C0D STY &0C0F \ \ End address for save = &00000C00 in &0C0E to &0C11 \ \ Y is left containing &C which we use below LDA #%10000001 \ Clear 6522 System VIA interrupt enable register IER STA VIA+&4E \ (SHEILA &4E) bit 1 (i.e. enable the CA2 interrupt, \ which comes from the keyboard) INC SVN \ Increment SVN to indicate we are about to start saving LDA #0 \ Call QUS1 with A = 0, Y = &C to save the commander JSR QUS1 \ file with the filename we copied to INWK at the start \ of this routine LDX #0 \ Set X = 0 for storing in SVN below \STX VIA+&4E \ This instruction is commented out in the original \ source. It would affect the 6522 System VIA interrupt \ enable register IER (SHEILA &4E) if any of bits 0-6 \ of X were set, but they aren't, so this instruction \ would have no effect anyway \DEX \ This instruction is commented out in the original \ source. It would end up setting SVN to &FF, which \ affects the logic in the IRQ1 handler STX SVN \ Set SVN to 0 to indicate we are done saving JMP BAY \ Go to the docking bay (i.e. show Status Mode) \ ****************************************************************************** \ \ Name: QUS1 \ Type: Subroutine \ Category: Save and load \ Summary: Save or load the commander file \ Deep dive: Commander save files \ \ ------------------------------------------------------------------------------ \ \ The filename should be stored at INWK, terminated with a carriage return (13). \ The routine should be called with Y set to &C. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A File operation to be performed. Can be one of the \ following: \ \ * 0 (save file) \ \ * &FF (load file) \ \ Y Points to the page number containing the OSFILE block, \ which must be &C because that's where the pointer to the \ filename in INWK is stored below (by the STX &0C00 \ instruction) \ \ ****************************************************************************** .QUS1 LDX #INWK \ Store a pointer to INWK at the start of the block at STX &0C00 \ &0C00, storing #INWK in the low byte because INWK is \ in zero page LDX #0 \ Set X to 0 so (Y X) = &0C00 JMP OSFILE \ Jump to OSFILE to do the file operation specified in \ &0C00 (i.e. save or load a file depending on the value \ of A), returning from the subroutine using a tail call \ ****************************************************************************** \ \ Name: LOD \ Type: Subroutine \ Category: Save and load \ Summary: Load a commander file \ \ ------------------------------------------------------------------------------ \ \ The filename should be stored at INWK, terminated with a carriage return (13). \ \ ****************************************************************************** .LOD LDX #2 \ Enable the ESCAPE key and clear memory if the BREAK JSR FX200 \ key is pressed (*FX 200,2) JSR ZERO \ Zero-fill pages &9, &A, &B, &C and &D, which clears \ the ship data blocks, the ship line heap, the ship \ slots for the local bubble of universe, and various \ flight and ship status variables LDY #&B \ Set up an OSFILE block at &0C00, containing: STY &0C03 \ INC &0C0B \ Load address = &00000B00 in &0C02 to &0C05 \ \ Length of file = &00000100 in &0C0A to &0C0D INY \ Increment Y to &C, which we use next LDA #&FF \ Call QUS1 with A = &FF, Y = &C to load the commander JSR QUS1 \ file to address &0B00 LDA &0B00 \ If the first byte of the loaded file has bit 7 set, BMI SPS1+1 \ jump to SPS+1, which is the second byte of an LDA #0 \ instruction, i.e. a BRK instruction, which will force \ an interrupt to call the address in BRKV, which is set \ to BR1... so this instruction restarts the game from \ the title screen. Valid commander files for the \ cassette version of Elite only have 0 for the first \ byte, as there are no missions in this version, so \ having bit 7 set is invalid anyway LDX #NT% \ We have successfully loaded the commander file at \ &0B00, so now we want to copy it to the last saved \ commander data block at NA%+8, so we set up a counter \ in X to copy NT% bytes .LOL1 LDA &0B00,X \ Copy the X-th byte of &0B00 to the X-th byte of NA%+8 STA NA%+8,X DEX \ Decrement the loop counter BPL LOL1 \ Loop back until we have copied all NT% bytes LDX #3 \ Fall through into FX200 to disable the ESCAPE key and \ clear memory if the BREAK key is pressed (*FX 200,3) \ and return from the subroutine there \ ****************************************************************************** \ \ Name: FX200 \ Type: Subroutine \ Category: Utility routines \ Summary: Set the behaviour of the ESCAPE and BREAK keys \ \ ------------------------------------------------------------------------------ \ \ This is the equivalent of a *FX 200 command, which controls the behaviour of \ the ESCAPE and BREAK keys. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X Controls the behaviour as follows: \ \ * 0 = Enable ESCAPE key \ Normal BREAK key action \ \ * 1 = Disable ESCAPE key \ Normal BREAK key action \ \ * 2 = Enable ESCAPE key \ Clear memory if the BREAK key is pressed \ \ * 3 = Disable ESCAPE key \ Clear memory if the BREAK key is pressed \ \ ****************************************************************************** .FX200 LDY #0 \ Call OSBYTE 200 with Y = 0, so the new value is set to LDA #200 \ X, and return from the subroutine using a tail call JMP OSBYTE RTS \ This instruction has no effect, as we already returned \ from the subroutine \ ****************************************************************************** \ \ Name: SPS1 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Calculate the vector to the planet and store it in XX15 \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ SPS1+1 A BRK instruction \ \ ****************************************************************************** .SPS1 LDX #0 \ Copy the two high bytes of the planet's x-coordinate JSR SPS3 \ into K3(2 1 0), separating out the sign bit into K3+2 LDX #3 \ Copy the two high bytes of the planet's y-coordinate JSR SPS3 \ into K3(5 4 3), separating out the sign bit into K3+5 LDX #6 \ Copy the two high bytes of the planet's z-coordinate JSR SPS3 \ into K3(8 7 6), separating out the sign bit into K3+8 \ Fall through into TAS2 to build XX15 from K3 \ ****************************************************************************** \ \ Name: TAS2 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Normalise the three-coordinate vector in K3 \ \ ------------------------------------------------------------------------------ \ \ Normalise the vector in K3, which has 16-bit values and separate sign bits, \ and store the normalised version in XX15 as a signed 8-bit vector. \ \ A normalised vector (also known as a unit vector) has length 1, so this \ routine takes an existing vector in K3 and scales it so the length of the \ new vector is 1. This is used in a number of places: when drawing the compass, \ when applying AI tactics to ships (so traders fly towards planets and missiles \ fly towards their targets, for example), and when implementing the docking \ computer in the enhanced versions of Elite. \ \ We do this in two stages. This stage shifts the 16-bit vector coordinates in \ K3 to the left as far as they will go without losing any bits off the end, so \ we can then take the high bytes and use them as the most accurate 8-bit vector \ to normalise. Then the next stage (in routine NORM) does the normalisation. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ K3(2 1 0) The 16-bit x-coordinate as (x_sign x_hi x_lo), where \ x_sign is just bit 7 \ \ K3(5 4 3) The 16-bit y-coordinate as (y_sign y_hi y_lo), where \ y_sign is just bit 7 \ \ K3(8 7 6) The 16-bit z-coordinate as (z_sign z_hi z_lo), where \ z_sign is just bit 7 \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ XX15 The normalised vector, with: \ \ * The x-coordinate in XX15 \ \ * The y-coordinate in XX15+1 \ \ * The z-coordinate in XX15+2 \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ TA2 Calculate the length of the vector in XX15 (ignoring the \ low coordinates), returning it in Q \ \ ****************************************************************************** .TAS2 LDA K3 \ OR the three low bytes and 1 to get a byte that has ORA K3+3 \ a 1 wherever any of the three low bytes has a 1 ORA K3+6 \ (as well as always having bit 0 set), and store in ORA #1 \ K3+9 STA K3+9 LDA K3+1 \ OR the three high bytes to get a byte in A that has a ORA K3+4 \ 1 wherever any of the three high bytes has a 1 ORA K3+7 \ (A K3+9) now has a 1 wherever any of the 16-bit \ values in K3 has a 1 .TAL2 ASL K3+9 \ Shift (A K3+9) to the left, so bit 7 of the high byte ROL A \ goes into the C flag BCS TA2 \ If the left shift pushed a 1 out of the end, then we \ know that at least one of the coordinates has a 1 in \ this position, so jump to TA2 as we can't shift the \ values in K3 any further to the left ASL K3 \ Shift K3(1 0), the x-coordinate, to the left ROL K3+1 ASL K3+3 \ Shift K3(4 3), the y-coordinate, to the left ROL K3+4 ASL K3+6 \ Shift K3(6 7), the z-coordinate, to the left ROL K3+7 BCC TAL2 \ Jump back to TAL2 to do another shift left (this BCC \ is effectively a JMP as we know bit 7 of K3+7 is not a \ 1, as otherwise bit 7 of A would have been a 1 and we \ would have taken the BCS above) .TA2 LDA K3+1 \ Fetch the high byte of the x-coordinate from our left- LSR A \ shifted K3, shift it right to clear bit 7, stick the ORA K3+2 \ sign bit in there from the x_sign part of K3, and STA XX15 \ store the resulting signed 8-bit x-coordinate in XX15 LDA K3+4 \ Fetch the high byte of the y-coordinate from our left- LSR A \ shifted K3, shift it right to clear bit 7, stick the ORA K3+5 \ sign bit in there from the y_sign part of K3, and STA XX15+1 \ store the resulting signed 8-bit y-coordinate in \ XX15+1 LDA K3+7 \ Fetch the high byte of the z-coordinate from our left- LSR A \ shifted K3, shift it right to clear bit 7, stick the ORA K3+8 \ sign bit in there from the z_sign part of K3, and STA XX15+2 \ store the resulting signed 8-bit z-coordinate in \ XX15+2 \ Now we have a signed 8-bit version of the vector K3 in \ XX15, so fall through into NORM to normalise it \ ****************************************************************************** \ \ Name: NORM \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Normalise the three-coordinate vector in XX15 \ Deep dive: Tidying orthonormal vectors \ Orientation vectors \ \ ------------------------------------------------------------------------------ \ \ We do this by dividing each of the three coordinates by the length of the \ vector, which we can calculate using Pythagoras. Once normalised, 96 (&60) is \ used to represent a value of 1, and 96 with bit 7 set (&E0) is used to \ represent -1. This enables us to represent fractional values of less than 1 \ using integers. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ XX15 The vector to normalise, with: \ \ * The x-coordinate in XX15 \ \ * The y-coordinate in XX15+1 \ \ * The z-coordinate in XX15+2 \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ XX15 The normalised vector \ \ Q The length of the original XX15 vector \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ NO1 Contains an RTS \ \ ****************************************************************************** .NORM LDA XX15 \ Fetch the x-coordinate into A JSR SQUA \ Set (A P) = A * A = x^2 STA R \ Set (R Q) = (A P) = x^2 LDA P STA Q LDA XX15+1 \ Fetch the y-coordinate into A JSR SQUA \ Set (A P) = A * A = y^2 STA T \ Set (T P) = (A P) = y^2 LDA P \ Set (R Q) = (R Q) + (T P) = x^2 + y^2 ADC Q \ STA Q \ First, doing the low bytes, Q = Q + P LDA T \ And then the high bytes, R = R + T ADC R STA R LDA XX15+2 \ Fetch the z-coordinate into A JSR SQUA \ Set (A P) = A * A = z^2 STA T \ Set (T P) = (A P) = z^2 LDA P \ Set (R Q) = (R Q) + (T P) = x^2 + y^2 + z^2 ADC Q \ STA Q \ First, doing the low bytes, Q = Q + P LDA T \ And then the high bytes, R = R + T ADC R STA R JSR LL5 \ We now have the following: \ \ (R Q) = x^2 + y^2 + z^2 \ \ so we can call LL5 to use Pythagoras to get: \ \ Q = SQRT(R Q) \ = SQRT(x^2 + y^2 + z^2) \ \ So Q now contains the length of the vector (x, y, z), \ and we can normalise the vector by dividing each of \ the coordinates by this value, which we do by calling \ routine TIS2. TIS2 returns the divided figure, using \ 96 to represent 1 and 96 with bit 7 set for -1 LDA XX15 \ Call TIS2 to divide the x-coordinate in XX15 by Q, JSR TIS2 \ with 1 being represented by 96 STA XX15 LDA XX15+1 \ Call TIS2 to divide the y-coordinate in XX15+1 by Q, JSR TIS2 \ with 1 being represented by 96 STA XX15+1 LDA XX15+2 \ Call TIS2 to divide the z-coordinate in XX15+2 by Q, JSR TIS2 \ with 1 being represented by 96 STA XX15+2 .NO1 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: RDKEY \ Type: Subroutine \ Category: Keyboard \ Summary: Scan the keyboard for key presses \ \ ------------------------------------------------------------------------------ \ \ Scan the keyboard, starting with internal key number 16 ("Q") and working \ through the set of internal key numbers (see page 142 of the "Advanced User \ Guide for the BBC Micro" by Bray, Dickens and Holmes for a list of internal \ key numbers). \ \ This routine is effectively the same as OSBYTE 122, though the OSBYTE call \ preserves A, unlike this routine. \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ X If a key is being pressed, X contains the internal key \ number, otherwise it contains 0 \ \ A Contains the same as X \ \ ****************************************************************************** .RDKEY LDX #16 \ Start the scan with internal key number 16 ("Q") .Rd1 JSR DKS4 \ Scan the keyboard to see if the key in X is currently \ being pressed, returning the result in A and X BMI Rd2 \ Jump to Rd2 if this key is being pressed (in which \ case DKS4 will have returned the key number with bit \ 7 set, which is negative) INX \ Increment the key number, which was unchanged by the \ above call to DKS4 BPL Rd1 \ Loop back to test the next key, ending the loop when \ X is negative (i.e. 128) TXA \ If we get here, nothing is being pressed, so copy X \ into A so that X = A = 128 = %10000000 .Rd2 EOR #%10000000 \ EOR A with #%10000000 to flip bit 7, so A now contains \ 0 if no key has been pressed, or the internal key \ number if a key has been pressed TAX \ Copy A into X RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: ECMOF \ Type: Subroutine \ Category: Dashboard \ Summary: Switch off the E.C.M. and turn off the dashboard bulb \ \ ****************************************************************************** .ECMOF LDA #0 \ Set ECMA and ECMP to 0 to indicate that no E.C.M. is STA ECMA \ currently running STA ECMP JSR ECBLB \ Update the E.C.M. indicator bulb on the dashboard LDA #72 \ Call the NOISE routine with A = 72 to make the sound BNE NOISE \ of the E.C.M. being turned off and return from the \ subroutine using a tail call (this BNE is effectively \ a JMP as A will never be zero) \ ****************************************************************************** \ \ Name: EXNO3 \ Type: Subroutine \ Category: Sound \ Summary: Make an explosion sound \ \ ------------------------------------------------------------------------------ \ \ Make the sound of death in the cold, hard vacuum of space. Apparently, in \ Elite space, everyone can hear you scream. \ \ This routine also makes the sound of a destroyed cargo canister if we don't \ get scooping right, the sound of us colliding with another ship, and the sound \ of us being hit with depleted shields. It is not a good sound to hear. \ \ ****************************************************************************** .EXNO3 LDA #16 \ Call the NOISE routine with A = 16 to make the first JSR NOISE \ death sound LDA #24 \ Call the NOISE routine with A = 24 to make the second BNE NOISE \ death sound and return from the subroutine using a \ tail call (this BNE is effectively a JMP as A will \ never be zero) \ ****************************************************************************** \ \ Name: SFRMIS \ Type: Subroutine \ Category: Tactics \ Summary: Add an enemy missile to our local bubble of universe \ \ ------------------------------------------------------------------------------ \ \ An enemy has fired a missile, so add the missile to our universe if there is \ room, and if there is, make the appropriate warnings and noises. \ \ ****************************************************************************** .SFRMIS LDX #MSL \ Set X to the ship type of a missile, and call SFS1-2 JSR SFS1-2 \ to add a missile to our universe that has AI (bit 7 \ set), is hostile (bit 6 set) and has been launched \ (bit 0 clear); the target slot number is set to 31, \ but this is ignored as the hostile flags means we \ are the target BCC NO1 \ The C flag will be set if the call to SFS1-2 was a \ success, so if it's clear, jump to NO1 to return from \ the subroutine (as NO1 contains an RTS) LDA #120 \ Print recursive token 120 ("INCOMING MISSILE") as an JSR MESS \ in-flight message LDA #48 \ Call the NOISE routine with A = 48 to make the sound BNE NOISE \ of the missile being launched and return from the \ subroutine using a tail call (this BNE is effectively \ a JMP as A will never be zero) \ ****************************************************************************** \ \ Name: EXNO2 \ Type: Subroutine \ Category: Status \ Summary: Process us making a kill \ Deep dive: Combat rank \ \ ------------------------------------------------------------------------------ \ \ We have killed a ship, so increase the kill tally, displaying an iconic \ message of encouragement if the kill total is a multiple of 256, and then \ make a nearby explosion sound. \ \ ****************************************************************************** .EXNO2 INC TALLY \ Increment the low byte of the kill count in TALLY BNE EXNO-2 \ If there is no carry, jump to the LDX #7 below (at \ EXNO-2) INC TALLY+1 \ Increment the high byte of the kill count in TALLY LDA #101 \ The kill total is a multiple of 256, so it's time JSR MESS \ for a pat on the back, so print recursive token 101 \ ("RIGHT ON COMMANDER!") as an in-flight message LDX #7 \ Set X = 7 and fall through into EXNO to make the \ sound of a ship exploding \ ****************************************************************************** \ \ Name: EXNO \ Type: Subroutine \ Category: Sound \ Summary: Make the sound of a laser strike on another ship or a ship \ explosion \ \ ------------------------------------------------------------------------------ \ \ Make the two-part explosion sound of us making a laser strike, or of another \ ship exploding. \ \ The volume of the first explosion is affected by the distance of the ship \ being hit, with more distant ships being quieter. The value in X also affects \ the volume of the first explosion, with a higher X giving a quieter sound \ (so X can be used to differentiate a laser strike from an explosion). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The larger the value of X, the fainter the explosion. \ Allowed values are: \ \ * 7 = explosion is louder (i.e. the ship has just \ exploded) \ \ * 15 = explosion is quieter (i.e. this is just a laser \ strike) \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ EXNO-2 Set X = 7 and fall through into EXNO to make the sound \ of a ship exploding \ \ ****************************************************************************** .EXNO STX T \ Store the distance in T LDA #24 \ Set A = 24 to denote the sound of us making a hit or JSR NOS1 \ kill (part 1 of the explosion), and call NOS1 to set \ up the sound block in XX16 LDA INWK+7 \ Fetch z_hi, the distance of the ship being hit in LSR A \ terms of the z-axis (in and out of the screen), and LSR A \ divide by 4. If z_hi has either bit 6 or 7 set then \ that ship is too far away to be shown on the scanner \ (as per the SCAN routine), so we know the maximum \ z_hi at this point is %00111111, and shifting z_hi \ to the right twice gives us a maximum value of \ %00001111 AND T \ This reduces A to a maximum of X; X can be either \ 7 = %0111 or 15 = %1111, so AND'ing with 15 will \ not affect A, while AND'ing with 7 will clear bit \ 3, reducing the maximum value in A to 7 ORA #%11110001 \ The SOUND statement's amplitude ranges from 0 (for no \ sound) to -15 (full volume), so we can set bits 0 and \ 4-7 in A, and keep bits 1-3 from the above to get \ a value between -15 (%11110001) and -1 (%11111111), \ with lower values of z_hi and argument X leading \ to a more negative, or quieter number (so the closer \ the ship, i.e. the smaller the value of X, the louder \ the sound) STA XX16+2 \ The amplitude byte of the sound block in XX16 is in \ byte #3 (where it's the low byte of the amplitude), so \ this sets the amplitude to the value in A JSR NO3 \ Make the sound from our updated sound block in XX16 LDA #16 \ Set A = 16 to denote we have made a hit or kill \ (part 2 of the explosion), and fall through into NOISE \ to make the sound EQUB &2C \ Skip the next instruction by turning it into \ &2C &A9 &20, or BIT &20A9, which does nothing apart \ from affect the flags \ ****************************************************************************** \ \ Name: BEEP \ Type: Subroutine \ Category: Sound \ Summary: Make a short, high beep \ \ ****************************************************************************** .BEEP LDA #32 \ Set A = 32 to denote a short, high beep, and fall \ through into the NOISE routine to make the sound \ ****************************************************************************** \ \ Name: NOISE \ Type: Subroutine \ Category: Sound \ Summary: Make the sound whose number is in A \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The number of the sound to be made. See the \ documentation for variable SFX for a list of sound \ numbers \ \ ****************************************************************************** .NOISE JSR NOS1 \ Set up the sound block in XX16 for the sound in A and \ fall through into NO3 to make the sound \ ****************************************************************************** \ \ Name: NO3 \ Type: Subroutine \ Category: Sound \ Summary: Make a sound from a prepared sound block \ \ ------------------------------------------------------------------------------ \ \ Make a sound from a prepared sound block in XX16 (if sound is enabled). See \ routine NOS1 for details of preparing the XX16 sound block. \ \ ****************************************************************************** .NO3 LDX DNOIZ \ Set X to the DNOIZ configuration setting BNE NO1 \ If DNOIZ is non-zero, then sound is disabled, so \ return from the subroutine (as NO1 contains an RTS) LDX #LO(XX16) \ Otherwise set (Y X) to point to the sound block in LDY #HI(XX16) \ XX16 LDA #7 \ Call OSWORD 7 to makes the sound, as described in the JMP OSWORD \ documentation for variable SFX, and return from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: NOS1 \ Type: Subroutine \ Category: Sound \ Summary: Prepare a sound block \ \ ------------------------------------------------------------------------------ \ \ Copy four sound bytes from SFX into XX16, interspersing them with null bytes, \ with Y indicating the sound number to copy (from the values in the sound \ table at SFX). So, for example, if we call this routine with A = 40 (long, \ low beep), the following bytes will be set in XX16 to XX16+7: \ \ &13 &00 &F4 &00 &0C &00 &08 &00 \ \ This block will be passed to OSWORD 7 to make the sound, which expects the \ four sound attributes as 16-bit big-endian values - in other words, with the \ low byte first. So the above block would pass the values &0013, &00F4, &000C \ and &0008 to the SOUND statement when used with OSWORD 7, or: \ \ SOUND &13, &F4, &0C, &08 \ \ as the high bytes are always zero. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The sound number to copy from SFX to XX16, which is \ always a multiple of 8 \ \ ****************************************************************************** .NOS1 LSR A \ Divide A by 2, and also clear the C flag, as bit 0 of \ A is always zero (as A is a multiple of 8) ADC #3 \ Set Y = A + 3, so Y now points to the last byte of TAY \ four within the block of four-byte values LDX #7 \ We want to copy four bytes, spread out into an \ eight-byte block, so set a counter in Y to cover eight \ bytes .NOL1 LDA #0 \ Set the X-th byte of XX16 to 0 STA XX16,X DEX \ Decrement the destination byte pointer LDA SFX,Y \ Set the X-th byte of XX16 to the value from SFX+Y STA XX16,X DEY \ Decrement the source byte pointer again DEX \ Decrement the destination byte pointer again BPL NOL1 \ Loop back for the next source byte \ Fall through into KYTB to return from the subroutine, \ as the first byte of KYTB is an RTS \ ****************************************************************************** \ \ Name: KYTB \ Type: Variable \ Category: Keyboard \ Summary: Lookup table for in-flight keyboard controls \ Deep dive: The key logger \ \ ------------------------------------------------------------------------------ \ \ Keyboard table for in-flight controls. This table contains the internal key \ codes for the flight keys (see page 142 of the "Advanced User Guide for the \ BBC Micro" by Bray, Dickens and Holmes for a list of internal key numbers). \ \ The pitch, roll, speed and laser keys (i.e. the seven primary flight \ control keys) have bit 7 set, so they have 128 added to their internal \ values. This doesn't appear to be used anywhere. \ \ Note that KYTB actually points to the byte before the start of the table, so \ the offset of the first key value is 1 (i.e. KYTB+1), not 0. \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ KYTB Contains an RTS \ \ ****************************************************************************** .KYTB RTS \ Return from the subroutine (used as an entry point and \ a fall-through from above) \ These are the primary flight controls (pitch, roll, \ speed and lasers): EQUB &68 + 128 \ ? KYTB+1 Slow down EQUB &62 + 128 \ Space KYTB+2 Speed up EQUB &66 + 128 \ < KYTB+3 Roll left EQUB &67 + 128 \ > KYTB+4 Roll right EQUB &42 + 128 \ X KYTB+5 Pull up EQUB &51 + 128 \ S KYTB+6 Pitch down EQUB &41 + 128 \ A KYTB+7 Fire lasers \ These are the secondary flight controls: EQUB &60 \ TAB KYTB+8 Energy bomb EQUB &70 \ ESCAPE KYTB+9 Launch escape pod EQUB &23 \ T KYTB+10 Arm missile EQUB &35 \ U KYTB+11 Unarm missile EQUB &65 \ M KYTB+12 Fire missile EQUB &22 \ E KYTB+13 E.C.M. EQUB &45 \ J KYTB+14 In-system jump EQUB &52 \ C KYTB+15 Docking computer \ ****************************************************************************** \ \ Name: DKS1 \ Type: Subroutine \ Category: Keyboard \ Summary: Scan the keyboard for a flight key \ Deep dive: The key logger \ \ ------------------------------------------------------------------------------ \ \ Scan the keyboard for the flight key given in register Y, where Y is the \ offset into the KYTB table above (so we can scan for Space by setting Y to \ 2, for example). If the key is pressed, set the corresponding byte in the \ key logger at KL to &FF. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ Y The offset into the KYTB table above of the key that we \ want to scan on the keyboard \ \ ****************************************************************************** .DKS1 LDX KYTB,Y \ Get the internal key number from the Y-th byte of the \ KYTB table above JSR DKS4 \ Call DKS4, which will set A and X to a negative value \ if the key is being pressed BPL DKS2-1 \ The key is not being pressed, so return from the \ subroutine (as DKS2-1 contains an RTS) LDX #&FF \ Store &FF in the Y-th byte of the key logger at KL STX KL,Y RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: CTRL \ Type: Subroutine \ Category: Keyboard \ Summary: Scan the keyboard to see if CTRL is currently pressed \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ X X = %10000001 (i.e. 129 or -127) if CTRL is being \ pressed \ \ X = 1 if CTRL is not being pressed \ \ A Contains the same as X \ \ ****************************************************************************** .CTRL LDX #1 \ Set X to the internal key number for CTRL and fall \ through into DKS4 to scan the keyboard \ ****************************************************************************** \ \ Name: DKS4 \ Type: Subroutine \ Category: Keyboard \ Summary: Scan the keyboard to see if a specific key is being pressed \ Deep dive: The key logger \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The internal number of the key to check (see page 142 of \ the "Advanced User Guide for the BBC Micro" by Bray, \ Dickens and Holmes for a list of internal key numbers) \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A If the key in A is being pressed, A contains the \ original argument A, but with bit 7 set (i.e. A + 128). \ If the key in A is not being pressed, the value in A is \ unchanged \ \ X Contains the same as A \ \ ****************************************************************************** .DKS4 LDA #%00000011 \ Set A to %00000011, so it's ready to send to SHEILA \ once interrupts have been disabled SEI \ Disable interrupts so we can scan the keyboard \ without being hijacked STA VIA+&40 \ Set 6522 System VIA output register ORB (SHEILA &40) \ to %00000011 to stop auto scan of keyboard LDA #%01111111 \ Set 6522 System VIA data direction register DDRA STA VIA+&43 \ (SHEILA &43) to %01111111. This sets the A registers \ (IRA and ORA) so that: \ \ * Bits 0-6 of ORA will be sent to the keyboard \ \ * Bit 7 of IRA will be read from the keyboard STX VIA+&4F \ Set 6522 System VIA output register ORA (SHEILA &4F) \ to X, the key we want to scan for; bits 0-6 will be \ sent to the keyboard, of which bits 0-3 determine the \ keyboard column, and bits 4-6 the keyboard row LDX VIA+&4F \ Read 6522 System VIA output register IRA (SHEILA &4F) \ into X; bit 7 is the only bit that will have changed. \ If the key is pressed, then bit 7 will be set, \ otherwise it will be clear LDA #%00001011 \ Set 6522 System VIA output register ORB (SHEILA &40) STA VIA+&40 \ to %00001011 to restart auto scan of keyboard CLI \ Allow interrupts again TXA \ Transfer X into A RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DKS2 \ Type: Subroutine \ Category: Keyboard \ Summary: Read the joystick position \ \ ------------------------------------------------------------------------------ \ \ Return the value of ADC channel in X (used to read the joystick). The value \ will be inverted if the game has been configured to reverse both joystick \ channels (which can be done by pausing the game and pressing J). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The ADC channel to read: \ \ * 1 = joystick X \ \ * 2 = joystick Y \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ (A X) The 16-bit value read from channel X, with the value \ inverted if the game has been configured to reverse the \ joystick \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ DKS2-1 Contains an RTS \ \ ****************************************************************************** .DKS2 LDA #128 \ Call OSBYTE with A = 128 to fetch the 16-bit value JSR OSBYTE \ from ADC channel X, returning (Y X), i.e. the high \ byte in Y and the low byte in X \ \ * Channel 1 is the x-axis: 0 = right, 65520 = left \ \ * Channel 2 is the y-axis: 0 = down, 65520 = up TYA \ Copy Y to A, so the result is now in (A X) EOR JSTE \ The high byte A is now EOR'd with the value in \ location JSTE, which contains &FF if both joystick \ channels are reversed and 0 otherwise (so A now \ contains the high byte but inverted, if that's what \ the current settings say) RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DKS3 \ Type: Subroutine \ Category: Keyboard \ Summary: Toggle a configuration setting and emit a beep \ \ ------------------------------------------------------------------------------ \ \ This is called when the game is paused and a key is pressed that changes the \ game's configuration. \ \ Specifically, this routine toggles the configuration settings for the \ following keys: \ \ * CAPS LOCK toggles keyboard flight damping (&40) \ * A toggles keyboard auto-recentre (&41) \ * X toggles author names on start-up screen (&42) \ * F toggles flashing console bars (&43) \ * Y toggles reverse joystick Y channel (&44) \ * J toggles reverse both joystick channels (&45) \ * K toggles keyboard and joystick (&46) \ \ The numbers in brackets are the internal key numbers (see page 142 of the \ "Advanced User Guide for the BBC Micro" by Bray, Dickens and Holmes for a list \ of internal key numbers). We pass the key that has been pressed in X, and the \ configuration option to check it against in Y, so this routine is typically \ called in a loop that loops through the various configuration options. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X The internal number of the key that's been pressed \ \ Y The internal number of the configuration key to check \ against, from the list above (i.e. Y must be from &40 to \ &46) \ \ ****************************************************************************** .DKS3 STY T \ Store the configuration key argument in T CPX T \ If X <> Y, jump to Dk3 to return from the subroutine BNE Dk3 \ We have a match between X and Y, so now to toggle \ the relevant configuration byte. CAPS LOCK has a key \ value of &40 and has its configuration byte at \ location DAMP, A has a value of &41 and has its byte \ at location DJD, which is DAMP+1, and so on. So we \ can toggle the configuration byte by changing the \ byte at DAMP + (X - &40), or to put it in indexing \ terms, DAMP-&40,X. It's no coincidence that the \ game's configuration bytes are set up in this order \ and with these keys (and this is also why the sound \ on/off keys are dealt with elsewhere, as the internal \ key for S and Q are &51 and &10, which don't fit \ nicely into this approach) LDA DAMP-&40,X \ Fetch the byte from DAMP + (X - &40), invert it and EOR #&FF \ put it back (0 means no and &FF means yes in the STA DAMP-&40,X \ configuration bytes, so this toggles the setting) JSR BELL \ Make a beep sound so we know something has happened JSR DELAY \ Wait for Y/50 seconds (Y is between 64 and 70, so this \ is always a bit longer than a second) LDY T \ Restore the configuration key argument into Y .Dk3 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DKJ1 \ Type: Subroutine \ Category: Keyboard \ Summary: Read joystick and flight controls \ \ ------------------------------------------------------------------------------ \ \ Specifically, scan the keyboard for the speed up and slow down keys, and read \ the joystick's fire button and X and Y axes, storing the results in the key \ logger and the joystick position variables. \ \ This routine is only called if joysticks are enabled (JSTK = non-zero). \ \ ****************************************************************************** .DKJ1 LDY #1 \ Update the key logger for key 1 in the KYTB table, so JSR DKS1 \ KY1 will be &FF if "?" (slow down) is being pressed INY \ Update the key logger for key 2 in the KYTB table, so JSR DKS1 \ KY2 will be &FF if Space (speed up) is being pressed LDA VIA+&40 \ Read 6522 System VIA input register IRB (SHEILA &40) TAX \ This instruction doesn't seem to have any effect, as \ X is overwritten in a few instructions. When the \ joystick is checked in a similar way in the TITLE \ subroutine for the "Press Fire Or Space,Commander." \ stage of the start-up screen, there's another \ unnecessary TAX instruction present, but there it's \ commented out AND #%00010000 \ Bit 4 of IRB (PB4) is clear if joystick 1's fire \ button is pressed, otherwise it is set, so AND'ing \ the value of IRB with %10000 extracts this bit EOR #%00010000 \ Flip bit 4 so that it's set if the fire button has STA KY7 \ been pressed, and store the result in the keyboard \ logger at location KY7, which is also where the A key \ (fire lasers) key is logged LDX #1 \ Call DKS2 to fetch the value of ADC channel 1 (the JSR DKS2 \ joystick X value) into (A X), and OR A with 1. This ORA #1 \ ensures that the high byte is at least 1, and then we STA JSTX \ store the result in JSTX LDX #2 \ Call DKS2 to fetch the value of ADC channel 2 (the JSR DKS2 \ joystick Y value) into (A X), and EOR A with JSTGY. EOR JSTGY \ JSTGY will be &FF if the game is configured to STA JSTY \ reverse the joystick Y channel, so this EOR does \ exactly that, and then we store the result in JSTY JMP DK4 \ We are done scanning the joystick flight controls, \ so jump to DK4 to scan for other keys, using a tail \ call so we can return from the subroutine there \ ****************************************************************************** \ \ Name: U% \ Type: Subroutine \ Category: Keyboard \ Summary: Clear the key logger \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ A A is set to 0 \ \ Y Y is set to 0 \ \ ****************************************************************************** .U% LDA #0 \ Set A to 0, as this means "key not pressed" in the \ key logger at KL LDY #15 \ We want to clear the 15 key logger locations from \ KY1 to KY19, so set a counter in Y .DKL3 STA KL,Y \ Store 0 in the Y-th byte of the key logger DEY \ Decrement the counter BNE DKL3 \ And loop back for the next key, until we have just \ cleared KL+1. We don't want to clear the first key \ logger location at KL, as the keyboard table at KYTB \ starts with offset 1, not 0, so KL is not technically \ part of the key logger (it's actually used for logging \ keys that don't appear in the keyboard table, and \ which therefore don't use the key logger) RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: DOKEY \ Type: Subroutine \ Category: Keyboard \ Summary: Scan for the seven primary flight controls \ Deep dive: The key logger \ The docking computer \ \ ------------------------------------------------------------------------------ \ \ Scan for the seven primary flight controls (or the equivalent on joystick), \ pause and configuration keys, and secondary flight controls, and update the \ key logger accordingly. Specifically: \ \ * If we are on keyboard configuration, clear the key logger and update it \ for the seven primary flight controls, and update the pitch and roll \ rates accordingly. \ \ * If we are on joystick configuration, clear the key logger and jump to \ DKJ1, which reads the joystick equivalents of the primary flight \ controls. \ \ Both options end up at DK4 to scan for other keys, beyond the seven primary \ flight controls. \ \ ****************************************************************************** .DOKEY JSR U% \ Call U% to clear the key logger LDA JSTK \ If JSTK is non-zero, then we are configured to use BNE DKJ1 \ the joystick rather than keyboard, so jump to DKJ1 \ to read the joystick flight controls, before jumping \ to DK4 to scan for pause, configuration and secondary \ flight keys LDY #7 \ We're going to work our way through the primary flight \ control keys (pitch, roll, speed and laser), so set a \ counter in Y so we can loop through all 7 .DKL2 JSR DKS1 \ Call DKS1 to see if the KYTB key at offset Y is being \ pressed, and set the key logger accordingly DEY \ Decrement the loop counter BNE DKL2 \ Loop back for the next key, working our way from A at \ KYTB+7 down to ? at KYTB+1 LDX JSTX \ Set X = JSTX, the current roll rate (as shown in the \ RL indicator on the dashboard) LDA #7 \ Set A to 7, which is the amount we want to alter the \ roll rate by if the roll keys are being pressed LDY KL+3 \ If the "<" key is being pressed, then call the BUMP2 BEQ P%+5 \ routine to increase the roll rate in X by A JSR BUMP2 LDY KL+4 \ If the ">" key is being pressed, then call the REDU2 BEQ P%+5 \ routine to decrease the roll rate in X by A, taking JSR REDU2 \ the keyboard auto re-centre setting into account STX JSTX \ Store the updated roll rate in JSTX ASL A \ Double the value of A, to 14 LDX JSTY \ Set X = JSTY, the current pitch rate (as shown in the \ DC indicator on the dashboard) LDY KL+5 \ If the "X" key is being pressed, then call the REDU2 BEQ P%+5 \ routine to decrease the pitch rate in X by A, taking JSR REDU2 \ the keyboard auto re-centre setting into account LDY KL+6 \ If the "S" key is being pressed, then call the BUMP2 BEQ P%+5 \ routine to increase the pitch rate in X by A JSR BUMP2 STX JSTY \ Store the updated roll rate in JSTY \ Fall through into DK4 to scan for other keys \ ****************************************************************************** \ \ Name: DK4 \ Type: Subroutine \ Category: Keyboard \ Summary: Scan for pause, configuration and secondary flight keys \ Deep dive: The key logger \ \ ------------------------------------------------------------------------------ \ \ Scan for pause and configuration keys, and if this is a space view, also scan \ for secondary flight controls. \ \ Specifically: \ \ * Scan for the pause button (COPY) and if it's pressed, pause the game and \ process any configuration key presses until the game is unpaused (DELETE) \ \ * If this is a space view, scan for secondary flight keys and update the \ relevant bytes in the key logger \ \ ****************************************************************************** .DK4 JSR RDKEY \ Scan the keyboard for a key press and return the \ internal key number in A and X (or 0 for no key press) STX KL \ Store X in KL, byte #0 of the key logger CPX #&69 \ If COPY is not being pressed, jump to DK2 below, BNE DK2 \ otherwise let's process the configuration keys .FREEZE \ COPY is being pressed, so we enter a loop that \ listens for configuration keys, and we keep looping \ until we detect a DELETE key press. This effectively \ pauses the game when COPY is pressed, and unpauses \ it when DELETE is pressed JSR WSCAN \ Call WSCAN to wait for the vertical sync, so the whole \ screen gets drawn JSR RDKEY \ Scan the keyboard for a key press and return the \ internal key number in A and X (or 0 for no key press) CPX #&51 \ If "S" is not being pressed, skip to DK6 BNE DK6 LDA #0 \ "S" is being pressed, so set DNOIZ to 0 to turn the STA DNOIZ \ sound on .DK6 LDY #&40 \ We now want to loop through the keys that toggle \ various settings. These have internal key numbers \ between &40 (CAPS LOCK) and &46 ("K"), so we set up \ the first key number in Y to act as a loop counter. \ See subroutine DKS3 for more details on this .DKL4 JSR DKS3 \ Call DKS3 to scan for the key given in Y, and toggle \ the relevant setting if it is pressed INY \ Increment Y to point to the next toggle key CPY #&47 \ The last toggle key is &46 (K), so check whether we \ have just done that one BNE DKL4 \ If not, loop back to check for the next toggle key .DK55 CPX #&10 \ If "Q" is not being pressed, skip to DK7 BNE DK7 STX DNOIZ \ "Q" is being pressed, so set DNOIZ to X, which is \ non-zero (&10), so this will turn the sound off .DK7 CPX #&70 \ If ESCAPE is not being pressed, skip over the next BNE P%+5 \ instruction JMP DEATH2 \ ESCAPE is being pressed, so jump to DEATH2 to end \ the game CPX #&59 \ If DELETE is not being pressed, we are still paused, BNE FREEZE \ so loop back up to keep listening for configuration \ keys, otherwise fall through into the rest of the \ key detection code, which unpauses the game .DK2 LDA QQ11 \ If the current view is non-zero (i.e. not a space BNE DK5 \ view), return from the subroutine (as DK5 contains \ an RTS) LDY #15 \ This is a space view, so now we want to check for all \ the secondary flight keys. The internal key numbers \ are in the keyboard table KYTB from KYTB+8 to \ KYTB+15, and their key logger locations are from KL+8 \ to KL+15. So set a decreasing counter in Y for the \ index, starting at 15, so we can loop through them LDA #&FF \ Set A to &FF so we can store this in the keyboard \ logger for keys that are being pressed .DKL1 LDX KYTB,Y \ Get the internal key number of the Y-th flight key \ the KYTB keyboard table CPX KL \ We stored the key that's being pressed in KL above, \ so check to see if the Y-th flight key is being \ pressed BNE DK1 \ If it is not being pressed, skip to DK1 below STA KL,Y \ The Y-th flight key is being pressed, so set that \ key's location in the key logger to &FF .DK1 DEY \ Decrement the loop counter CPY #7 \ Have we just done the last key? BNE DKL1 \ If not, loop back to process the next key .DK5 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TT217 \ Type: Subroutine \ Category: Keyboard \ Summary: Scan the keyboard until a key is pressed \ \ ------------------------------------------------------------------------------ \ \ Scan the keyboard until a key is pressed, and return the key's ASCII code. \ If, on entry, a key is already being held down, then wait until that key is \ released first (so this routine detects the first key down event following \ the subroutine call). \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ X The ASCII code of the key that was pressed \ \ A Contains the same as X \ \ Y Y is preserved \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ out Contains an RTS \ \ ****************************************************************************** .TT217 STY YSAV \ Store Y in temporary storage, so we can restore it \ later .t JSR DELAY-5 \ Wait for 8/50 of a second (0.16 seconds) to implement \ a simple keyboard debounce and prevent multiple key \ presses being recorded JSR RDKEY \ Scan the keyboard for a key press and return the \ internal key number in A and X (or 0 for no key press) BNE t \ If a key was already being held down when we entered \ this routine, keep looping back up to t, until the \ key is released .t2 JSR RDKEY \ Any pre-existing key press is now gone, so we can \ start scanning the keyboard again, returning the \ internal key number in A and X (or 0 for no key press) BEQ t2 \ Keep looping up to t2 until a key is pressed TAY \ Copy A to Y, so Y contains the internal key number \ of the key pressed LDA (TRTB%),Y \ The address in TRTB% points to the MOS key \ translation table, which is used to translate \ internal key numbers to ASCII, so this fetches the \ key's ASCII code into A LDY YSAV \ Restore the original value of Y we stored above TAX \ Copy A into X .out RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: me1 \ Type: Subroutine \ Category: Flight \ Summary: Erase an old in-flight message and display a new one \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ X Must be set to 0 \ \ ****************************************************************************** .me1 STX DLY \ Set the message delay in DLY to 0, so any new \ in-flight messages will be shown instantly PHA \ Store the new message token we want to print LDA MCH \ Set A to the token number of the message that is JSR mes9 \ currently on-screen, and call mes9 to print it (which \ will remove it from the screen, as printing is done \ using EOR logic) PLA \ Restore the new message token EQUB &2C \ Fall through into ou2 to print the new message, but \ skip the first instruction by turning it into \ &2C &A9 &6C, or BIT &6CA9, which does nothing apart \ from affect the flags \ ****************************************************************************** \ \ Name: ou2 \ Type: Subroutine \ Category: Flight \ Summary: Display "E.C.M.SYSTEM DESTROYED" as an in-flight message \ \ ****************************************************************************** .ou2 LDA #108 \ Set A to recursive token 108 ("E.C.M.SYSTEM") EQUB &2C \ Fall through into ou3 to print the new message, but \ skip the first instruction by turning it into \ &2C &A9 &6F, or BIT &6FA9, which does nothing apart \ from affect the flags \ ****************************************************************************** \ \ Name: ou3 \ Type: Subroutine \ Category: Flight \ Summary: Display "FUEL SCOOPS DESTROYED" as an in-flight message \ \ ****************************************************************************** .ou3 LDA #111 \ Set A to recursive token 111 ("FUEL SCOOPS") \ ****************************************************************************** \ \ Name: MESS \ Type: Subroutine \ Category: Flight \ Summary: Display an in-flight message \ \ ------------------------------------------------------------------------------ \ \ Display an in-flight message in capitals at the bottom of the space view, \ erasing any existing in-flight message first. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ A The text token to be printed \ \ ****************************************************************************** .MESS LDX #0 \ Set QQ17 = 0 to switch to ALL CAPS STX QQ17 LDY #9 \ Move the text cursor to column 9, row 22, at the STY XC \ bottom middle of the screen, and set Y = 22 LDY #22 STY YC CPX DLY \ If the message delay in DLY is not zero, jump up to BNE me1 \ me1 to erase the current message first (whose token \ number will be in MCH) STY DLY \ Set the message delay in DLY to 22 STA MCH \ Set MCH to the token we are about to display \ Fall through into mes9 to print the token in A \ ****************************************************************************** \ \ Name: mes9 \ Type: Subroutine \ Category: Flight \ Summary: Print a text token, possibly followed by " DESTROYED" \ \ ------------------------------------------------------------------------------ \ \ Print a text token, followed by " DESTROYED" if the destruction flag is set \ (for when a piece of equipment is destroyed). \ \ ****************************************************************************** .mes9 JSR TT27 \ Call TT27 to print the text token in A LSR de \ If bit 0 of variable de is clear, return from the BCC out \ subroutine (as out contains an RTS) LDA #253 \ Print recursive token 93 (" DESTROYED") and return JMP TT27 \ from the subroutine using a tail call \ ****************************************************************************** \ \ Name: OUCH \ Type: Subroutine \ Category: Flight \ Summary: Potentially lose cargo or equipment following damage \ \ ------------------------------------------------------------------------------ \ \ Our shields are dead and we are taking damage, so there is a small chance of \ losing cargo or equipment. \ \ ****************************************************************************** .OUCH JSR DORND \ Set A and X to random numbers BMI out \ If A < 0 (50% chance), return from the subroutine \ (as out contains an RTS) CPX #22 \ If X >= 22 (91% chance), return from the subroutine BCS out \ (as out contains an RTS) LDA QQ20,X \ If we do not have any of item QQ20+X, return from the BEQ out \ subroutine (as out contains an RTS). X is in the range \ 0-21, so this not only checks for cargo, but also for \ E.C.M., fuel scoops, energy bomb, energy unit and \ docking computer, all of which can be destroyed LDA DLY \ If there is already an in-flight message on-screen, BNE out \ return from the subroutine (as out contains an RTS) LDY #3 \ Set bit 1 of de, the equipment destruction flag, so STY de \ that when we call MESS below, " DESTROYED" is appended \ to the in-flight message STA QQ20,X \ A is 0 (as we didn't branch with the BNE above), so \ this sets QQ20+X to 0, which destroys any cargo or \ equipment we have of that type CPX #17 \ If X >= 17 then we just lost a piece of equipment, so BCS ou1 \ jump to ou1 to print the relevant message TXA \ Print recursive token 48 + A as an in-flight token, ADC #208 \ which will be in the range 48 ("FOOD") to 64 ("ALIEN BNE MESS \ ITEMS") as the C flag is clear, so this prints the \ destroyed item's name, followed by " DESTROYED" (as we \ set bit 1 of the de flag above), and returns from the \ subroutine using a tail call .ou1 BEQ ou2 \ If X = 17, jump to ou2 to print "E.C.M.SYSTEM \ DESTROYED" and return from the subroutine using a tail \ call CPX #18 \ If X = 18, jump to ou3 to print "FUEL SCOOPS BEQ ou3 \ DESTROYED" and return from the subroutine using a tail \ call TXA \ Otherwise X is in the range 19 to 21 and the C flag is ADC #113-20 \ set (as we got here via a BCS to ou1), so we set A as \ follows: \ \ A = 113 - 20 + X + C \ = 113 - 19 + X \ = 113 to 115 BNE MESS \ Print recursive token A ("ENERGY BOMB", "ENERGY UNIT" \ or "DOCKING COMPUTERS") as an in-flight message, \ followed by " DESTROYED", and return from the \ subroutine using a tail call \ ****************************************************************************** \ \ Name: QQ16 \ Type: Variable \ Category: Text \ Summary: The two-letter token lookup table \ Deep dive: Printing text tokens \ \ ------------------------------------------------------------------------------ \ \ Two-letter token lookup table for tokens 128-159. \ \ ****************************************************************************** .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 159 \ ****************************************************************************** \ \ Name: ITEM \ Type: Macro \ Category: Market \ Summary: Macro definition for the market prices table \ Deep dive: Market item prices and availability \ \ ------------------------------------------------------------------------------ \ \ The following macro is used to build the market prices table: \ \ ITEM price, factor, units, quantity, mask \ \ It inserts an item into the market prices table at QQ23. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ price Base price \ \ factor Economic factor \ \ units Units: "t", "g" or "k" \ \ quantity Base quantity \ \ mask Fluctuations mask \ \ ****************************************************************************** MACRO ITEM price, factor, units, quantity, mask IF factor < 0 s = 1 << 7 ELSE s = 0 ENDIF IF units = 't' u = 0 ELIF units = 'k' u = 1 << 5 ELSE u = 1 << 6 ENDIF e = ABS(factor) EQUB price EQUB s + u + e EQUB quantity EQUB mask ENDMACRO \ ****************************************************************************** \ \ Name: QQ23 \ Type: Variable \ Category: Market \ Summary: Market prices table \ Deep dive: Market item prices and availability \ \ ------------------------------------------------------------------------------ \ \ Each item has four bytes of data, like this: \ \ Byte #0 = Base price \ Byte #1 = Economic factor in bits 0-4, with the sign in bit 7 \ Unit in bits 5-6 \ Byte #2 = Base quantity \ Byte #3 = Mask to control price fluctuations \ \ To make it easier for humans to follow, I've defined a macro called ITEM \ that takes the following arguments and builds the four bytes for us: \ \ ITEM base price, economic factor, units, base quantity, mask \ \ So for food, we have the following, for example: \ \ * Base price = 19 \ * Economic factor = -2 \ * Unit = tonnes \ * Base quantity = 6 \ * Mask = %00000001 \ \ ****************************************************************************** .QQ23 ITEM 19, -2, 't', 6, %00000001 \ 0 = Food ITEM 20, -1, 't', 10, %00000011 \ 1 = Textiles ITEM 65, -3, 't', 2, %00000111 \ 2 = Radioactives ITEM 40, -5, 't', 226, %00011111 \ 3 = Slaves ITEM 83, -5, 't', 251, %00001111 \ 4 = Liquor/Wines ITEM 196, 8, 't', 54, %00000011 \ 5 = Luxuries ITEM 235, 29, 't', 8, %01111000 \ 6 = Narcotics ITEM 154, 14, 't', 56, %00000011 \ 7 = Computers ITEM 117, 6, 't', 40, %00000111 \ 8 = Machinery ITEM 78, 1, 't', 17, %00011111 \ 9 = Alloys ITEM 124, 13, 't', 29, %00000111 \ 10 = Firearms ITEM 176, -9, 't', 220, %00111111 \ 11 = Furs ITEM 32, -1, 't', 53, %00000011 \ 12 = Minerals ITEM 97, -1, 'k', 66, %00000111 \ 13 = Gold ITEM 171, -2, 'k', 55, %00011111 \ 14 = Platinum ITEM 45, -1, 'g', 250, %00001111 \ 15 = Gem-Stones ITEM 53, 15, 't', 192, %00000111 \ 16 = Alien items \ ****************************************************************************** \ \ Name: TIDY \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Orthonormalise the orientation vectors for a ship \ Deep dive: Tidying orthonormal vectors \ Orientation vectors \ \ ------------------------------------------------------------------------------ \ \ This routine orthonormalises the orientation vectors for a ship. This means \ making the three orientation vectors orthogonal (perpendicular to each other), \ and normal (so each of the vectors has length 1). \ \ We do this because we use the small angle approximation to rotate these \ vectors in space. It is not completely accurate, so the three vectors tend \ to get stretched over time, so periodically we tidy the vectors with this \ routine to ensure they remain as orthonormal as possible. \ \ ****************************************************************************** .TI2 \ Called from below with A = 0, X = 0, Y = 4 when \ nosev_x and nosev_y are small, so we assume that \ nosev_z is big TYA \ A = Y = 4 LDY #2 JSR TIS3 \ Call TIS3 with X = 0, Y = 2, A = 4, to set roofv_z = STA INWK+20 \ -(nosev_x * roofv_x + nosev_y * roofv_y) / nosev_z JMP TI3 \ Jump to TI3 to keep tidying .TI1 \ Called from below with A = 0, Y = 4 when nosev_x is \ small TAX \ Set X = A = 0 LDA XX15+1 \ Set A = nosev_y, and if the top two magnitude bits AND #%01100000 \ are both clear, jump to TI2 with A = 0, X = 0, Y = 4 BEQ TI2 LDA #2 \ Otherwise nosev_y is big, so set up the index values \ to pass to TIS3 JSR TIS3 \ Call TIS3 with X = 0, Y = 4, A = 2, to set roofv_y = STA INWK+18 \ -(nosev_x * roofv_x + nosev_z * roofv_z) / nosev_y JMP TI3 \ Jump to TI3 to keep tidying .TIDY LDA INWK+10 \ Set (XX15, XX15+1, XX15+2) = nosev STA XX15 LDA INWK+12 STA XX15+1 LDA INWK+14 STA XX15+2 JSR NORM \ Call NORM to normalise the vector in XX15, i.e. nosev LDA XX15 \ Set nosev = (XX15, XX15+1, XX15+2) STA INWK+10 LDA XX15+1 STA INWK+12 LDA XX15+2 STA INWK+14 LDY #4 \ Set Y = 4 LDA XX15 \ Set A = nosev_x, and if the top two magnitude bits AND #%01100000 \ are both clear, jump to TI1 with A = 0, Y = 4 BEQ TI1 LDX #2 \ Otherwise nosev_x is big, so set up the index values LDA #0 \ to pass to TIS3 JSR TIS3 \ Call TIS3 with X = 2, Y = 4, A = 0, to set roofv_x = STA INWK+16 \ -(nosev_y * roofv_y + nosev_z * roofv_z) / nosev_x .TI3 LDA INWK+16 \ Set (XX15, XX15+1, XX15+2) = roofv STA XX15 LDA INWK+18 STA XX15+1 LDA INWK+20 STA XX15+2 JSR NORM \ Call NORM to normalise the vector in XX15, i.e. roofv LDA XX15 \ Set roofv = (XX15, XX15+1, XX15+2) STA INWK+16 LDA XX15+1 STA INWK+18 LDA XX15+2 STA INWK+20 LDA INWK+12 \ Set Q = nosev_y STA Q LDA INWK+20 \ Set A = roofv_z JSR MULT12 \ Set (S R) = Q * A = nosev_y * roofv_z LDX INWK+14 \ Set X = nosev_z LDA INWK+18 \ Set A = roofv_y JSR TIS1 \ Set (A ?) = (-X * A + (S R)) / 96 \ = (-nosev_z * roofv_y + nosev_y * roofv_z) / 96 \ \ This also sets Q = nosev_z EOR #%10000000 \ Set sidev_x = -A STA INWK+22 \ = (nosev_z * roofv_y - nosev_y * roofv_z) / 96 LDA INWK+16 \ Set A = roofv_x JSR MULT12 \ Set (S R) = Q * A = nosev_z * roofv_x LDX INWK+10 \ Set X = nosev_x LDA INWK+20 \ Set A = roofv_z JSR TIS1 \ Set (A ?) = (-X * A + (S R)) / 96 \ = (-nosev_x * roofv_z + nosev_z * roofv_x) / 96 \ \ This also sets Q = nosev_x EOR #%10000000 \ Set sidev_y = -A STA INWK+24 \ = (nosev_x * roofv_z - nosev_z * roofv_x) / 96 LDA INWK+18 \ Set A = roofv_y JSR MULT12 \ Set (S R) = Q * A = nosev_x * roofv_y LDX INWK+12 \ Set X = nosev_y LDA INWK+16 \ Set A = roofv_x JSR TIS1 \ Set (A ?) = (-X * A + (S R)) / 96 \ = (-nosev_y * roofv_x + nosev_x * roofv_y) / 96 EOR #%10000000 \ Set sidev_z = -A STA INWK+26 \ = (nosev_y * roofv_x - nosev_x * roofv_y) / 96 LDA #0 \ Set A = 0 so we can clear the low bytes of the \ orientation vectors LDX #14 \ We want to clear the low bytes, so start from sidev_y \ at byte #9+14 (we clear all except sidev_z_lo, though \ I suspect this is in error and that X should be 16) .TIL1 STA INWK+9,X \ Set the low byte in byte #9+X to zero DEX \ Set X = X - 2 to jump down to the next low byte DEX BPL TIL1 \ Loop back until we have zeroed all the low bytes RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TIS2 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate A = A / Q \ Deep dive: Shift-and-subtract division \ \ ------------------------------------------------------------------------------ \ \ Calculate the following division, where A is a sign-magnitude number and Q is \ a positive integer: \ \ A = A / Q \ \ The value of A is returned as a sign-magnitude number with 96 representing 1, \ and the maximum value returned is 1 (i.e. 96). This routine is used when \ normalising vectors, where we represent fractions using integers, so this \ gives us an approximation to two decimal places. \ \ ****************************************************************************** .TIS2 TAY \ Store the argument A in Y AND #%01111111 \ Strip the sign bit from the argument, so A = |A| CMP Q \ If A >= Q then jump to TI4 to return a 1 with the BCS TI4 \ correct sign LDX #%11111110 \ Set T to have bits 1-7 set, so we can rotate through 7 STX T \ loop iterations, getting a 1 each time, and then \ getting a 0 on the 8th iteration... and we can also \ use T to catch our result bits into bit 0 each time .TIL2 ASL A \ Shift A to the left CMP Q \ If A < Q skip the following subtraction BCC P%+4 SBC Q \ A >= Q, so set A = A - Q \ \ Going into this subtraction we know the C flag is \ set as we passed through the BCC above, and we also \ know that A >= Q, so the C flag will still be set once \ we are done ROL T \ Rotate the counter in T 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 TIL2 \ If we still have set bits in T, loop back to TIL2 to \ do the next iteration of 7 \ We've done the division and now have a result in the \ range 0-255 here, which we need to reduce to the range \ 0-96. We can do that by multiplying the result by 3/8, \ as 256 * 3/8 = 96 LDA T \ Set T = T / 4 LSR A LSR A STA T LSR A \ Set T = T / 8 + T / 4 ADC T \ = 3T / 8 STA T TYA \ Fetch the sign bit of the original argument A AND #%10000000 ORA T \ Apply the sign bit to T RTS \ Return from the subroutine .TI4 TYA \ Fetch the sign bit of the original argument A AND #%10000000 ORA #96 \ Apply the sign bit to 96 (which represents 1) RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: TIS3 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate -(nosev_1 * roofv_1 + nosev_2 * roofv_2) / nosev_3 \ \ ------------------------------------------------------------------------------ \ \ Calculate the following expression: \ \ A = -(nosev_1 * roofv_1 + nosev_2 * roofv_2) / nosev_3 \ \ where 1, 2 and 3 are x, y, or z, depending on the values of X, Y and A. This \ routine is called with the following values: \ \ X = 0, Y = 2, A = 4 -> \ A = -(nosev_x * roofv_x + nosev_y * roofv_y) / nosev_z \ \ X = 0, Y = 4, A = 2 -> \ A = -(nosev_x * roofv_x + nosev_z * roofv_z) / nosev_y \ \ X = 2, Y = 4, A = 0 -> \ A = -(nosev_y * roofv_y + nosev_z * roofv_z) / nosev_x \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ X Index 1 (0 = x, 2 = y, 4 = z) \ \ Y Index 2 (0 = x, 2 = y, 4 = z) \ \ A Index 3 (0 = x, 2 = y, 4 = z) \ \ ****************************************************************************** .TIS3 STA P+2 \ Store P+2 in A for later LDA INWK+10,X \ Set Q = nosev_x_hi (plus X) STA Q LDA INWK+16,X \ Set A = roofv_x_hi (plus X) JSR MULT12 \ Set (S R) = Q * A \ = nosev_x_hi * roofv_x_hi LDX INWK+10,Y \ Set Q = nosev_x_hi (plus Y) STX Q LDA INWK+16,Y \ Set A = roofv_x_hi (plus Y) JSR MAD \ Set (A X) = Q * A + (S R) \ = (nosev_x,X * roofv_x,X) + \ (nosev_x,Y * roofv_x,Y) STX P \ Store low byte of result in P, so result is now in \ (A P) LDY P+2 \ Set Q = roofv_x_hi (plus argument A) LDX INWK+10,Y STX Q EOR #%10000000 \ Flip the sign of A \ Fall through into DIVDT to do: \ \ (P+1 A) = (A P) / Q \ \ = -((nosev_x,X * roofv_x,X) + \ (nosev_x,Y * roofv_x,Y)) \ / nosev_x,A \ ****************************************************************************** \ \ Name: DVIDT \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (P+1 A) = (A P) / Q \ \ ------------------------------------------------------------------------------ \ \ Calculate the following integer division between sign-magnitude numbers: \ \ (P+1 A) = (A P) / Q \ \ This uses the same shift-and-subtract algorithm as TIS2. \ \ ****************************************************************************** .DVIDT STA P+1 \ Set P+1 = A, so P(1 0) = (A P) EOR Q \ Set T = the sign bit of A EOR Q, so it's 1 if A and Q AND #%10000000 \ have different signs, i.e. it's the sign of the result STA T \ of A / Q LDA #0 \ Set A = 0 for us to build a result LDX #16 \ Set a counter in X to count the 16 bits in P(1 0) ASL P \ Shift P(1 0) left ROL P+1 ASL Q \ Clear the sign bit of Q the C flag at the same time LSR Q .DVL2 ROL A \ Shift A to the left CMP Q \ If A < Q skip the following subtraction BCC P%+4 SBC Q \ Set A = A - Q \ \ Going into this subtraction we know the C flag is \ set as we passed through the BCC above, and we also \ know that A >= Q, so the C flag will still be set once \ we are done ROL P \ Rotate P(1 0) to the left, and catch the result bit ROL P+1 \ into the C flag (which will be a 0 if we didn't \ do the subtraction, or 1 if we did) DEX \ Decrement the loop counter BNE DVL2 \ Loop back for the next bit until we have done all 16 \ bits of P(1 0) LDA P \ Set A = P so the low byte is in the result in A ORA T \ Set A to the correct sign bit that we set in T above RTS \ Return from the subroutine \ ****************************************************************************** \ \ Save ELTF.bin \ \ ****************************************************************************** PRINT "ELITE F" PRINT "Assembled at ", ~CODE_F% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_F%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_F% PRINT "S.ELTF ", ~CODE_F%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_F% SAVE "3-assembled-output/ELTF.bin", CODE_F%, P%, LOAD% \ ****************************************************************************** \ \ ELITE G FILE \ \ Produces the binary file ELTG.bin that gets loaded by elite-bcfs.asm. \ \ ****************************************************************************** CODE_G% = P% LOAD_G% = LOAD% + P% - CODE% \ ****************************************************************************** \ \ Name: SHPPT \ Type: Subroutine \ Category: Drawing ships \ Summary: Draw a distant ship as a point rather than a full wireframe \ \ ****************************************************************************** .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) \ \ The addition works as the Shpt routine clears the C \ flag 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 four-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 (i.e. Y1) INY \ Store A in byte Y+2 of the ship line heap (i.e. Y2) 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 (i.e. X2) 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 (i.e. X1) DEY STA (XX19),Y RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: LL5 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate Q = SQRT(R Q) \ Deep dive: Calculating square roots \ \ ------------------------------------------------------------------------------ \ \ Calculate the following square root: \ \ Q = SQRT(R Q) \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Name: LL28 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate R = 256 * A / Q \ Deep dive: Shift-and-subtract division \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Name: LL38 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (S A) = (S R) + (A Q) \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Name: LL51 \ Type: Subroutine \ Category: Maths (Geometry) \ Summary: Calculate the dot product of XX15 and XX16 \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Name: LL9 (Part 1 of 12) \ Type: Subroutine \ Category: Drawing ships \ Summary: Draw ship: Check if ship is exploding, check if ship is in front \ Deep dive: Drawing ships \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .LL25 JMP PLANET \ Jump to the PLANET routine, returning from the \ subroutine using a tail call .LL9 LDA TYPE \ If the ship type is negative then this indicates a BMI LL25 \ planet or sun, so jump to PLANET via LL25 above 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 #%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 \LDA XX1+32 \ These instructions are commented out in the original \AND #&7F \ source \ 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 \.LL24 \ This label is commented out in the original source, \ and was presumably used to label the RTS which is \ actually called by LL10-1 above, not LL24 RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: LL9 (Part 2 of 12) \ Type: Subroutine \ Category: Drawing ships \ Summary: Draw ship: Check if ship is in field of view, close enough to draw \ Deep dive: Drawing ships \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .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 at 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 call \ ****************************************************************************** \ \ Name: LL9 (Part 3 of 12) \ Type: Subroutine \ Category: Drawing ships \ Summary: Draw ship: Set up orientation vector, ship coordinate variables \ Deep dive: Drawing ships \ \ ------------------------------------------------------------------------------ \ \ 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 space \ \ ****************************************************************************** .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, but this allows us to force a vertex \ to always be visible by associating it with face 15 \ (see the ship blueprints for the Cobra Mk III at \ SHIP_COBRA_MK_3 and the asteroid at SHIP_ASTEROID for \ examples of vertices that are associated with face 15) 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 ship \ ****************************************************************************** \ \ Name: LL9 (Part 4 of 12) \ Type: Subroutine \ Category: Drawing ships \ Summary: Draw ship: Set visibility for exploding ship (all faces visible) \ Deep dive: Drawing ships \ \ ------------------------------------------------------------------------------ \ \ 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. \ \ ****************************************************************************** LDA (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 explosion \ ****************************************************************************** \ \ Name: LL9 (Part 5 of 12) \ Type: Subroutine \ Category: Drawing ships \ Summary: Draw ship: Calculate the visibility of each of the ship's faces \ Deep dive: Drawing ships \ Back-face culling \ \ ****************************************************************************** .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 face \ ****************************************************************************** \ \ Name: LL9 (Part 6 of 12) \ 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 \ \ ****************************************************************************** .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 yet \ ****************************************************************************** \ \ Name: LL61 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (U R) = 256 * A / Q \ \ ------------------------------------------------------------------------------ \ \ 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. \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Name: LL62 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate 128 - (U R) \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .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 LL66 \ ****************************************************************************** \ \ Name: LL9 (Part 7 of 12) \ 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 \ \ ****************************************************************************** .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 more \ ****************************************************************************** \ \ Name: LL9 (Part 8 of 12) \ 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) \ \ LL66 A re-entry point into the ship-drawing routine, used by \ the LL62 routine to store 128 - (U R) on the XX3 heap \ \ ****************************************************************************** .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 LL50 to move on to the next vertex .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 vertex \ ****************************************************************************** \ \ Name: LL9 (Part 9 of 12) \ 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. \ \ ****************************************************************************** .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 #%00001000 \ #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 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 U \ ****************************************************************************** \ \ Name: LL9 (Part 10 of 12) \ 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. \ \ ****************************************************************************** .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 LL78 \ 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 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 zero then we decided in part 5 that BEQ 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 \ \ Byte #2 contains the vertex number multiplied by 4, \ so we can use it as an index into the heap at XX3 to \ fetch the vertex's screen coordinates, which are \ stored as four bytes containing two 16-bit numbers 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 \ \ Byte #3 contains the vertex number multiplied by 4, \ so we can use it as an index into the heap at XX3 to \ fetch the vertex's screen coordinates, which are \ stored as four bytes containing two 16-bit numbers 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 XX12+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 LL78 \ If the C flag is set then the line is not visible on \ screen, so jump to LL78 so we don't store this line \ in the ship line heap \ ****************************************************************************** \ \ Name: LL9 (Part 11 of 12) \ Type: Subroutine \ Category: Drawing ships \ Summary: Draw ship: Add all visible edges to the ship line heap \ Deep dive: Drawing ships \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .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 to \ skip the following instruction 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 up \ ****************************************************************************** \ \ Name: LL9 (Part 12 of 12) \ 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. \ \ ****************************************************************************** .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 \.LL82 \ This label is commented out in the original source RTS \ Return from the subroutine \ ****************************************************************************** \ \ Name: LL118 \ Type: Subroutine \ Category: Drawing lines \ Summary: Move a point along a line until it is on-screen \ Deep dive: Line-clipping \ \ ------------------------------------------------------------------------------ \ \ 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. \ \ ------------------------------------------------------------------------------ \ \ 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 gradient of slope: \ \ * 0 if it's a shallow slope \ \ * &FF if it's a steep slope \ \ ------------------------------------------------------------------------------ \ \ Returns: \ \ XX15 x1 as an 8-bit coordinate \ \ XX15+2 y1 as an 8-bit coordinate \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ LL118-1 Contains an RTS \ \ ****************************************************************************** .LL118 LDA XX15+1 \ If x1_hi is positive, jump down to LL119 to skip the BPL LL119 \ 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 \BNE LL139 \ This instruction is commented out in the original \ source LDA XX15+2 \ Set (S R) = (y1_hi y1_lo) - screen height 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 < screen \ height, 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 >= screen height, i.e. off the \ bottom of the screen JSR LL123 \ Call LL123 to calculate: \ \ (Y X) = (S R) / XX12+2 if T = 0 \ = (y1 - screen height) / gradient \ \ (Y X) = (S R) * XX12+2 if T <> 0 \ = (y1 - screen height) * 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 subroutine \ ****************************************************************************** \ \ Name: LL120 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (Y X) = (S x1_lo) * XX12+2 or (S x1_lo) / XX12+2 \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ * If T = 0, this is a shallow slope, so calculate (Y X) = (S x1_lo) * XX12+2 \ \ * If T <> 0, this is a steep slope, so calculate (Y X) = (S x1_lo) / XX12+2 \ \ giving (Y X) the opposite sign to the slope direction in XX12+3. \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ T The gradient of slope: \ \ * 0 if it's a shallow slope \ \ * &FF if it's a steep slope \ \ ------------------------------------------------------------------------------ \ \ Other entry points: \ \ LL122 Calculate (Y X) = (S R) * Q and set the sign to the \ opposite of the top byte on the stack \ \ ****************************************************************************** .LL120 LDA XX15 \ Set R = x1_lo STA R \.LL120 \ This label is commented out in the original source 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, then it's a steep slope, so jump BNE LL121 \ 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 subroutine \ ****************************************************************************** \ \ Name: LL123 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate (Y X) = (S R) / XX12+2 or (S R) * XX12+2 \ \ ------------------------------------------------------------------------------ \ \ Calculate the following: \ \ * If T = 0, this is a shallow slope, so calculate (Y X) = (S R) / XX12+2 \ \ * If T <> 0, this is a steep slope, so 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 \ \ T The gradient of slope: \ \ * 0 if it's a shallow slope \ \ * &FF if it's a steep slope \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .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, then it's a steep slope, so jump up BNE LL122 \ 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 \CLC \ ADC #1 \ The CLC instruction is commented out in the original TAX \ source. It would have no effect 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 subroutine \ ****************************************************************************** \ \ Name: LL129 \ Type: Subroutine \ Category: Maths (Arithmetic) \ Summary: Calculate Q = XX12+2, A = S EOR XX12+3 and (S R) = |S R| \ \ ------------------------------------------------------------------------------ \ \ 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 XX12+3. \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Name: LL145 (Part 1 of 4) \ Type: Subroutine \ Category: Drawing lines \ Summary: Clip line: Work out which end-points are on-screen, if any \ Deep dive: Line-clipping \ Extended screen coordinates \ \ ------------------------------------------------------------------------------ \ \ 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 \ \ ****************************************************************************** .LL145 LDA #0 \ Set SWAP = 0 STA SWAP LDA XX15+5 \ Set A = x2_hi .LL147 LDX #Y*2-1 \ Set X = #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, leaving X at 191 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 \ 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 \ screen edge (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 95 \ ****************************************************************************** \ \ Name: LL145 (Part 2 of 4) \ 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. \ \ ****************************************************************************** .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-screen \ ****************************************************************************** \ \ Name: LL145 (Part 3 of 4) \ Type: Subroutine \ Category: Drawing lines \ Summary: Clip line: Calculate the line's gradient \ Deep dive: Line-clipping \ Extended screen coordinates \ \ ****************************************************************************** .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 \ If we get here then our line is more horizontal than \ vertical, so it is a shallow slope 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 \ If we get here then our line is more vertical than \ horizontal, so it is a steep slope 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 = &FF when our \ line is steep \ ****************************************************************************** \ \ Name: LL145 (Part 4 of 4) \ 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 gradient of slope: \ \ * 0 = shallow slope (more horizontal than vertical) \ \ * &FF = steep slope (more vertical than horizontal) \ \ 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 \ \ ****************************************************************************** .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 subroutine \ ****************************************************************************** \ \ Save ELTG.bin \ \ ****************************************************************************** PRINT "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.ELTG ", ~CODE_G%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_G% SAVE "3-assembled-output/ELTG.bin", CODE_G%, P%, LOAD% \ ****************************************************************************** \ \ Name: checksum0 \ Type: Variable \ Category: Copy protection \ Summary: Checksum for the entire main game code \ \ ------------------------------------------------------------------------------ \ \ This byte contains a checksum for the entire main game code. It is populated \ by elite-checksum.py and is used by the encryption checks in elite-loader.asm \ (see the CHK routine in the loader for more details). \ \ ****************************************************************************** .checksum0 SKIP 1 \ This value is checked against the calculated checksum \ in part 6 of the loader in elite-loader.asm \ ****************************************************************************** \ \ ELITE SHIP BLUEPRINTS FILE \ \ Produces the binary file SHIPS.bin that gets loaded by elite-bcfs.asm. \ \ ****************************************************************************** CODE_SHIPS% = P% LOAD_SHIPS% = LOAD% + P% - CODE% \ ****************************************************************************** \ \ Name: XX21 \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprints lookup table \ Deep dive: Ship blueprints \ \ ****************************************************************************** .XX21 EQUW SHIP_SIDEWINDER \ 1 = Sidewinder EQUW SHIP_VIPER \ COPS = 2 = Viper EQUW SHIP_MAMBA \ 3 = Mamba EQUW SHIP_PYTHON \ 4 = Python EQUW SHIP_COBRA_MK_3 \ 5 = Cobra Mk III (bounty hunter) EQUW SHIP_THARGOID \ THG = 6 = Thargoid EQUW SHIP_COBRA_MK_3 \ CYL = 7 = Cobra Mk III (trader) EQUW SHIP_CORIOLIS \ SST = 8 = Coriolis space station EQUW SHIP_MISSILE \ MSL = 9 = Missile EQUW SHIP_ASTEROID \ AST = 10 = Asteroid EQUW SHIP_CANISTER \ OIL = 11 = Cargo canister EQUW SHIP_THARGON \ TGL = 12 = Thargon EQUW SHIP_ESCAPE_POD \ ESC = 13 = Escape pod \ ****************************************************************************** \ \ Name: VERTEX \ Type: Macro \ Category: Drawing ships \ Summary: Macro definition for adding vertices to ship blueprints \ Deep dive: Ship blueprints \ Drawing ships \ \ ------------------------------------------------------------------------------ \ \ The following macro is used to build the ship blueprints: \ \ VERTEX x, y, z, face1, face2, face3, face4, visibility \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ x The vertex's x-coordinate \ \ y The vertex's y-coordinate \ \ z The vertex's z-coordinate \ \ face1 The number of face 1 associated with this vertex \ \ face2 The number of face 2 associated with this vertex \ \ face3 The number of face 3 associated with this vertex \ \ face4 The number of face 4 associated with this vertex \ \ visibility The visibility distance, beyond which the vertex is not \ shown \ \ ****************************************************************************** MACRO VERTEX x, y, z, face1, face2, face3, face4, visibility IF x < 0 s_x = 1 << 7 ELSE s_x = 0 ENDIF IF y < 0 s_y = 1 << 6 ELSE s_y = 0 ENDIF IF z < 0 s_z = 1 << 5 ELSE s_z = 0 ENDIF s = s_x + s_y + s_z + visibility f1 = face1 + (face2 << 4) f2 = face3 + (face4 << 4) ax = ABS(x) ay = ABS(y) az = ABS(z) EQUB ax, ay, az, s, f1, f2 ENDMACRO \ ****************************************************************************** \ \ Name: EDGE \ Type: Macro \ Category: Drawing ships \ Summary: Macro definition for adding edges to ship blueprints \ Deep dive: Ship blueprints \ Drawing ships \ \ ------------------------------------------------------------------------------ \ \ The following macro is used to build the ship blueprints: \ \ EDGE vertex1, vertex2, face1, face2, visibility \ \ When stored in memory, bytes #2 and #3 contain the vertex numbers multiplied \ by 4, so we can use them as indices into the heap at XX3 to fetch the screen \ coordinates for each vertex, as they are stored as four bytes containing two \ 16-bit numbers (see part 10 of the LL9 routine for details). \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ vertex1 The number of the vertex at the start of the edge \ \ vertex1 The number of the vertex at the end of the edge \ \ face1 The number of face 1 associated with this edge \ \ face2 The number of face 2 associated with this edge \ \ visibility The visibility distance, beyond which the edge is not \ shown \ \ ****************************************************************************** MACRO EDGE vertex1, vertex2, face1, face2, visibility f = face1 + (face2 << 4) EQUB visibility, f, vertex1 << 2, vertex2 << 2 ENDMACRO \ ****************************************************************************** \ \ Name: FACE \ Type: Macro \ Category: Drawing ships \ Summary: Macro definition for adding faces to ship blueprints \ Deep dive: Ship blueprints \ Drawing ships \ \ ------------------------------------------------------------------------------ \ \ The following macro is used to build the ship blueprints: \ \ FACE normal_x, normal_y, normal_z, visibility \ \ ------------------------------------------------------------------------------ \ \ Arguments: \ \ normal_x The face normal's x-coordinate \ \ normal_y The face normal's y-coordinate \ \ normal_z The face normal's z-coordinate \ \ visibility The visibility distance, beyond which the edge is always \ shown \ \ ****************************************************************************** MACRO FACE normal_x, normal_y, normal_z, visibility IF normal_x < 0 s_x = 1 << 7 ELSE s_x = 0 ENDIF IF normal_y < 0 s_y = 1 << 6 ELSE s_y = 0 ENDIF IF normal_z < 0 s_z = 1 << 5 ELSE s_z = 0 ENDIF s = s_x + s_y + s_z + visibility ax = ABS(normal_x) ay = ABS(normal_y) az = ABS(normal_z) EQUB s, ax, ay, az ENDMACRO \ ****************************************************************************** \ \ Name: SHIP_SIDEWINDER \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a Sidewinder \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_SIDEWINDER EQUB 0 \ Max. canisters on demise = 0 EQUW 65 * 65 \ Targetable area = 65 * 65 EQUB LO(SHIP_SIDEWINDER_EDGES - SHIP_SIDEWINDER) \ Edges data offset (low) EQUB LO(SHIP_SIDEWINDER_FACES - SHIP_SIDEWINDER) \ Faces data offset (low) EQUB 61 \ Max. edge count = (61 - 1) / 4 = 15 EQUB 0 \ Gun vertex = 0 EQUB 30 \ Explosion count = 6, as (4 * n) + 6 = 30 EQUB 60 \ Number of vertices = 60 / 6 = 10 EQUB 15 \ Number of edges = 15 EQUW 50 \ Bounty = 50 EQUB 28 \ Number of faces = 28 / 4 = 7 EQUB 20 \ Visibility distance = 20 EQUB 70 \ Max. energy = 70 EQUB 37 \ Max. speed = 37 EQUB HI(SHIP_SIDEWINDER_EDGES - SHIP_SIDEWINDER) \ Edges data offset (high) EQUB HI(SHIP_SIDEWINDER_FACES - SHIP_SIDEWINDER) \ Faces data offset (high) EQUB 2 \ Normals are scaled by = 2^2 = 4 EQUB %00010000 \ Laser power = 2 \ Missiles = 0 .SHIP_SIDEWINDER_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX -32, 0, 36, 0, 1, 4, 5, 31 \ Vertex 0 VERTEX 32, 0, 36, 0, 2, 5, 6, 31 \ Vertex 1 VERTEX 64, 0, -28, 2, 3, 6, 6, 31 \ Vertex 2 VERTEX -64, 0, -28, 1, 3, 4, 4, 31 \ Vertex 3 VERTEX 0, 16, -28, 0, 1, 2, 3, 31 \ Vertex 4 VERTEX 0, -16, -28, 3, 4, 5, 6, 31 \ Vertex 5 VERTEX -12, 6, -28, 3, 3, 3, 3, 15 \ Vertex 6 VERTEX 12, 6, -28, 3, 3, 3, 3, 15 \ Vertex 7 VERTEX 12, -6, -28, 3, 3, 3, 3, 12 \ Vertex 8 VERTEX -12, -6, -28, 3, 3, 3, 3, 12 \ Vertex 9 .SHIP_SIDEWINDER_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 1, 0, 5, 31 \ Edge 0 EDGE 1, 2, 2, 6, 31 \ Edge 1 EDGE 1, 4, 0, 2, 31 \ Edge 2 EDGE 0, 4, 0, 1, 31 \ Edge 3 EDGE 0, 3, 1, 4, 31 \ Edge 4 EDGE 3, 4, 1, 3, 31 \ Edge 5 EDGE 2, 4, 2, 3, 31 \ Edge 6 EDGE 3, 5, 3, 4, 31 \ Edge 7 EDGE 2, 5, 3, 6, 31 \ Edge 8 EDGE 1, 5, 5, 6, 31 \ Edge 9 EDGE 0, 5, 4, 5, 31 \ Edge 10 EDGE 6, 7, 3, 3, 15 \ Edge 11 EDGE 7, 8, 3, 3, 12 \ Edge 12 EDGE 6, 9, 3, 3, 12 \ Edge 13 EDGE 8, 9, 3, 3, 12 \ Edge 14 .SHIP_SIDEWINDER_FACES \ normal_x, normal_y, normal_z, visibility FACE 0, 32, 8, 31 \ Face 0 FACE -12, 47, 6, 31 \ Face 1 FACE 12, 47, 6, 31 \ Face 2 FACE 0, 0, -112, 31 \ Face 3 FACE -12, -47, 6, 31 \ Face 4 FACE 0, -32, 8, 31 \ Face 5 FACE 12, -47, 6, 31 \ Face 6 \ ****************************************************************************** \ \ Name: SHIP_VIPER \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a Viper \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_VIPER EQUB 0 \ Max. canisters on demise = 0 EQUW 75 * 75 \ Targetable area = 75 * 75 EQUB LO(SHIP_VIPER_EDGES - SHIP_VIPER) \ Edges data offset (low) EQUB LO(SHIP_VIPER_FACES - SHIP_VIPER) \ Faces data offset (low) EQUB 77 \ Max. edge count = (77 - 1) / 4 = 19 EQUB 0 \ Gun vertex = 0 EQUB 42 \ Explosion count = 9, as (4 * n) + 6 = 42 EQUB 90 \ Number of vertices = 90 / 6 = 15 EQUB 20 \ Number of edges = 20 EQUW 0 \ Bounty = 0 EQUB 28 \ Number of faces = 28 / 4 = 7 EQUB 23 \ Visibility distance = 23 EQUB 120 \ Max. energy = 120 EQUB 32 \ Max. speed = 32 EQUB HI(SHIP_VIPER_EDGES - SHIP_VIPER) \ Edges data offset (high) EQUB HI(SHIP_VIPER_FACES - SHIP_VIPER) \ Faces data offset (high) EQUB 1 \ Normals are scaled by = 2^1 = 2 EQUB %00010001 \ Laser power = 2 \ Missiles = 1 .SHIP_VIPER_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 0, 0, 72, 1, 2, 3, 4, 31 \ Vertex 0 VERTEX 0, 16, 24, 0, 1, 2, 2, 30 \ Vertex 1 VERTEX 0, -16, 24, 3, 4, 5, 5, 30 \ Vertex 2 VERTEX 48, 0, -24, 2, 4, 6, 6, 31 \ Vertex 3 VERTEX -48, 0, -24, 1, 3, 6, 6, 31 \ Vertex 4 VERTEX 24, -16, -24, 4, 5, 6, 6, 30 \ Vertex 5 VERTEX -24, -16, -24, 5, 3, 6, 6, 30 \ Vertex 6 VERTEX 24, 16, -24, 0, 2, 6, 6, 31 \ Vertex 7 VERTEX -24, 16, -24, 0, 1, 6, 6, 31 \ Vertex 8 VERTEX -32, 0, -24, 6, 6, 6, 6, 19 \ Vertex 9 VERTEX 32, 0, -24, 6, 6, 6, 6, 19 \ Vertex 10 VERTEX 8, 8, -24, 6, 6, 6, 6, 19 \ Vertex 11 VERTEX -8, 8, -24, 6, 6, 6, 6, 19 \ Vertex 12 VERTEX -8, -8, -24, 6, 6, 6, 6, 18 \ Vertex 13 VERTEX 8, -8, -24, 6, 6, 6, 6, 18 \ Vertex 14 .SHIP_VIPER_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 3, 2, 4, 31 \ Edge 0 EDGE 0, 1, 1, 2, 30 \ Edge 1 EDGE 0, 2, 3, 4, 30 \ Edge 2 EDGE 0, 4, 1, 3, 31 \ Edge 3 EDGE 1, 7, 0, 2, 30 \ Edge 4 EDGE 1, 8, 0, 1, 30 \ Edge 5 EDGE 2, 5, 4, 5, 30 \ Edge 6 EDGE 2, 6, 3, 5, 30 \ Edge 7 EDGE 7, 8, 0, 6, 31 \ Edge 8 EDGE 5, 6, 5, 6, 30 \ Edge 9 EDGE 4, 8, 1, 6, 31 \ Edge 10 EDGE 4, 6, 3, 6, 30 \ Edge 11 EDGE 3, 7, 2, 6, 31 \ Edge 12 EDGE 3, 5, 6, 4, 30 \ Edge 13 EDGE 9, 12, 6, 6, 19 \ Edge 14 EDGE 9, 13, 6, 6, 18 \ Edge 15 EDGE 10, 11, 6, 6, 19 \ Edge 16 EDGE 10, 14, 6, 6, 18 \ Edge 17 EDGE 11, 14, 6, 6, 16 \ Edge 18 EDGE 12, 13, 6, 6, 16 \ Edge 19 .SHIP_VIPER_FACES \ normal_x, normal_y, normal_z, visibility FACE 0, 32, 0, 31 \ Face 0 FACE -22, 33, 11, 31 \ Face 1 FACE 22, 33, 11, 31 \ Face 2 FACE -22, -33, 11, 31 \ Face 3 FACE 22, -33, 11, 31 \ Face 4 FACE 0, -32, 0, 31 \ Face 5 FACE 0, 0, -48, 31 \ Face 6 \ ****************************************************************************** \ \ Name: SHIP_MAMBA \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a Mamba \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_MAMBA EQUB 1 \ Max. canisters on demise = 1 EQUW 70 * 70 \ Targetable area = 70 * 70 EQUB LO(SHIP_MAMBA_EDGES - SHIP_MAMBA) \ Edges data offset (low) EQUB LO(SHIP_MAMBA_FACES - SHIP_MAMBA) \ Faces data offset (low) EQUB 93 \ Max. edge count = (93 - 1) / 4 = 23 EQUB 0 \ Gun vertex = 0 EQUB 34 \ Explosion count = 7, as (4 * n) + 6 = 34 EQUB 150 \ Number of vertices = 150 / 6 = 25 EQUB 28 \ Number of edges = 28 EQUW 150 \ Bounty = 150 EQUB 20 \ Number of faces = 20 / 4 = 5 EQUB 25 \ Visibility distance = 25 EQUB 90 \ Max. energy = 90 EQUB 30 \ Max. speed = 30 EQUB HI(SHIP_MAMBA_EDGES - SHIP_MAMBA) \ Edges data offset (high) EQUB HI(SHIP_MAMBA_FACES - SHIP_MAMBA) \ Faces data offset (high) EQUB 2 \ Normals are scaled by = 2^2 = 4 EQUB %00010010 \ Laser power = 2 \ Missiles = 2 .SHIP_MAMBA_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 0, 0, 64, 0, 1, 2, 3, 31 \ Vertex 0 VERTEX -64, -8, -32, 0, 2, 4, 4, 31 \ Vertex 1 VERTEX -32, 8, -32, 1, 2, 4, 4, 30 \ Vertex 2 VERTEX 32, 8, -32, 1, 3, 4, 4, 30 \ Vertex 3 VERTEX 64, -8, -32, 0, 3, 4, 4, 31 \ Vertex 4 VERTEX -4, 4, 16, 1, 1, 1, 1, 14 \ Vertex 5 VERTEX 4, 4, 16, 1, 1, 1, 1, 14 \ Vertex 6 VERTEX 8, 3, 28, 1, 1, 1, 1, 13 \ Vertex 7 VERTEX -8, 3, 28, 1, 1, 1, 1, 13 \ Vertex 8 VERTEX -20, -4, 16, 0, 0, 0, 0, 20 \ Vertex 9 VERTEX 20, -4, 16, 0, 0, 0, 0, 20 \ Vertex 10 VERTEX -24, -7, -20, 0, 0, 0, 0, 20 \ Vertex 11 VERTEX -16, -7, -20, 0, 0, 0, 0, 16 \ Vertex 12 VERTEX 16, -7, -20, 0, 0, 0, 0, 16 \ Vertex 13 VERTEX 24, -7, -20, 0, 0, 0, 0, 20 \ Vertex 14 VERTEX -8, 4, -32, 4, 4, 4, 4, 13 \ Vertex 15 VERTEX 8, 4, -32, 4, 4, 4, 4, 13 \ Vertex 16 VERTEX 8, -4, -32, 4, 4, 4, 4, 14 \ Vertex 17 VERTEX -8, -4, -32, 4, 4, 4, 4, 14 \ Vertex 18 VERTEX -32, 4, -32, 4, 4, 4, 4, 7 \ Vertex 19 VERTEX 32, 4, -32, 4, 4, 4, 4, 7 \ Vertex 20 VERTEX 36, -4, -32, 4, 4, 4, 4, 7 \ Vertex 21 VERTEX -36, -4, -32, 4, 4, 4, 4, 7 \ Vertex 22 VERTEX -38, 0, -32, 4, 4, 4, 4, 5 \ Vertex 23 VERTEX 38, 0, -32, 4, 4, 4, 4, 5 \ Vertex 24 .SHIP_MAMBA_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 1, 0, 2, 31 \ Edge 0 EDGE 0, 4, 0, 3, 31 \ Edge 1 EDGE 1, 4, 0, 4, 31 \ Edge 2 EDGE 1, 2, 2, 4, 30 \ Edge 3 EDGE 2, 3, 1, 4, 30 \ Edge 4 EDGE 3, 4, 3, 4, 30 \ Edge 5 EDGE 5, 6, 1, 1, 14 \ Edge 6 EDGE 6, 7, 1, 1, 12 \ Edge 7 EDGE 7, 8, 1, 1, 13 \ Edge 8 EDGE 5, 8, 1, 1, 12 \ Edge 9 EDGE 9, 11, 0, 0, 20 \ Edge 10 EDGE 9, 12, 0, 0, 16 \ Edge 11 EDGE 10, 13, 0, 0, 16 \ Edge 12 EDGE 10, 14, 0, 0, 20 \ Edge 13 EDGE 13, 14, 0, 0, 14 \ Edge 14 EDGE 11, 12, 0, 0, 14 \ Edge 15 EDGE 15, 16, 4, 4, 13 \ Edge 16 EDGE 17, 18, 4, 4, 14 \ Edge 17 EDGE 15, 18, 4, 4, 12 \ Edge 18 EDGE 16, 17, 4, 4, 12 \ Edge 19 EDGE 20, 21, 4, 4, 7 \ Edge 20 EDGE 20, 24, 4, 4, 5 \ Edge 21 EDGE 21, 24, 4, 4, 5 \ Edge 22 EDGE 19, 22, 4, 4, 7 \ Edge 23 EDGE 19, 23, 4, 4, 5 \ Edge 24 EDGE 22, 23, 4, 4, 5 \ Edge 25 EDGE 0, 2, 1, 2, 30 \ Edge 26 EDGE 0, 3, 1, 3, 30 \ Edge 27 .SHIP_MAMBA_FACES \ normal_x, normal_y, normal_z, visibility FACE 0, -24, 2, 30 \ Face 0 FACE 0, 24, 2, 30 \ Face 1 FACE -32, 64, 16, 30 \ Face 2 FACE 32, 64, 16, 30 \ Face 3 FACE 0, 0, -127, 30 \ Face 4 \ ****************************************************************************** \ \ Name: SHIP_COBRA_MK_3 \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a Cobra Mk III \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_COBRA_MK_3 EQUB 3 \ Max. canisters on demise = 3 EQUW 95 * 95 \ Targetable area = 95 * 95 EQUB LO(SHIP_COBRA_MK_3_EDGES - SHIP_COBRA_MK_3) \ Edges data offset (low) EQUB LO(SHIP_COBRA_MK_3_FACES - SHIP_COBRA_MK_3) \ Faces data offset (low) EQUB 153 \ Max. edge count = (153 - 1) / 4 = 38 EQUB 84 \ Gun vertex = 84 / 4 = 21 EQUB 42 \ Explosion count = 9, as (4 * n) + 6 = 42 EQUB 168 \ Number of vertices = 168 / 6 = 28 EQUB 38 \ Number of edges = 38 EQUW 0 \ Bounty = 0 EQUB 52 \ Number of faces = 52 / 4 = 13 EQUB 50 \ Visibility distance = 50 EQUB 150 \ Max. energy = 150 EQUB 28 \ Max. speed = 28 EQUB HI(SHIP_COBRA_MK_3_EDGES - SHIP_COBRA_MK_3) \ Edges data offset (low) EQUB HI(SHIP_COBRA_MK_3_FACES - SHIP_COBRA_MK_3) \ Faces data offset (low) EQUB 1 \ Normals are scaled by = 2^1 = 2 EQUB %00010011 \ Laser power = 2 \ Missiles = 3 .SHIP_COBRA_MK_3_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 32, 0, 76, 15, 15, 15, 15, 31 \ Vertex 0 VERTEX -32, 0, 76, 15, 15, 15, 15, 31 \ Vertex 1 VERTEX 0, 26, 24, 15, 15, 15, 15, 31 \ Vertex 2 VERTEX -120, -3, -8, 3, 7, 10, 10, 31 \ Vertex 3 VERTEX 120, -3, -8, 4, 8, 12, 12, 31 \ Vertex 4 VERTEX -88, 16, -40, 15, 15, 15, 15, 31 \ Vertex 5 VERTEX 88, 16, -40, 15, 15, 15, 15, 31 \ Vertex 6 VERTEX 128, -8, -40, 8, 9, 12, 12, 31 \ Vertex 7 VERTEX -128, -8, -40, 7, 9, 10, 10, 31 \ Vertex 8 VERTEX 0, 26, -40, 5, 6, 9, 9, 31 \ Vertex 9 VERTEX -32, -24, -40, 9, 10, 11, 11, 31 \ Vertex 10 VERTEX 32, -24, -40, 9, 11, 12, 12, 31 \ Vertex 11 VERTEX -36, 8, -40, 9, 9, 9, 9, 20 \ Vertex 12 VERTEX -8, 12, -40, 9, 9, 9, 9, 20 \ Vertex 13 VERTEX 8, 12, -40, 9, 9, 9, 9, 20 \ Vertex 14 VERTEX 36, 8, -40, 9, 9, 9, 9, 20 \ Vertex 15 VERTEX 36, -12, -40, 9, 9, 9, 9, 20 \ Vertex 16 VERTEX 8, -16, -40, 9, 9, 9, 9, 20 \ Vertex 17 VERTEX -8, -16, -40, 9, 9, 9, 9, 20 \ Vertex 18 VERTEX -36, -12, -40, 9, 9, 9, 9, 20 \ Vertex 19 VERTEX 0, 0, 76, 0, 11, 11, 11, 6 \ Vertex 20 VERTEX 0, 0, 90, 0, 11, 11, 11, 31 \ Vertex 21 VERTEX -80, -6, -40, 9, 9, 9, 9, 8 \ Vertex 22 VERTEX -80, 6, -40, 9, 9, 9, 9, 8 \ Vertex 23 VERTEX -88, 0, -40, 9, 9, 9, 9, 6 \ Vertex 24 VERTEX 80, 6, -40, 9, 9, 9, 9, 8 \ Vertex 25 VERTEX 88, 0, -40, 9, 9, 9, 9, 6 \ Vertex 26 VERTEX 80, -6, -40, 9, 9, 9, 9, 8 \ Vertex 27 .SHIP_COBRA_MK_3_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 1, 0, 11, 31 \ Edge 0 EDGE 0, 4, 4, 12, 31 \ Edge 1 EDGE 1, 3, 3, 10, 31 \ Edge 2 EDGE 3, 8, 7, 10, 31 \ Edge 3 EDGE 4, 7, 8, 12, 31 \ Edge 4 EDGE 6, 7, 8, 9, 31 \ Edge 5 EDGE 6, 9, 6, 9, 31 \ Edge 6 EDGE 5, 9, 5, 9, 31 \ Edge 7 EDGE 5, 8, 7, 9, 31 \ Edge 8 EDGE 2, 5, 1, 5, 31 \ Edge 9 EDGE 2, 6, 2, 6, 31 \ Edge 10 EDGE 3, 5, 3, 7, 31 \ Edge 11 EDGE 4, 6, 4, 8, 31 \ Edge 12 EDGE 1, 2, 0, 1, 31 \ Edge 13 EDGE 0, 2, 0, 2, 31 \ Edge 14 EDGE 8, 10, 9, 10, 31 \ Edge 15 EDGE 10, 11, 9, 11, 31 \ Edge 16 EDGE 7, 11, 9, 12, 31 \ Edge 17 EDGE 1, 10, 10, 11, 31 \ Edge 18 EDGE 0, 11, 11, 12, 31 \ Edge 19 EDGE 1, 5, 1, 3, 29 \ Edge 20 EDGE 0, 6, 2, 4, 29 \ Edge 21 EDGE 20, 21, 0, 11, 6 \ Edge 22 EDGE 12, 13, 9, 9, 20 \ Edge 23 EDGE 18, 19, 9, 9, 20 \ Edge 24 EDGE 14, 15, 9, 9, 20 \ Edge 25 EDGE 16, 17, 9, 9, 20 \ Edge 26 EDGE 15, 16, 9, 9, 19 \ Edge 27 EDGE 14, 17, 9, 9, 17 \ Edge 28 EDGE 13, 18, 9, 9, 19 \ Edge 29 EDGE 12, 19, 9, 9, 19 \ Edge 30 EDGE 2, 9, 5, 6, 30 \ Edge 31 EDGE 22, 24, 9, 9, 6 \ Edge 32 EDGE 23, 24, 9, 9, 6 \ Edge 33 EDGE 22, 23, 9, 9, 8 \ Edge 34 EDGE 25, 26, 9, 9, 6 \ Edge 35 EDGE 26, 27, 9, 9, 6 \ Edge 36 EDGE 25, 27, 9, 9, 8 \ Edge 37 .SHIP_COBRA_MK_3_FACES \ normal_x, normal_y, normal_z, visibility FACE 0, 62, 31, 31 \ Face 0 FACE -18, 55, 16, 31 \ Face 1 FACE 18, 55, 16, 31 \ Face 2 FACE -16, 52, 14, 31 \ Face 3 FACE 16, 52, 14, 31 \ Face 4 FACE -14, 47, 0, 31 \ Face 5 FACE 14, 47, 0, 31 \ Face 6 FACE -61, 102, 0, 31 \ Face 7 FACE 61, 102, 0, 31 \ Face 8 FACE 0, 0, -80, 31 \ Face 9 FACE -7, -42, 9, 31 \ Face 10 FACE 0, -30, 6, 31 \ Face 11 FACE 7, -42, 9, 31 \ Face 12 \ ****************************************************************************** \ \ Name: SHIP_THARGOID \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a Thargoid mothership \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_THARGOID EQUB 0 \ Max. canisters on demise = 0 EQUW 99 * 99 \ Targetable area = 99 * 99 EQUB LO(SHIP_THARGOID_EDGES - SHIP_THARGOID) \ Edges data offset (low) EQUB LO(SHIP_THARGOID_FACES - SHIP_THARGOID) \ Faces data offset (low) EQUB 101 \ Max. edge count = (101 - 1) / 4 = 25 EQUB 60 \ Gun vertex = 60 / 4 = 15 EQUB 38 \ Explosion count = 8, as (4 * n) + 6 = 38 EQUB 120 \ Number of vertices = 120 / 6 = 20 EQUB 26 \ Number of edges = 26 EQUW 500 \ Bounty = 500 EQUB 40 \ Number of faces = 40 / 4 = 10 EQUB 55 \ Visibility distance = 55 EQUB 240 \ Max. energy = 240 EQUB 39 \ Max. speed = 39 EQUB HI(SHIP_THARGOID_EDGES - SHIP_THARGOID) \ Edges data offset (high) EQUB HI(SHIP_THARGOID_FACES - SHIP_THARGOID) \ Faces data offset (high) EQUB 2 \ Normals are scaled by = 2^2 = 4 EQUB %00010110 \ Laser power = 2 \ Missiles = 6 .SHIP_THARGOID_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 32, -48, 48, 0, 4, 8, 8, 31 \ Vertex 0 VERTEX 32, -68, 0, 0, 1, 4, 4, 31 \ Vertex 1 VERTEX 32, -48, -48, 1, 2, 4, 4, 31 \ Vertex 2 VERTEX 32, 0, -68, 2, 3, 4, 4, 31 \ Vertex 3 VERTEX 32, 48, -48, 3, 4, 5, 5, 31 \ Vertex 4 VERTEX 32, 68, 0, 4, 5, 6, 6, 31 \ Vertex 5 VERTEX 32, 48, 48, 4, 6, 7, 7, 31 \ Vertex 6 VERTEX 32, 0, 68, 4, 7, 8, 8, 31 \ Vertex 7 VERTEX -24, -116, 116, 0, 8, 9, 9, 31 \ Vertex 8 VERTEX -24, -164, 0, 0, 1, 9, 9, 31 \ Vertex 9 VERTEX -24, -116, -116, 1, 2, 9, 9, 31 \ Vertex 10 VERTEX -24, 0, -164, 2, 3, 9, 9, 31 \ Vertex 11 VERTEX -24, 116, -116, 3, 5, 9, 9, 31 \ Vertex 12 VERTEX -24, 164, 0, 5, 6, 9, 9, 31 \ Vertex 13 VERTEX -24, 116, 116, 6, 7, 9, 9, 31 \ Vertex 14 VERTEX -24, 0, 164, 7, 8, 9, 9, 31 \ Vertex 15 VERTEX -24, 64, 80, 9, 9, 9, 9, 30 \ Vertex 16 VERTEX -24, 64, -80, 9, 9, 9, 9, 30 \ Vertex 17 VERTEX -24, -64, -80, 9, 9, 9, 9, 30 \ Vertex 18 VERTEX -24, -64, 80, 9, 9, 9, 9, 30 \ Vertex 19 .SHIP_THARGOID_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 7, 4, 8, 31 \ Edge 0 EDGE 0, 1, 0, 4, 31 \ Edge 1 EDGE 1, 2, 1, 4, 31 \ Edge 2 EDGE 2, 3, 2, 4, 31 \ Edge 3 EDGE 3, 4, 3, 4, 31 \ Edge 4 EDGE 4, 5, 4, 5, 31 \ Edge 5 EDGE 5, 6, 4, 6, 31 \ Edge 6 EDGE 6, 7, 4, 7, 31 \ Edge 7 EDGE 0, 8, 0, 8, 31 \ Edge 8 EDGE 1, 9, 0, 1, 31 \ Edge 9 EDGE 2, 10, 1, 2, 31 \ Edge 10 EDGE 3, 11, 2, 3, 31 \ Edge 11 EDGE 4, 12, 3, 5, 31 \ Edge 12 EDGE 5, 13, 5, 6, 31 \ Edge 13 EDGE 6, 14, 6, 7, 31 \ Edge 14 EDGE 7, 15, 7, 8, 31 \ Edge 15 EDGE 8, 15, 8, 9, 31 \ Edge 16 EDGE 8, 9, 0, 9, 31 \ Edge 17 EDGE 9, 10, 1, 9, 31 \ Edge 18 EDGE 10, 11, 2, 9, 31 \ Edge 19 EDGE 11, 12, 3, 9, 31 \ Edge 20 EDGE 12, 13, 5, 9, 31 \ Edge 21 EDGE 13, 14, 6, 9, 31 \ Edge 22 EDGE 14, 15, 7, 9, 31 \ Edge 23 EDGE 16, 17, 9, 9, 30 \ Edge 24 EDGE 18, 19, 9, 9, 30 \ Edge 25 .SHIP_THARGOID_FACES \ normal_x, normal_y, normal_z, visibility FACE 103, -60, 25, 31 \ Face 0 FACE 103, -60, -25, 31 \ Face 1 FACE 103, -25, -60, 31 \ Face 2 FACE 103, 25, -60, 31 \ Face 3 FACE 64, 0, 0, 31 \ Face 4 FACE 103, 60, -25, 31 \ Face 5 FACE 103, 60, 25, 31 \ Face 6 FACE 103, 25, 60, 31 \ Face 7 FACE 103, -25, 60, 31 \ Face 8 FACE -48, 0, 0, 31 \ Face 9 \ ****************************************************************************** \ \ Name: SHIP_CORIOLIS \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a Coriolis space station \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_CORIOLIS EQUB 0 \ Max. canisters on demise = 0 EQUW 160 * 160 \ Targetable area = 160 * 160 EQUB LO(SHIP_CORIOLIS_EDGES - SHIP_CORIOLIS) \ Edges data offset (low) EQUB LO(SHIP_CORIOLIS_FACES - SHIP_CORIOLIS) \ Faces data offset (low) EQUB 85 \ Max. edge count = (85 - 1) / 4 = 21 EQUB 0 \ Gun vertex = 0 EQUB 54 \ Explosion count = 12, as (4 * n) + 6 = 54 EQUB 96 \ Number of vertices = 96 / 6 = 16 EQUB 28 \ Number of edges = 28 EQUW 0 \ Bounty = 0 EQUB 56 \ Number of faces = 56 / 4 = 14 EQUB 120 \ Visibility distance = 120 EQUB 240 \ Max. energy = 240 EQUB 0 \ Max. speed = 0 EQUB HI(SHIP_CORIOLIS_EDGES - SHIP_CORIOLIS) \ Edges data offset (high) EQUB HI(SHIP_CORIOLIS_FACES - SHIP_CORIOLIS) \ Faces data offset (high) EQUB 0 \ Normals are scaled by = 2^0 = 1 EQUB %00000110 \ Laser power = 0 \ Missiles = 6 .SHIP_CORIOLIS_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 160, 0, 160, 0, 1, 2, 6, 31 \ Vertex 0 VERTEX 0, 160, 160, 0, 2, 3, 8, 31 \ Vertex 1 VERTEX -160, 0, 160, 0, 3, 4, 7, 31 \ Vertex 2 VERTEX 0, -160, 160, 0, 1, 4, 5, 31 \ Vertex 3 VERTEX 160, -160, 0, 1, 5, 6, 10, 31 \ Vertex 4 VERTEX 160, 160, 0, 2, 6, 8, 11, 31 \ Vertex 5 VERTEX -160, 160, 0, 3, 7, 8, 12, 31 \ Vertex 6 VERTEX -160, -160, 0, 4, 5, 7, 9, 31 \ Vertex 7 VERTEX 160, 0, -160, 6, 10, 11, 13, 31 \ Vertex 8 VERTEX 0, 160, -160, 8, 11, 12, 13, 31 \ Vertex 9 VERTEX -160, 0, -160, 7, 9, 12, 13, 31 \ Vertex 10 VERTEX 0, -160, -160, 5, 9, 10, 13, 31 \ Vertex 11 VERTEX 10, -30, 160, 0, 0, 0, 0, 30 \ Vertex 12 VERTEX 10, 30, 160, 0, 0, 0, 0, 30 \ Vertex 13 VERTEX -10, 30, 160, 0, 0, 0, 0, 30 \ Vertex 14 VERTEX -10, -30, 160, 0, 0, 0, 0, 30 \ Vertex 15 .SHIP_CORIOLIS_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 3, 0, 1, 31 \ Edge 0 EDGE 0, 1, 0, 2, 31 \ Edge 1 EDGE 1, 2, 0, 3, 31 \ Edge 2 EDGE 2, 3, 0, 4, 31 \ Edge 3 EDGE 3, 4, 1, 5, 31 \ Edge 4 EDGE 0, 4, 1, 6, 31 \ Edge 5 EDGE 0, 5, 2, 6, 31 \ Edge 6 EDGE 5, 1, 2, 8, 31 \ Edge 7 EDGE 1, 6, 3, 8, 31 \ Edge 8 EDGE 2, 6, 3, 7, 31 \ Edge 9 EDGE 2, 7, 4, 7, 31 \ Edge 10 EDGE 3, 7, 4, 5, 31 \ Edge 11 EDGE 8, 11, 10, 13, 31 \ Edge 12 EDGE 8, 9, 11, 13, 31 \ Edge 13 EDGE 9, 10, 12, 13, 31 \ Edge 14 EDGE 10, 11, 9, 13, 31 \ Edge 15 EDGE 4, 11, 5, 10, 31 \ Edge 16 EDGE 4, 8, 6, 10, 31 \ Edge 17 EDGE 5, 8, 6, 11, 31 \ Edge 18 EDGE 5, 9, 8, 11, 31 \ Edge 19 EDGE 6, 9, 8, 12, 31 \ Edge 20 EDGE 6, 10, 7, 12, 31 \ Edge 21 EDGE 7, 10, 7, 9, 31 \ Edge 22 EDGE 7, 11, 5, 9, 31 \ Edge 23 EDGE 12, 13, 0, 0, 30 \ Edge 24 EDGE 13, 14, 0, 0, 30 \ Edge 25 EDGE 14, 15, 0, 0, 30 \ Edge 26 EDGE 15, 12, 0, 0, 30 \ Edge 27 .SHIP_CORIOLIS_FACES \ normal_x, normal_y, normal_z, visibility FACE 0, 0, 160, 31 \ Face 0 FACE 107, -107, 107, 31 \ Face 1 FACE 107, 107, 107, 31 \ Face 2 FACE -107, 107, 107, 31 \ Face 3 FACE -107, -107, 107, 31 \ Face 4 FACE 0, -160, 0, 31 \ Face 5 FACE 160, 0, 0, 31 \ Face 6 FACE -160, 0, 0, 31 \ Face 7 FACE 0, 160, 0, 31 \ Face 8 FACE -107, -107, -107, 31 \ Face 9 FACE 107, -107, -107, 31 \ Face 10 FACE 107, 107, -107, 31 \ Face 11 FACE -107, 107, -107, 31 \ Face 12 FACE 0, 0, -160, 31 \ Face 13 \ ****************************************************************************** \ \ Name: SHIP_MISSILE \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a missile \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_MISSILE EQUB 0 \ Max. canisters on demise = 0 EQUW 40 * 40 \ Targetable area = 40 * 40 EQUB LO(SHIP_MISSILE_EDGES - SHIP_MISSILE) \ Edges data offset (low) EQUB LO(SHIP_MISSILE_FACES - SHIP_MISSILE) \ Faces data offset (low) EQUB 81 \ Max. edge count = (81 - 1) / 4 = 20 EQUB 0 \ Gun vertex = 0 EQUB 10 \ Explosion count = 1, as (4 * n) + 6 = 10 EQUB 102 \ Number of vertices = 102 / 6 = 17 EQUB 24 \ Number of edges = 24 EQUW 0 \ Bounty = 0 EQUB 36 \ Number of faces = 36 / 4 = 9 EQUB 14 \ Visibility distance = 14 EQUB 2 \ Max. energy = 2 EQUB 44 \ Max. speed = 44 EQUB HI(SHIP_MISSILE_EDGES - SHIP_MISSILE) \ Edges data offset (high) EQUB HI(SHIP_MISSILE_FACES - SHIP_MISSILE) \ Faces data offset (high) EQUB 2 \ Normals are scaled by = 2^2 = 4 EQUB %00000000 \ Laser power = 0 \ Missiles = 0 .SHIP_MISSILE_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 0, 0, 68, 0, 1, 2, 3, 31 \ Vertex 0 VERTEX 8, -8, 36, 1, 2, 4, 5, 31 \ Vertex 1 VERTEX 8, 8, 36, 2, 3, 4, 7, 31 \ Vertex 2 VERTEX -8, 8, 36, 0, 3, 6, 7, 31 \ Vertex 3 VERTEX -8, -8, 36, 0, 1, 5, 6, 31 \ Vertex 4 VERTEX 8, 8, -44, 4, 7, 8, 8, 31 \ Vertex 5 VERTEX 8, -8, -44, 4, 5, 8, 8, 31 \ Vertex 6 VERTEX -8, -8, -44, 5, 6, 8, 8, 31 \ Vertex 7 VERTEX -8, 8, -44, 6, 7, 8, 8, 31 \ Vertex 8 VERTEX 12, 12, -44, 4, 7, 8, 8, 8 \ Vertex 9 VERTEX 12, -12, -44, 4, 5, 8, 8, 8 \ Vertex 10 VERTEX -12, -12, -44, 5, 6, 8, 8, 8 \ Vertex 11 VERTEX -12, 12, -44, 6, 7, 8, 8, 8 \ Vertex 12 VERTEX -8, 8, -12, 6, 7, 7, 7, 8 \ Vertex 13 VERTEX -8, -8, -12, 5, 6, 6, 6, 8 \ Vertex 14 VERTEX 8, 8, -12, 4, 7, 7, 7, 8 \ Vertex 15 VERTEX 8, -8, -12, 4, 5, 5, 5, 8 \ Vertex 16 .SHIP_MISSILE_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 1, 1, 2, 31 \ Edge 0 EDGE 0, 2, 2, 3, 31 \ Edge 1 EDGE 0, 3, 0, 3, 31 \ Edge 2 EDGE 0, 4, 0, 1, 31 \ Edge 3 EDGE 1, 2, 4, 2, 31 \ Edge 4 EDGE 1, 4, 1, 5, 31 \ Edge 5 EDGE 3, 4, 0, 6, 31 \ Edge 6 EDGE 2, 3, 3, 7, 31 \ Edge 7 EDGE 2, 5, 4, 7, 31 \ Edge 8 EDGE 1, 6, 4, 5, 31 \ Edge 9 EDGE 4, 7, 5, 6, 31 \ Edge 10 EDGE 3, 8, 6, 7, 31 \ Edge 11 EDGE 7, 8, 6, 8, 31 \ Edge 12 EDGE 5, 8, 7, 8, 31 \ Edge 13 EDGE 5, 6, 4, 8, 31 \ Edge 14 EDGE 6, 7, 5, 8, 31 \ Edge 15 EDGE 6, 10, 5, 8, 8 \ Edge 16 EDGE 5, 9, 7, 8, 8 \ Edge 17 EDGE 8, 12, 7, 8, 8 \ Edge 18 EDGE 7, 11, 5, 8, 8 \ Edge 19 EDGE 9, 15, 4, 7, 8 \ Edge 20 EDGE 10, 16, 4, 5, 8 \ Edge 21 EDGE 12, 13, 6, 7, 8 \ Edge 22 EDGE 11, 14, 5, 6, 8 \ Edge 23 .SHIP_MISSILE_FACES \ normal_x, normal_y, normal_z, visibility FACE -64, 0, 16, 31 \ Face 0 FACE 0, -64, 16, 31 \ Face 1 FACE 64, 0, 16, 31 \ Face 2 FACE 0, 64, 16, 31 \ Face 3 FACE 32, 0, 0, 31 \ Face 4 FACE 0, -32, 0, 31 \ Face 5 FACE -32, 0, 0, 31 \ Face 6 FACE 0, 32, 0, 31 \ Face 7 FACE 0, 0, -176, 31 \ Face 8 \ ****************************************************************************** \ \ Name: SHIP_ASTEROID \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for an asteroid \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_ASTEROID EQUB 0 \ Max. canisters on demise = 0 EQUW 80 * 80 \ Targetable area = 80 * 80 EQUB LO(SHIP_ASTEROID_EDGES - SHIP_ASTEROID) \ Edges data offset (low) EQUB LO(SHIP_ASTEROID_FACES - SHIP_ASTEROID) \ Faces data offset (low) EQUB 65 \ Max. edge count = (65 - 1) / 4 = 16 EQUB 0 \ Gun vertex = 0 EQUB 34 \ Explosion count = 7, as (4 * n) + 6 = 34 EQUB 54 \ Number of vertices = 54 / 6 = 9 EQUB 21 \ Number of edges = 21 EQUW 5 \ Bounty = 5 EQUB 56 \ Number of faces = 56 / 4 = 14 EQUB 50 \ Visibility distance = 50 EQUB 60 \ Max. energy = 60 EQUB 30 \ Max. speed = 30 EQUB HI(SHIP_ASTEROID_EDGES - SHIP_ASTEROID) \ Edges data offset (high) EQUB HI(SHIP_ASTEROID_FACES - SHIP_ASTEROID) \ Faces data offset (high) EQUB 1 \ Normals are scaled by = 2^1 = 2 EQUB %00000000 \ Laser power = 0 \ Missiles = 0 .SHIP_ASTEROID_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 0, 80, 0, 15, 15, 15, 15, 31 \ Vertex 0 VERTEX -80, -10, 0, 15, 15, 15, 15, 31 \ Vertex 1 VERTEX 0, -80, 0, 15, 15, 15, 15, 31 \ Vertex 2 VERTEX 70, -40, 0, 15, 15, 15, 15, 31 \ Vertex 3 VERTEX 60, 50, 0, 5, 6, 12, 13, 31 \ Vertex 4 VERTEX 50, 0, 60, 15, 15, 15, 15, 31 \ Vertex 5 VERTEX -40, 0, 70, 0, 1, 2, 3, 31 \ Vertex 6 VERTEX 0, 30, -75, 15, 15, 15, 15, 31 \ Vertex 7 VERTEX 0, -50, -60, 8, 9, 10, 11, 31 \ Vertex 8 .SHIP_ASTEROID_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 1, 2, 7, 31 \ Edge 0 EDGE 0, 4, 6, 13, 31 \ Edge 1 EDGE 3, 4, 5, 12, 31 \ Edge 2 EDGE 2, 3, 4, 11, 31 \ Edge 3 EDGE 1, 2, 3, 10, 31 \ Edge 4 EDGE 1, 6, 2, 3, 31 \ Edge 5 EDGE 2, 6, 1, 3, 31 \ Edge 6 EDGE 2, 5, 1, 4, 31 \ Edge 7 EDGE 5, 6, 0, 1, 31 \ Edge 8 EDGE 0, 5, 0, 6, 31 \ Edge 9 EDGE 3, 5, 4, 5, 31 \ Edge 10 EDGE 0, 6, 0, 2, 31 \ Edge 11 EDGE 4, 5, 5, 6, 31 \ Edge 12 EDGE 1, 8, 8, 10, 31 \ Edge 13 EDGE 1, 7, 7, 8, 31 \ Edge 14 EDGE 0, 7, 7, 13, 31 \ Edge 15 EDGE 4, 7, 12, 13, 31 \ Edge 16 EDGE 3, 7, 9, 12, 31 \ Edge 17 EDGE 3, 8, 9, 11, 31 \ Edge 18 EDGE 2, 8, 10, 11, 31 \ Edge 19 EDGE 7, 8, 8, 9, 31 \ Edge 20 .SHIP_ASTEROID_FACES \ normal_x, normal_y, normal_z, visibility FACE 9, 66, 81, 31 \ Face 0 FACE 9, -66, 81, 31 \ Face 1 FACE -72, 64, 31, 31 \ Face 2 FACE -64, -73, 47, 31 \ Face 3 FACE 45, -79, 65, 31 \ Face 4 FACE 135, 15, 35, 31 \ Face 5 FACE 38, 76, 70, 31 \ Face 6 FACE -66, 59, -39, 31 \ Face 7 FACE -67, -15, -80, 31 \ Face 8 FACE 66, -14, -75, 31 \ Face 9 FACE -70, -80, -40, 31 \ Face 10 FACE 58, -102, -51, 31 \ Face 11 FACE 81, 9, -67, 31 \ Face 12 FACE 47, 94, -63, 31 \ Face 13 \ ****************************************************************************** \ \ Name: SHIP_CANISTER \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a cargo canister \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_CANISTER EQUB 0 \ Max. canisters on demise = 0 EQUW 20 * 20 \ Targetable area = 20 * 20 EQUB LO(SHIP_CANISTER_EDGES - SHIP_CANISTER) \ Edges data offset (low) EQUB LO(SHIP_CANISTER_FACES - SHIP_CANISTER) \ Faces data offset (low) EQUB 49 \ Max. edge count = (49 - 1) / 4 = 12 EQUB 0 \ Gun vertex = 0 EQUB 18 \ Explosion count = 3, as (4 * n) + 6 = 18 EQUB 60 \ Number of vertices = 60 / 6 = 10 EQUB 15 \ Number of edges = 15 EQUW 0 \ Bounty = 0 EQUB 28 \ Number of faces = 28 / 4 = 7 EQUB 12 \ Visibility distance = 12 EQUB 17 \ Max. energy = 17 EQUB 15 \ Max. speed = 15 EQUB HI(SHIP_CANISTER_EDGES - SHIP_CANISTER) \ Edges data offset (high) EQUB HI(SHIP_CANISTER_FACES - SHIP_CANISTER) \ Faces data offset (high) EQUB 2 \ Normals are scaled by = 2^2 = 4 EQUB %00000000 \ Laser power = 0 \ Missiles = 0 .SHIP_CANISTER_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 24, 16, 0, 0, 1, 5, 5, 31 \ Vertex 0 VERTEX 24, 5, 15, 0, 1, 2, 2, 31 \ Vertex 1 VERTEX 24, -13, 9, 0, 2, 3, 3, 31 \ Vertex 2 VERTEX 24, -13, -9, 0, 3, 4, 4, 31 \ Vertex 3 VERTEX 24, 5, -15, 0, 4, 5, 5, 31 \ Vertex 4 VERTEX -24, 16, 0, 1, 5, 6, 6, 31 \ Vertex 5 VERTEX -24, 5, 15, 1, 2, 6, 6, 31 \ Vertex 6 VERTEX -24, -13, 9, 2, 3, 6, 6, 31 \ Vertex 7 VERTEX -24, -13, -9, 3, 4, 6, 6, 31 \ Vertex 8 VERTEX -24, 5, -15, 4, 5, 6, 6, 31 \ Vertex 9 .SHIP_CANISTER_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 1, 0, 1, 31 \ Edge 0 EDGE 1, 2, 0, 2, 31 \ Edge 1 EDGE 2, 3, 0, 3, 31 \ Edge 2 EDGE 3, 4, 0, 4, 31 \ Edge 3 EDGE 0, 4, 0, 5, 31 \ Edge 4 EDGE 0, 5, 1, 5, 31 \ Edge 5 EDGE 1, 6, 1, 2, 31 \ Edge 6 EDGE 2, 7, 2, 3, 31 \ Edge 7 EDGE 3, 8, 3, 4, 31 \ Edge 8 EDGE 4, 9, 4, 5, 31 \ Edge 9 EDGE 5, 6, 1, 6, 31 \ Edge 10 EDGE 6, 7, 2, 6, 31 \ Edge 11 EDGE 7, 8, 3, 6, 31 \ Edge 12 EDGE 8, 9, 4, 6, 31 \ Edge 13 EDGE 9, 5, 5, 6, 31 \ Edge 14 .SHIP_CANISTER_FACES \ normal_x, normal_y, normal_z, visibility FACE 96, 0, 0, 31 \ Face 0 FACE 0, 41, 30, 31 \ Face 1 FACE 0, -18, 48, 31 \ Face 2 FACE 0, -51, 0, 31 \ Face 3 FACE 0, -18, -48, 31 \ Face 4 FACE 0, 41, -30, 31 \ Face 5 FACE -96, 0, 0, 31 \ Face 6 \ ****************************************************************************** \ \ Name: SHIP_THARGON \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a Thargon \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ------------------------------------------------------------------------------ \ \ The ship blueprint for the Thargon reuses the edges data from the cargo \ canister, so the edges data offset is negative. \ \ ****************************************************************************** .SHIP_THARGON EQUB 0 \ Max. canisters on demise = 0 EQUW 40 * 40 \ Targetable area = 40 * 40 EQUB LO(SHIP_CANISTER_EDGES - SHIP_THARGON) \ Edges from canister EQUB LO(SHIP_THARGON_FACES - SHIP_THARGON) \ Faces data offset (low) EQUB 65 \ Max. edge count = (65 - 1) / 4 = 16 EQUB 0 \ Gun vertex = 0 EQUB 18 \ Explosion count = 3, as (4 * n) + 6 = 18 EQUB 60 \ Number of vertices = 60 / 6 = 10 EQUB 15 \ Number of edges = 15 EQUW 50 \ Bounty = 50 EQUB 28 \ Number of faces = 28 / 4 = 7 EQUB 20 \ Visibility distance = 20 EQUB 20 \ Max. energy = 20 EQUB 30 \ Max. speed = 30 EQUB HI(SHIP_CANISTER_EDGES - SHIP_THARGON) \ Edges from canister EQUB HI(SHIP_THARGON_FACES - SHIP_THARGON) \ Faces data offset (high) EQUB 2 \ Normals are scaled by = 2^2 = 4 EQUB %00010000 \ Laser power = 2 \ Missiles = 0 .SHIP_THARGON_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX -9, 0, 40, 1, 0, 5, 5, 31 \ Vertex 0 VERTEX -9, -38, 12, 1, 0, 2, 2, 31 \ Vertex 1 VERTEX -9, -24, -32, 2, 0, 3, 3, 31 \ Vertex 2 VERTEX -9, 24, -32, 3, 0, 4, 4, 31 \ Vertex 3 VERTEX -9, 38, 12, 4, 0, 5, 5, 31 \ Vertex 4 VERTEX 9, 0, -8, 5, 1, 6, 6, 31 \ Vertex 5 VERTEX 9, -10, -15, 2, 1, 6, 6, 31 \ Vertex 6 VERTEX 9, -6, -26, 3, 2, 6, 6, 31 \ Vertex 7 VERTEX 9, 6, -26, 4, 3, 6, 6, 31 \ Vertex 8 VERTEX 9, 10, -15, 5, 4, 6, 6, 31 \ Vertex 9 .SHIP_THARGON_FACES \ normal_x, normal_y, normal_z, visibility FACE -36, 0, 0, 31 \ Face 0 FACE 20, -5, 7, 31 \ Face 1 FACE 46, -42, -14, 31 \ Face 2 FACE 36, 0, -104, 31 \ Face 3 FACE 46, 42, -14, 31 \ Face 4 FACE 20, 5, 7, 31 \ Face 5 FACE 36, 0, 0, 31 \ Face 6 \ ****************************************************************************** \ \ Name: SHIP_ESCAPE_POD \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for an escape pod \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_ESCAPE_POD EQUB 0 \ Max. canisters on demise = 0 EQUW 16 * 16 \ Targetable area = 16 * 16 EQUB LO(SHIP_ESCAPE_POD_EDGES - SHIP_ESCAPE_POD) \ Edges data offset (low) EQUB LO(SHIP_ESCAPE_POD_FACES - SHIP_ESCAPE_POD) \ Faces data offset (low) EQUB 25 \ Max. edge count = (25 - 1) / 4 = 6 EQUB 0 \ Gun vertex = 0 EQUB 22 \ Explosion count = 4, as (4 * n) + 6 = 22 EQUB 24 \ Number of vertices = 24 / 6 = 4 EQUB 6 \ Number of edges = 6 EQUW 0 \ Bounty = 0 EQUB 16 \ Number of faces = 16 / 4 = 4 EQUB 8 \ Visibility distance = 8 EQUB 17 \ Max. energy = 17 EQUB 8 \ Max. speed = 8 EQUB HI(SHIP_ESCAPE_POD_EDGES - SHIP_ESCAPE_POD) \ Edges data offset (high) EQUB HI(SHIP_ESCAPE_POD_FACES - SHIP_ESCAPE_POD) \ Faces data offset (high) EQUB 3 \ Normals are scaled by = 2^3 = 8 EQUB %00000000 \ Laser power = 0 \ Missiles = 0 .SHIP_ESCAPE_POD_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX -7, 0, 36, 2, 1, 3, 3, 31 \ Vertex 0 VERTEX -7, -14, -12, 2, 0, 3, 3, 31 \ Vertex 1 VERTEX -7, 14, -12, 1, 0, 3, 3, 31 \ Vertex 2 VERTEX 21, 0, 0, 1, 0, 2, 2, 31 \ Vertex 3 .SHIP_ESCAPE_POD_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 1, 3, 2, 31 \ Edge 0 EDGE 1, 2, 3, 0, 31 \ Edge 1 EDGE 2, 3, 1, 0, 31 \ Edge 2 EDGE 3, 0, 2, 1, 31 \ Edge 3 EDGE 0, 2, 3, 1, 31 \ Edge 4 EDGE 3, 1, 2, 0, 31 \ Edge 5 .SHIP_ESCAPE_POD_FACES \ normal_x, normal_y, normal_z, visibility FACE 26, 0, -61, 31 \ Face 0 FACE 19, 51, 15, 31 \ Face 1 FACE 19, -51, 15, 31 \ Face 2 FACE -56, 0, 0, 31 \ Face 3 \ ****************************************************************************** \ \ Save SHIPS.bin \ \ ****************************************************************************** PRINT "SHIPS" PRINT "Assembled at ", ~CODE_SHIPS% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_SHIPS%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_SHIPS% PRINT "S.SHIPS ", ~CODE_SHIPS%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_SHIPS% SAVE "3-assembled-output/SHIPS.bin", CODE_SHIPS%, P%, LOAD% \ ****************************************************************************** \ \ ELITE PYTHON SHIP BLUEPRINT FILE \ \ Produces the binary file PYTHON.bin that gets loaded by elite-bcfs.asm. \ \ ****************************************************************************** CLEAR 0, &7F00 CODE_PYTHON% = &7F00 LOAD_PYTHON% = &1B00 ORG CODE_PYTHON% \ Set the assembly address to CODE_PYTHON% \ ****************************************************************************** \ \ Name: SHIP_PYTHON \ Type: Variable \ Category: Drawing ships \ Summary: Ship blueprint for a Python \ Deep dive: Ship blueprints \ Comparing ship specifications \ \ ****************************************************************************** .SHIP_PYTHON EQUB 3 \ Max. canisters on demise = 3 EQUW 120 * 120 \ Targetable area = 120 * 120 EQUB LO(SHIP_PYTHON_EDGES - SHIP_PYTHON) \ Edges data offset (low) EQUB LO(SHIP_PYTHON_FACES - SHIP_PYTHON) \ Faces data offset (low) EQUB 85 \ Max. edge count = (85 - 1) / 4 = 21 EQUB 0 \ Gun vertex = 0 EQUB 46 \ Explosion count = 10, as (4 * n) + 6 = 46 EQUB 66 \ Number of vertices = 66 / 6 = 11 EQUB 26 \ Number of edges = 26 EQUW 200 \ Bounty = 200 EQUB 52 \ Number of faces = 52 / 4 = 13 EQUB 40 \ Visibility distance = 40 EQUB 250 \ Max. energy = 250 EQUB 20 \ Max. speed = 20 EQUB HI(SHIP_PYTHON_EDGES - SHIP_PYTHON) \ Edges data offset (high) EQUB HI(SHIP_PYTHON_FACES - SHIP_PYTHON) \ Faces data offset (high) EQUB 0 \ Normals are scaled by = 2^0 = 1 EQUB %00011011 \ Laser power = 3 \ Missiles = 3 .SHIP_PYTHON_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 0, 0, 224, 0, 1, 2, 3, 31 \ Vertex 0 VERTEX 0, 48, 48, 0, 1, 4, 5, 30 \ Vertex 1 VERTEX 96, 0, -16, 15, 15, 15, 15, 31 \ Vertex 2 VERTEX -96, 0, -16, 15, 15, 15, 15, 31 \ Vertex 3 VERTEX 0, 48, -32, 4, 5, 8, 9, 30 \ Vertex 4 VERTEX 0, 24, -112, 9, 8, 12, 12, 31 \ Vertex 5 VERTEX -48, 0, -112, 8, 11, 12, 12, 31 \ Vertex 6 VERTEX 48, 0, -112, 9, 10, 12, 12, 31 \ Vertex 7 VERTEX 0, -48, 48, 2, 3, 6, 7, 30 \ Vertex 8 VERTEX 0, -48, -32, 6, 7, 10, 11, 30 \ Vertex 9 VERTEX 0, -24, -112, 10, 11, 12, 12, 30 \ Vertex 10 .SHIP_PYTHON_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 8, 2, 3, 30 \ Edge 0 EDGE 0, 3, 0, 2, 31 \ Edge 1 EDGE 0, 2, 1, 3, 31 \ Edge 2 EDGE 0, 1, 0, 1, 30 \ Edge 3 EDGE 2, 4, 9, 5, 29 \ Edge 4 EDGE 1, 2, 1, 5, 29 \ Edge 5 EDGE 2, 8, 7, 3, 29 \ Edge 6 EDGE 1, 3, 0, 4, 29 \ Edge 7 EDGE 3, 8, 2, 6, 29 \ Edge 8 EDGE 2, 9, 7, 10, 29 \ Edge 9 EDGE 3, 4, 4, 8, 29 \ Edge 10 EDGE 3, 9, 6, 11, 29 \ Edge 11 EDGE 3, 5, 8, 8, 5 \ Edge 12 EDGE 3, 10, 11, 11, 5 \ Edge 13 EDGE 2, 5, 9, 9, 5 \ Edge 14 EDGE 2, 10, 10, 10, 5 \ Edge 15 EDGE 2, 7, 9, 10, 31 \ Edge 16 EDGE 3, 6, 8, 11, 31 \ Edge 17 EDGE 5, 6, 8, 12, 31 \ Edge 18 EDGE 5, 7, 9, 12, 31 \ Edge 19 EDGE 7, 10, 12, 10, 29 \ Edge 20 EDGE 6, 10, 11, 12, 29 \ Edge 21 EDGE 4, 5, 8, 9, 29 \ Edge 22 EDGE 9, 10, 10, 11, 29 \ Edge 23 EDGE 1, 4, 4, 5, 29 \ Edge 24 EDGE 8, 9, 6, 7, 29 \ Edge 25 .SHIP_PYTHON_FACES \ normal_x, normal_y, normal_z, visibility FACE -27, 40, 11, 30 \ Face 0 FACE 27, 40, 11, 30 \ Face 1 FACE -27, -40, 11, 30 \ Face 2 FACE 27, -40, 11, 30 \ Face 3 FACE -19, 38, 0, 30 \ Face 4 FACE 19, 38, 0, 30 \ Face 5 FACE -19, -38, 0, 30 \ Face 6 FACE 19, -38, 0, 30 \ Face 7 FACE -25, 37, -11, 30 \ Face 8 FACE 25, 37, -11, 30 \ Face 9 FACE 25, -37, -11, 30 \ Face 10 FACE -25, -37, -11, 30 \ Face 11 FACE 0, 0, -112, 30 \ Face 12 SKIP 11 \ This space appears to be unused \ ****************************************************************************** \ \ Name: SVN \ Type: Variable \ Category: Save and load \ Summary: The "saving in progress" flag \ \ ****************************************************************************** .SVN SKIP 1 \ "Saving in progress" flag \ \ * Non-zero while we are saving a commander \ \ * 0 otherwise \ ****************************************************************************** \ \ Name: VEC \ Type: Variable \ Category: Drawing the screen \ Summary: The original value of the IRQ1 vector \ \ ****************************************************************************** .VEC SKIP 2 \ VEC = &7FFE \ \ This gets set to the value of the original IRQ1 vector \ by the loading process \ ****************************************************************************** \ \ Save PYTHON.bin \ \ ****************************************************************************** PRINT "PYTHON" PRINT "Assembled at ", ~CODE_PYTHON% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_PYTHON%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_PYTHON% PRINT "S.PYTHON ", ~CODE_B%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_PYTHON% SAVE "3-assembled-output/PYTHON.bin", CODE_PYTHON%, P%, LOAD% \ ****************************************************************************** \ \ Show free space \ \ ****************************************************************************** PRINT "ELITE game code ", ~(&6000-P%), " bytes free" PRINT "Ends at ", ~P% ================================================ FILE: 1-source-files/original-sources/$.DEFEDIT.inf ================================================ $.DEFEDIT 000000 000000 000557 ================================================ FILE: 1-source-files/original-sources/$.DEFEDIT.txt ================================================ 10 REM DEFSHIP EDITOR 20 MODE7:@%=3 30 PROCPR(" DEFSHIP EDITOR",3,1) 40 INPUT''"Input filename of DEFSHIPS",A$:IFA$<>"" DF$=A$ 50 PRINTTAB(0,22):PROCPR(" EDITING "+DF$+" DEFSHIPS",4,6) 60 VDU28,0,22,39,2,10,10:FORN%=&7C50TO&7F80STEP40:?N%=130:NEXT 70 MEM=&6000:HIMEM=MEM:OSCLI("L."+DF$+" "+STR$~MEM) 80 nodes=MEM+27:lines=MEM+?(MEM+3)+?(MEM+16)*256:norms=MEM+?(MEM+4)+?(MEM+17)*256 90 Nnodes=?(MEM+8)/8:Nlines=?(MEM+9):Nnorms=?(MEM+12)/4 100 REM PRINT NODES 110 PROCPR(" Node Definitions",7,2) 115 PRINT 120 FORN=0TONnodes-1 130 loc=N*8+nodes:x=?loc:y=loc?1:z=loc?2:b=loc?3:PROCSG 160@%=2:PRINTN;:@%=4:PRINT".PV="x y z;:@%=3:PRINT"Pr"b AND31"Fs"loc?4 loc?5 loc?6 loc?7; 170A=GET:NEXT 180 PROCPR(" Node Walk - i.e. lines",7,4):PRINT 190FORN=0TONlines-1 200loc=N*5+lines:@%=3:PRINTN,".Pr"?loc,"Faces"loc?1,loc?2"From"loc?3/4" to"loc?4/4 210A=GET:NEXT 220PROCPR(" Face Normals",5,7):PRINT 225@%=4 230FORN=0TONnorms-1 240loc=N*4+norms:b=?loc:x=loc?1:y=loc?2:z=loc?3:PROCSG:PRINTN,".Pr"b AND31,"Vector"x,y,z 250A=GET:NEXT:GOTO80 999END 1000DEFPROCPR(A$,for,bck):VDU128+bck,157,128+for,141:PRINTA$:VDU128+bck,157,128+for,141:PRINTA$;:ENDPROC 2000DEFPROCSG:IFb AND128x=-x 2010IFb AND64y=-y 2020IFb AND32z=-z 2030ENDPROC ================================================ FILE: 1-source-files/original-sources/$.DEFGEN.inf ================================================ $.DEFGEN 000000 000000 0006BB ================================================ FILE: 1-source-files/original-sources/$.DEFGEN.txt ================================================ >LIST 10 REM DEFSHIP EDITOR 20 MODE7:@%=3:*OPT1,2 30 PROCPR(" DEFSHIP GENERATOR",3,1) 40 INPUT''"Input filename of DEFSHIPS",A$:IFA$<>"" DF$=A$ 50 PRINTTAB(0,22):PROCPR(" CREATING "+DF$+" DEFSHIPS",4,6) 60 VDU28,0,22,39,2,10,10:FORN%=&7C50TO&7F80STEP40:?N%=130:NEXT 70 MEM=&6000:FORN=MEM TOMEM+&400STEP4:!N=0:NEXT 75 INPUT"Number of nodes",Nnodes 76 INPUT"Number of lines",Nlines 77 INPUT"Number of faces",Nnorms 80 nodes=MEM+27:lines=nodes+Nnodes*8:norms=lines+Nlines*5:end=norms+Nnorms*4 90 MEM?3=(lines-MEM)MOD256:MEM?16=(lines-MEM)DIV256:MEM?4=(norms-MEM)MOD256:MEM?17=(norms-MEM)DIV256:MEM?8=Nnodes*8:MEM?9=Nlines:MEM?12=Nnorms*4 100 REM PRINT NODES 110 PROCPR(" Node Definitions",7,2) 115 PRINT 120 FORN=0TONnodes-1 130 loc=N*8+nodes:@%=2:PRINTN;:@%=4:INPUT".PV="x,y,z,"Pr"b,"Fs"loc?4,loc?5,loc?6,loc?7 160PROCS:?loc=x:loc?1=y:loc?2=z:loc?3=b 170NEXT 175OSCLI("SAVE C."+DF$+"1 "+STR$~MEM+" "+STR$~end) 180 PROCPR(" Node Walk - i.e. lines",7,4):PRINT 190FORN=0TONlines-1 200loc=N*5+lines:@%=3:PRINTN;:INPUT".Pr"?loc,"Faces"loc?1,loc?2,"From"a," to"b:loc?3=a*4:loc?4=b*4 210NEXT 215OSCLI("SAVE C."+DF$+"2 "+STR$~MEM+" "+STR$~end) 220PROCPR(" Face Normals",5,7):PRINT 225@%=4 230FORN=0TONnorms-1 240loc=N*4+norms:PRINTN;:INPUT".Pr"b,"Vector"x,y,z:PROCS:?loc=b:loc?1=x:loc?2=y:loc?3=z 250NEXT 260OSCLI("SAVE C."+DF$+"3 "+STR$~MEM+" "+STR$~end) 999END 1000DEFPROCPR(A$,for,bck):VDU128+bck,157,128+for,141:PRINTA$:VDU128+bck,157,128+for,141:PRINTA$;:ENDPROC 2000DEFPROCS:IFx<0 x=-x:b=b OR128 2010IFy<0 y=-y:b=b OR64 2020IFz<0 z=-z:b=b OR32 2030ENDPROC >*SPOOL ================================================ FILE: 1-source-files/original-sources/$.DEFTRAN.inf ================================================ $.DEFTRAN 000000 000000 0007C4 ================================================ FILE: 1-source-files/original-sources/$.DEFTRAN.txt ================================================ >LIST 10 REM DEFSHIP EDITOR 20 MODE7:@%=3 30 PROCPR(" DEFSHIP EDITOR",3,1) 40 INPUT''"Input filename of DEFSHIPS",A$:IFA$<>"" DF$=A$ 50 PRINTTAB(0,22):PROCPR(" EDITING "+DF$+" DEFSHIPS",4,6) 60 VDU28,0,22,39,2,10,10:FORN%=&7C50TO&7F80STEP40:?N%=130:NEXT 70 MEM=&6000:HIMEM=MEM:OSCLI("L."+DF$+" "+STR$~MEM) 80 nodes=MEM+27:lines=MEM+?(MEM+3)+?(MEM+16)*256:norms=MEM+?(MEM+4)+?(MEM+17)*256 90 Nnodes=?(MEM+8)/8:Nlines=?(MEM+9):Nnorms=?(MEM+12)/4 92 REM Zlines=lines-7:Znorms=norms- 95 NWS=OPENOUT(":2.S."+DF$):PTR#NWS=20 100 REM PRINT NODES 110 PROCPR(" Node Definitions",7,2) 120 PRINT 130 FORN=0TONnodes-1 140 loc=N*8+nodes:x=?loc:y=loc?1:z=loc?2:b=loc?3:PROCSG 150@%=2:PRINTN;:@%=4:PRINT".PV="x y z;:@%=3:PRINT"Pr"b AND31"Fs"loc?4 loc?5 loc?6 loc?7; 155 BPUT#NWS,?loc:BPUT#NWS,loc?1:BPUT#NWS,loc?2:BPUT#NWS,loc?3:BPUT#NWS,(loc?4 OR (loc?5*16)):BPUT#NWS,(loc?6 OR (loc?7*16)) 160NEXT 165 T%=PTR#NWS:PTR#NWS=3:BPUT#NWS,(T%MOD256):PTR#NWS=16:BPUT#NWS,(T%DIV256):PTR#NWS=T% 170 PROCPR(" Node Walk - i.e. lines",7,4):PRINT 180FORN=0TONlines-1 190loc=N*5+lines:@%=3:PRINTN,".Pr"?loc,"Faces"loc?1,loc?2"From"loc?3/4" to"loc?4/4 195BPUT#NWS,?loc:BPUT#NWS,(loc?1 OR (loc?2 *16)):BPUT#NWS,loc?3:BPUT#NWS,loc?4 200NEXT 205 T%=PTR#NWS:PTR#NWS=4:BPUT#NWS,(T%MOD256):PTR#NWS=17:BPUT#NWS,(T%DIV256):PTR#NWS=T% 210PROCPR(" Face Normals",5,7):PRINT 220@%=4 230FORN=0TONnorms-1 240loc=N*4+norms:b=?loc:x=loc?1:y=loc?2:z=loc?3:PROCSG:PRINTN,".Pr"b AND31,"Vector"x,y,z 245BPUT#NWS,?loc:BPUT#NWS,loc?1:BPUT#NWS,loc?2:BPUT#NWS,loc?3 250NEXT 255PTR#NWS=6:BPUT#NWS,MEM?6:PTR#NWS=8:BPUT#NWS,MEM?8:BPUT#NWS,MEM?9:PTR#NWS=12:BPUT#NWS,MEM?12 260CLOSE#NWS:END 270DEFPROCPR(A$,for,bck):VDU128+bck,157,128+for,141:PRINTA$:VDU128+bck,157,128+for,141:PRINTA$;:ENDPROC 280DEFPROCSG:IFb AND128x=-x 290IFb AND64y=-y 300IFb AND32z=-z 310ENDPROC >*SPOOL ================================================ FILE: 1-source-files/original-sources/$.DIALGEN.inf ================================================ $.DIALGEN 000000 000000 00048D ================================================ FILE: 1-source-files/original-sources/$.DIALGEN.txt ================================================ 10 REM Generate new DIALS bitdump 20 30 XMAX=68*4:YMAX=18*4: REM Ellipse 32 CYC=53*4:CXC=196*4:RD=11*4 35 XC=125*4:YC=35*4 36 PHI=PI/10:PSI=3*PI/4.1 37 MODE5 40 45 DIL%=&6000 50 *LOAD :2.NDIALS 7600 53 REMGCOL0,3:MOVEXC+XMAX*SINPHI,YC+YMAX*COSPHI:PLOT21,XC,YC:PLOT21,XC-XMAX*SINPHI,YC+YMAX*COSPHI 55 GCOL0,1:MOVEXC+XMAX*SINPHI,YC+YMAX*COSPHI:PLOT21,XC+XMAX*SINPSI,YC+YMAX*COSPSI:MOVEXC-XMAX*SINPHI,YC+YMAX*COSPHI:PLOT21,XC-XMAX*SINPSI,YC+YMAX*COSPSI 57 MOVEXC-XMAX,YC:PLOT21,XC+XMAX,YC 58 MOVEXC,YC-YMAX:PLOT21,XC,YC+YMAX-4 60 GCOL0,1:PROCELLIPSE(XMAX,YMAX,.05) 65 GCOL0,2:PLOT69,XC,YC:PLOT69,XC-8,YC:PLOT69,XC+8,YC:PLOT69,XC,YC+4:PLOT69,XC,YC-4 67 FORTHETA=0TO2*PI STEP.1:PLOT69,RD*COSTHETA+CXC,RD*SINTHETA+CYC:NEXT 68 GCOL0,1:MOVECXC+RD,CYC:PLOT21,CXC-RD,CYC:MOVECXC,CYC+RD:PLOT21,CXC,CYC-RD 70 FORI%=0TO7:FORJ%=0TO255STEP4:!(J%+DIL%+I%*256)=!(J%+&7600+I%*320):NEXT, 80 OSCLI"SAVE DIALSHP "+STR$~DIL%+"+800 0000 7800" 400 END 500 DEFPROCELLIPSE(A,B,S) 510 FORTHETA=0TO2*PI STEPS 520 X%=A*COSTHETA+XC:Y%=B*SINTHETA+YC-4:PLOT69,X%,Y% 540 NEXT:ENDPROC ================================================ FILE: 1-source-files/original-sources/$.ELITEA.inf ================================================ $.ELITEA 000000 000000 002FA2 ================================================ FILE: 1-source-files/original-sources/$.ELITEA.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 5GOTO120 20REM ELITE 30MODE7:VDU28,0,23,39,19 40LOMEM=&3D70 100C%=&F40:W%=&7200:L%=&1128:HIMEM=W%:Z=0 120D%=&563A:WP=&D40:K%=&900:LS%=WP-1:QQ18=&400:T%=&300 220NOST=18:NOSH=12:COPS=2:SH3=COPS:CYL=7:THG=6:SST=8:MSL=9:AST=10:OIL=11:TGL=12:ESC=13:NI%=36:POW=15:B=&30 1000FF=&FF:OSWRCH=&FFEE:OSBYTE=&FFF4:OSWORD=&FFF1:OSFILE=&FFDD:SCLI=&FFF7:VIA=&FE40:USVIA=VIA:IRQ1V=&204:VSCAN=57:XX21=D% 1020ZP=0:X=128:Y=96:RAND=FNZT(4):TRTB%=FNZ2:T1=FNZ:SC=FNZ2:SCH=SC+1:XX16=FNZT(18):P=FNZT(3) 1060XX0=FNZ2:INF=FNZ2:V=FNZ2:XX=FNZ2:YY=FNZ2:SUNX=FNZ2:BETA=FNZ:BET1=FNZ:XC=FNZ:YC=FNZ:QQ22=FNZ2:ECMA=FNZ 1120XX15=FNZT(6):XX12=FNZT(6):X1=XX15:Y1=X1+1:X2=Y1+1:Y2=X2+1:K=FNZT(4) 1125KL=FNZT(16):LAS=FNZ:MSTG=FNZ 1126f0=&20:f1=&71:f2=&72:f3=&73:f4=&14:f5=&74:f6=&75:f7=&16:f8=&76:f9=&77 1128KY1=KL+1:KY2=KL+2:KY3=KL+3:KY4=KL+4:KY5=KL+5:KY6=KL+6:KY7=KL+7:KY12=KL+8:KY13=KL+9:KY14=KL+10:KY15=KL+11:KY16=KL+12:KY17=KL+13:KY18=KL+14:KY19=KL+15 1130INWK=FNZT(NI%):XX19=INWK+33:XX1=INWK:LSP=FNZ:QQ15=FNZT(6):XX18=FNZT(9):QQ17=XX18:QQ19=QQ17+1:K5=XX18:K6=K5+4:ALP1=FNZ:ALP2=FNZ2 1150BET2=FNZ2:DELTA=FNZ:DELT4=FNZ2:U=FNZ:Q=FNZ:R=FNZ:S=FNZ:XSAV=FNZ:YSAV=FNZ:XX17=FNZ 1160QQ11=FNZ:ZZ=FNZ:XX13=FNZ:MCNT=FNZ:DL=FNZ:TYPE=FNZ:JSTX=FNZ:JSTY=FNZ:ALPHA=FNZ 1195QQ12=FNZ:TGT=FNZ:SWAP=FNZ:COL=FNZ:FLAG=FNZ:CNT=FNZ:CNT2=FNZ:STP=FNZ:XX4=FNZ:XX20=FNZ:XX14=FNZ:RAT=FNZ:RAT2=FNZ:K2=FNZT(4) 1400P%=C%:O%=W%:H%=L%+P%-C% 1410IFZ=4THENZ=6ELSEZ=4 1450FRIN=FNWT(NOSH+1):MANY=FNWT(14):SSPR=MANY+SST 1460ECMP=FNW:MJ=FNW:CABTMP=MANY:LAS2=FNW:MSAR=FNW:VIEW=FNW:LASCT=FNW:GNTMP=FNW:HFX=FNW:EV=FNW:DLY=FNW 1465de=FNW:T=&D1:XX2=&D2:K3=XX2:K4=K3+14:REM16 1470LSO=FNWT(192):LSX=LSO:LSX2=FNWT(78):LSY2=FNWT(78):SY=FNWT(NOST+1):SYL=FNWT(NOST+1):SZ=FNWT(NOST+1):SZL=FNWT(NOST+1) 1480XSAV2=FNW:YSAV2=FNW 1500TP=FNTP:QQ0=FNTP:QQ1=FNTP:QQ21=FNTPT(6):CASH=FNTPT(4):QQ14=FNTP:COK=FNTP:GCNT=FNTP:LASER=FNTPT(6):CRGO=FNTP:QQ20=FNTPT(17):ECM=FNTP:BST=FNTP:BOMB=FNTP:ENGY=FNTP:DKCMP=FNTP:GHYP=FNTP:ESCP=FNTPT(5) 1520NOMSL=FNTP:FIST=FNTP:AVL=FNTPT(17):QQ26=FNTP:TALLY=FNTPT(2):SVC=FNTPT(3):NT%=SVC+2-TP:MCH=FNW 1600SX=T%:SXL=SX+NOST+1:XX3=256:REM&70 1628FSH=FNW:ASH=FNW:ENERGY=FNW:REMFF 1630LASX=FNW:LASY=FNW:COMX=FNW:COMY=FNW:QQ24=FNW:QQ25=FNW:QQ28=FNW:QQ29=FNW:gov=FNW:tek=FNW:SLSP=FNW2:XX24=FNW:ALTIT=FNW:VEC=&7FFE:svn=&7FFD 1650QQ2=FNWT(6):QQ3=FNW:QQ4=FNW:QQ5=FNW:QQ6=FNW2:QQ7=FNW2:QQ8=FNW2:QQ9=FNW:QQ10=FNW:NOSTM=FNW 1800[OPTZ:.S% EQUWTT170:EQUWTT26:EQUWIRQ1:EQUWBR1 1830.COMC brk:.DNOIZ brk:.DAMP brk:.DJD brk:.PATG brk:.FLH brk:.JSTGY brk:.JSTE brk:.JSTK brk 4000.M% LDAK%:STARAND 4020LDXJSTX:JSRcntr:JSRcntr:TXA:EOR#128:TAY:AND#128:STAALP2:STXJSTX:EOR#128:STAALP2+1:TYA:BPLP%+7:EOR#FF:CLC:ADC#1:LSRA:LSRA:CMP#8:BCSP%+4:LSRA:CLC:STAALP1:ORAALP2:STAALPHA 4030LDXJSTY:JSRcntr:TXA:EOR#128:TAY:AND#128:STXJSTY:STABET2+1:EOR#128:STABET2:TYA:BPLP%+4:EOR#FF:ADC#4:LSRA:LSRA:LSRA:LSRA:CMP#3:BCSP%+3:LSRA:STABET1:ORABET2:STABETA 4050LDAKY2:BEQMA17:LDADELTA:CMP#40:BCSMA17:INCDELTA:.MA17 LDAKY1:BEQMA4:DECDELTA:BNEMA4:INCDELTA:.MA4 4060LDAKY15:ANDNOMSL:BEQMA20:LDY#&EE:JSRABORT:LDA#40:JSRNOISE:.MA31 LDA#0:STAMSAR:.MA20 LDAMSTG:BPLMA25:LDAKY14:BEQMA25:LDXNOMSL:BEQMA25:STAMSAR:LDY#&E0:JSRMSBAR:.MA25 4064LDAKY16:BEQMA24:LDAMSTG:BMIMA64:JSRFRMIS:.MA24 LDAKY12:BEQMA76:ASLBOMB:.MA76 4070LDAKY13:ANDESCP:BEQP%+5:JMPESCAPE:LDAKY18:BEQP%+5:JSRWARP:LDAKY17:ANDECM:BEQMA64:LDAECMA:BNEMA64:DECECMP:JSRECBLB2:.MA64 4075LDAKY19:ANDDKCMP:ANDSSPR:BEQMA68:LDAK%+NI%+32:BMIMA68:JMPGOIN:.MA68 4080LDA#0:STALAS:STADELT4:LDADELTA:LSRA:RORDELT4:LSRA:RORDELT4:STADELT4+1 4090LDALASCT:BNEMA3:LDAKY7:BEQMA3:LDAGNTMP:CMP#242:BCSMA3:LDXVIEW:LDALASER,X:BEQMA3:PHA:AND#127:STALAS:STALAS2:LDA#0:JSRNOISE:JSRLASLI:PLA:BPLma1:LDA#0:.ma1 AND#&FA:STALASCT:.MA3 4100LDX#0:.MAL1 4105STXXSAV:LDAFRIN,X:BNEP%+5:JMPMA18:STATYPE:JSRGINF 4110LDY#(NI%-1):.MAL2 LDA(INF),Y:STAINWK,Y:DEY:BPLMAL2:LDATYPE:BMIMA21:ASLA:TAY:LDAXX21-2,Y:STAXX0:LDAXX21-1,Y:STAXX0+1 4115LDABOMB:BPLMA21:CPY#2*SST:BEQMA21:LDAINWK+31:AND#32:BNEMA21:LDAINWK+31:ORA#128:STAINWK+31:JSREXNO2 4130.MA21 JSRMVEIT:LDY#(NI%-1):.MAL3 LDAINWK,Y:STA(INF),Y:DEY:BPLMAL3 4134LDAINWK+31:AND#&A0:JSRMAS4:BNEMA65:LDAINWK:ORAINWK+3:ORAINWK+6:BMIMA65:LDXTYPE:BMIMA65:CPX#SST:BEQISDK:AND#&C0:BNEMA65:CPX#MSL:BEQMA65 4138CPX#OIL:BCSP%+5:JMPMA58:LDABST:ANDINWK+5:BPLMA58:LDA#3:CPX#TGL:BCCoily:BNEslvy2:LDA#16:BNEslvy2 4140.oily JSRDORND:AND#7:.slvy2 STAQQ29:LDA#1:JSRtnpr:LDY#78:BCSMA59:LDYQQ29:ADCQQ20,Y:STAQQ20,Y:TYA:ADC#208:JSRMESS 4141JMPMA60:.MA65 JMPMA26 4142.ISDK LDAK%+NI%+32:BMIMA62:LDAINWK+14:CMP#&D6:BCCMA62:JSRSPS4:LDAXX15+2:BMIMA62:CMP#89:BCCMA62:LDAINWK+16:AND#&7F:CMP#80:BCCMA62:.GOIN LDA#0:STAQQ22+1:LDA#8:JSRLAUN:JSRRES4:JMPBAY:.MA62 LDADELTA:CMP#5:BCCMA67:JMPDEATH 4143.MA59 JSREXNO3:.MA60 ASLINWK+31:SEC:RORINWK+31:.MA61 BNEMA26 4144.MA67 LDA#1:STADELTA:LDA#5:BNEMA63:.MA58 ASLINWK+31:SEC:RORINWK+31:LDAINWK+35:SEC:RORA:.MA63 JSROOPS:JSREXNO3:.MA26 4146LDAQQ11:BNEMA15:JSRPLUT 4150JSRHITCH:BCCMA8:LDAMSAR:BEQMA47:JSRBEEP:LDXXSAV:LDY#&E:JSRABORT2:.MA47 LDALAS:BEQMA8:LDX#15:JSREXNO:LDAINWK+35:SEC:SBCLAS:BCSMA14 4155LDATYPE:CMP#SST:BEQMA14+2:LDAINWK+31:ORA#128:STAINWK+31:BCSMA8:JSRDORND:BPLoh:LDY#0:AND(XX0),Y:STACNT:.um BEQoh:LDX#OIL:LDA#0:JSRSFS1:DECCNT:BPLum:.oh JSREXNO2 4160.MA14 STAINWK+35:LDATYPE:JSRANGRY:.MA8 4180JSRLL9:.MA15 LDY#35:LDAINWK+35:STA(INF),Y 4190LDAINWK+31:BPLMAC1:AND#&20:BEQNBOUN:LDATYPE:CMP#COPS:BNEq2:LDAFIST:ORA#64:STAFIST:.q2 LDADLY:ORAMJ:BNEKS1S:LDY#10:LDA(XX0),Y:BEQKS1S:TAX:INY:LDA(XX0),Y:TAY:JSRMCASH:LDA#0:JSRMESS:.KS1S JMPKS1:.NBOUN 4240.MAC1 LDATYPE:BMIMA27:JSRFAROF:BCCKS1S:.MA27 LDY#31:LDAINWK+31:STA(INF),Y:LDXXSAV:INX:JMPMAL1:.MA18 LDABOMB:BPLMA77:ASLBOMB:JSRWSCAN:LDA#&30:STA&FE21:.MA77 4250LDAMCNT:AND#7:BNEMA22:LDXENERGY:BPLb:LDXASH:JSRSHD:STXASH:LDXFSH:JSRSHD:STXFSH:.b SEC:LDAENGY:ADCENERGY:BCSP%+5:STAENERGY 4260LDAMJ:BNEMA23S:LDAMCNT:AND#31:BNEMA93:LDASSPR:BNEMA23S:TAY:JSRMAS2:BNEMA23S 4270LDX#28:.MAL4 LDAK%,X:STAINWK,X:DEX:BPLMAL4:INX:LDY#9:JSRMAS1:BNEMA23S:LDX#3:LDY#11:JSRMAS1:BNEMA23S:LDX#6:LDY#13:JSRMAS1:BNEMA23S 4280LDA#&C0:JSRFAROF2:BCCMA23S 4290LDAQQ11:BNEP%+5\!:JSRWPLS:JSRNWSPS:.MA23S JMPMA23 4300.MA22 LDAMJ:BNEMA23:LDAMCNT:AND#31:.MA93 CMP#10:BNEMA29:LDA#50:CMPENERGY:BCCP%+6:ASLA:JSRMESS:LDY#FF:STYALTIT:INY:JSRm:BNEMA23:JSRMAS3:BCSMA23:SBC#&24:BCCMA28:STAR:JSRLL5:LDAQ:STAALTIT:BNEMA23:.MA28 JMPDEATH 4310.MA29 CMP#20:BNEMA23:LDA#30:STACABTMP:LDASSPR:BNEMA23:LDY#NI%:JSRMAS2:BNEMA23:JSRMAS3:EOR#FF:ADC#30:STACABTMP:BCSMA28 4320CMP#&E0:BCCMA23:LDABST:BEQMA23:LDADELT4+1:LSRA:ADCQQ14:CMP#70:BCCP%+4:LDA#70:STAQQ14:LDA#160:JSRMESS 4350.MA23 LDALAS2:BEQMA16:LDALASCT:CMP#8:BCSMA16:JSRLASLI2:LDA#0:STALAS2:.MA16 4360LDAECMP:BEQMA69:JSRDENGY:BEQMA70:.MA69 LDAECMA:BEQMA66:DECECMA:BNEMA66:.MA70 JSRECMOF:.MA66 4380LDAQQ11:BNEMA9:JMPSTARS 4900.MAS1 LDAINWK,Y:ASLA:STAK+1:LDAINWK+1,Y:ROLA:STAK+2:LDA#0:RORA:STAK+3:JSRMVT3:STAINWK+2,X:LDYK+1:STYINWK,X:LDYK+2:STYINWK+1,X:AND#127:.MA9 RTS:.m LDA#0:.MAS2 ORAK%+2,Y:ORAK%+5,Y:ORAK%+8,Y:AND#127:RTS 4940.MAS3 LDAK%+1,Y:JSRSQUA2:STAR:LDAK%+4,Y:JSRSQUA2:ADCR:BCSMA30:STAR:LDAK%+7,Y:JSRSQUA2:ADCR:BCCP%+4:.MA30 LDA#FF:RTS 7000.MVEIT LDAINWK+31:AND#&A0:BNEMV30 7011LDAMCNT:EORXSAV:AND#15:BNEMV3:JSRTIDY:.MV3 LDXTYPE:BPLP%+5:JMPMV40:LDAINWK+32:BPLMV30:CPX#MSL:BEQMV26 7014LDAMCNT:EORXSAV:AND#7:BNEMV30:.MV26 JSRTACTICS:.MV30 JSRSCAN 7020LDAINWK+27:ASLA:ASLA:STAQ:LDAINWK+10:AND#127:JSRFMLTU:STAR:LDAINWK+10:LDX#0:JSRMVT1-2 7025LDAINWK+12:AND#127:JSRFMLTU:STAR:LDAINWK+12:LDX#3:JSRMVT1-2:LDAINWK+14:AND#127:JSRFMLTU:STAR:LDAINWK+14:LDX#6:JSRMVT1-2 7030LDAINWK+27:CLC:ADCINWK+28:BPLP%+4:LDA#0:LDY#15:CMP(XX0),Y:BCCP%+4:LDA(XX0),Y:STAINWK+27 7032LDA#0:STAINWK+28 7040LDXALP1:LDAINWK:EOR#FF:STAP:LDAINWK+1:JSRMLTU2-2:STAP+2:LDAALP2+1:EORINWK+2:LDX#3:JSRMVT6 7045STAK2+3:LDAP+1:STAK2+1:EOR#FF:STAP:LDAP+2:STAK2+2\K2=Y-aX 7050LDXBET1:JSRMLTU2-2:STAP+2:LDAK2+3:EORBET2:LDX#6:JSRMVT6:STAINWK+8:LDAP+1:STAINWK+6:EOR#FF:STAP:LDAP+2:STAINWK+7\Z=Z+bK2 7060JSRMLTU2:STAP+2:LDAK2+3:STAINWK+5:EORBET2:EORINWK+8:BPLMV43:LDAP+1:ADCK2+1:STAINWK+3:LDAP+2:ADCK2+2:STAINWK+4:JMPMV44:.MV43 7070LDAK2+1:SBCP+1:STAINWK+3:LDAK2+2:SBCP+2:STAINWK+4:BCSMV44:LDA#1:SBCINWK+3:STAINWK+3:LDA#0:SBCINWK+4:STAINWK+4:LDAINWK+5:EOR#128:STAINWK+5 7080.MV44\Y=K2-bZ:LDXALP1:LDAINWK+3:EOR#FF:STAP:LDAINWK+4:JSRMLTU2-2:STAP+2:LDAALP2:EORINWK+5:LDX#0:JSRMVT6:STAINWK+2:LDAP+2:STAINWK+1:LDAP+1:STAINWK\X=X+aY 7110.MV45 LDADELTA:STAR:LDA#128:LDX#6:JSRMVT1:LDATYPE:AND#&81:CMP#&81:BNEP%+3:RTS \Z=Z-d 7120LDY#9:JSRMVS4:LDY#15:JSRMVS4:LDY#21:JSRMVS4:LDAINWK+30:AND#128:STARAT2:LDAINWK+30:AND#127:BEQMV8:CMP#127:SBC#0:ORARAT2:STAINWK+30 7130LDX#15:LDY#9:JSRMVS5:LDX#17:LDY#11:JSRMVS5:LDX#19:LDY#13:JSRMVS5 7160.MV8 LDAINWK+29:AND#128:STARAT2:LDAINWK+29:AND#127:BEQMV5:CMP#127:SBC#0:ORARAT2:STAINWK+29 7170LDX#15:LDY#21:JSRMVS5:LDX#17:LDY#23:JSRMVS5:LDX#19:LDY#25:JSRMVS5 7210.MV5 LDAINWK+31:AND#&A0:BNEMVD1:LDAINWK+31:ORA#16:STAINWK+31:JMPSCAN:.MVD1 LDAINWK+31:AND#&EF:STAINWK+31:RTS 7300AND#128:.MVT1 ASLA:STAS:LDA#0:RORA:STAT:LSRS:EORINWK+2,X:BMIMV10:LDAR:ADCINWK,X:STAINWK,X:LDAS:ADCINWK+1,X:STAINWK+1,X:LDAINWK+2,X:ADC#0:ORAT:STAINWK+2,X:RTS 7310.MV10 LDAINWK,X:SEC:SBCR:STAINWK,X:LDAINWK+1,X:SBCS:STAINWK+1,X:LDAINWK+2,X:AND#127:SBC#0:ORA#128:EORT:STAINWK+2,X:BCSMV11 7320LDA#1:SBCINWK,X:STAINWK,X:LDA#0:SBCINWK+1,X:STAINWK+1,X:LDA#0:SBCINWK+2,X:AND#127:ORAT:STAINWK+2,X:.MV11 RTS 7400.MVT3 LDAK+3:STAS:AND#128:STAT:EORINWK+2,X:BMIMV13:LDAK+1:CLC:ADCINWK,X:STAK+1:LDAK+2:ADCINWK+1,X:STAK+2:LDAK+3:ADCINWK+2,X:AND#127:ORAT:STAK+3:RTS 7410.MV13 LDAS:AND#127:STAS:LDAINWK,X:SEC:SBCK+1:STAK+1:LDAINWK+1,X:SBCK+2:STAK+2:LDAINWK+2,X:AND#127:SBCS:ORA#128:EORT:STAK+3:BCSMV14 7420LDA#1:SBCK+1:STAK+1:LDA#0:SBCK+2:STAK+2:LDA#0:SBCK+3:AND#127:ORAT:STAK+3:.MV14 RTS 7500.MVS4 LDAALPHA:STAQ:LDXINWK+2,Y:STXR:LDXINWK+3,Y:STXS:LDXINWK,Y:STXP:LDAINWK+1,Y:EOR#128:JSRMAD:STAINWK+3,Y:STXINWK+2,Y:STXP \Y=Y-aX 7520LDXINWK,Y:STXR:LDXINWK+1,Y:STXS:LDAINWK+3,Y:JSRMAD:STAINWK+1,Y:STXINWK,Y:STXP \X=X+aY 7530LDABETA:STAQ:LDXINWK+2,Y:STXR:LDXINWK+3,Y:STXS:LDXINWK+4,Y:STXP:LDAINWK+5,Y:EOR#128:JSRMAD:STAINWK+3,Y:STXINWK+2,Y:STXP\Y=Y-bZ 7540LDXINWK+4,Y:STXR:LDXINWK+5,Y:STXS:LDAINWK+3,Y:JSRMAD:STAINWK+5,Y:STXINWK+4,Y:RTS\Z=Z+bY 7600.MVS5 LDAINWK+1,X:AND#127:LSRA:STAT:LDAINWK,X:SEC:SBCT:STAR:LDAINWK+1,X:SBC#0:STAS:LDAINWK,Y:STAP:LDAINWK+1,Y:AND#128:STAT:LDAINWK+1,Y:AND#127:LSRA:RORP:LSRA:RORP:LSRA:RORP:LSRA:RORP:ORAT:EORRAT2:STXQ:JSRADD:STAK+1:STXK 7610LDXQ:LDAINWK+1,Y:AND#127:LSRA:STAT:LDAINWK,Y:SEC:SBCT:STAR:LDAINWK+1,Y:SBC#0:STAS:LDAINWK,X:STAP:LDAINWK+1,X:AND#128:STAT:LDAINWK+1,X:AND#127:LSRA:RORP:LSRA:RORP:LSRA:RORP:LSRA:RORP:ORAT:EOR#128:EORRAT2 7620STXQ:JSRADD:STAINWK+1,Y:STXINWK,Y:LDXQ:LDAK:STAINWK,X:LDAK+1:STAINWK+1,X:RTS 7650.MVT6 TAY:EORINWK+2,X:BMIMV50:LDAP+1:CLC:ADCINWK,X:STAP+1:LDAP+2:ADCINWK+1,X:STAP+2:TYA:RTS 7660.MV50 LDAINWK,X:SEC:SBCP+1:STAP+1:LDAINWK+1,X:SBCP+2:STAP+2:BCCMV51:TYA:EOR#128:RTS:.MV51 LDA#1:SBCP+1:STAP+1:LDA#0:SBCP+2:STAP+2:TYA:RTS 7700.MV40 LDAALPHA:EOR#128:STAQ:LDAINWK:STAP:LDAINWK+1:STAP+1:LDAINWK+2:JSRMULT3:LDX#3:JSRMVT3\K=Y-aX 7710LDAK+1:STAK2+1:STAP:LDAK+2:STAK2+2:STAP+1:LDABETA:STAQ:LDAK+3:STAK2+3:JSRMULT3:LDX#6:JSRMVT3:LDAK+1:STAP:STAINWK+6:LDAK+2:STAP+1:STAINWK+7:LDAK+3:STAINWK+8\Z=Z+bK2 7720EOR#128:JSRMULT3:LDAK+3:AND#128:STAT:EORK2+3:BMIMV1 7730LDAK:\CLC:ADCK2:LDAK+1:ADCK2+1:STAINWK+3:LDAK+2:ADCK2+2:STAINWK+4:LDAK+3:ADCK2+3:JMPMV2 7740.MV1 LDAK:SEC:SBCK2:LDAK+1:SBCK2+1:STAINWK+3:LDAK+2:SBCK2+2:STAINWK+4:LDAK2+3:AND#127:STAP:LDAK+3:AND#127:SBCP:STAP:BCSMV2 7750LDA#1:SBCINWK+3:STAINWK+3:LDA#0:SBCINWK+4:STAINWK+4:LDA#0:SBCP:ORA#128:.MV2 EORT:STAINWK+5\Y=K2-bZ 7760LDAALPHA:STAQ:LDAINWK+3:STAP:LDAINWK+4:STAP+1:LDAINWK+5:JSRMULT3:LDX#0:JSRMVT3:LDAK+1:STAINWK:LDAK+2:STAINWK+1:LDAK+3:STAINWK+2\X=X+aY 7770JMPMV45:] 9510IFZ>4OSCLI"S.ELTA "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H% 9520PRINT"A d,";:GOTO2 10100DEFFNZ=FNZT(1) 10110DEFFNZ2=FNZT(2) 10120DEFFNZT(N%):ZP=ZP+N%:=ZP-N% 10300DEFFNW=FNWT(1) 10310DEFFNW2=FNWT(2) 10320DEFFNWT(N%):WP=WP+N%:=WP-N% 10400DEFFNTP=FNTPT(1) 10410DEFFNTPT(N%):T%=T%+N%:=T%-N% ================================================ FILE: 1-source-files/original-sources/$.ELITEB.inf ================================================ $.ELITEB 000000 000000 002D20 ================================================ FILE: 1-source-files/original-sources/$.ELITEB.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 20REM ELITE 1000O%=W%:H%=L%+P%-C%:Q%=FALSE 1010J%=O%:[OPTZ 1100.NA% EQUS("JAMESON"):EQUB13:EQUB0 1110EQUB20\QQ0:EQUB173\QQ1:EQUD&2485A4A\QQ21:EQUW&B753 \Base seed 1120EQUD(((&E8030000)AND(NOTQ%))+((&CA9A3B)ANDQ%))\CASH,&80969800 1130EQUB70 fuel 1135EQUB 0 COK-UP 1137EQUB0 GALACTIC COUNT 1140EQUBPOW+(128ANDQ%):EQUB(POW):EQUB0:EQUB0:EQUW0 LASER:EQUB22+(15ANDQ%) \37 CRGO 1150EQUD0:EQUD0:EQUD0:EQUD0:EQUB0\crgo 1160EQUB Q% ECM 1170EQUB Q% BST 1180EQUB Q%AND127 BOMB 1190EQUB Q%AND1 ENGY++ 1200EQUB Q% DCK COMP 1203EQUB Q% GHYP 1205EQUB Q% ESCP 1207EQUD FALSE EXPAND 1210EQUB 3+(Q%AND1) MISSILES 1220EQUB FALSE FIST 1222EQUB16:EQUB15:EQUB17:EQUB0:EQUB3:EQUB28:EQUB14:EQUW0:EQUB10:EQUB0:EQUB17:EQUB58:EQUB7:EQUB9:EQUB8:EQUB0 1224EQUB 0 QQ26 1230EQUW 0 TALLY 1240EQUB 128 SVC 1245]CH%=NT%-2:CY%=0:FORI%=CH%+J%TO1+J%STEP-1:CH%=CH%+CY%+(I%?7):CY%=(CH%>255)AND1:CH%=CH%MOD256:CH%=CH%EOR(I%?8):NEXT:[OPTZ 1247.CHK2 EQUB CH% EOR&A9 1250.CHK EQUB CH% 1300.UNIV:]FORI%=0TO12:!O%=K%+I%*NI%:O%=O%+2:P%=P%+2:NEXT:[OPTZ 1800.TWOS EQUD&10204080:EQUD&01020408:.TWOS2 EQUD&183060C0:EQUD&0303060C:.CTWOS EQUD&11224488:EQUB&88 2000.LL30:.LOIN STYYSAV 2020LDA#128:STAS:ASLA:STASWAP:LDAX2:SBCX1:BCSLI1:EOR#FF:ADC#1:SEC:.LI1 STAP 2030LDAY2:SBCY1:BCSLI2:EOR#FF:ADC#1:.LI2 STAQ:CMPP:BCCSTPX:JMPSTPY 2040.STPX LDXX1:CPXX2:BCCLI3:DECSWAP:LDAX2:STAX1:STXX2:TAX:LDAY2:LDYY1:STAY1:STYY2:.LI3 2050LDAY1:LSRA:LSRA:LSRA:ORA#&60:STASCH:LDAY1:AND#7:TAY:TXA:AND#&F8:STASC 2060TXA:AND#7:TAX:LDATWOS,X:STAR 2064LDAQ:LDX#254:STXQ:.LIL1 ASLA:BCSLI4:CMPP:BCCLI5:.LI4 SBCP:SEC:.LI5 ROLQ:BCSLIL1 2070LDXP:INX:LDAY2:SBCY1:BCSDOWN 2080LDASWAP:BNELI6:DEX:.LIL2 LDAR:EOR(SC),Y:STA(SC),Y 2090.LI6 LSRR:BCCLI7:RORR:LDASC:ADC#8:STASC 2100.LI7 LDAS:ADCQ:STAS:BCCLIC2:DEY:BPLLIC2:DECSCH:LDY#7 2110.LIC2 DEX:BNELIL2:LDYYSAV:RTS 2150.DOWN LDASWAP:BEQLI9:DEX:.LIL3 LDAR:EOR(SC),Y:STA(SC),Y 2160.LI9 LSRR:BCCLI10:RORR:LDASC:ADC#8:STASC 2170.LI10 LDAS:ADCQ:STAS:BCCLIC3:INY:CPY#8:BNELIC3:INCSCH:LDY#0 2180.LIC3 DEX:BNELIL3:LDYYSAV:RTS 2200.STPY LDYY1:TYA:LDXX1:CPYY2:BCSLI15:DECSWAP:LDAX2:STAX1:STXX2:TAX:LDAY2:STAY1:STYY2:TAY 2210.LI15 LSRA:LSRA:LSRA:ORA#&60:STASCH:TXA:AND#&F8:STASC 2214TXA:AND#7:TAX:LDATWOS,X:STAR:LDAY1:AND#7:TAY 2220LDAP:LDX#1:STXP:.LIL4 ASLA:BCSLI13:CMPQ:BCCLI14:.LI13 SBCQ:SEC:.LI14 ROLP:BCCLIL4:LDXQ:INX:LDAX2:SBCX1:BCCLFT 2230CLC:LDASWAP:BEQLI17:DEX:.LIL5 LDAR:EOR(SC),Y:STA(SC),Y:.LI17 DEY:BPLLI16:DECSCH:LDY#7 2240.LI16 LDAS:ADCP:STAS:BCCLIC5:LSRR:BCCLIC5:RORR:LDASC:ADC#8:STASC 2250.LIC5 DEX:BNELIL5:LDYYSAV:RTS 2300.LFT LDASWAP:BEQLI18:DEX:.LIL6 LDAR:EOR(SC),Y:STA(SC),Y:.LI18 DEY:BPLLI19:DECSCH:LDY#7:.LI19 LDAS:ADCP:STAS:BCCLIC6 2310ASLR:BCCLIC6:ROLR:LDASC:SBC#7:STASC:CLC:.LIC6 DEX:BNELIL6:LDYYSAV 2390.HL6 RTS 2392.NLIN3 JSRTT27:.NLIN4 LDA#19:BNENLIN2:.NLIN LDA#23:INCYC:.NLIN2 STAY1:LDX#2:STXX1:LDX#254:STXX2:BNEHLOIN 2395.HLOIN2 JSREDGES:STYY1:LDA#0:STALSO,Y 2400.HLOIN STYYSAV:LDXX1:CPXX2:BEQHL6:BCCHL5:LDAX2:STAX1:STXX2:TAX:.HL5 DECX2 2410LDAY1:LSRA:LSRA:LSRA:ORA#&60:STASCH:LDAY1:AND#7:STASC:TXA:AND#&F8:TAY 2420.HL1 TXA:AND#&F8:STAT:LDAX2:AND#&F8:SEC:SBCT:BEQHL2:LSRA:LSRA:LSRA:STAR 2430LDAX1:AND#7:TAX:LDATWFR,X:EOR(SC),Y:STA(SC),Y:TYA:ADC#8:TAY:LDXR:DEX:BEQHL3 2440CLC:.HLL1 LDA#FF:EOR(SC),Y:STA(SC),Y:TYA:ADC#8:TAY:DEX:BNEHLL1 2450.HL3 LDAX2:AND#7:TAX:LDATWFL,X:EOR(SC),Y:STA(SC),Y:LDYYSAV:RTS 2460.HL2 LDAX1:AND#7:TAX:LDATWFR,X:STAT:LDAX2:AND#7:TAX:LDATWFL,X:ANDT:EOR(SC),Y:STA(SC),Y:LDYYSAV:RTS 2470.TWFL EQUD&F0E0C080:EQUW&FCF8:EQUB&FE:.TWFR EQUD&1F3F7FFF:EQUD&0103070F 2520.PX3 LDATWOS,X:EOR(SC),Y:STA(SC),Y:LDYT1:RTS 2580.PIX1 JSRADD:STAYY+1:TXA:STASYL,Y 2600.PIXEL2 2610LDAX1:BPLPX1:EOR#&7F:CLC:ADC#1:.PX1 EOR#128:TAX:LDAY1:AND#127:CMP#96:BCSPX4:LDAY1:BPLPX2:EOR#&7F:ADC#1:.PX2 STAT:LDA#97:SBCT 2620.PIXEL STYT1:TAY:LSRA:LSRA:LSRA:ORA#&60:STASCH:TXA:AND#&F8:STASC:TYA:AND#7:TAY:TXA:AND#7:TAX 2630LDAZZ:CMP#&90:BCSPX3:LDATWOS2,X:EOR(SC),Y:STA(SC),Y:LDAZZ:CMP#&50:BCSPX13:DEY:BPLPX14:LDY#1:.PX14 LDATWOS2,X:EOR(SC),Y:STA(SC),Y:.PX13 LDYT1:.PX4 RTS 3000.BLINE TXA:ADCK4:STAK6+2:LDAK4+1:ADCT:STAK6+3 3010LDAFLAG:BEQBL1:INCFLAG:.BL5 LDYLSP:LDA#FF:CMPLSY2-1,Y:BEQBL7:STALSY2,Y:INCLSP:BNEBL7:.BL1 LDAK5:STAXX15:LDAK5+1:STAXX15+1 3012LDAK5+2:STAXX15+2:LDAK5+3:STAXX15+3 3014LDAK6:STAXX15+4:LDAK6+1:STAXX15+5 3016LDAK6+2:STAXX12:LDAK6+3:STAXX12+1 3040JSRLL145:BCSBL5:LDASWAP:BEQBL9:LDAX1:LDYX2:STAX2:STYX1:LDAY1:LDYY2:STAY2:STYY1:.BL9 3050LDYLSP:LDALSY2-1,Y:CMP#FF:BNEBL8:LDAX1:STALSX2,Y:LDAY1:STALSY2,Y:INY:.BL8 LDAX2:STALSX2,Y:LDAY2:STALSY2,Y:INY:STYLSP:JSRLOIN 3051LDAXX13:BNEBL5 3052.BL7 LDAK6:STAK5:LDAK6+1:STAK5+1:LDAK6+2:STAK5+2:LDAK6+3:STAK5+3:LDACNT:CLC:ADCSTP:STACNT 3700RTS:.FLIP \LDAMJ\BNEFLIP-1:LDYNOSTM:.FLL1 LDXSY,Y:LDASX,Y:STAY1:STASY,Y:TXA:STAX1:STASX,Y:LDASZ,Y:STAZZ:JSRPIXEL2:DEY:BNEFLL1:RTS 3800.STARS \LDA#FF:\STACOL:LDXVIEW:BEQSTARS1:DEX:BNEST11:JMPSTARS6:.ST11 JMPSTARS2 4000.STARS1 4010LDYNOSTM:.STL1 JSRDV42:LDAR:LSRP:RORA:LSRP:RORA:ORA#1:STAQ 4012LDASZL,Y:SBCDELT4:STASZL,Y:LDASZ,Y:STAZZ:SBCDELT4+1:STASZ,Y 4020JSRMLU1:STAYY+1:LDAP:ADCSYL,Y:STAYY:STAR:LDAY1:ADCYY+1:STAYY+1:STAS 4030LDASX,Y:STAX1:JSRMLU2:STAXX+1:LDAP:ADCSXL,Y:STAXX:LDAX1:ADCXX+1:STAXX+1 4050EORALP2+1:JSRMLS1:JSRADD:STAYY+1:STXYY 4060EORALP2:JSRMLS2:JSRADD:STAXX+1:STXXX 4070LDXBET1:LDAYY+1:EORBET2+1:JSRMULTS-2:STAQ:JSRMUT2:ASLP:ROLA:STAT:LDA#0:RORA:ORAT:JSRADD:STAXX+1:TXA:STASXL,Y 4080LDAYY:STAR:LDAYY+1:STAS:\JSRMADSTASSTXR:LDA#0:STAP:LDABETA:EOR#128 4110JSRPIX1:LDAXX+1:STAX1:STASX,Y:AND#127:CMP#120:BCSKILL1:LDAYY+1:STASY,Y:STAY1:AND#127:CMP#120:BCSKILL1 4130LDASZ,Y:CMP#16:BCCKILL1:STAZZ 4140.STC1 JSRPIXEL2:DEY:BEQP%+5:JMPSTL1:RTS 4150.KILL1 JSRDORND:ORA#4:STAY1:STASY,Y:JSRDORND:ORA#8:STAX1:STASX,Y:JSRDORND:ORA#&90:STASZ,Y:STAZZ:LDAY1:JMPSTC1 4200.STARS6 4210LDYNOSTM:.STL6 JSRDV42:LDAR:LSRP:RORA:LSRP:RORA:ORA#1:STAQ 4220LDASX,Y:STAX1:JSRMLU2:STAXX+1:LDASXL,Y:SBCP:STAXX:LDAX1:SBCXX+1:STAXX+1 4230JSRMLU1:STAYY+1:LDASYL,Y:SBCP:STAYY:STAR:LDAY1:SBCYY+1:STAYY+1:STAS 4240LDASZL,Y:ADCDELT4:STASZL,Y:LDASZ,Y:STAZZ:ADCDELT4+1:STASZ,Y 4250LDAXX+1:EORALP2:JSRMLS1:JSRADD:STAYY+1:STXYY 4260EORALP2+1:JSRMLS2:JSRADD:STAXX+1:STXXX 4270LDAYY+1:EORBET2+1:LDXBET1:JSRMULTS-2:STAQ:LDAXX+1:STAS:EOR#128:JSRMUT1:ASLP:ROLA:STAT:LDA#0:RORA:ORAT:JSRADD:STAXX+1:TXA:STASXL,Y 4280LDAYY:STAR:LDAYY+1:STAS:\EOR#128:\JSRMADSTASSTXR:LDA#0:STAP:LDABETA 4310JSRPIX1:LDAXX+1:STAX1:STASX,Y:LDAYY+1:STASY,Y:STAY1:AND#127:CMP#110:BCSKILL6 4330LDASZ,Y:CMP#160:BCSKILL6:STAZZ 4340.STC6 JSRPIXEL2:DEY:BEQST3:JMPSTL6:.ST3 RTS 4350.KILL6 JSRDORND:AND#127:ADC#10:STASZ,Y:STAZZ:LSRA:BCSST4:LSRA:LDA#&FC:RORA:STAX1:STASX,Y:JSRDORND:STAY1:STASY,Y:JMPSTC6 4360.ST4 JSRDORND:STAX1:STASX,Y:LSRA:LDA#230:RORA:STAY1:STASY,Y:BNESTC6 5000.PRXS EQUW1:EQUW300:EQUW4000:EQUW6000:EQUW4000:EQUW10000:EQUW5250:EQUW10000:EQUW9000:EQUW15000:EQUW10000:EQUW50000 6990.st4 LDX#9:CMP#25:BCSst3:DEX:CMP#10:BCSst3:DEX:CMP#2:BCSst3:DEX:BNEst3 7000.STATUS LDA#8:JSRTT66:JSRTT111:LDA#7:STAXC:LDA#126:JSRNLIN3:LDA#15:LDYQQ12:BNEst6:LDA#230:LDYMANY+AST:LDXFRIN+2,Y:BEQst6:LDYENERGY:CPY#128:ADC#1:.st6 JSRplf:LDA#125:JSRspc:LDA#19:LDYFIST:BEQst5:CPY#50:ADC#1:.st5 JSRplf:LDA#16 7010JSRspc:LDATALLY+1:BNEst4:TAX:LDATALLY:LSRA:LSRA:INX:LSRA:BNEP%-2:.st3 TXA:CLC:ADC#21:JSRplf 7030LDA#18:JSRplf2:LDACRGO:CMP#26:BCCP%+7:LDA#&6B:JSRplf2:LDABST:BEQP%+7:LDA#111:JSRplf2:LDAECM:BEQP%+7:LDA#&6C:JSRplf2:LDA#113:STAXX4:.stqv TAY:LDXBOMB-113,Y:BEQP%+5:JSRplf2:INCXX4:LDAXX4:CMP#117:BCCstqv 7040LDX#0:.st STXCNT:LDYLASER,X:BEQst1:TXA:CLC:ADC#96:JSRspc:LDA#103:LDXCNT:LDYLASER,X:BPLP%+4:LDA#104:JSRplf2:.st1 LDXCNT:INX:CPX#4:BCCst:RTS 7100.plf2 JSRplf:LDX#6:STXXC:RTS 7600.TENS EQUD&E87648 7605.pr2 LDA#3:LDY#0 7610.TT11 STAU:LDA#0:STAK:STAK+1:STYK+2:STXK+3:.BPRNT LDX#11:STXT:PHP:BCCTT30:DECT:DECU 7630.TT30 LDA#11:SEC:STAXX17:SBCU:STAU:INCU:LDY#0:STYS:JMPTT36 7640.TT35 ASLK+3:ROLK+2:ROLK+1:ROLK:ROLS:LDX#3:.tt35 LDAK,X:STAXX15,X:DEX:BPLtt35:LDAS:STAXX15+4 7650ASLK+3:ROLK+2:ROLK+1:ROLK:ROLS:ASLK+3:ROLK+2:ROLK+1:ROLK:ROLS:CLC:LDX#3:.tt36 LDAK,X:ADCXX15,X:STAK,X:DEX:BPLtt36:LDAXX15+4:ADCS:STAS 7660LDY#0:.TT36 LDX#3:SEC:.tt37 LDAK,X:SBCTENS,X:STAXX15,X:DEX:BPLtt37:LDAS:SBC#23:STAXX15+4 7670BCCTT37:LDX#3:.tt38 LDAXX15,X:STAK,X:DEX:BPLtt38:LDAXX15+4:STAS:INY:JMPTT36 7680.TT37 TYA:BNETT32:LDAT:BEQTT32:DECU:BPLTT34:LDA#32:BNEtt34:.TT32 LDY#0:STYT:CLC:ADC#B:.tt34 JSRTT26 7700.TT34 DECT:BPLP%+4:INCT:DECXX17:BMIRR3+1 \!!:BNEP%+10:PLP:BCCP%+7:LDA#&2E:JSRTT26:JMPTT35 8000.BELL LDA#7 8200.TT26 \PRINT 8205STAK3:STYYSAV2:STXXSAV2:LDYQQ17:CPY#FF:BEQRR4 8210CMP#7:BEQR5:CMP#32:BCSRR1:CMP#10:BEQRRX1:LDX#1:STXXC:.RRX1 INCYC:BNERR4 8220.RR1 \LDX#(K3 MOD256)\INX\STXP+1\DEX\LDY#(K3 DIV256)\STYP+2\LDA#10\JSROSWORD 8225TAY:LDX#&BF:ASLA:ASLA:BCCP%+4:LDX#&C1:ASLA:BCCP%+3:INX:STAP+1:STXP+2 8240LDAXC:ASLA:ASLA:ASLA:STASC:LDAYC:CPY#&7F:BNERR2:DECXC:ADC#&5E:TAX:LDY#&F8:JSRZES2:BEQRR4:.RR2 INCXC:\LDAYC:CMP#24:BCCRR3:JSRTTX66:JMPRR4 8250.RR3 ORA#&60:.RREN STASC+1:LDY#7:.RRL1 LDA(P+1),Y:EOR(SC),Y:STA(SC),Y:DEY:BPLRRL1 8260.RR4 LDYYSAV2:LDXXSAV2:LDAK3:CLC:.rT9 RTS 8270.R5 JSRBEEP:JMPRR4 9500.DIALS LDA#&D0:STASC:LDA#&78:STASC+1:JSRPZW:STXK+1:STAK:LDA#14:STAT1:LDADELTA:\LSRA:JSRDIL-1 9502LDA#0:STAR:STAP:LDA#8:STAS:LDAALP1:LSRA:LSRA:ORAALP2:EOR#128:JSRADD:JSRDIL2:LDABETA:LDXBET1:BEQP%+4:SBC#1:JSRADD:JSRDIL2 9503LDAMCNT:AND#3:BNErT9 9504LDY#0:JSRPZW:STXK:STAK+1:LDX#3:STXT1:.DLL23 STYXX12,X:DEX:BPLDLL23:LDX#3:LDAENERGY:LSRA:LSRA:STAQ:.DLL24 SEC:SBC#16:BCCDLL26:STAQ:LDA#16:STAXX12,X:LDAQ:DEX:BPLDLL24:BMIDLL9:.DLL26 9505LDAQ:STAXX12,X:.DLL9 LDAXX12,Y:STYP:JSRDIL:LDYP:INY:CPY#4:BNEDLL9 9506LDA#&78:STASC+1:LDA#16:\"<80<:STASC:LDAFSH:JSRDILX:LDAASH:JSRDILX:LDAQQ14:JSRDILX+2 9510JSRPZW:STXK+1:STAK:LDX#11:STXT1:LDACABTMP:JSRDILX:LDAGNTMP:JSRDILX 9530LDA#&F0:STAT1:STAK+1:LDAALTIT:JSRDILX:JMPCOMPAS 9540.PZW LDX#&F0:LDAMCNT:AND#8:ANDFLH:BEQP%+4:TXA:EQUB&2C:LDA#15:RTS 9690.DILX LSRA:LSRA:LSRA:LSRA 9700.DIL STAQ:LDX#FF:STXR:CMPT1:BCSDL30:LDAK+1:BNEDL31:.DL30 LDAK:.DL31 STACOL:LDY#2:LDX#3:.DL1 LDAQ:CMP#4:BCCDL2:SBC#4:STAQ:LDAR:.DL5 ANDCOL:STA(SC),Y:INY:STA(SC),Y:INY:STA(SC),Y:TYA:CLC:ADC#6:TAY:DEX:BMIDL6:BPLDL1 9710.DL2 EOR#3:STAQ:LDAR:.DL3 ASLA:AND#239:DECQ:BPLDL3:PHA:LDA#0:STAR:LDA#99:STAQ:PLA:JMPDL5:.DL6 INCSC+1:.DL9 RTS 9712.DIL2 LDY#1:STAQ:.DLL10 SEC:LDAQ:SBC#4:BCSDLL11:LDA#FF:LDXQ:STAQ:LDACTWOS,X:AND#&F0:BNEDLL12:.DLL11 STAQ:LDA#0:.DLL12 STA(SC),Y:INY:STA(SC),Y:INY:STA(SC),Y:INY:STA(SC),Y:TYA:CLC:ADC#5:TAY:CPY#30:BCCDLL10:INCSC+1:RTS 9730.TVT1 EQUD&8494C4D4:\TVT2:EQUD&A5B5E5F5:EQUD&26366676:EQUD&A1B1F1E1:\TVT3:EQUD&A0B0E0F0:EQUD&8090C0D0:EQUD&27376777 9740.LINSCN LDA#30:STADL:STAUSVIA+4:LDA#VSCAN:STAUSVIA+5:LDAHFX:BNEVNT1:LDA#8:STA&FE20:.VNT3 LDATVT1+16,Y:STA&FE21:DEY:BPLVNT3:LDALASCT:BEQP%+5:DECLASCT:\VNT4:LDAsvn:BNEjvec:PLA:TAY:LDA&FE41:LDA&FC:RTI 9750.IRQ1 TYA:PHA:LDY#11:LDA#2:BITVIA+&D:BNELINSCN:BVCjvec:ASLA\4:STA&FE20:LDAESCP:BNEVNT1:\VNT2:LDATVT1,Y:STA&FE21:DEY:BPLP%-7:.jvec PLA:TAY:JMP(VEC):.VNT1 LDY#7:LDATVT1+8,Y:STA&FE21:DEY:BPLVNT1+2:BMIjvec 9800.ESCAPE LDAMJ:PHA:JSRRES2:LDX#CYL:STXTYPE:JSRFRS1:LDA#8:STAINWK+27:LDA#&C2:STAINWK+30:LSRA:STAINWK+32:.ESL1 JSRMVEIT:JSRLL9:DECINWK+32:BNEESL1 9810JSRSCAN:JSRRESET:PLA:BEQP%+5:JMPDEATH:LDX#16:.ESL2 STAQQ20,X:DEX:BPLESL2:STAFIST:STAESCP:LDA#70:STAQQ14:JMPBAY 9900] 9910IFZ>4OSCLI("S.ELTB "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9920PRINT"B done,";:GOTO6 ================================================ FILE: 1-source-files/original-sources/$.ELITEC.inf ================================================ $.ELITEC 000000 000000 002F56 ================================================ FILE: 1-source-files/original-sources/$.ELITEC.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 20REM ELITE 1000O%=W%:H%=L%+P%-C% 1010[OPTZ 1880.TA34 LDA#0:JSRMAS4:BEQP%+5:JMPTA21:JSRTA87+3:JSREXNO3:LDA#250:JMPOOPS 1900.TA18\msl 1910LDAECMA:BNETA35:LDAINWK+32:ASLA:BMITA34:LSRA 1915TAX:LDAUNIV,X:STAV:LDAUNIV+1,X:STAV+1:LDY#2:JSRTAS1:LDY#5:JSRTAS1:LDY#8:JSRTAS1 1920LDAK3+2:ORAK3+5:ORAK3+8:AND#127:ORAK3+1:ORAK3+4:ORAK3+7:BNETA64 1930LDAINWK+32:CMP#&82:BEQTA35:LDY#31:LDA(V),Y:BITM32+1:BNETA35:ORA#128:STA(V),Y:.TA35 LDAINWK:ORAINWK+3:ORAINWK+6:BNETA87:LDA#80:JSROOPS:.TA87 JSREXNO2:ASLINWK+31:SEC:RORINWK+31 1940.TA1 RTS 1944.TA64 JSRDORND:CMP#16:BCSTA19:.M32 LDY#32:LDA(V),Y:LSRA:BCCTA19:JMPECBLB2 2000.TACTICS 2005CPX#MSL:BEQTA18:CPX#ESC:BNEP%+8:JSRSPS1:JMPTA15:CPX#SST:BNETA13:JSRDORND:CMP#140:BCCTA14-1:LDAMANY+SH3:CMP#4:BCSTA14-1:LDX#COPS:LDA#&F1:JMPSFS1:.TA13 2008CPX#TGL:BNETA14:LDAMANY+THG:BNETA14:LSRINWK+32:ASLINWK+32:LSRINWK+27:RTS:.TA14 CPX#CYL:BCSTA62:CPX#COPS:BEQTA62:LDASSPR:BEQTA62:LDAINWK+32:AND#129:STAINWK+32 2010.TA62 LDY#14:LDAINWK+35:CMP(XX0),Y:BCSTA21:INCINWK+35:.TA21 2020LDX#8:.TAL1 LDAINWK,X:STAK3,X:DEX:BPLTAL1 2030.TA19 JSRTAS2\XX15=r~96 2040LDY#10:JSRTAS3:STACNT:LDATYPE:CMP#MSL:BNEP%+5:JMPTA20:JSRDORND:CMP#250:BCCTA7:JSRDORND:ORA#&68:STAINWK+29:.TA7\VRol 2100LDY#14:LDA(XX0),Y:LSRA:CMPINWK+35:BCCTA3:LSRA:LSRA:CMPINWK+35:BCCta3:JSRDORND:CMP#230:BCCta3:LDATYPE:CMP#THG:BEQta3:LDA#0:STAINWK+32:JMPSESCP 2102.ta3 LDAINWK+31:AND#7:BEQTA3:STAT:JSRDORND:AND#31:CMPT:BCSTA3:LDAECMA:BNETA3:DECINWK+31:LDATYPE:CMP#THG:BNETA16:LDX#TGL:LDAINWK+32:JMPSFS1:.TA16 JMPSFRMIS:.TA3 2110LDA#0:JSRMAS4:AND#&E0:BNETA4:LDXCNT:CPX#160:BCCTA4:LDAINWK+31:ORA#64:STAINWK+31:CPX#163:BCCTA4 2120LDY#19:LDA(XX0),Y:LSRA:JSROOPS:DECINWK+28:LDAECMA:BNETA10:LDA#8:JMPNOISE:\frLs 2190.TA4 LDAINWK+7:CMP#3:BCSTA5:LDAINWK+1:ORAINWK+4:AND#&FE:BEQTA15:.TA5 JSRDORND:ORA#128:CMPINWK+32:BCSTA15 2194.TA20 LDAXX15:EOR#128:STAXX15:LDAXX15+1:EOR#128:STAXX15+1:LDAXX15+2:EOR#128:STAXX15+2:LDACNT:EOR#128:STACNT 2200.TA15\^XX15 2220LDY#16:JSRTAS3:EOR#128:AND#128:ORA#3:STAINWK+30 2235LDAINWK+29:AND#127:CMP#16:BCSTA6 2240LDY#22:JSRTAS3:EORINWK+30:AND#128:EOR#&85:STAINWK+29 2260.TA6 LDACNT:BMITA9:CMP#22:BCCTA9:LDA#3:STAINWK+28:RTS 2280.TA9 AND#127:CMP#18:BCCTA10:LDA#FF:LDXTYPE:CPX#MSL:BNEP%+3:ASLA:STAINWK+28:.TA10 RTS 2900.TAS1 LDA(V),Y:EOR#128:STAK+3:DEY:LDA(V),Y:STAK+2:DEY:LDA(V),Y:STAK+1:STYU:LDXU:JSRMVT3:LDYU 2910STAK3+2,X:LDAK+2:STAK3+1,X:LDAK+1:STAK3,X:RTS 3000.HITCH CLC:LDAINWK+8:BNEHI1:LDATYPE:BMIHI1:LDAINWK+31:AND#32:ORAINWK+1:ORAINWK+4:BNEHI1 3005LDAINWK:JSRSQUA2:STAS:LDAP:STAR 3010LDAINWK+3:JSRSQUA2:TAX:LDAP:ADCR:STAR:TXA:ADCS:BCSFR1-2:STAS:LDY#2:LDA(XX0),Y:CMPS:BNEHI1:DEY:LDA(XX0),Y:CMPR:.HI1 RTS 3210.FRS1 JSRZINF:LDA#28:STAINWK+3:LSRA:STAINWK+6:LDA#128:STAINWK+5:LDAMSTG:ASLA:ORA#128:STAINWK+32 3220.fq1 LDA#96:STAINWK+14:ORA#128:STAINWK+22:LDADELTA:ROLA:STAINWK+27:TXA:JMPNWSHP 3230.FRMIS LDX#MSL:JSRFRS1:BCCFR1:LDXMSTG:JSRGINF:LDAFRIN,X:JSRANGRY:LDY#0:JSRABORT:DECNOMSL:LDA#48:JMPNOISE 3234.ANGRY CMP#SST:BEQAN2:BCSHI1:CMP#CYL:BNEP%+5:JSRAN2:LDY#32:LDA(INF),Y:BEQHI1:ORA#128:STA(INF),Y:LDY#28:LDA#2:STA(INF),Y:ASLA:LDY#30:STA(INF),Y:RTS 3236.AN2 ASLK%+NI%+32:SEC:RORK%+NI%+32:CLC:RTS:.FR1 LDA#201:JMPMESS 3310.SESCP LDX#ESC:LDA#&FE:.SFS1 STAT1:LDAXX0:PHA:LDAXX0+1:PHA:LDAINF:PHA:LDAINF+1:PHA:LDY#NI%-1:.FRL2 LDAINWK,Y:STAXX3,Y:LDA(INF),Y:STAINWK,Y:DEY:BPLFRL2 3315LDATYPE:CMP#SST:BNErx:TXA:PHA:LDA#32:STAINWK+27:LDX#0:LDAINWK+10:JSRSFS2:LDX#3:LDAINWK+12:JSRSFS2:LDX#6:LDAINWK+14:JSRSFS2:PLA:TAX:.rx 3320LDAT1:STAINWK+32:LSRINWK+29:ASLINWK+29:TXA:CMP#OIL:BNENOIL:JSRDORND:ASLA:STAINWK+30:TXA:AND#15:STAINWK+27:LDA#FF:RORA:STAINWK+29:LDA#OIL:.NOIL JSRNWSHP 3330PLA:STAINF+1:PLA:STAINF:LDX#NI%-1:.FRL3 LDAXX3,X:STAINWK,X:DEX:BPLFRL3:PLA:STAXX0+1:PLA:STAXX0:RTS 3350.SFS2 ASLA:STAR:LDA#0:RORA:JMPMVT1 3400.LL164 LDA#56:JSRNOISE:LDA#1:STAHFX:LDA#4:JSRHFS2:DECHFX:RTS 3410.LAUN LDA#48:JSRNOISE:LDA#8:.HFS2 STASTP:JSRTTX66:JSRHFS1 3510.HFS1 LDA#128:STAK3:LDX#Y:STXK4:ASLA:STAXX4:STAK3+1:STAK4+1:.HFL5 JSRHFL1:INCXX4:LDXXX4:CPX#8:BNEHFL5:RTS 3520.HFL1 LDAXX4:AND#7:CLC:ADC#8:STAK:.HFL2 LDA#1:STALSP:JSRCIRCLE2:ASLK:BCSHF8:LDAK:CMP#160:BCCHFL2:.HF8 RTS 4400.STARS2 LDA#0:CPX#2:RORA:STARAT:EOR#128:STARAT2:JSRST2 4410LDYNOSTM:.STL2 LDASZ,Y:STAZZ:LSRA:LSRA:LSRA:JSRDV41:LDAP:EORRAT2:STAS:LDASXL,Y:STAP:LDASX,Y:STAX1:JSRADD 4420STAS:STXR:LDASY,Y:STAY1:EORBET2:LDXBET1:JSRMULTS-2:JSRADD:STXXX:STAXX+1 4430LDXSYL,Y:STXR:LDXY1:STXS:LDXBET1:EORBET2+1:JSRMULTS-2:JSRADD:STXYY:STAYY+1 4440LDXALP1:EORALP2:JSRMULTS-2:STAQ:LDAXX:STAR:LDAXX+1:STAS:EOR#128:JSRMAD:STAXX+1:TXA:STASXL,Y 4450LDAYY:STAR:LDAYY+1:STAS:JSRMAD:STAS:STXR:LDA#0:STAP:LDAALPHA 4460JSRPIX1:LDAXX+1:STASX,Y:STAX1 4470AND#127:CMP#116:BCSKILL2:LDAYY+1:STASY,Y:STAY1:AND#127:CMP#116:BCSST5:.STC2 JSRPIXEL2:DEY:BEQST2:JMPSTL2 4480.ST2 LDAALPHA:EORRAT:STAALPHA:LDAALP2:EORRAT:STAALP2:EOR#128:STAALP2+1:LDABET2:EORRAT:STABET2:EOR#128:STABET2+1:RTS 4500.KILL2 JSRDORND:STAY1:STASY,Y:LDA#115:ORARAT:STAX1:STASX,Y:BNESTF1 4510.ST5 JSRDORND:STAX1:STASX,Y:LDA#110:ORAALP2+1:STAY1:STASY,Y:.STF1 JSRDORND:ORA#8:STAZZ:STASZ,Y:BNESTC2 4700.SNE:] 4720FORI%=0TO31:N=ABS(SIN(I%/64*2*PI)):IFN>=1 I%?O%=FF:ELSEI%?O%=INT(256*N+.5) 4730NEXT:O%=O%+32:P%=P%+32 4740[OPTZ 6040.MU5 STAK:STAK+1:STAK+2:STAK+3:CLC:RTS 6050.MULT3\K(4)=AP(2)*Q:STAR:AND#127:STAK+2:LDAQ:AND#127:BEQMU5:SEC:SBC#1:STAT:LDAP+1:LSRK+2:RORA:STAK+1:LDAP:RORA:STAK:LDA#0:LDX#24 6060.MUL2 BCCP%+4:ADCT:RORA:RORK+2:RORK+1:RORK:DEX:BNEMUL2:STAT:LDAR:EORQ:AND#128:ORAT:STAK+3:RTS 6070.MLS2 LDXXX:STXR:LDXXX+1:STXS:.MLS1 LDXALP1:STXP 6080.MULTS\AP=A*P(P+<32) 6090TAX:AND#128:STAT:TXA:AND#127:BEQMU6:TAX:DEX:STXT1:LDA#0 6100LSRP:BCCP%+4:ADCT1:RORA:RORP:BCCP%+4:ADCT1:RORA:RORP:BCCP%+4:ADCT1:RORA:RORP:BCCP%+4:ADCT1:RORA:RORP:BCCP%+4:ADCT1:RORA:RORP 6110LSRA:RORP:LSRA:RORP:LSRA:RORP:ORAT:RTS 6112.SQUA\AP=A*ApresQ:AND#127:.SQUA2 STAP:TAX:BNEMU11:.MU1 CLC:STXP:TXA:RTS 6114.MLU1 LDASY,Y:STAY1:.MLU2 AND#127:STAP 6116.MULTU\AP=P*Qunsg 6118LDXQ:BEQMU1:.MU11 DEX:STXT:LDA#0:LDX#8:LSRP:.MUL6 BCCP%+4:ADCT:RORA:RORP:DEX:BNEMUL6:RTS 6119.MU6 STAP+1:STAP:RTS 6120.FMLTU2 AND#31:TAX:LDASNE,X:STAQ:LDAK 6125.FMLTU\A=A*Q/256unsg:EOR#FF:SEC:RORA:STAP:LDA#0:.MUL3 BCSMU7:ADCQ:RORA:LSRP:BNEMUL3:RTS:.MU7 LSRA:LSRP:BNEMUL3:RTS 6130LDXQ:BEQMU1:DEX:STXT:LDA#0:LDX#8:LSRP:.MUL6 BCCP%+4:ADCT:RORA:RORP:DEX:BNEMUL6:RTS 6140STXQ:.MLTU2\AP(2)=AP*Qunsg(EORP) 6142EOR#FF:LSRA:STAP+1:LDA#0:LDX#16:RORP:.MUL7 BCSMU21:ADCQ:RORA:RORP+1:RORP:DEX:BNEMUL7:RTS:.MU21 LSRA:RORP+1:RORP:DEX:BNEMUL7:RTS 6146.MUT3 LDXALP1:STXP:.MUT2 LDXXX+1:STXS 6148.MUT1 LDXXX:STXR 6150.MULT1 \AP=Q*A 6160TAX:AND#127:LSRA:STAP:TXA:EORQ:AND#128:STAT:LDAQ:AND#127:BEQmu10:TAX:DEX:STXT1:LDA#0:LDX#7 6170.MUL4 BCCP%+4:ADCT1:RORA:RORP:DEX:BNEMUL4:LSRA:RORP:ORAT:RTS:.mu10 STAP:RTS 6190.MULT12 JSRMULT1:STAS:LDAP:STAR:RTS 6194.TAS3 LDXINWK,Y:STXQ:LDAXX15:JSRMULT12:LDXINWK+2,Y:STXQ:LDAXX15+1:JSRMAD:STAS:STXR 6196LDXINWK+4,Y:STXQ:LDAXX15+2:.MAD JSRMULT1 6200.ADD\AX=AP+SR 6210STAT1:AND#128:STAT:EORS:BMIMU8:LDAR:CLC:ADCP:TAX:LDAS:ADCT1:ORAT:RTS 6220.MU8 LDAS:AND#127:STAU:LDAP:SEC:SBCR:TAX:LDAT1:AND#127:SBCU:BCSMU9:STAU:TXA:EOR#FF:ADC#1:TAX:LDA#0:SBCU:ORA#128:.MU9 EORT:RTS 6330\DVIDT(A=AP/Q)inF 6345.TIS1 STXQ:EOR#128:JSRMAD 6350.DVID96\A=A/96:TAX:AND#128:STAT:TXA:AND#127:LDX#254:STXT1:.DVL3 ASLA:CMP#96:BCCDV4:SBC#96:.DV4 ROLT1:BCSDVL3:LDAT1:ORAT:RTS 6360.DV42 LDASZ,Y:.DV41 STAQ:LDADELTA 6370.DVID4\P-R=A/Qunsg 6380LDX#8:ASLA:STAP:LDA#0:.DVL4 ROLA:BCSDV8:CMPQ:BCCDV5:.DV8 SBCQ:SEC:.DV5 ROLP:DEX:BNEDVL4:JMPLL28+4 6395.DVID3B2 STAP+2:LDAINWK+6:STAQ:LDAINWK+7:STAR:LDAINWK+8:STAS 6400.DVID3B\K+1(3)-K=P(3)/SRQaprx 6410LDAP:ORA#1:STAP:LDAP+2:EORS:AND#128:STAT:LDY#0:LDAP+2:AND#127:.DVL9 CMP#&40:BCSDV14:ASLP:ROLP+1:ROLA:INY:BNEDVL9 6420.DV14 STAP+2:LDAS:AND#127:BMIDV9:.DVL6 DEY:ASLQ:ROLR:ROLA:BPLDVL6:.DV9 STAQ:LDA#254:STAR:LDAP+2:JSRLL31 6440LDA#0:STAK+1:STAK+2:STAK+3:TYA:BPLDV12:LDAR:.DVL8 ASLA:ROLK+1:ROLK+2:ROLK+3:INY:BNEDVL8:STAK:LDAK+3:ORAT:STAK+3:RTS 6450.DV13 LDAR:STAK:LDAT:STAK+3:RTS 6460.DV12 BEQDV13:LDAR:.DVL10 LSRA:DEY:BNEDVL10:STAK:LDAT:STAK+3:RTS 6500.cntr LDADAMP:BNERE1:TXA:BPLBUMP:DEX:BMIRE1 6530.BUMP INX:BNERE1 6540.REDU DEX:BEQBUMP:.RE1 RTS 6550.BUMP2 STAT:TXA:CLC:ADCT:TAX:BCCRE2:LDX#FF:.RE2 BPLRE3+2:LDAT:RTS 6560.REDU2 STAT:TXA:SEC:SBCT:TAX:BCSRE3:LDX#1:.RE3 BPLRE2+2:LDADJD:BNERE2+2:LDX#128:BMIRE2+2 6800.ARCTAN\A=TAN-1(P/Q) 6810LDAP:EORQ:STAT1:LDAQ:BEQAR2:ASLA:STAQ:LDAP:ASLA:CMPQ:BCSAR1:JSRARS1:SEC:.AR4 LDXT1:BMIAR3:RTS 6830.AR1 LDXQ:STAQ:STXP:TXA:JSRARS1:STAT:LDA#64:SBCT:BCSAR4:.AR2 LDA#63:RTS:.AR3 STAT:LDA#128:\SEC:SBCT:RTS 6845.ARS1 JSRLL28:LDAR:LSRA:LSRA:LSRA:TAX:LDAACT,X:RTS 6850.ACT:]FORI%=0TO31:I%?O%=INT(128/PI*ATN(I%/32)+.5):NEXT:P%=P%+32:O%=O%+32:[OPTZ 6900.WARP LDAMANY+AST:CLC:ADCMANY+ESC:CLC:ADCMANY+OIL:TAX:LDAFRIN+2,X:ORASSPR:ORAMJ:BNEWA1:LDYK%+8:BMIWA3:TAY:JSRMAS2:CMP#2:BCCWA1:.WA3 LDYK%+NI%+8:BMIWA2:LDY#NI%:JSRm:CMP#2:BCCWA1:.WA2 6910LDA#&81:STAS:STAR:STAP:LDAK%+8:JSRADD:STAK%+8:LDAK%+NI%+8:JSRADD:STAK%+NI%+8 6920LDA#1:STAQQ11:STAMCNT:LSRA:STAEV:LDXVIEW:JMPLOOK1:.WA1 LDA#40:JMPNOISE 7000.LASLI JSRDORND:AND#7:ADC#Y-4:STALASY:JSRDORND:AND#7:ADC#X-4:STALASX:LDAGNTMP:ADC#8:STAGNTMP:JSRDENGY 7005.LASLI2 LDAQQ11:BNEPU1-1:LDA#32:LDY#224:JSRlas:LDA#48:LDY#208 7050.las STAX2:LDALASX:STAX1:LDALASY:STAY1:LDA#2*Y-1:STAY2:JSRLOIN:LDALASX:STAX1:LDALASY:STAY1:STYX2:LDA#2*Y-1:STAY2:JMPLOIN 8500.PLUT LDXVIEW:BNEPU1:RTS:.PU1 DEX:BNEPU2 8510LDAINWK+2:EOR#128:STAINWK+2:LDAINWK+8:EOR#128:STAINWK+8:LDAINWK+10:EOR#128:STAINWK+10:LDAINWK+14:EOR#128:STAINWK+14:LDAINWK+16:EOR#128:STAINWK+16 8520LDAINWK+20:EOR#128:STAINWK+20:LDAINWK+22:EOR#128:STAINWK+22:LDAINWK+26:EOR#128:STAINWK+26:RTS 8530.PU2 LDA#0:CPX#2:RORA:STARAT2:EOR#128:STARAT 8540LDAINWK:LDXINWK+6:STAINWK+6:STXINWK:LDAINWK+1:LDXINWK+7:STAINWK+7:STXINWK+1:LDAINWK+2:EORRAT:TAX:LDAINWK+8:EORRAT2:STAINWK+2:STXINWK+8 8550LDY#9:JSRPUS1 8560LDY#15:JSRPUS1 8570LDY#21 8600.PUS1 LDAINWK,Y:LDXINWK+4,Y:STAINWK+4,Y:STXINWK,Y:LDAINWK+1,Y:EORRAT:TAX:LDAINWK+5,Y:EORRAT2:STAINWK+1,Y:STXINWK+5,Y:.LO2 RTS 8990.LQ STXVIEW:JSRTT66:JSRSIGHT:JMPNWSTARS 9000.LOOK1 LDA#0:LDYQQ11:BNELQ:CPXVIEW:BEQLO2:STXVIEW:JSRTT66:JSRFLIP:JSRWPSHPS 9010.SIGHT LDYVIEW:LDALASER,Y:BEQLO2:LDA#128:STAQQ19:LDA#Y-24:STAQQ19+1:LDA#20:STAQQ19+2:JSRTT15:LDA#10:STAQQ19+2:JMPTT15 9400LDA#1:.TT66 STAQQ11:.TTX66 LDA#128:STAQQ17:ASLA:STALASCT:STADLY:STAde:LDX#&60:.BOL1 JSRZES1:INX:CPX#&78:BNEBOL1 9410LDXQQ22+1:BEQBOX:JSRee3:.BOX LDY#1:STYYC:LDAQQ11:BNEtt66:LDY#11:STYXC:LDAVIEW:ORA#&60:JSRTT27:JSRTT162:LDA#175:JSRTT27:.tt66 9420LDX#0:STXX1:STXY1:STXQQ17:DEX:STXX2:JSRHLOIN 9430LDA#2:STAX1:STAX2:JSRBOS2 9440.BOS2 JSRBOS1:.BOS1 LDA#0:STAY1:LDA#2*Y-1:STAY2:DECX1:DECX2:JMPLOIN 9450LDY#2:EQUB&2C:.DEL8 LDY#8:.DELAY JSRWSCAN:DEY:BNEDELAY:RTS 9460.hm JSRTT103:JSRTT111:JSRTT103:LDAQQ11:BEQSC5:.CLYNS LDA#20:STAYC:LDA#&75:STASC+1:LDA#7:STASC:JSRTT67:LDA#0:JSRLYN:INCSC+1:JSRLYN:INCSC+1:INY:STYXC 9470.LYN LDY#233:.EE2 STA(SC),Y:DEY:BNEEE2:.SC5 RTS 9500.SCAN LDAINWK+31:AND#16:BEQSC5:LDATYPE:BMISC5:LDX#FF:\CMP#TGL\BEQSC49:CMP#MSL:BNEP%+4:LDX#&F0:\CMP#AST:\BCCP%+4:\LDX#&F:\SC49:STXCOL:LDAINWK+1:ORAINWK+4:ORAINWK+7:AND#&C0:BNESC5 9510LDAINWK+1:CLC:LDXINWK+2:BPLSC2:EOR#FF:ADC#1:.SC2 ADC#123:STAX1 9520LDAINWK+7:LSRA:LSRA:CLC:LDXINWK+8:BPLSC3:EOR#FF:SEC:.SC3 ADC#35:EOR#FF:STASC 9530LDAINWK+4:LSRA:CLC:LDXINWK+5:BMISCD6:EOR#FF:SEC:.SCD6 ADCSC:BPLld246:CMP#194:BCSP%+4:LDA#194:CMP#247:BCCP%+4:.ld246 LDA#246 9535STAY1:SEC:SBCSC:PHP:\BCSSC48:\EOR#FF:\ADC#1:.SC48 PHA:JSRCPIX4:LDACTWOS+1,X:ANDCOL:STAX1:PLA:PLP:TAX:BEQRTS:BCCRTS+1 9540.VLL1 DEY:BPLVL1:LDY#7:DECSC+1:.VL1 LDAX1:EOR(SC),Y:STA(SC),Y:DEX:BNEVLL1:.RTS RTS 9545INY:CPY#8:BNEP%+6:LDY#0:INCSC+1 9550.VLL2 INY:CPY#8:BNEVL2:LDY#0:INCSC+1:.VL2 LDAX1:EOR(SC),Y:STA(SC),Y:INX:BNEVLL2:RTS 9700.WSCAN LDA#0:STADL:LDADL:BEQP%-2:RTS 9900] 9910IFZ>4OSCLI("S.ELTC "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9920PRINT"C d,";:GOTO8 ================================================ FILE: 1-source-files/original-sources/$.ELITED.inf ================================================ $.ELITED 000000 000000 002E49 ================================================ FILE: 1-source-files/original-sources/$.ELITED.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 20REM ELITE 30H%=L%+P%-C%:O%=W% 300[OPTZ 700.tnpr pha:LDX#12:CPXQQ29:BCCkg:.Tml ADCQQ20,X:DEX:BPLTml:CMPCRGO:pla:RTS:.kg LDYQQ29:ADCQQ20,Y:cmp#200:pla:rts 840.TT20 JSRP%+3:JSRP%+3 850.TT54 LDAQQ15:CLC:ADCQQ15+2:TAX:LDAQQ15+1:ADCQQ15+3:TAY 860LDAQQ15+2:STAQQ15:LDAQQ15+3:STAQQ15+1:LDAQQ15+5:STAQQ15+3:LDAQQ15+4:STAQQ15+2:CLC:TXA:ADCQQ15+2:STAQQ15+4:TYA:ADCQQ15+3:STAQQ15+5:RTS 950.TT146 LDAQQ8:ORAQQ8+1:BNETT63:INCYC:RTS:.TT63 LDA#191:JSRTT68 955LDXQQ8:LDYQQ8+1:SEC:JSRpr5:LDA#195:.TT60 JSRTT27:.TTX69 INCYC:.TT69 LDA#128:STAQQ17:.TT67 LDA#13:JMPTT27 990.TT70 LDA#173:JSRTT27:JMPTT72:.spc JSRTT27:JMPTT162 1000.TT25\ DATA 1010JSRTT66-2:LDA#9:STAXC:LDA#163:JSRTT27:JSRNLIN:JSRTTX69:INCYC:JSRTT146:LDA#194 1030JSRTT68:LDAQQ3:CLC:ADC#1:LSRA:CMP#2:BEQTT70:LDAQQ3:BCCTT71 1040SBC#5:CLC:.TT71 ADC#170:JSRTT27:.TT72 LDAQQ3:LSRA:LSRA:CLC:ADC#168:JSRTT60:LDA#162:JSRTT68:LDAQQ4:CLC:ADC#177:JSRTT60:LDA#196:JSRTT68 1070LDXQQ5:INX:CLC:JSRpr2:JSRTTX69:LDA#192:JSRTT68:SEC:LDXQQ6:JSRpr2:LDA#198:JSRTT60:LDA#&28:JSRTT27:LDAQQ15+4:BMITT75:LDA#188:JSRTT27:JMPTT76:.TT75 LDAQQ15+5 1110LSRA:LSRA:PHA:AND#7:CMP#3:BCSTT205:ADC#227:JSRspc:.TT205 PLA:LSRA:LSRA:LSRA:CMP#6:BCSTT206:ADC#230:JSRspc:.TT206 LDAQQ15+3:EORQQ15+1:AND#7 1116STAQQ19:CMP#6:BCSTT207:ADC#236:JSRspc:.TT207 LDAQQ15+5:AND#3:CLC:ADCQQ19:AND#7:ADC#242:JSRTT27:.TT76 LDA#&53:JSRTT27:LDA#&29:JSRTT60 1127LDA#193:JSRTT68:LDXQQ7:LDYQQ7+1:JSRpr6:JSRTT162:LDA#0:STAQQ17:LDA#&4D:JSRTT27:LDA#226:JSRTT60:LDA#250:JSRTT68:LDAQQ15+5:LDXQQ15+3:AND#15:CLC:ADC#11:TAY 1150JSRpr5:JSRTT162:LDA#&6B:JSRTT26:LDA#&6D:JMPTT26 1200.TT24 1210LDAQQ15+1:AND#7:STAQQ3:LDAQQ15+2:LSRA:LSRA:LSRA:AND#7:STAQQ4:LSRA:BNETT77:LDAQQ3:ORA#2:STAQQ3:.TT77 LDAQQ3:EOR#7:CLC:STAQQ5:LDAQQ15+3:AND#3:ADCQQ5:STAQQ5 1240LDAQQ4:LSRA:ADCQQ5:STAQQ5:ASLA:ASLA:ADCQQ3:ADCQQ4:ADC#1:STAQQ6:LDAQQ3:EOR#7:ADC#3:STAP:LDAQQ4:ADC#4:STAQ:JSRMULTU:LDAQQ6:STAQ:JSRMULTU:ASLP:ROLA:ASLP:ROLA:ASLP:ROLA:STAQQ7+1:LDAP:STAQQ7:RTS 1400.TT22\Lng Sc 1410LDA#64:JSRTT66:LDA#7:STAXC:JSRTT81:LDA#199:JSRTT27:JSRNLIN:LDA#152:JSRNLIN2:JSRTT14 1460LDX#0:.TT83 STXXSAV:LDXQQ15+3:LDYQQ15+4:TYA:ORA#&50:STAZZ 1470LDAQQ15+1:LSRA:CLC:ADC#24:STAXX15+1:JSRPIXEL:JSRTT20:LDXXSAV:INX:BNETT83:LDAQQ9:STAQQ19:LDAQQ10:LSRA:STAQQ19+1:LDA#4:STAQQ19+2 1700.TT15 1705LDA#24:LDXQQ11:BPLP%+4:LDA#0:STAQQ19+5:LDAQQ19:SEC:SBCQQ19+2:BCSTT84:LDA#0:.TT84 STAXX15:LDAQQ19:CLC:ADCQQ19+2:BCCP%+4:LDA#FF:STAXX15+2 1725LDAQQ19+1:CLC:ADCQQ19+5:STAXX15+1:JSRHLOIN:LDAQQ19+1:SEC:SBCQQ19+2:BCSTT86:LDA#0:.TT86 CLC:ADCQQ19+5:STAXX15+1:LDAQQ19+1:CLC:ADCQQ19+2:ADCQQ19+5:CMP#152:BCCTT87 1750LDXQQ11:BMITT87:LDA#151:.TT87 STAXX15+3:LDAQQ19:STAXX15:STAXX15+2:JMPLL30 1800.TT126 LDA#104:STAQQ19:LDA#90:STAQQ19+1:LDA#16:STAQQ19+2:JSRTT15:LDAQQ14:STAK:JMPTT128 2000.TT14\Crcl/+ 2010LDAQQ11:BMITT126:LDAQQ14:LSRA:LSRA:STAK:LDAQQ0:STAQQ19:LDAQQ1:LSRA:STAQQ19+1:LDA#7:STAQQ19+2:JSRTT15:LDAQQ19+1:CLC:ADC#24:STAQQ19+1 2300.TT128 LDAQQ19:STAK3:LDAQQ19+1:STAK4:LDX#0:STXK4+1:STXK3+1:\STXLSX:INX:STXLSP:LDX#2:STXSTP 2310JSRCIRCLE2:\LDA#FFSTALSX:RTS 2650.TT219\Buy 2655\LDA#2:JSRTT66-2:JSRTT163:LDA#128:STAQQ17:\JSRFLKB:LDA#0:STAQQ29 2660.TT220 JSRTT151:LDAQQ25:BNETT224:JMPTT222:.TQ4 LDY#176:.Tc JSRTT162:TYA:JSRprq:.TTX224 JSRdn2:.TT224 2671JSRCLYNS:LDA#204:JSRTT27:LDAQQ29:CLC:ADC#208:JSRTT27:LDA#&2F:JSRTT27:JSRTT152:LDA#&3F:JSRTT27:JSRTT67:LDX#0:STXR:LDX#12:STXT1:.TT223 2700JSRgnum:BCSTQ4:STAP:JSRtnpr:LDY#206:BCSTc:LDAQQ24:STAQ:JSRGCASH:JSRLCASH:LDY#197:BCCTc 2708LDYQQ29:LDAR:PHA:CLC:ADCQQ20,Y:STAQQ20,Y:LDAAVL,Y:SEC:SBCR:STAAVL,Y:PLA:BEQTT222:JSRdn 2710.TT222 LDAQQ29:CLC:ADC#5:STAYC:LDA#0:STAXC:INCQQ29:LDAQQ29:CMP#17:BCSBAY2:JMPTT220:.BAY2 LDA#f9:JMPFRCE 2750.gnum LDX#0:STXR:LDX#12:STXT1:.TT223 JSRTT217:STAQ:SEC:SBC#&30:BCCOUT:CMP#10:BCSBAY2:STAS:LDAR:CMP#26:BCSOUT:ASLA:STAT:ASLA:ASLA:ADCT:ADCS:STAR:CMPQQ25:BEQTT226:BCSOUT:.TT226 LDAQ:JSRTT26:DECT1:BNETT223:.OUT LDAR:RTS 2850.TT208\Sel 2855LDA#4:JSRTT66:LDA#4:STAYC:STAXC:\JSRFLKB:LDA#205:JSRTT27:LDA#206:JSRTT68 2900.TT210\Crgo 2910LDY#0:.TT211 STYQQ29:LDXQQ20,Y:BEQTT212 2912TYA:ASLA:ASLA:TAY:LDAQQ23+1,Y:STAQQ19+1 2915TXA:PHA:JSRTT69:CLC:LDAQQ29:ADC#208 2917JSRTT27:LDA#14:STAXC:PLA:TAX:CLC:JSRpr2:JSRTT152 2922LDAQQ11:CMP#4:BNETT212:LDA#205:JSRTT214 2923BCCTT212:LDAQQ29:LDX#255:STXQQ17:JSRTT151 2925LDYQQ29:LDAQQ20,Y:STAP:LDAQQ24:STAQ:JSRGCASH:JSRMCASH 2935LDA#0:LDYQQ29:STAQQ20,Y:STAQQ17 2940.TT212 LDYQQ29:INY:CPY#17:BCSP%+5:JMPTT211:LDAQQ11:CMP#4:BNEP%+8:JSRdn2:JMPBAY2:RTS 2942.TT213\Invntry 2945LDA#8:JSRTT66:LDA#11:STAXC:LDA#164:JSRTT60:JSRNLIN4:JSRfwl 2950LDACRGO:CMP#26:BCCP%+7:LDA#&6B:JSRTT27:JMPTT210 2965.TT214 PHA:JSRTT162:PLA:.TT221 JSRTT27:LDA#225:JSRTT27 2966JSRTT217:ORA#32:CMP#&79:BEQTT218:LDA#&6E:JMPTT26:.TT218 JSRTT26:SEC:RTS 3000.TT16 TXA:PHA:DEY:TYA:EOR#255:PHA:JSRWSCAN:JSRTT103:PLA:STAQQ19+3 3010LDAQQ10:JSRTT123:LDAQQ19+4:STAQQ10:STAQQ19+1:PLA 3020STAQQ19+3:LDAQQ9:JSRTT123:LDAQQ19+4:STAQQ9:STAQQ19:.TT103 3030LDAQQ11:BEQTT180:BMITT105:LDAQQ9:STAQQ19:LDAQQ10:LSRA:STAQQ19+1 3040LDA#4:STAQQ19+2:JMPTT15 3045.TT123 STAQQ19+4:CLC:ADCQQ19+3:LDXQQ19+3:BMITT124:BCCTT125 3047RTS:.TT124 BCCTT180:.TT125 STAQQ19+4:.TT180 RTS 3050.TT105 LDAQQ9:SEC:SBCQQ0:CMP#38:BCCTT179:CMP#230:BCCTT180 3055.TT179 ASLA:ASLA:CLC:ADC#104:STAQQ19 3060LDAQQ10:SEC:SBCQQ1:CMP#38:BCCP%+6:CMP#220:BCCTT180 3065ASLA:CLC:ADC#90:STAQQ19+1:LDA#8:STAQQ19+2:JMPTT15 3300.TT23\ShrtSc 3310LDA#128:JSRTT66:LDA#7:STAXC:LDA#190:JSRNLIN3:JSRTT14:JSRTT103:JSRTT81 3349LDA#0:STAXX20:LDX#24:.EE3 STAINWK,X:DEX:BPLEE3 3350.TT182 LDAQQ15+3:SEC:SBCQQ0:BCSTT184:EOR#FF:ADC#1:.TT184 CMP#20:BCSTT187:LDAQQ15+1:SEC:SBCQQ1:BCSTT186:EOR#FF:ADC#1:.TT186 CMP#38:BCSTT187 3370LDAQQ15+3:SEC:SBCQQ0:ASLA:ASLA:ADC#104:STAXX12:LSRA:LSRA:LSRA:STAXC:INCXC:LDAQQ15+1:SEC:SBCQQ1:ASLA:ADC#90:STAK4:LSRA:LSRA:LSRA 3377TAY:LDXINWK,Y:BEQEE4:INY:LDXINWK,Y:BEQEE4:DEY:DEY:LDXINWK,Y:BNEee1:.EE4 STYYC:CPY#3:BCCTT187:DEX:STXINWK,Y 3380LDA#128:STAQQ17:JSRcpl:.ee1 3390\bigstars:LDA#0:STAK3+1:STAK4+1:STAK+1:LDAXX12:STAK3:LDAQQ15+5:AND#1:ADC#2:STAK:JSRFLFLLS:JSRSUN:JSRFLFLLS 3400.TT187 JSRTT20:INCXX20:BEQTT111-1:JMPTT182 3450.TT81 LDX#5:LDAQQ21,X:STAQQ15,X:DEX:BPLTT81+2 3500RTS:.TT111 JSRTT81:LDY#127:STYT:LDA#0:STAU 3510.TT130 LDAQQ15+3:SEC:SBCQQ9:BCSTT132:EOR#FF:ADC#1:.TT132 LSRA:STAS:LDAQQ15+1:SEC:SBCQQ10:BCSTT134:EOR#FF:ADC#1:.TT134 LSRA:CLC:ADCS:CMPT:BCSTT135 3550STAT:LDX#5:.TT136 LDAQQ15,X:STAQQ19,X:DEX:BPLTT136:.TT135 3560JSRTT20:INCU:BNETT130:LDX#5:.TT137 LDAQQ19,X:STAQQ15,X:DEX 3570BPLTT137:LDAQQ15+1:STAQQ10:LDAQQ15+3:STAQQ9 3575SEC:SBCQQ0:BCSTT139:EOR#FF:ADC#1:.TT139 JSRSQUA2:STAK+1:LDAP:STAK:LDAQQ10 3590SEC:SBCQQ1:BCSTT141:EOR#FF:ADC#1:.TT141 LSRA:JSRSQUA2:PHA:LDAP:CLC:ADCK 3610STAQ:PLA:ADCK+1:STAR:JSRLL5:LDAQ:ASLA:LDX#0:STXQQ8+1:ROLQQ8+1:ASLA:ROLQQ8+1:STAQQ8:JMPTT24 4340.hy6 JSRCLYNS:LDA#15:STAXC:JMPTT27 4350.hyp LDAQQ12:BNEhy6:LDAQQ22+1:BNEzZ+1:JSRCTRL:BMIGhy 4353JSRhm 4355LDAQQ8:ORAQQ8+1:BEQzZ+1:LDA#7:STAXC:LDA#23:STAYC:LDA#0:STAQQ17:LDA#189:JSRTT27:LDAQQ8+1:BNETT147:LDAQQ14:CMPQQ8:BCCTT147 4380LDA#&2D:JSRTT27:JSRcpl:.wW LDA#15:STAQQ22+1:STAQQ22:TAX:JMPee3\hy5 RTS 4392.Ghy LDXGHYP:BEQhy5:INX:STXQQ8:STXQQ8+1:STXGHYP:STXFIST:JSRwW:LDX#5:INCGCNT:LDAGCNT:AND#7:STAGCNT:.G1 LDAQQ21,X:ASLA:ROLQQ21,X:DEX:BPLG1:\JSRDORND:.zZ LDA#&60:STAQQ9:STAQQ10:JSRTT110:LDA#116:JSRMESS:.jmp LDAQQ9:STAQQ0:LDAQQ10 4393STAQQ1:.hy5 RTS 4395.ee3 LDY#1:STYYC:DEY:STYXC:.pr6 CLC:.pr5 LDA#5:JMPTT11 4400.TT147 LDA#202:.prq JSRTT27:LDA#&3F:JMPTT27 5000.TT151\Pmk-A 5010PHA:STAQQ19+4:ASLA:ASLA:STAQQ19:LDA#1:STAXC:PLA:ADC#208 5015JSRTT27:LDA#14:STAXC:LDXQQ19:LDAQQ23+1,X:STAQQ19+1:LDAQQ26:ANDQQ23+3,X:CLC:ADCQQ23,X:STAQQ24:JSRTT152 5050JSRvar:LDAQQ19+1:BMITT155:LDAQQ24:ADCQQ19+3:JMPTT156 5060.TT155 LDAQQ24:SEC:SBCQQ19+3:.TT156 STAQQ24:STAP:LDA#0:JSRGC2 5070SEC:JSRpr5:LDYQQ19+4:LDA#5:LDXAVL,Y:STXQQ25 5100CLC:BEQTT172:JSRpr2+2:JMPTT152:.TT172 LDAXC:ADC#4:STAXC:LDA#&2D:BNETT162+2 5110.TT152 LDAQQ19+1:AND#96:BEQTT160:CMP#32:BEQTT161 5120JSRTT16a:.TT162 LDA#32:JMPTT27 5130.TT160 LDA#&74:JSRTT26:BCCTT162 5140.TT161 LDA#&6B:JSRTT26:.TT16a LDA#&67:JMPTT26 5160.TT163 LDA#17:STAXC:LDA#FF:BNETT162+2 5200.TT167\MktP 5210LDA#16:JSRTT66:LDA#5:STAXC:LDA#167:JSRNLIN3:LDA#3:STAYC:JSRTT163:LDA#0:STAQQ29:.TT168 LDX#128:STXQQ17:JSRTT151:INCYC 5250INCQQ29:LDAQQ29:CMP#17:BCCTT168:RTS 5900.var LDAQQ19+1:AND#31:LDYQQ28:STAQQ19+2:CLC:LDA#0:STAAVL+16:.TT153 DEY:BMITT154:ADCQQ19+2:JMPTT153:.TT154 STAQQ19+3:RTS 5980.hyp1 JSRTT111:JSRjmp:LDX#5:.TT112 LDAQQ15,X:STAQQ2,X:DEX:BPLTT112:INX:STXEV:LDAQQ3:STAQQ28:LDAQQ5:STAtek:LDAQQ4:STAgov:RTS 5990.GVL JSRDORND:STAQQ26:LDX#0:STXXX4:.hy9 LDAQQ23+1,X:STAQQ19+1:JSRvar:LDAQQ23+3,X:ANDQQ26:CLC:ADCQQ23+2,X:LDYQQ19+1:BMITT157:SEC:SBCQQ19+3:JMPTT158:.TT157 CLC:ADCQQ19+3:.TT158 BPLTT159:LDA#0:.TT159 5994LDYXX4:AND#63:STAAVL,Y:INY:TYA:STAXX4:ASLA:ASLA:TAX:CMP#63:BCChy9:.hyR RTS 5995.GTHG JSRZe:LDA#FF:STAINWK+32:LDA#THG:JSRNWSHP:LDA#TGL:JMPNWSHP 5996.ptg LSRCOK:SEC:ROLCOK 5998.MJP\LDA#1:JSRTT66-2:JSRLL164:JSRRES2:STYMJ:.MJP1 JSRGTHG:LDA#3:CMPMANY+THG:BCSMJP1:STANOSTM:LDX#0:JSRLOOK1:LDAQQ1:EOR#31:STAQQ1:RTS 6000.TT18\HSPC 6005LDAQQ14:SEC:SBCQQ8:STAQQ14:LDAQQ11:BNEee5:JSRTT66:JSRLL164:.ee5 JSRCTRL:ANDPATG:BMIptg:JSRDORND:CMP#253:BCSMJP\JSRTT111:JSRhyp1+3:JSRGVL:JSRRES2:JSRSOLAR 6500LDAQQ11:AND#63:BNEhyR:JSRTTX66:LDAQQ11:BNETT114:INCQQ11:.TT110 LDXQQ12:BEQNLUNCH:JSRLAUN:JSRRES2:JSRTT111:INCINWK+8:JSRSOS1:LDA#128:STAINWK+8:INCINWK+7:JSRNWSPS:LDA#12:STADELTA:JSRBAD:ORAFIST:STAFIST 6510.NLUNCH LDX#0:STXQQ12:JMPLOOK1:.TT114 BMITT115:JMPTT22:.TT115 JMPTT23 6530.LCASH STXT1:LDACASH+3:SEC:SBCT1:STACASH+3:STYT1:LDACASH+2:SBCT1:STACASH+2:LDACASH+1:SBC#0:STACASH+1:LDACASH:SBC#0:STACASH:BCSTT113 6540.MCASH TXA:CLC:ADCCASH+3:STACASH+3:TYA:ADCCASH+2:STACASH+2:LDACASH+1:ADC#0:STACASH+1:LDACASH:ADC#0:STACASH:CLC:.TT113 RTS 6550.GCASH JSRMULTU:.GC2 ASLP:ROLA:ASLP:ROLA:TAY:LDXP:RTS 6690.bay JMPBAY 6700.EQSHP JSRDIALS:LDA#32:JSRTT66:LDA#12:STAXC:LDA#207:JSRspc:LDA#185:JSRNLIN3:LDA#128:STAQQ17:INCYC:LDAtek:CLC:ADC#3:CMP#12:BCCP%+4:LDA#12:STAQ:STAQQ25:INCQ:LDA#70:SEC:SBCQQ14:ASLA:STAPRXS 6710LDX#1:.EQL1 STXXX13:JSRTT67:LDXXX13:CLC:JSRpr2:JSRTT162:LDAXX13:CLC:ADC#&68:JSRTT27:LDAXX13:JSRprx-3:SEC:LDA#25:STAXC:LDA#6:JSRTT11:LDXXX13:INX:CPXQ:BCCEQL1 6720JSRCLYNS:LDA#127:JSRprq:JSRgnum:beqbay:bcsbay:SBC#0:LDX#2:STXXC:INCYC:PHA:JSReq:PLA:BNEet0:STAMCNT:LDX#70:STXQQ14:.et0 CMP#1:BNEet1:LDXNOMSL:INX:LDY#&75:CPX#5:BCSpres 6730STXNOMSL:JSRmsblob:.et1 LDY#&6B:CMP#2:BNEet2:LDX#37:CPXCRGO:BEQpres:STXCRGO:.et2 CMP#3:BNEet3:INY:LDXECM:BNEpres:DECECM:.et3 CMP#4:BNEet4:JSRqv:LDA#4:LDYLASER,X:BEQed4:.ed7 LDY#187:BNEpres:.ed4 LDA#POW:STALASER,X:LDA#4:.et4 6740CMP#5:BNEet5:JSRqv:STXT1:LDA#5:LDYLASER,X:BEQed5:\BPLP%+4:BMIed7:LDA#4:JSRprx:JSRMCASH:.ed5 LDA#POW+128:LDXT1:STALASER,X:.et5 6750LDY#&6F:CMP#6:BNEet6:LDXBST:BEQed9:.pres STYK:JSRprx:JSRMCASH:LDAK:JSRspc:LDA#31:JSRTT27:.err JSRdn2:JMPBAY:.ed9 DECBST:.et6 INY:CMP#7:BNEet7:LDXESCP:BNEpres:DECESCP:.et7 INY:CMP#8:BNEet8:LDXBOMB:BNEpres:LDX#&7F:STXBOMB:.et8 6800INY:CMP#9:BNEetA:LDXENGY:BNEpres:INCENGY:.etA INY:CMP#10:BNEetB:LDXDKCMP:BNEpres:DECDKCMP:.etB:INY:CMP#11:BNEet9:LDXGHYP:BNEpres:DECGHYP:.et9 JSRdn:JMPEQSHP:.dn JSRTT162:LDA#119:JSRspc:.dn2 JSRBEEP:LDY#50:JMPDELAY 6900.eq JSRprx:JSRLCASH:BCSc:LDA#197:JSRprq:JMPerr:SEC:SBC#1:.prx ASLA:TAY:LDXPRXS,Y:LDAPRXS+1,Y:TAY:.c RTS 6910.qv LDY#16:STYYC:.qv1 LDX#12:STXXC:TYA:CLC:ADC#B-16:JSRspc:LDAYC:CLC:ADC#&50:JSRTT27:INCYC:LDYYC:CPY#20:BCCqv1:.qv3 JSRCLYNS:.qv2 LDA#175:JSRprq:JSRTT217:SEC:SBC#&30:CMP#4:BCSqv3:TAX:RTS 9900] 9910IFZ>4OSCLI("S.ELTD "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9920PRINT"D d,";:GOTO10 ================================================ FILE: 1-source-files/original-sources/$.ELITEE.inf ================================================ $.ELITEE 000000 000000 002DDB ================================================ FILE: 1-source-files/original-sources/$.ELITEE.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 11GOTO20 12*L.ELITEF 20REM ELITE 100H%=L%+P%-C%:O%=W%:A$="(C)Bell/Braben1984":B$=STRING$(26," "):B$="":FORI%=1TOLENA$:B$=B$+CHR$(ASC(MID$(A$,I%,1))EOR&A4):NEXT:[OPTZ:EQUSB$ 190.cpl LDX#5:.TT53 LDAQQ15,X:STAQQ19,X:DEX:BPLTT53:LDY#3:BITQQ15:BVSP%+3:DEY:STYT:.TT55 LDAQQ15+5:AND#31:BEQP%+7:ORA#128:JSRTT27:JSRTT54:DECT:BPLTT55:LDX#5:.TT56 LDAQQ19,X:STAQQ15,X:DEX:BPLTT56:RTS 200.cmn LDY#0:.QUL4 LDANA%,Y:CMP#13:BEQypl-1:JSRTT26:INY:BNEQUL4:RTS 300.ypl LDAMJ:BNEcmn-1:JSRTT62:JSRcpl:.TT62 LDX#5:.TT78 LDAQQ15,X:LDYQQ2,X:STAQQ2,X:STYQQ15,X:DEX:BPLTT78:RTS 500.tal CLC:LDXGCNT:INX:JMPpr2:.fwl LDA#105:JSRTT68:LDXQQ14:SEC:JSRpr2:LDA#195:JSRplf:.PCASH LDA#119:BNETT27 510.csh LDX#3:.pc1 LDACASH,X:STAK,X:DEX:BPLpc1:LDA#9:STAU:SEC:JSRBPRNT:LDA#226:.plf JSRTT27:JMPTT67:.TT68 JSRTT27:.TT73 LDA#&3A 600.TT27 TAX:BEQcsh:BMITT43:DEX:BEQtal:DEX:BEQypl:dex:bneP%+5:JMPcpl:dex:beqcmn:dex:beqfwl:dex:bneP%+7:LDA#128:STAQQ17:RTS:DEX:DEX:BNEP%+5:STXQQ17:RTS:dex:beqcrlf:CMP#&60:BCSex:CMP#14:BCCP%+6:CMP#32:BCCqw:LDXQQ17 620BEQTT74:BMITT41:BITQQ17:BVSTT46:.TT42 CMP#65:BCCTT44:CMP#&5B:BCSTT44:ADC#32:.TT44 JMPTT26:.TT41 BITQQ17:BVSTT45:CMP#65:BCCTT74:PHA:TXA:ORA#64:STAQQ17:PLA:BNETT44 630.qw ADC#114:BNEex:.crlf LDA#21:STAXC:BNETT73:.TT45 CPX#FF:BEQTT48:CMP#65:BCSTT42:.TT46 PHA:TXA:AND#191:STAQQ17:PLA:.TT74 JMPTT26:.TT43 CMP#160:BCSTT47:AND#127:ASLA:TAY:LDAQQ16,Y 670JSRTT27:LDAQQ16+1,Y:CMP#63:BEQTT48:JMPTT27:.TT47 SBC#160:.ex TAX:LDA#(QQ18 MOD256):STAV:LDA#(QQ18 DIV256):STAV+1:LDY#0:TXA:BEQTT50 680.TT51 LDA(V),Y:BEQTT49:INY:BNETT51:INCV+1:BNETT51:.TT49 INY:BNETT59:INCV+1:.TT59 DEX:BNETT51:.TT50 693TYA:PHA:LDAV+1:PHA:LDA(V),Y:EOR#35 695JSRTT27:PLA:STAV+1:PLA:TAY:INY:BNEP%+4:INCV+1:LDA(V),Y:BNETT50:.TT48 RTS 1990.EX2 LDAINWK+31:ORA#&A0:STAINWK+31:RTS 2000.DOEXP LDAINWK+31:AND#64:BEQP%+5:JSRPTCLS:LDAINWK+6:STAT:LDAINWK+7:CMP#&20:BCCP%+6:LDA#&FE:BNEyy:ASLT:ROLA:ASLT:ROLA:SEC:ROLA:.yy STAQ:LDY#1:LDA(XX19),Y:ADC#4:BCSEX2 2040STA(XX19),Y:JSRDVID4:LDAP:CMP#&1C:BCCP%+6:LDA#&FE:BNE`_:ASLR:ROLA:ASLR:ROLA:ASLR:ROLA:.`_ DEY:STA(XX19),Y:LDAINWK+31:AND#&BF:STAINWK+31:AND#8:BEQTT48 2050LDY#2:LDA(XX19),Y:TAY:.EXL1 LDAXX3-7,Y:STA(XX19),Y:DEY:CPY#6:BNEEXL1:LDAINWK+31:ORA#64:STAINWK+31 2100.PTCLS LDY#0:LDA(XX19),Y:STAQ:INY:LDA(XX19),Y:BPLP%+4:EOR#FF:LSRA:LSRA:LSRA:ORA#1:STAU:INY:LDA(XX19),Y:STATGT:LDARAND+1:PHA 2110LDY#6:.EXL5 LDX#3:.EXL3 INY:LDA(XX19),Y:STAK3,X:DEX:BPLEXL3:STYCNT:LDY#2:.EXL2 INY:LDA(XX19),Y:EORCNT:STARAND-3,Y:CPY#6:BNEEXL2:LDYU 2140.EXL4 JSRDORND2:STAZZ:LDAK3+1:STAR:LDAK3:JSREXS1:BNEEX11:CPX#2*Y-1:BCSEX11:STXY1:LDAK3+3:STAR:LDAK3+2:JSREXS1:BNEEX4:LDAY1:JSRPIXEL:.EX4 DEY:BPLEXL4:LDYCNT:CPYTGT:BCCEXL5 2180PLA:STARAND+1:LDAK%+6:STARAND+3:RTS:.EX11 JSRDORND2:JMPEX4 2200.EXS1 STAS:JSRDORND2:ROLA:BCSEX5:JSRFMLTU:ADCR:TAX:LDAS:ADC#0:RTS 2210.EX5 JSRFMLTU:STAT:LDAR:SBCT:TAX:LDAS:SBC#0:RTS 3008.SOS1 JSRmsblob:LDA#127:STAINWK+29:STAINWK+30:LDAtek:AND#2:ORA#128:JMPNWSHP 3010.SOLAR LSRFIST:JSRZINF:LDAQQ15+1:AND#7:ADC#6:LSRA:STAINWK+8:RORA:STAINWK+2:STAINWK+5 3020JSRSOS1:LDAQQ15+3:AND#7:ORA#129:STAINWK+8:LDAQQ15+5:AND#3:STAINWK+2:STAINWK+1:LDA#0:STAINWK+29:STAINWK+30:LDA#&81:JSRNWSHP 3600.NWSTARS LDAQQ11:\ORAMJ:BNEWPSHPS:.nWq LDYNOSTM:.SAL4 JSRDORND:ORA#8:STASZ,Y:STAZZ:JSRDORND:STASX,Y:STAX1:JSRDORND:STASY,Y:STAY1:JSRPIXEL2:DEY:BNESAL4 3710.WPSHPS LDX#0:.WSL1 LDAFRIN,X:BEQWS2:BMIWS1:STATYPE:JSRGINF:LDY#31 3730.WSL2 LDA(INF),Y:STAINWK,Y:DEY:BPLWSL2:STXXSAV:JSRSCAN:LDXXSAV:LDY#31:LDA(INF),Y:AND#&A7:STA(INF),Y:.WS1 INX:BNEWSL1:.WS2 LDX#FF:STXLSX2:STXLSY2 3740.FLFLLS LDY#2*Y-1:LDA#0:.SAL6 STALSO,Y:DEY:BNESAL6:DEY:STYLSX:RTS 3810.DET1 LDA#6:SEI:STA&FE00:STX&FE01:CLI:RTS 3900DEX:RTS:.SHD INX:BEQSHD-2:.DENGY DECENERGY:PHP:BNEP%+5:INCENERGY:PLP:RTS 4000.COMPAS JSRDOT:LDASSPR:BNESP1:JSRSPS1:JMPSP2:.SPS2 ASLA:TAX:LDA#0:RORA:TAY:LDA#20 \14:STAQ:TXA:JSRDVID4:LDXP 4080TYA:BMILL163:LDY#0:RTS:.LL163 LDY#FF:TXA:EOR#FF:TAX:INX:RTS 4090.SPS4 LDX#8:.SPL1 LDAK%+NI%,X:STAK3,X:DEX:BPLSPL1:JMPTAS2 4100.SP1 JSRSPS4:.SP2 LDAXX15:JSRSPS2:TXA:ADC#195\X-1:STACOMX:LDAXX15+1:JSRSPS2:STXT:LDA#204:SBCT:STACOMY 4130LDA#&F0:LDXXX15+2:BPLP%+4:LDA#FF:STACOMC 4200.DOT LDACOMY:STAY1:LDACOMX:STAX1:LDACOMC:STACOL:CMP#&F0:BNECPIX2:.CPIX4 JSRCPIX2:DECY1:.CPIX2 LDAY1 4250\.CPIX:TAY:LSRA:LSRA:LSRA:ORA#&60:STASCH:LDAX1:AND#&F8:STASC:TYA:AND#7:TAY:LDAX1:AND#6:LSRA:TAX:LDACTWOS,X:ANDCOL:EOR(SC),Y:STA(SC),Y 4260LDACTWOS+1,X:BPLCP1:LDASC:ADC#8:STASC:LDACTWOS+1,X:.CP1 ANDCOL:EOR(SC),Y:STA(SC),Y:RTS 4300.OOPS STAT:LDY#8:LDX#0:LDA(INF),Y:BMIOO1:LDAFSH:SBCT:BCCOO2:STAFSH:RTS:.OO2 \LDX#0:STXFSH:BCCOO3:.OO1 LDAASH:SBCT:BCCOO5:STAASH:RTS:.OO5 \LDX#0:STXASH:.OO3 ADCENERGY:STAENERGY:BEQP%+4:BCSP%+5:JMPDEATH:JSREXNO3:JMPOUCH 4410.SPS3 LDAK%+1,X:STAK3,X:LDAK%+2,X:TAY:AND#127:STAK3+1,X:TYA:AND#128:STAK3+2,X:RTS 4450.GINF TXA:ASLA:TAY:LDAUNIV,Y:STAINF:LDAUNIV+1,Y:STAINF+1:RTS 4480.NWSPS JSRSPBLB:LDX#1:STXINWK+32:DEX:STXINWK+30:\STXINWK+31:STXFRIN+1:DEX:STXINWK+29:LDX#10:JSRNwS1:JSRNwS1:JSRNwS1 4490LDA#(LSO MOD256):STAINWK+33:LDA#(LSO DIV256):STAINWK+34:LDA#SST 4500.NWSHP STAT:LDX#0:.NWL1 LDAFRIN,X:BEQNW1:INX:CPX#NOSH:BCCNWL1:.NW3 CLC:RTS 4510.NW1 JSRGINF:LDAT:BMINW2:ASLA:TAY:LDAXX21-2,Y:STAXX0:LDAXX21-1,Y:STAXX0+1:CPY#2*SST:BEQNW6:LDY#5:LDA(XX0),Y:STAT1:LDASLSP:SEC:SBCT1:STAINWK+33:LDASLSP+1:SBC#0:STAINWK+34 4530LDAINWK+33:\SEC:SBCINF:TAY:LDAINWK+34:SBCINF+1:BCCNW3+1:BNENW4:CPY#NI%:BCCNW3+1:.NW4 4550LDAINWK+33:STASLSP:LDAINWK+34:STASLSP+1:.NW6 LDY#14:LDA(XX0),Y:STAINWK+35:LDY#19:LDA(XX0),Y:AND#7:STAINWK+31 4560LDAT:.NW2 STAFRIN,X:TAX:BMIP%+5:INCMANY,X:LDY#(NI%-1):.NWL3 LDAINWK,Y:STA(INF),Y:DEY:BPLNWL3:SEC:RTS 4600.NwS1 LDAINWK,X:EOR#128:STAINWK,X:INX:INX:RTS 4710.ABORT LDX#FF:.ABORT2 STXMSTG:LDXNOMSL:JSRMSBAR:STYMSAR:RTS 4730.ECBLB2 LDA#32:STAECMA:ASLA:JSRNOISE:.ECBLB LDA#7*8:\" <<120<":LDX#(ECBT MOD256):LDY#(ECBT DIV256):BNEBULB-2 4740.SPBLB LDA#24*8:\"<<128<":LDX#(SPBT MOD256):LDY#(SPBT DIV256):.BULB STASC:STXP+1:STYP+2:LDA#&7D:JMPRREN 4800.ECBT EQUW&E0E0:EQUB&80:.SPBT EQUD&E080E0E0:EQUD&E0E020E0 4900.MSBAR TXA:ASLA:ASLA:ASLA:STAT:LDA#49\113:SBCT:STASC:LDA#&7E:STASCH:TYA:LDY#5:.MBL1 STA(SC),Y:DEY:BNEMBL1:RTS 5000.PROJ LDAINWK:STAP:LDAINWK+1:STAP+1:LDAINWK+2:JSRPLS6:BCSPL2-1:LDAK:ADC#X:STAK3:TXA:ADC#0:STAK3+1 5010LDAINWK+3:STAP:LDAINWK+4:STAP+1:LDAINWK+5:EOR#128:JSRPLS6:BCSPL2-1:LDAK:ADC#Y:STAK4:TXA:ADC#0:STAK4+1:CLC:RTS 5020.PL2 LDATYPE:LSRA:BCSP%+5:JMPWPLS2:JMPWPLS 5040.PLANET LDAINWK+8:BMIPL2:CMP#48:BCSPL2:ORAINWK+7:BEQPL2:JSRPROJ:BCSPL2 5090LDA#96:STAP+1:LDA#0:STAP:JSRDVID3B2:LDAK+1:BEQPL82:LDA#&F8:STAK:.PL82 5110LDATYPE:LSRA:BCCPL9:JMPSUN:.PL9 JSRWPLS2:JSRCIRCLE:BCSPL20:LDAK+1:BEQPL25:.PL20 RTS 5160.PL25 LDATYPE:CMP#&80:BNEPL26:LDAK:CMP#6:BCCPL20:LDAINWK+14:EOR#128:STAP:LDAINWK+20:JSRPLS4:LDX#9:JSRPLS1:STAK2:STYXX16:JSRPLS1:STAK2+1:STYXX16+1:LDX#15:JSRPLS5 5230JSRPLS2:LDAINWK+14:EOR#128:STAP:LDAINWK+26:JSRPLS4 5240LDX#21:JSRPLS5:JMPPLS2 5270.PL26\crtr:LDAINWK+20:BMIPL20 5280LDX#15:JSRPLS3:CLC:ADCK3:STAK3:TYA:ADCK3+1:STAK3+1:JSRPLS3:STAP:LDAK4:SEC:SBCP:STAK4:STYP:LDAK4+1:SBCP:STAK4+1 5300LDX#9:JSRPLS1:LSRA:STAK2:STYXX16:JSRPLS1:LSRA:STAK2+1:STYXX16+1 5310LDX#21:JSRPLS1:LSRA:STAK2+2:STYXX16+2:JSRPLS1:LSRA:STAK2+3:STYXX16+3 5320LDA#64:STATGT:LDA#0:STACNT2:JMPPLS22 5330.PLS1 LDAINWK,X:STAP:LDAINWK+1,X:AND#127:STAP+1:LDAINWK+1,X:AND#128 5340JSRDVID3B2:LDAK:LDYK+1:BEQP%+4:LDA#&FE:LDYK+3:INX:INX:RTS 5350.PLS2 LDA#31:STATGT:.PLS22 LDX#0:STXCNT:DEX:STXFLAG:.PLL4 5360LDACNT2:AND#31:TAX:LDASNE,X:STAQ:LDAK2+2:JSRFMLTU:STAR:LDAK2+3:JSRFMLTU:STAK:LDXCNT2:CPX#33:LDA#0:RORA:STAXX16+5 5370LDACNT2:CLC:ADC#16:AND#31:TAX:LDASNE,X:STAQ:LDAK2+1:JSRFMLTU:STAK+2:LDAK2:JSRFMLTU:STAP:LDACNT2:ADC#15:AND#63:CMP#33:LDA#0:RORA:STAXX16+4 5380LDAXX16+5:EORXX16+2:STAS:LDAXX16+4:EORXX16:JSRADD:STAT:BPLPL42:TXA:EOR#FF:CLC:ADC#1:TAX:LDAT:EOR#&7F:ADC#0:STAT:.PL42:TXA:ADCK3:STAK6:LDAT:ADCK3+1:STAK6+1 5390LDAK:STAR:LDAXX16+5:EORXX16+3:STAS:LDAK+2:STAP:LDAXX16+4:EORXX16+1:JSRADD:EOR#128:STAT:BPLPL43:TXA:EOR#FF:CLC:ADC#1:TAX:LDAT:EOR#&7F:ADC#0:STAT:.PL43 5400JSRBLINE:CMPTGT:BEQP%+4:BCSPL40:LDACNT2:CLC:ADCSTP:AND#63:STACNT2:JMPPLL4:.PL40 RTS 5410JMPWPLS:.PLF3 TXA:EOR#FF:CLC:ADC#1:TAX:.PLF17 LDA#FF:JMPPLF5 5430.SUN LDA#1:STALSX:JSRCHKON:BCSPLF3-3:LDA#0:LDXK:CPX#&60:ROLA:CPX#&28:ROLA:CPX#&10:ROLA 5450.PLF18 STACNT:LDA#2*Y-1:LDXP+2:BNEPLF2:CMPP+1:BCCPLF2:LDAP+1:BNEPLF2:LDA#1:.PLF2 STATGT 5460LDA#2*Y-1:SEC:SBCK4:TAX:LDA#0:SBCK4+1:BMIPLF3:BNEPLF4:INX:DEX:BEQPLF17:CPXK:BCCPLF5:.PLF4 LDXK:LDA#0:.PLF5 STXV:STAV+1 5470LDAK:JSRSQUA2:STAK2+1:LDAP:STAK2:LDY#2*Y-1:LDASUNX:STAYY:LDASUNX+1:STAYY+1:.PLFL2 CPYTGT:BEQPLFL:LDALSO,Y:BEQPLF13:JSRHLOIN2:.PLF13 DEY:BNEPLFL2 5480.PLFL LDAV:JSRSQUA2:STAT:LDAK2:SEC:SBCP:STAQ:LDAK2+1:SBCT:STAR:STYY1:JSRLL5:LDYY1:JSRDORND:ANDCNT:CLC:ADCQ:BCCPLF44:LDA#FF:.PLF44 5490LDXLSO,Y:STALSO,Y:BEQPLF11:LDASUNX:STAYY:LDASUNX+1:STAYY+1:TXA:JSREDGES:LDAX1:STAXX:LDAX2:STAXX+1 5500LDAK3:STAYY:LDAK3+1:STAYY+1:LDALSO,Y:JSREDGES:BCSPLF23:LDAX2:LDXXX:STXX2:STAXX:JSRHLOIN:.PLF23 LDAXX:STAX1:LDAXX+1:STAX2:.PLF16 JSRHLOIN:.PLF6 5530DEY:BEQPLF8:LDAV+1:BNEPLF10:DECV:BNEPLFL:DECV+1:.PLFLS JMPPLFL 5535.PLF11 LDXK3:STXYY:LDXK3+1:STXYY+1:JSREDGES:BCCPLF16:LDA#0:STALSO,Y:BEQPLF6 5540.PLF10 LDXV:INX:STXV:CPXK:BCCPLFLS:BEQPLFLS:LDASUNX:STAYY:LDASUNX+1:STAYY+1:.PLFL3 LDALSO,Y:BEQPLF9:JSRHLOIN2 5550.PLF9 DEY:BNEPLFL3:.PLF8 CLC:LDAK3:STASUNX:LDAK3+1:STASUNX+1:.RTS2 RTS 5600.CIRCLE JSRCHKON:BCSRTS2 5610LDA#0:STALSX2 5700LDXK:LDA#8:CPX#8:BCCPL89:LSRA:CPX#60:BCCPL89:LSRA:.PL89 STASTP:.CIRCLE2 LDX#FF:STXFLAG:INX:STXCNT:.PLL3 5710LDACNT:JSRFMLTU2:LDX#0:STXT:LDXCNT:CPX#33:BCCPL37:EOR#FF:ADC#0:TAX:LDA#FF:ADC#0:STAT:TXA:CLC 5720.PL37 ADCK3:STAK6:LDAK3+1:ADCT:STAK6+1 5730LDACNT:CLC:ADC#16:JSRFMLTU2:TAX:LDA#0:STAT:LDACNT:ADC#15:AND#63:CMP#33:BCCPL38:TXA:EOR#FF:ADC#0:TAX:LDA#FF:ADC#0:STAT:CLC 5740.PL38 JSRBLINE:CMP#65:BCSP%+5:JMPPLL3:CLC:RTS 5750.WPLS2 LDYLSX2:BNEWP1:.WPL1 CPYLSP:BCSWP1:LDALSY2,Y:CMP#FF:BEQWP2:STAY2:LDALSX2,Y:STAX2:JSRLOIN:INY:LDASWAP:BNEWPL1 5760LDAX2:STAX1:LDAY2:STAY1:JMPWPL1:.WP2 INY:LDALSX2,Y:STAX1:LDALSY2,Y:STAY1:INY:JMPWPL1:.WP1 LDA#1:STALSP:LDA#FF:STALSX2:RTS 5790.WPLS LDALSX:BMIWPLS-1:LDASUNX:STAYY:LDASUNX+1:STAYY+1:LDY#2*Y-1:.WPL2 LDALSO,Y:BEQP%+5:JSRHLOIN2:DEY:BNEWPL2:DEY:STYLSX:RTS 5800.EDGES STAT:CLC:ADCYY:STAX2:LDAYY+1:ADC#0:BMIED1:BEQP%+6:LDA#254:STAX2 5810LDAYY:SEC:SBCT:STAX1:LDAYY+1:SBC#0:BNEED3:CLC:RTS 5820.ED3 BPLED1:LDA#2:STAX1:CLC:RTS:.ED1 LDA#0:STALSO,Y:SEC:RTS 5850.CHKON LDAK3:CLC:ADCK:LDAK3+1:ADC#0:BMIPL21:LDAK3:SEC:SBCK:LDAK3+1:SBC#0:BMIPL31:BNEPL21:.PL31 5860LDAK4:CLC:ADCK:STAP+1:LDAK4+1:ADC#0:BMIPL21:STAP+2:LDAK4:SEC:SBCK:TAX:LDAK4+1:SBC#0:BMIPL44:BNEPL21:CPX#2*Y-1:RTS:.PL21 SEC:RTS 5900.PLS3 JSRPLS1:STAP:LDA#222:STAQ:STXU:JSRMULTU:LDXU:LDYK+3:BPLPL12:EOR#FF:CLC:ADC#1:BEQPL12:LDY#FF:RTS:.PL12 LDY#0:RTS 5910.PLS4 STAQ:JSRARCTAN:LDXINWK+14:BMIP%+4:EOR#128:LSRA:LSRA:STACNT2:RTS 5920.PLS5 JSRPLS1:STAK2+2:STYXX16+2:JSRPLS1:STAK2+3:STYXX16+3:RTS 5930.PLS6 JSRDVID3B2:LDAK+3:AND#127:ORAK+2:BNEPL21:LDXK+1:CPX#4:BCSPL6:LDAK+3:\CLC:BPLPL6:LDAK:EOR#FF:ADC#1:STAK:TXA:EOR#FF:ADC#0:TAX:.PL44 CLC:.PL6 RTS 7200.TT17 JSRDOKEY:LDAJSTK:BEQTJ1:LDAJSTX:EOR#FF:JSRTJS1:TYA:TAX 7210LDAJSTY:.TJS1 TAY:LDA#0:CPY#&10:SBC#0:\CPY#&20SBC#0:CPY#&40:SBC#0:CPY#&C0:ADC#0:CPY#&E0:ADC#0:\CPY#&F0ADC#0 7220TAY:LDAKL:RTS 7250.TJ1 LDAKL:LDX#0:LDY#0:CMP#&19:BNEP%+3:DEX:CMP#&79:BNEP%+3:INX:CMP#&39:BNEP%+3:INY:CMP#&29:BNEP%+3:DEY:RTS 7550.ping LDX#1:.pl1 LDAQQ0,X:STAQQ9,X:DEX:BPLpl1:RTS 9500]PRINT"E d,"; 9710IFZ>4OSCLI("S.ELTE "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9720GOTO12 ================================================ FILE: 1-source-files/original-sources/$.ELITEF.inf ================================================ $.ELITEF 000000 000000 002ED2 ================================================ FILE: 1-source-files/original-sources/$.ELITEF.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 11GOTO20 12*L.ELITEF 13GOTO20 14*L.ELITEG 20REM ELITE 100 H%=L%+P%-C%:O%=W% 900[OPTZ 1000.KS3 LDAP:STASLSP:LDAP+1:STASLSP+1:RTS:.KS1 LDXXSAV:JSRKILLSHP:LDXXSAV:JMPMAL1 1010.KS4 JSRZINF:JSRFLFLLS:STAFRIN+1:STASSPR:JSRSPBLB:LDA#6:STAINWK+5:LDA#&81:JMPNWSHP 1020.KS2 LDX#FF:.KSL4 INX:LDAFRIN,X:BEQKS3:CMP#MSL:BNEKSL4:TXA:ASLA:TAY:LDAUNIV,Y:STASC:LDAUNIV+1,Y:STASC+1 1030LDY#32:LDA(SC),Y:BPLKSL4:AND#&7F:LSRA:CMPXX4:BCCKSL4:BEQKS6:SBC#1:ASLA:ORA#128:STA(SC),Y:BNEKSL4:.KS6 LDA#0:STA(SC),Y:BEQKSL4 1050.KILLSHP STXXX4:LDAMSTG:CMPXX4:BNEKS5:LDY#&EE:JSRABORT:LDA#200:JSRMESS:.KS5 LDYXX4:LDXFRIN,Y:CPX#SST:BEQKS4:DECMANY,X:LDXXX4 1060LDY#5:LDA(XX0),Y:LDY#33:CLC:ADC(INF),Y:STAP:INY:LDA(INF),Y:ADC#0:STAP+1 1070.KSL1 INX:LDAFRIN,X:STAFRIN-1,X:BEQKS2:ASLA:TAY:LDAXX21-2,Y:STASC:LDAXX21-1,Y:STASC+1:LDY#5:LDA(SC),Y:STAT:LDAP:SEC:SBCT:STAP:LDAP+1:SBC#0:STAP+1 1080TXA:ASLA:TAY:LDAUNIV,Y:STASC:LDAUNIV+1,Y:STASC+1:LDY#35:LDA(SC),Y:STA(INF),Y:DEY 1090LDA(SC),Y:STAK+1:LDAP+1:STA(INF),Y:DEY:LDA(SC),Y:STAK:LDAP:STA(INF),Y:DEY:.KSL2 LDA(SC),Y:STA(INF),Y:DEY:BPLKSL2:LDASC:STAINF:LDASC+1:STAINF+1 1100LDYT:.KSL3 DEY:LDA(K),Y:STA(P),Y:TYA:BNEKSL3:BEQKSL1 1500.SFX EQUS FNS("12010010"):EQUS FNS("12022C08"):EQUS FNS("1103F018"):EQUS FNS("10F1071A") 1510EQUS FNS("03F1BC01"):EQUS FNS("13F40C08"):EQUS FNS("10F1060C"):EQUS FNS("10026010") HYP:EQUS FNS("1304C2FF"):EQUS FNS("13000000") 3000.RESET \"<<<<":JSRZERO:LDX#6:.SAL3 STABETA,X:DEX:BPLSAL3:STXQQ12:.RES4 LDA#FF:LDX#2:.REL5 STAFSH,X:DEX:BPLREL5 3002.RES2 LDA#NOST:STANOSTM:LDX#FF:STXLSX2:STXLSY2:STXMSTG:LDA#128:STAJSTY:STAALP2:STABET2:ASLA:STAALP2+1:STABET2+1:STAMCNT:LDA#3:STADELTA:STAALPHA:STAALP1 3005LDASSPR:BEQP%+5:JSRSPBLB:LDAECMA:BEQyu:JSRECMOF:.yu JSRWPSHPS:JSRZERO:LDA#(LS%MOD256):STASLSP:LDA#(LS%DIV256):STASLSP+1:JSRDIALS 3006.ZINF LDY#NI%-1:LDA#0:.ZI1 STAINWK,Y:DEY:BPLZI1:LDA#96:STAINWK+18:STAINWK+22:ORA#128:STAINWK+14:RTS 3007.msblob LDX#4:.ss CPXNOMSL:BEQSAL8:LDY#0:JSRMSBAR:DEX:BNEss:RTS:.SAL8 LDY#&EE:JSRMSBAR:DEX:BNESAL8:RTS 3890.me2 LDAMCH:JSRMESS:LDA#0:STADLY:JMPme3 3900.Ze JSRZINF:JSRDORND:STAT1:AND#128:STAINWK+2:TXA:AND#128:STAINWK+5:LDA#32:STAINWK+1:STAINWK+4:STAINWK+7:TXA:CMP#245:ROLA:ORA#&C0:STAINWK+32 3904.DORND2 CLC:.DORND LDARAND:ROLA:TAX:ADCRAND+2:STARAND:STXRAND+2:LDARAND+1:TAX:ADCRAND+3:STARAND+1:STXRAND+3:RTS 3910.MTT4 LSRA:STAINWK+32:STAINWK+29:ROLINWK+31:AND#31:ORA#16:STAINWK+27:LDA#CYL:JSRNWSHP 4000.TT100 JSRM%:DECDLY:BEQme2:BPLme3:INCDLY:.me3 DECMCNT:BEQP%+5:.ytq JMPMLOOP:LDAMJ:BNEytq 4020JSRDORND:CMP#35:BCSMTT1:LDAMANY+AST:CMP#3:BCSMTT1:JSRZINF:LDA#38:STAINWK+7:JSRDORND:STAINWK:STXINWK+3:AND#128:STAINWK+2:TXA:AND#128:STAINWK+5:ROLINWK+1:ROLINWK+1 4022JSRDORND:BVSMTT4:ORA#&6F:STAINWK+29:LDASSPR:BNEMTT1:TXA:BCSMTT2:AND#31:ORA#16:STAINWK+27:BCCMTT3 4025.MTT2 ORA#127:STAINWK+30:.MTT3 JSRDORND:CMP#5:LDA#AST:BCSP%+4:LDA#OIL:JSRNWSHP 4030.MTT1 4040LDASSPR:BNEMLOOP:JSRBAD:ASLA:LDXMANY+COPS:BEQP%+5:ORAFIST:STAT:JSRZe:CMPT:BCSP%+7:LDA#COPS:JSRNWSHP:LDAMANY+COPS:BNEMLOOP:DECEV:BPLMLOOP:INCEV:JSRDORND:LDYgov:BEQ`:CMP#90:BCSMLOOP:AND#7:CMPgov:BCCMLOOP:.` 4050JSRZe:CMP#200:BCSmt1:INCEV:AND#3:ADC#3:TAY:TXA:CMP#200:ROLA:ORA#&C0:CPY#6:BEQtha:STAINWK+32:TYA:JSRNWSHP:.mj1 JMPMLOOP:.mt1 AND#3:STAEV:STAXX13:.mt3 JSRDORND:AND#3:ORA#1:JSRNWSHP 4100DECXX13:BPLmt3:.MLOOP LDA#1:STAVIA+&E:LDX#FF:TXS:LDXGNTMP:BEQEE20:DECGNTMP:.EE20 JSRDIALS:LDAQQ11:BEQP%+11:ANDPATG:LSRA:BCSP%+5:JSRDELAY-5 4200JSRTT17:.FRCE JSRTT102:LDAQQ12:BNEMLOOP:JMPTT100 4250.tha JSRDORND:CMP#200:BCCP%+5:JSRGTHG:JMPMLOOP 4500.TT102 CMP#f8:BNEP%+5:JMPSTATUS:CMP#f4:BNEP%+5:JMPTT22:CMP#f5:BNEP%+5:JMPTT23:CMP#f6:BNETT92:JSRTT111:JMPTT25:.TT92 CMP#f9:BNEP%+5:JMPTT213:CMP#f7:BNEP%+5:JMPTT167:CMP#f0:BNEfvw:JMPTT110:.fvw BITQQ12 4505BPLINSP:CMP#f3:BNEP%+5:JMPEQSHP:CMP#f1:BNEP%+5:JMPTT219:CMP#&47:BNEP%+5:JMPSVE 4510CMP#f2:BNE``:JMPTT208:.INSP CMP#&71:BCC``:CMP#&74:BCS``:AND#3:TAX:JMPLOOK1:.`` CMP#&54:BNEP%+5:JMPhyp:CMP#&32:BEQT95:STAT1:LDAQQ11:AND#192:BEQTT107:LDAQQ22+1:BNETT107:LDAT1:CMP#&36:BNEee2:JSRTT103:JSRping 4520JSRTT103:.ee2 JSRTT16:.TT107:LDAQQ22+1:BEQt95:DECQQ22:BNEt95:LDXQQ22+1:DEX:JSRee3:LDA#5:STAQQ22:LDXQQ22+1:JSRee3:DECQQ22+1:BNEt95:JMPTT18:.t95 RTS 4550.T95 LDAQQ11:AND#192:BEQt95:JSRhm:STAQQ17:JSRcpl:LDA#128:STAQQ17:LDA#1:STAXC:INCYC:JMPTT146 4800.BAD LDAQQ20+3:CLC:ADCQQ20+6:ASLA:ADCQQ20+10:RTS 4850.FAROF LDA#&E0:.FAROF2 CMPINWK+1:BCCMA34:CMPINWK+4:BCCMA34:CMPINWK+7:.MA34 RTS:.MAS4 ORAINWK+1:ORAINWK+4:ORAINWK+7:RTS 4900.DEATH JSREXNO3:JSRRES2:ASLDELTA:ASLDELTA:LDX#24:JSRDET1:JSRTT66:JSRBOX:JSRnWq:LDA#12:STAYC:STAXC:LDA#146:JSRex:.D1 JSRZe:LSRA:LSRA:STAINWK:LDY#0:STYQQ11:STYINWK+1:STYINWK+4:STYINWK+7:STYINWK+32:DEY:STYMCNT:STYLASCT:EOR#42 4905STAINWK+3:ORA#80:STAINWK+6:TXA:AND#&8F:STAINWK+29 4910RORA:AND#&87:STAINWK+30:PHP:LDX#OIL:JSRfq1:PLP:LDA#0:RORA:LDY#31:STA(INF),Y:LDAFRIN+3:BEQD1:JSRU%:STADELTA:.D2 JSRM%:LDALASCT:BNED2:LDX#31:JSRDET1:.DEATH2 JSRRES2 5000.TT170 LDX#FF:TXS 5010.BR1 LDX#3:STXXC:JSRFX200:LDX#CYL:LDA#128:JSRTITLE:CMP#&44:BNEQU5:\BR1 LDX#3STXXCJSRFX200LDA#1JSRTT66JSRFLKB 5015\LDA#14JSRTT214BCCQU5:JSRGTNME:JSRLOD:JSRTRNME:JSRTTX66 5020.QU5 \JSRTTX66:LDX#NT%:.QUL1 LDANA%+7,X:STATP-1,X:DEX:BNEQUL1:STXQQ11:JSRCHECK:CMPCHK:BNEP%-6:EOR#&A9:TAX:LDACOK:CPXCHK2:BEQtZ:ORA#128:.tZ ORA#2:STACOK:JSRmsblob:LDA#147:LDX#3:JSRTITLE:JSRping:JSRhyp1 5021.BAY LDA#FF:STAQQ12:LDA#f8:JMPFRCE 5110.TITLE PHA:STXTYPE:JSRRESET:LDA#1:JSRTT66:DECQQ11:LDA#96:STAINWK+14 5120\LSRA:STAINWK+7:LDX#127:STXINWK+29:STXINWK+30:INX:STXQQ17 5130LDATYPE:JSRNWSHP 5140LDY#6:STYXC:JSRDELAY:LDA#30:JSRplf:LDY#6:STYXC:INCYC:LDAPATG:BEQawe:LDA#254:JSRTT27:.awe JSRCLYNS:STYDELTA:STYJSTK:PLA:JSRex:LDA#148:LDX#7:STXXC:JSRex 5150.TLL2 LDAINWK+7:CMP#1:BEQTL1:DECINWK+7:.TL1 JSRMVEIT:LDA#128:STAINWK+6:ASLA:STAINWK:STAINWK+3:JSRLL9:DECMCNT:LDA&FE40:AND#16:\TAX:BEQTL2:JSRRDKEY:BEQTLL2:RTS:.TL2 DECJSTK:RTS 5200.CHECK LDX#NT%-2:CLC:TXA:.QUL2 ADCNA%+7,X:EORNA%+8,X:DEX:BNEQUL2:RTS 5250.TRNME LDX#7:.GTL1 LDAINWK,X:STANA%,X:DEX:BPLGTL1:.TR1 LDX#7:.GTL2 LDANA%,X:STAINWK,X:DEX:BPLGTL2:RTS 5300.GTNME LDA#1:JSRTT66:LDA#123:JSRTT27:JSRDEL8:LDA#&81:STAVIA+&E:LDA#15:TAX:JSROSBYTE:LDX#(RLINE MOD256):LDY#(RLINE DIV256):LDA#0:JSROSWORD\LDA#1STAVIA+&E:BCSTR1:TYA:BEQTR1:JMPTT67 5350.RLINE EQUWINWK:EQUB7:EQUB33:EQUB&7A 5400.ZERO LDX#&D:.ZEL JSRZES1:DEX:CPX#9:BNEZEL 5410.ZES1 LDY#0:STYSC:.ZES2 LDA#0:STXSC+1:.ZEL1 STA(SC),Y:INY:BNEZEL1:RTS 5500.SVE JSRGTNME:JSRTRNME:JSRZERO:LSRSVC:LDX#NT%:.SVL1 LDATP,X:STA&B00,X:STANA%+8,X:DEX:BPLSVL1:JSRCHECK:STACHK:PHA:ORA#128:STAK:EORCOK:STAK+2:EORCASH+2:STAK+1:EOR#&5A:EORTALLY+1:STAK+3:JSRBPRNT:JSRTT67:JSRTT67:PLA:STA&B00+NT%:EOR#&A9 5501STACHK2:STA&AFF+NT%:LDY#&B:STY&C0B:INY:STY&C0F 5510LDA#&81:STAVIA+&E:INCsvn:LDA#0:JSRQUS1:LDX#0\STXVIA+&EDEX:STXsvn:JMPBAY 5520.QUS1 LDX#INWK:STX&C00:LDX#0:JMPOSFILE 5600.LOD LDX#2:JSRFX200:JSRZERO:LDY#&B:STY&C03:INC&C0B:INY:LDA#FF:JSRQUS1:LDA&B00:BMISPS1+1:LDX#NT%:.LOL1 LDA&B00,X:STANA%+8,X:DEX:BPLLOL1:LDX#3 5620.FX200\MOS:LDY#0:LDA#200:JMPOSBYTE 6500RTS:.SPS1 LDX#0:JSRSPS3:LDX#3:JSRSPS3:LDX#6:JSRSPS3 6600.TAS2 LDAK3:ORAK3+3:ORAK3+6:ORA#1:STAK3+9:LDAK3+1:ORAK3+4:ORAK3+7 6610.TAL2 ASLK3+9:ROLA:BCSTA2:ASLK3:ROLK3+1:ASLK3+3:ROLK3+4:ASLK3+6:ROLK3+7:BCCTAL2 6620.TA2 LDAK3+1:LSRA:ORAK3+2:STAXX15:LDAK3+4:LSRA:ORAK3+5:STAXX15+1:LDAK3+7:LSRA:ORAK3+8:STAXX15+2 6700.NORM 6705LDAXX15:JSRSQUA:STAR:LDAP:STAQ:LDAXX15+1:JSRSQUA:STAT:LDAP:ADCQ:STAQ:LDAT:ADCR:STAR:LDAXX15+2:JSRSQUA:STAT:LDAP:ADCQ:STAQ:LDAT:ADCR:STAR 6710JSRLL5 6720LDAXX15:JSRTIS2:STAXX15 \*96/Q 6730LDAXX15+1:JSRTIS2:STAXX15+1 6740LDAXX15+2:JSRTIS2:STAXX15+2:.NO1 RTS 6800.RDKEY \OSBYTE7A:LDX#16:.Rd1 JSRDKS4:BMIRd2:INX:BPLRd1:TXA:.Rd2 EOR#128:TAX:RTS 7000.ECMOF LDA#0:STAECMA:STAECMP:JSRECBLB:LDA#72:BNENOISE 7001.EXNO3 LDA#16:JSRNOISE:LDA#24:BNENOISE 7003.SFRMIS LDX#MSL:JSRSFS1-2:BCCNO1:LDA#&78:JSRMESS:LDA#48:BNENOISE 7004.EXNO2 INCTALLY:BNEEXNO-2:INCTALLY+1:LDA#101:JSRMESS:LDX#7 \15:.EXNO STXT:LDA#24:JSRNOS1:LDAINWK+7:LSRA:LSRA:ANDT:ORA#&F1:STAXX16+2:JSRNO3:LDA#16 7006EQUB&2C:.BEEP LDA#32 7010.NOISE JSRNOS1:.NO3 LDXDNOIZ:BNENO1:LDX#(XX16 MOD256):LDY#(XX16 DIV256):LDA#7:JMPOSWORD 7015.NOS1 LSRA:ADC#3:TAY:LDX#7:.NOL1 LDA#0:STAXX16,X:DEX:LDASFX,Y:STAXX16,X:DEY:DEX:BPLNOL1 7020.KYTB RTS:EQUB&E8:EQUB&E2:EQUB&E6:EQUB&E7:EQUB&C2:EQUB&D1:EQUB&C1:EQUD&35237060:EQUW&2265:EQUB&45:EQUB&52 \? <>XSA.FBRLtabescTUMEJC 7030.DKS1 LDXKYTB,Y:JSRDKS4:BPLDKS2-1:LDX#FF:STXKL,Y:RTS 7032.CTRL LDX#1:.DKS4 LDA#3:SEI:STA&FE40:LDA#&7F:STA&FE43:STX&FE4F:LDX&FE4F:LDA#&B:STA&FE40:CLI:TXA 7035RTS:.DKS2 LDA#&80:JSROSBYTE:TYA:EORJSTE 7037RTS:.DKS3 STYT:CPXT:BNEDk3:LDADAMP-&40,X:EOR#FF:STADAMP-&40,X:JSRBELL:JSRDELAY:LDYT:.Dk3 RTS 7040.DKJ1 LDY#1:JSRDKS1:INY:JSRDKS1 7050LDA&FE40:TAX:AND#16:EOR#16:STAKL+7:LDX#1:JSRDKS2:ORA#1:STAJSTX:LDX#2:JSRDKS2:EORJSTGY:STAJSTY:JMPDK4 7065.U% LDA#0:LDY#15:.DKL3 STAKL,Y:DEY:BNEDKL3:RTS 7070.DOKEY JSRU%:LDAJSTK:BNEDKJ1 7080LDY#7:.DKL2 JSRDKS1:DEY:BNEDKL2 7090LDXJSTX:LDA#7:LDYKL+3:BEQP%+5:JSRBUMP2:LDYKL+4:BEQP%+5:JSRREDU2:STXJSTX 7100ASLA:LDXJSTY:LDYKL+5:BEQP%+5:JSRREDU2:LDYKL+6:BEQP%+5:JSRBUMP2:STXJSTY 7110.DK4 JSRRDKEY:STXKL:CPX#&69:BNEDK2:.FREEZE JSRWSCAN:JSRRDKEY:CPX#&51:BNEDK6:LDA#0:STADNOIZ 7114.DK6 LDY#&40:.DKL4 JSRDKS3:INY:CPY#&47:BNEDKL4:.DK55 CPX#&10:BNEDK7:STXDNOIZ:.DK7 CPX#&70:BNEP%+5:JMPDEATH2:CPX#&59:BNEFREEZE:.DK2 LDAQQ11:BNEDK5:LDY#15:LDA#FF 7120.DKL1 LDXKYTB,Y:CPXKL:BNEDK1:STAKL,Y:.DK1 DEY:CPY#7:BNEDKL1 7130.DK5 RTS 7140.TT217 STYYSAV:.t JSRDELAY-5:JSRRDKEY:BNEt:.t2 JSRRDKEY:BEQt2:TAY:LDA(TRTB%),Y:LDYYSAV:TAX:.out RTS 7190.me1 STXDLY:PHA:LDAMCH:JSRmes9:PLA:EQUB&2C:.ou2 lda#108:EQUB&2C:.ou3 lda#111 7200.MESS LDX#0:STXQQ17:LDY#9:STYXC:LDY#22:STYYC:CPXDLY:BNEme1:STYDLY:STAMCH:.mes9 JSRTT27:LSRde:BCCout:LDA#253:JMPTT27 7300.OUCH JSRDORND:BMIout:CPX#22:BCSout:LDAQQ20,X:BEQout:LDADLY:BNEout:LDY#3:STYde:STAQQ20,X:CPX#17:BCSou1:TXA:ADC#208:BNEMESS:.ou1 7310BEQou2:CPX#18:BEQou3:TXA:ADC#113-20:BNEMESS 7410.QQ16 EQUS"ALLEXEGEZACEBISOUSESARMAINDIREA?ERATENBERALAVETIEDORQUANTEISRION" 7420.QQ23\Prxs:EQUD&1068213:EQUD&30A8114:EQUD&7028341\Food 7430EQUD&1FE28528:EQUD&FFB8553:EQUD&33608C4:EQUD &78081DEB \slvs.. 7440EQUD&3380E9A:EQUD&7280675:EQUD&1F11014E:EQUD&71D0D7C \comps 7450EQUD&3FDC89B0:EQUD&03358120:EQUD&742A161:EQUD&1F37A2AB \pltnm 7460EQUD&FFAC12D:EQUD&7C00F35 \Gms. 8000.TI2 TYA:LDY#2:JSRTIS3:STAINWK+20\Uz=-(FxUx+FyUy)/Fz:JMPTI3 8010.TI1 TAX:LDAXX15+1:AND#&60:BEQTI2:LDA#2:JSRTIS3:STAINWK+18:JMPTI3 8020.TIDY LDAINWK+10:STAXX15:LDAINWK+12:STAXX15+1:LDAINWK+14:STAXX15+2:JSRNORM:LDAXX15:STAINWK+10:LDAXX15+1:STAINWK+12:LDAXX15+2:STAINWK+14 8030LDY#4:LDAXX15:AND#&60:BEQTI1:LDX#2:LDA#0:JSRTIS3:STAINWK+16 8040.TI3 LDAINWK+16:STAXX15:LDAINWK+18:STAXX15+1:LDAINWK+20:STAXX15+2:JSRNORM:LDAXX15:STAINWK+16:LDAXX15+1:STAINWK+18:LDAXX15+2:STAINWK+20 8050LDAINWK+12:STAQ:LDAINWK+20:JSRMULT12:LDXINWK+14:LDAINWK+18:JSRTIS1:EOR#128:STAINWK+22 8060LDAINWK+16:JSRMULT12:LDXINWK+10:LDAINWK+20:JSRTIS1:EOR#128:STAINWK+24 8070LDAINWK+18:JSRMULT12:LDXINWK+12:LDAINWK+16:JSRTIS1:EOR#128:STAINWK+26 \FxU/96(LHS) 8080LDA#0:LDX#14:.TIL1 STAINWK+9,X:DEX:DEX:BPLTIL1:RTS 8100.TIS2 TAY:AND#127:CMPQ:BCSTI4:LDX#254:STXT:.TIL2 ASLA:CMPQ:BCCP%+4:SBCQ:ROLT:BCSTIL2:LDAT 8110LSRA:LSRA:STAT:LSRA:ADCT:STAT:TYA:AND#128:ORAT:RTS:.TI4 TYA:AND#128:ORA#96:RTS 8130.TIS3 STAP+2:LDAINWK+10,X:STAQ:LDAINWK+16,X:JSRMULT12:LDXINWK+10,Y:STXQ:LDAINWK+16,Y:JSRMAD 8140STXP:LDYP+2:LDXINWK+10,Y:STXQ:EOR#128 8150.DVIDT\A=AP/Q:STAP+1:EORQ:AND#128:STAT:LDA#0:LDX#16:ASLP:ROLP+1:ASLQ:LSRQ:.DVL2 ROLA:CMPQ:BCCP%+4:SBCQ:ROLP:ROLP+1:DEX:BNEDVL2:LDAP:ORAT:RTS 9000]:PRINT"F d,"; 9710IFZ>4OSCLI("S.ELTF "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9720GOTO14 10200DEFFNS(A$):N%=LEN(A$)DIV2:FORI%=0TON%-1:I%?O%=EVAL("&"+MID$(A$,2*I%+1,2)):NEXT:P%=P%+N%:O%=O%+N%:="" ================================================ FILE: 1-source-files/original-sources/$.ELITEG.inf ================================================ $.ELITEG 000000 000000 002EDB ================================================ FILE: 1-source-files/original-sources/$.ELITEG.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 11GOTO20 12*L.ELITEF 13GOTO20 14*L.ELITEG 20REM ELITE 100H%=L%+P%-C%:O%=W% 1000[OPTZ 7000.SHPPT JSREE51:JSRPROJ:ORAK3+1:BNEnono:LDAK4:CMP#Y*2-2:BCSnono:LDY#2:jsrShpt:ldy#6:ldaK4:ADC#1:jsrShpt:LDA#8:ORAXX1+31:STAXX1+31:LDA#8:JMPLL81+2:PLA:PLA:.nono lda#&F7:andXX1+31:staXX1+31:RTS 7010.Shpt STA(XX19),Y:iny:iny:STA(XX19),Y:LDAK3:DEY:STA(XX19),Y:ADC#3:BCSnono-2:dey:dey:STA(XX19),Y:rts 8040.LL5 \2BSQRT Q=SQR(RQ) 8045LDYR:LDAQ:STAS:LDX#0:STXQ:LDA#8:STAT:.LL6 CPXQ:BCCLL7:BNELL8:CPY#&40:BCCLL7:.LL8 TYA:SBC#&40:TAY:TXA:SBCQ:TAX:.LL7 ROLQ:ASLS:TYA:ROLA:TAY:TXA:ROLA:TAX:ASLS:TYA:ROLA:TAY:TXA:ROLA:TAX:DECT:BNELL6:RTS 8065.LL28 \BFRDIV R=A*256/Q 8070CMPQ:BCSLL2:LDX#254:STXR:.LL31 ASLA:BCSLL29:CMPQ:BCCP%+4:SBCQ:ROLR:BCSLL31:RTS:.LL29 SBCQ:SEC:ROLR:BCSLL31:RTS:.LL2 LDA#FF:STAR:RTS 8085.LL38 \BADD(S)A=R+Q(SA) 8090EORS:BMILL39:LDAQ:CLC:ADCR:RTS:.LL39 LDAR:SEC:SBCQ 8095BCCP%+4:CLC:RTS:PHA:LDAS:EOR#128:STAS:PLA:EOR#255:ADC#1:RTS 8100.LL51 \XX12=XX15.XX16 8105LDX#0:LDY#0:.ll51 LDAXX15:STAQ:LDAXX16,X:JSRFMLTU:STAT:LDAXX15+1:EORXX16+1,X:STAS:LDAXX15+2 8115STAQ:LDAXX16+2,X:JSRFMLTU:STAQ:LDAT:STAR:LDAXX15+3 8120EORXX16+3,X:JSRLL38:STAT:LDAXX15+4:STAQ:LDAXX16+4,X:JSRFMLTU:STAQ:LDAT:STAR:LDAXX15+5:EORXX16+5,X 8130JSRLL38:STAXX12,Y:LDAS:STAXX12+1,Y:INY:INY:TXA:CLC:ADC#6:TAX:CMP#17:BCCll51:RTS 8132.LL25 JMPPLANET 8135.LL9 \ ENTRY 8137LDATYPE:BMILL25 8140LDA#31:STAXX4:LDA#32:BITXX1+31:BNEEE28 8144BPLEE28:ORAXX1+31:AND#&3F:STAXX1+31:LDA#0:LDY#28:STA(INF),Y:LDY#30:STA(INF),Y:JSREE51:LDY#1:LDA#18:STA(XX19),Y:LDY#7:LDA(XX0),Y:LDY#2:STA(XX19),Y 8146\LDAXX1+32\AND#&7F\STAXX1+32:.EE55 INY:JSRDORND:STA(XX19),Y:CPY#6:BNEEE55:.EE28 8150LDAXX1+8:.EE49 BPLLL10:.LL14 LDAXX1+31:AND#32:BEQEE51:LDAXX1+31:AND#&F7:STAXX1+31:JMPDOEXP:.EE51 8155LDA#8:BITXX1+31:BEQLL10-1:EORXX1+31:STAXX1+31:JMPLL155:\LL24 8165RTS:.LL10 8175LDAXX1+7:CMP#&C0:BCSLL14:LDAXX1:CMPXX1+6:LDAXX1+1:SBCXX1+7:BCSLL14:LDAXX1+3:CMPXX1+6:LDAXX1+4:SBCXX1+7:BCSLL14 8205LDY#6:LDA(XX0),Y:TAX:LDA#255:STAXX3,X:STAXX3+1,X 8215LDAXX1+6:STAT:LDAXX1+7:LSRA:RORT:LSRA:RORT:LSRA:RORT:LSRA:BNELL13:LDAT:RORA:LSRA:LSRA:LSRA:STAXX4 8225BPLLL17:.LL13 LDY#13:LDA(XX0),Y:CMPXX1+7:BCSLL17:LDA#32:ANDXX1+31:BNELL17:JMPSHPPT:.LL17 8275LDX#5:.LL15 LDAXX1+21,X:STAXX16,X:LDAXX1+15,X:STAXX16+6,X:LDAXX1+9,X:STAXX16+12,X:DEX:BPLLL15 8290LDA#197 \NORM:STAQ:LDY#16:.LL21 LDAXX16,Y:ASLA:LDAXX16+1,Y 8295ROLA:JSRLL28:LDXR:STXXX16,Y:DEY:DEY:BPLLL21 8300LDX#8:.ll91 LDAXX1,X:STAXX18,X:DEX:BPLll91 8315LDA#255:STAXX2+15 8320LDY#12:LDAXX1+31:AND#32:BEQEE29:LDA(XX0),Y:LSRA:LSRA:TAX:LDA#FF:.EE30 STAXX2,X:DEX:BPLEE30:INX:STXXX4:.LL41 JMPLL42:.EE29 LDA(XX0),Y:BEQLL41:STAXX20 8330\DtProd^XX2 8335LDY#18:LDA(XX0),Y:TAX:LDAXX18+7:.LL90 TAY:BEQLL91:INX:LSRXX18+4:RORXX18+3:LSRXX18+1:RORXX18:LSRA:RORXX18+6:TAY:BNELL90+3:.LL91 STXXX17:LDAXX18+8 8350STAXX15+5:LDAXX18:STAXX15:LDAXX18+2:STAXX15+1:LDAXX18+3:STAXX15+2:LDAXX18+5:STAXX15+3:LDAXX18+6:STAXX15+4:JSRLL51:LDAXX12:STAXX18:LDAXX12+1:STAXX18+2:LDAXX12+2 8365STAXX18+3:LDAXX12+3:STAXX18+5:LDAXX12+4:STAXX18+6:LDAXX12+5:STAXX18+8 8375LDY#4:LDA(XX0),Y:CLC:ADCXX0:STAV:LDY#17:LDA(XX0),Y:ADCXX0+1:STAV+1:LDY#0 8385.LL86 LDA(V),Y:STAXX12+1:AND#31:CMPXX4:BCSLL87 8390TYA:LSRA:LSRA:TAX:LDA#255:STAXX2,X:TYA:ADC#4 8395TAY:JMPLL88:.LL87 LDAXX12+1:ASLA:STAXX12+3:ASLA:STAXX12+5 8400INY:LDA(V),Y:STAXX12:INY:LDA(V),Y:STAXX12+2:INY:LDA(V),Y 8405STAXX12+4:LDXXX17:CPX#4:BCCLL92:.LL143 8410\Face offset<255 9090TXA:CLC:ADCXX15+2:STAXX15+2:TYA:ADCXX15+3:STAXX15+3 9095LDX#FF:STXXX15:INX:STXXX15+1 9100.LL134 LDAXX15+3:BPLLL135:STAS:LDAXX15+2:STAR \ Y1<0 9105JSRLL123:TXA:CLC:ADCXX15:STAXX15:TYA:ADCXX15+1:STAXX15+1 9110LDA#0:STAXX15+2:STAXX15+3 9115.LL135 \BNELL139:LDAXX15+2:SEC:SBC#Y*2:STAR \ Y1>191 9120LDAXX15+3:SBC#0:STAS:BCCLL136:.LL139 JSRLL123:TXA:CLC:ADCXX15 9130STAXX15:TYA:ADCXX15+1:STAXX15+1:LDA#Y*2-1:STAXX15+2:LDA#0:STAXX15+3:.LL136 RTS 9140\ YX=SR*M/256 9142.LL120 LDAXX15:STAR 9145\.LL120:JSRLL129:PHA:LDXT:BNELL121:.LL122 9160LDA#0:TAX:TAY:LSRS:RORR:ASLQ:BCCLL126:.LL125 TXA:CLC 9165ADCR:TAX:TYA:ADCS:TAY:.LL126 LSRS:RORR:ASLQ:BCSLL125 9170BNELL126:PLA:BPLLL133:RTS 9180\ YX=SR*256/M (M=grad.) 9185.LL123 JSRLL129:PHA:LDXT:BNELL122:.LL121 9200LDA#255:TAY:ASLA:TAX:.LL130 ASLR:ROLS:LDAS:BCSLL131 9205CMPQ:BCCLL132:.LL131 SBCQ:STAS:LDAR:SBC#0:STAR:SEC 9210.LL132 TXA:ROLA:TAX:TYA:ROLA:TAY:BCSLL130:PLA:BMILL128 9215.LL133 TXA:EOR#FF:\CLC:ADC#1:TAX:TYA:EOR#FF:ADC#0:TAY:.LL128 RTS 9216.LL129 LDXXX12+2:STXQ:LDAS:BPLLL127:LDA#0:SEC:SBCR:STAR:LDAS:PHA:EOR#255:ADC#0:STAS:PLA:.LL127 EORXX12+3:RTS 9300.LL145 \CLIP 9305LDA#0:STASWAP 9310LDAXX15+5:.LL147 LDX#Y*2-1:ORAXX12+1:BNELL107:CPXXX12 9315BCCLL107:LDX#0:.LL107 STXXX13:LDAXX15+1:ORAXX15+3:BNELL83 9320LDA#Y*2-1:CMPXX15+2:BCCLL83 9325LDAXX13:BNELL108:.LL146 LDAXX15+2 9330STAXX15+1:LDAXX15+4:STAXX15+2:LDAXX12:STAXX15+3:CLC:RTS 9335.LL109 SEC:RTS:.LL108 LSRXX13:.LL83 9340LDAXX13:BPLLL115 9345LDAXX15+1:ANDXX15+5:BMILL109:LDAXX15+3:ANDXX12+1:BMILL109 9350LDXXX15+1:DEX:TXA:LDXXX15+5:DEX:STXXX12+2:ORAXX12+2 9355BPLLL109:LDAXX15+2:CMP#Y*2:LDAXX15+3:SBC#0:STAXX12+2 9360LDAXX12:CMP#Y*2:LDAXX12+1:SBC#0:ORAXX12+2:BPLLL109 9365.LL115 TYA:PHA:LDAXX15+4:SEC:SBCXX15:STAXX12+2:LDAXX15+5 9370SBCXX15+1:STAXX12+3:LDAXX12:SEC:SBCXX15+2:STAXX12+4 9375LDAXX12+1:SBCXX15+3:STAXX12+5:EORXX12+3:STAS 9380LDAXX12+5:BPLLL110:LDA#0:SEC:SBCXX12+4:STAXX12+4:LDA#0:SBCXX12+5:STAXX12+5 9385.LL110 LDAXX12+3:BPLLL111:SEC:LDA#0:SBCXX12+2:STAXX12+2:LDA#0:SBCXX12+3 9390\GETgrad 9395.LL111 TAX:BNELL112:LDXXX12+5:BEQLL113:.LL112 LSRA:RORXX12+2 9400LSRXX12+5:RORXX12+4:JMPLL111:.LL113 STXT:LDAXX12+2 9405CMPXX12+4:BCCLL114:STAQ:LDAXX12+4:JSRLL28 9410 \ Use Y/X grad. 9415JMPLL116:.LL114 LDAXX12+4:STAQ:LDAXX12+2:JSRLL28 9420 \ Use X/Y grad. 9425DECT:.LL116 LDAR:STAXX12+2:LDAS:STAXX12+3 9430LDAXX13:BEQLL138:BPLLLX117:.LL138 JSRLL118 9435LDAXX13:BPLLL124 9440.LL117 LDAXX15+1:ORAXX15+3:BNELL137:LDAXX15+2:CMP#Y*2 9445BCSLL137:.LLX117 LDXXX15:LDAXX15+4:STAXX15:STXXX15+4:LDAXX15+5 9450LDXXX15+1:STXXX15+5:STAXX15+1:LDXXX15+2:LDAXX12:STAXX15+2 9455STXXX12:LDAXX12+1:LDXXX15+3:STXXX12+1:STAXX15+3:JSRLL118 9460DECSWAP 9465.LL124 PLA:TAY:JMPLL146:.LL137 PLA:TAY:SEC:RTS 9520] 9530F%=P%:PRINT"G d." 9710IFZ>4OSCLI("SAVE ELTG "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9720IFZ=4GOTO4 9730 PRINT~C% F% S%,D%-F% ================================================ FILE: 1-source-files/original-sources/$.ELITES.inf ================================================ $.ELITES 000000 000000 002B49 ================================================ FILE: 1-source-files/original-sources/$.ELITES.txt ================================================ 1 DISC=TRUE:PROT=(NOT DISC) 5REM Source Code for ELITE (the loader) 7MODE7 8HIMEM=&4000:CODE=&4000:DIMTEMP%256 10 IF NOT DISC THEN LOD%=&F1F ELSE LOD%=&1100 14C%=&F40:S%=C%:L%=LOD%+&28:D%=&563A:LC%=&6000-C%:svn=&7FFD:len1=15:len2=18:len=len1+len2 15LE%=&B00: REM Move Mover to here while CODE loading 16LL%=&E00+(DISC AND&300): REM Where this loader loads 20MOS=S%+8:TRTB%=4:NETV=&224 1000OSWRCH=&FFEE:OSBYTE=&FFF4:OSWORD=&FFF1:SCLI=&FFF7:IRQ1V=&204:osprnt=&234 1010ZP=&70:P=&72:Q=&73:YY=&74:T=&75:sc=&76:BLPTR=&78:V219=&7A:K3=&80:BLCNT=&81:BLN=&83:EXCN=&85 1020FF=&FF 1030VIA=&FE40:USVIA=VIA:VSCAN=57-1:VEC=&7FFE 2000OSCLI("L.:0.WORDS9 "+STR$~CODE) 2010OSCLI("L.:0.DIALSHP "+STR$~(CODE+&400)) 2020OSCLI("L.:2.P.ELITE "+STR$~(CODE+&C00)) 2030OSCLI("L.:2.P.A-SOFT "+STR$~(CODE+&D00)) 2040OSCLI("L.:2.P.(C)ASFT "+STR$~(CODE+&E00)) 2050REMOSCLI("L.:2.P.NAME$ "+STR$~(CODE+&E00)) 3000FORZ=4TO6STEP2 3010P%=LL%+&400+&800+&300:O%=CODE+&400+&800+&300 3012[OPTZ:.run JMPENTRY:] 3015RESTORE:READN% 3020B%=P%:FORI%=0TON%-1:READA:PROCP(A):NEXT 3100E%=P%:FORI%=1TO4:FORJ%=1TO14:READA:PROCP(A):NEXT, 4000[OPTZ:.swine LDA#&7F:STA&FE4E:JMP(&FFFC) 4010\ This bit runs where it loads 4900.OSB LDY#0:JMPOSBYTE:EQUS"R.ELITEcode":EQUB13:EQUS"By D.Braben/I.Bell":EQUB13:EQUB&B0:.oscliv EQUW&FFF7:.David9 EQUW David5:CLD:.David23 EQUW (512-len) 4910.doPROT1 LDY#&DB:STYTRTB%:LDY#&EF \0.1 look-up keys:STYTRTB%+1:LDY#2:STYV219+1:STAPROT1-255,X:LDY#&18:STYV219+1,X:RTS:.MHCA EQUB&CA:.David7 BCCIan1 5000.ENTRY SEI:CLD:]IF NOT DISC THEN[OPTZ:LDA#0:LDX#FF:JSROSBYTE:TXA:BEQOS100:LDY&FFB6:LDA&FFB7:STAZP:LDA&FFB8:STAZP+1:DEY:.ABCDEFG LDA(ZP),Y:STA&200,Y:DEY:BPLABCDEFG:.OS100:]IF0ELSE:[OPTZ 5002LDA#&7F:STA&FE4E:STA&FE6E:LDA&FFFC:STA&200:STA&202:STA&206:STA&220:LDA&FFFD:STA&201:STA&203:STA&207:STA&221 \ Cold reset (Power on) on BRK,USER,& unrecog IRQ 5003LDX#&2F-2:.purge LDA&202,X:ORA#&C0:STA&202,X:DEX:DEX:BPLpurge 5004LDA#&60:STA&232:LDA#2:STANETV+1:LDA#&32:STANETV \Knock out NETVEC 5005LDA#32:EQUB&2C:.Ian1 BNEDavid3:STADavid2:LSRA:LDX#3:STXBLPTR+1:STXBLN+1:STXEXCN+1:DEX:JSROSBYTE \ADC 5006EQUB&2C:.FRED1 BNEDavid7 5007LDX#255:LDA#&48:JSRdoPROT1:LDA#144:JSROSB \TV 5008LDA#247:LDX#0:JSROSB \BREAK vec 5009\LDA#&81\LDY#FF\LDX#1\JSROSBYTE\TXA\BPLOS01 \Damn 0.1 5010LDA#190:LDX#8:JSROSB \8bitADC 5012EQUB&2C:.David8 BNEFRED1 5015LDA#&8F:LDX#&C:LDY#FF:JSROSBYTE \ claim NMIs 5030LDA#13:.abrk LDX#0:JSROSB \otput bffer 5050LDA#225:LDX#128:JSROSB \fn keys 5055LDA#172:LDX#0:LDY#255:JSROSBYTE:STXTRTB%:STYTRTB%+1 \int-ascii table 5058LDA#200:LDX#3:JSROSB:]IF PROT AND NOT DISC THEN[OPTZ:CPX#3:BNEabrk+1 \Clear memory on BREAK :] 5059[OPTZ 5060LDA#13:LDX#2:JSROSB \kybrd buffer 5062.OS01 5065LDX#FF:TXS:INX:.David3 LDABEGIN%,X:.PROT1 INY \PHA:INX:CPX#len:BNEDavid8 \^stack 5070LDA#(B% MOD256):STAZP:LDA#&C8:STAPROT1:LDA#(B% DIV256):STAZP+1:LDY#0:.LOOP LDA(ZP),Y:JSROSWRCH:INY:CPY#N%:BNELOOP \set up pokey-mode-4 5080LDA#1:TAX:TAY:STA(V219),Y:LDA#4:JSROSB \cursor 5090LDA#9:LDX#0:JSROSB \flashing 5095LDA#&6C:EORcrunchit:STAcrunchit 5101EQUS FNE(0):EQUS FNE(1):EQUS FNE(2):EQUS FNE(3) \envelopes 5103\ 5110LDX#4:STXP+1:LDA#(LL%DIV256):STAZP+1:LDY#0:LDA#256-len1:STA(V219-4,X):STYZP:STYP:JSRcrunchit \Move WORDS9 to &400 5115LDX#1:LDA#((LL%DIV256)+&C):STAZP+1:LDA#&63:STAP+1:LDY#0:JSRcrunchit:LDX#1:LDA#((LL%DIV256)+&D):STAZP+1:LDA#&61:STAP+1:LDY#0:JSRcrunchit:LDX#1:LDA#((LL%DIV256)+&E):STAZP+1:LDA#&76:STAP+1:LDY#0:JSRcrunchit 5117JSRPLL1 \draw Saturn 5120LDX#8:LDA#((LL%DIV256)+4):STAZP+1:LDA#&78:STAP+1:LDY#0:STYZP:STYBLCNT:STYP:JSRcrunchit \Move DIALSHP to &7800 5130LDX#(3-(DISC AND1)):LDA#(UU%DIV256):STAZP+1:LDA#(UU%MOD256):STAZP:LDA#(LE%DIV256):STAP+1:LDY#0:STYP:JSRcrunchit \Move Part of this program to LE% 5135STYDavid3-2:\LDY#0:.David2 EQUB&AC:EQUW&FFD4 \JSR&FFD4:.LBLa LDAC%,X:EOR#&A5:STAC%,X:DEX:BNELBLa:JMP(C%+&CF):.swine2 jmpswine:EQUW&4CFF:.crunchit BRK:EQUW David23:.RAND EQUD &6C785349:.David5 INY:CPY#(ENDBLOCK-BLOCK):BNEDavid2 5140SEI:LDA#&C2:STAVIA+&E:LDA#&7F:STA&FE6E:LDAIRQ1V:STAVEC:LDAIRQ1V+1:BPLswine2:STAVEC+1:LDA#(IRQ1 DIV256):STAIRQ1V+1:LDA#(IRQ1 MOD256):STAIRQ1V:LDA#VSCAN:STAUSVIA+5:CLI \ INTERRUPTS NOW OK 5145:] IF DISC THEN [OPTZ:LDA#&81:STA&FE4E:LDY#20:JSROSBYTE:LDA#1:STA&FE4E:] 5146[OPTZ 5190RTS \ENTRY2 on stack already 5210.PLL1 LDAVIA+4:STARAND+1:JSRDORND:JSRSQUA2:STAZP+1:LDAP:STAZP:JSRDORND:STAYY:JSRSQUA2:TAX:LDAP:ADCZP:STAZP:TXA:ADCZP+1:BCSPLC1 5220STAZP+1:LDA#1:SBCZP:STAZP:LDA#&40:SBCZP+1:STAZP+1:BCCPLC1:JSRROOT:LDAZP:LSRA:TAX:LDAYY:CMP#128:RORA:JSRPIX 5230.PLC1 DECCNT:BNEPLL1:DECCNT+1:BNEPLL1:LDX#&C2:STXEXCN 5240.PLL2 JSRDORND:TAX:JSRSQUA2:STAZP+1:JSRDORND:STAYY:JSRSQUA2:ADCZP+1:CMP#&11:BCCPLC2:LDAYY:JSRPIX 5250.PLC2 DECCNT2:BNEPLL2:DECCNT2+1:BNEPLL2:LDXMHCA:STXBLPTR:LDX#&C6:STXBLN 5260.PLL3 JSRDORND:STAZP:JSRSQUA2:STAZP+1:JSRDORND:STAYY:JSRSQUA2:STAT 5270ADCZP+1:STAZP+1:LDAZP:CMP#128:RORA:CMP#128:RORA:ADCYY:TAX:JSRSQUA2:TAY:ADCZP+1 5280BCSPLC3:CMP#&50:BCSPLC3:CMP#&20:BCCPLC3:TYA:ADCT:CMP#&10:BCSPL1:LDAZP:BPLPLC3:.PL1 LDAYY:JSRPIX 5290.PLC3 DECCNT3:BNEPLL3:DECCNT3+1:BNEPLL3 5300.DORND LDARAND+1:TAX:ADCRAND+3:STARAND+1:STXRAND+3:LDARAND:TAX:ADCRAND+2:STARAND:STXRAND+2:RTS 5320.SQUA2 BPLSQUA:EOR#FF:CLC:ADC#1 5330.SQUA STAQ:STAP:LDA#0:LDY#8:LSRP:.SQL1 BCCSQ1:CLC:ADCQ:.SQ1 RORA:RORP:DEY:BNESQL1:RTS 5340.PIX TAY:EOR#128:LSRA:LSRA:LSRA:ORA#&60:STAZP+1:TXA:EOR#128:AND#&F8:STAZP:TYA:AND#7:TAY:TXA:AND#7:TAX 5350LDATWOS,X:ORA(ZP),Y:STA(ZP),Y:RTS 5360.TWOS EQUD &10204080:EQUD&01020408 5370.CNT EQUW&500:.CNT2 EQUW &1DD:.CNT3 EQUW &500 5380.ROOT LDYZP+1:LDAZP:STAQ:LDX#0:STXZP:LDA#8:STAP:.LL6 CPXZP:BCCLL7:BNELL8:CPY#&40:BCCLL7:.LL8 TYA:SBC#&40:TAY:TXA:SBCZP:TAX:.LL7 ROLZP:ASLQ:TYA:ROLA:TAY:TXA:ROLA:TAX:ASLQ:TYA:ROLA:TAY:TXA:ROLA:TAX:DECP:BNELL6:RTS 5390.BEGIN% EQUB(David9 DIV256):EQUB(David9 MOD256):EQUB&6C \JMP:EQUB(TUT DIV256):EQUB(TUT MOD256):EQUB&99 \STA,Y:EQUB(TUT DIV256):EQUB(TUT MOD256):EQUB&59 \EOR,Y:PHA:EQUB((BLOCK)DIV256):EQUB((BLOCK)MOD256):EQUB&B9 \LDA,Y:PLA:PLA 5394.DOMOVE RTS:EQUW&D0EF \BNEMVDL:DEX:EQUBZP+1:INCP+1:EQUB&E6 \INCP+1 INCZP+1:EQUW&D0F6 \BNEMVDL:DEY:EQUBP:EQUB&91 \STA(),Y:EQUB(OSB DIV256):EQUB(OSB MOD256):EQUB&59 \EOR:EQUBZP:EQUB&B1 \LDA(),Y \ 18 Bytes ^ Stack 5400.UU%:]:Q%=P%-LE%:P%=LE%:[OPTZ 5450.CHECKbyt BRK:.MAINSUM EQUB&CB:EQUB0:.FOOLV EQUW FOOL:.CHECKV EQUWLOD%+1 5460.block1 EQUD&A5B5E5F5:EQUD&26366676:EQUD&8494C4D4:.block2 EQUD&A0B0C0D0:EQUD&8090E0F0:EQUD&27376777 \ Colours for interrupts 5500.TT26\ PRINT Please tidy this up! 5510STAK3:TYA:PHA:TXA:PHA 5520.rr LDAK3:CMP#7:BEQR5:CMP#32:BCSRR1:CMP#13:BEQRRX1:INCYC:.RRX1 LDX#7:STXXC:BNERR4 5530.RR1 5540LDX#&BF:ASLA:ASLA:BCCP%+4:LDX#&C1:ASLA:BCCP%+3:INX:STAP:STXP+1 5550LDAXC:CMP#20:BCCNOLF:LDA#7:STAXC:INCYC:.NOLF ASLA:ASLA:ASLA:STAZP:INCXC:LDAYC:CMP#19:BCCRR3:LDA#7:STAXC:lda#&65:stasc+1:ldy#7*8:ldx#14:stysc:lda#0:tay:.David1 sta(sc),Y:iny:cpy#14*8:bccDavid1:tay:incsc+1:dex:bplDavid1:lda#5:STAYC 5560bnerr:.RR3 ORA#&60:STAZP+1:LDY#7:.RRL1 LDA(P),Y:STA(ZP),Y:DEY:BPLRRL1 5570.RR4 PLA:TAX:PLA:TAY:LDAK3:.FOOL RTS 5580.R5 lda#7:jsrosprint:JMPRR4 5590.TUT \EOR here onward:.osprint jmp(osprnt):EQUB&6C:.command jmp(oscliv):.MESS1 EQUS FNLSTR:EQUB13 \*LOAD ELITEcode 5800.ENTRY2 lda&20E:staosprnt:LDA#(TT26 MOD256):STA&20E:LDX#(MESS1 MOD256):lda&20F:staosprnt+1:LDA#(TT26 DIV256):LDY#(MESS1 DIV256):STA&20F \OSWRCH for loading messages 5805JSRAFOOL:JSRcommand:JSR512-len+CHECKER-ENDBLOCK :JSRAFOOL: \ (Gratuitous JSRs)- LOAD Mcode and checksum it. 5810]IF DISC THEN [OPTZ:LDA#140:LDX#12:JSROSBYTE \*TAPE :] 5811[OPTZ 5820LDA#0:STAsvn 5830LDX#(LC% DIV256):LDA#(L% MOD256):STAZP:LDA#(L% DIV256):STAZP+1:LDA#(C% MOD256):STAP:LDA#(C% DIV256):STAP+1:LDY#0 5840.ML1 TYA:EOR(ZP),Y:STA(P),Y:INY:BNEML1:INCZP+1:INCP+1:DEX:BPLML1 \Move code down (d) 5850LDAS%+6:STA&202:LDAS%+7:STA&203:LDAS%+2:STA&20E:LDAS%+3:STA&20F \BRK,OSWRCH :RTS - ON STACK :.AFOOL JMP(FOOLV) 5852.M2 EQUB2:.VIA2 LDA#4:STA&FE20:LDY#11:.inlp1 LDAblock1,Y:STA&FE21:DEY:BPLinlp1:PLA:TAY:JMP(VEC):.IRQ1:TYA:PHA:] 5853IF PROT AND NOT DISC THEN [OPTZ:LDY#0:LDA(BLPTR),Y:BITM2:BNEitdone:EOR#128+3:INCBLCNT:BNEZQK:DECBLCNT:.ZQK STA(BLPTR),Y:LDA#&23:CMP(BLN),Y:BEQP%+4:EOR#17:CMP(EXCN),Y:BEQitdone:DECLOD%:.itdone:] 5854[OPTZ:LDAVIA+&D:BITM2:BNELINSCN:AND#64:BNEVIA2:PLA:TAY:JMP(VEC) 5856.LINSCN LDA#50:STAUSVIA+4:LDA#VSCAN:STAUSVIA+5:LDA#8:STA&FE20:LDY#11:.inlp2 LDAblock2,Y:STA&FE21:DEY:BPLinlp2:PLA:TAY:JMP(VEC) 5857\ 5859.BLOCK \ Pushed onto stack for execution :EQUW ENTRY2-1:EQUW 512-len+BLOCK-ENDBLOCK+3 5860LDAVIA+4:STA1:SEI:LDA#&39:STAVIA+&E:\LDA#&7F:\STA&FE6E:\LDAIRQ1V:\STAVEC:\LDAIRQ1V+1:\STAVEC+1 Already done:LDAS%+4:STAIRQ1V:LDAS%+5:STAIRQ1V+1:LDA#VSCAN:STAUSVIA+5:CLI \Interrupt vectors 5870\LDA#&81LDY#FFLDX#1JSROSBYTETXAEOR#FFSTAMOS \FF if MOS0.1 else 0 5880\BMIBLAST:LDY#0:LDA#200:LDX#3:JSROSBYTE:.BLAST \break,escape 5890LDA#(S% DIV256):STAZP+1:LDA#(S% MOD256):STAZP:LDX#&45:LDY#0:TYA:.CHK CLC:ADC(ZP),Y:INY:BNECHK:INCZP+1:DEX:BPLCHK:CMPD%-1:BEQitsOK:.nononono STAS%+1:LDA#&7F:STA&FE4E:JMP(&FFFC):.itsOK JMP(S%) 5900.CHECKER LDY#0:LDX#4:STXZP+1:STYZP:TYA:.CHKq CLC:ADC(ZP),Y:INY:BNECHKq:INCZP+1:DEX:BNECHKq:CMPMAINSUM+1:BNEnononono 5905TYA:.CHKb CLC:ADCLOD%,Y:INY:CPY#&28:BNECHKb:CMPMAINSUM:BNEnononono 5910] IF PROT AND NOT DISC THEN [OPTZ:LDABLCNT:CMP#&4F:BCCnononono:] 5920[OPTZ:JMP(CHECKV) 6050.ENDBLOCK \ no more on to stack 6060.XC EQUB7:.YC EQUB6 7000] 7020NEXTZ 7040FORI%=0TO ENDBLOCK-BLOCK STEP4:I%!TEMP%=I%!(BLOCK-P%+O%):NEXT:FORI%=0TO ENDBLOCK-BLOCK-1:?(ENDBLOCK-P%+O%-I%-1)=I%?TEMP%:NEXT 7042A%=0:FORI%=CODE TOCODE+&3FF:A%=A%+?I%:NEXT:?(MAINSUM-P%+O%+1)=A% 7045A%=0:FORI%=LE%-P%+O%+1TOLE%-P%+O%+383:A%=A%+?I%:NEXT:?(CHECKbyt-P%+O%)=A% 7050FORI%=0TO ENDBLOCK-BLOCK-1:?(I%+TUT-P%+O%)=(?(I%+TUT-P%+O%))EOR(?(I%+BLOCK-P%+O%)):NEXT 7060FORI%=0TO2-(DISC AND1):FORJ%=0TO255STEP4:!(J%+I%*256+UU%-P%-Q%+O%)=(!(J%+I%*256+UU%-P%-Q%+O%))EOR(!(OSB-P%-Q%+O%+J%)):NEXT, 7070FORI%=0TO&E:FORJ%=0TO255STEP4:!(J%+I%*256+CODE)=(!(J%+I%*256+CODE))EOR(!(OSB-P%-Q%+O%+J%)):NEXT, 7100PRINT"Memory usage: B00 - ";~P%'~LL%;" - ";~P%+Q%'"Stack :";len+ENDBLOCK-BLOCK 7110INPUT'"Press to save on drive 0"A$ 7120OSCLI("S.:0.ELITE "+STR$~CODE +" "+STR$~O% +" "+STR$~run +" "+STR$~LL%) 7200END 8000DATA67 8100DATA 22,4,28,2,17,15,16 8110DATA 23,0, 6,31,0,0,0,0,0,0 8112DATA 23,0,12,12,0,0,0,0,0,0 8114DATA 23,0,13, 0,0,0,0,0,0,0 8116DATA 23,0, 1,32,0,0,0,0,0,0 8118DATA 23,0, 2,45,0,0,0,0,0,0 8120DATA 23,0,10,32,0,0,0,0,0,0 9100DATA1,1,0,111,-8,4,1,8, 8,-2,0,-1,112,44 9110DATA2,1,14,-18,-1,44,32,50, 6,1,0,-2,120,126 9120DATA3,1,1,-1,-3,17,32,128,1,0,0,-1,1,1 9130DATA4,1,4,-8,44,4,6,8,22,0,0,-127,126,0 10000DEFPROCP(A):?O%=A:O%=O%+1:P%=P%+1:ENDPROC 10100DEF FNE(I%) 10110[OPTZ 10120LDX#((E%+I%*14)MOD256):LDY#((E%+I%*14)DIV256):LDA#8:JSROSWORD 10130] 10140="" 10200DEFFNLSTR:IF DISC THEN ="L.ELTcode 1100" ELSE ="L.ELITEcode F1F" ================================================ FILE: 1-source-files/original-sources/$.FINDSC2.inf ================================================ $.FINDSC2 000000 000000 0004FB ================================================ FILE: 1-source-files/original-sources/$.FINDSC2.txt ================================================ 10 REM FIND SOURCE 20 R=&76:S=&77:T=&78:J=&79:Q=&7A:FL=&7B 40 ctl=&70:add=&74:OSARGS=&FFDA:page=24:OSWRCH=&FFEE 43 FORZ=0TO2STEP2 45 P%=&C00 50[OPTZ 70.ENTRY ldapage:staadd+1:ldy#0:styFL:styadd:lda#1:ldx#ctl:jsrOSARGS:ldy#0:.fn2 lda(ctl),Y:cmp#13:bnefn1 75brk:brk:EQUS"DJB Vs1.1":.err brk:brk:EQUS("Can't Find."+CHR$0) 80.fn1 lda(add),Y:cmp#13:bnesrch:iny:lda(add),Y:bmiend:stactl+2:iny:lda(add),Y:stactl+3:ldaadd:clc:adc#4:staadd:lda#0:tay:adcadd+1:staadd+1 90.srch lda(ctl),Y:cmp#13:beqprt:cmp#ASC"@":beqfn6:cmp(add),Y:bnenxt:.fn6 iny:bnesrch:.end ldaFL:beqerr:jmp&FFE7:.nxt ldy#0:incadd:bnefn1:incadd+1:bnefn1 500.prt lda#ASC",":ldxFL:beqfn4:jsrOSWRCH:.fn4 staFL:ldactl+3:staQ:ldactl+2:staR:ldx#8:stxT:lda#5:staJ:ldx#0:stxS:BEQTT36 515.nxt2 bminxt 520.TT35 LDAQ:ASLA:TAX:STAQ:LDAR:ROLA:TAY:STAR:LDAS:ROLA:PHA 530ASLQ:ROLR:ROLA:ASLQ:ROLR:ROLA:STAS:TXA:ADCQ:STAQ:TYA:ADCR 540STAR:PLA:ADCS:STAS:LDX#0:.TT36 LDAQ:CMP#&A0:LDAR:SBC#&86 542LDAS:SBC#1:BCCTT37:LDAQ:SBC#&A0:STAQ:LDAR:SBC#&86:STAR 543LDAS:SBC#1:STAS:INX:BNETT36:.TT37 TXA 545BNETT32:LDAT:BNETT34 550.TT32 LDY#0:STYT:CLC:ADC#&30:.TT33 JSROSWRCH 560.TT34 ASLT:DECJ:BPLTT35:bminxt2 999]NEXT 10000OSCLI("SAVE FIND C00 "+STR$~P%) ================================================ FILE: 1-source-files/original-sources/$.GENTOK.inf ================================================ $.GENTOK 000000 000000 000931 ================================================ FILE: 1-source-files/original-sources/$.GENTOK.txt ================================================ 10 REM Generate TOKENS file 20 words=OPENOUT"WORDS9" 30 ONERRORGOTO150 40 REPEATREADA$:FORN%=1TOLENA$:CH%=ASCMID$(A$,N%,1) 50 IFCH%=ASC"#"THENGOSUB100:ELSEbyte=CH% 60 BPUT#words,byte EOR35:NEXT:BPUT#words,0 70 UNTILFALSE 100 byte=VAL(MID$(A$,N%+1,3)):N%=N%+4:RETURN 150 IFERR=42THENCLOSE#words:END ELSE CLOSE#words:PRINT"Line "ERL:REPORT:END 160 DATA#111##224##007#," CH#138#T",GO#150#RNM#146#T,D#145#A#224#,#140##150#NT#153#Y#013#,SYS#156#M,P#158##133#,#139#RKET #166#S,#140#D#136#T#158#AL,AG#158#CULTU#148#L 170 DATA#158#CH ,A#150##148##131# ,PO#153# ,#139##140#LY ,UNIT,VIEW ,#154##155##151#TY,#155##138#CHY,FEUDAL,MUL#151#-#162# 180 DATA#141#CT#145##153##185#,#251#MUN#157#T,C#159#F#152##144#ACY,DEMOC#148#CY,C#153#P#153##145#E ST#145#E,SHIP,PRODUCT,#149#S#144#,HUM#155#,"HYP#144#SPA#133# " 190 DATASH#153#T #202#,#141#ST#155##133#,POPUL#145#I#159#,GROSS #186#IVITY,EC#159#OMY," #203#YE#138#S",#156#CH.#129##150#L," CASH"," #134##118#I#159#",KNOWN GA#149#XY 200 DATAT#138##131#T LOST,#106# JAMM#152#,R#155##131#,LIGHT ,"#176# OF ",SE#118#," C#138#GO",E#154#IP ,FOOD,#156#X#151#L#137# 210 DATA#148##141#OAC#151##150#S,S#149##150#S,LI#154##153#/W#140##137#,LUXU#158##137#,N#138#CO#151#CS,#251#PUT#144#S,#139#CH#140##144#Y,S#156#EL,FI#142##138#MS,FURS 220 DATASIL#150#R,GOLD,PL#145##140#UM,#131#M-ST#159##137#," #159# ",(Y/N)?," CR",L#138##131#,FI#144##133#,S#139##118# 230 DATAG#142##146#,YE#118#OW,R#152#,BLUE,B#149#CK,WHI#156#,SLIMY,BUG-EY#152#,H#153#N#152#,B#159#Y 240 DATAF#145#,FURRY,ROD#146#T,FROG,LI#132#RD,LOBST#144#,#134#RD,#188#OID,T#152#DY,SPID#144# 250 DATA#171##148##141##136#,COM,#251#M#155#D#144#," D#137#TROY#152#"," D.B#148##147#N & I.#147##118# (C) 1983" 260 DATA"#174# #176##013# #186# #174# #166# F#153# SA#129##013##010#",FR#159#T,#142##138#,#158#GHT,#129#FT,#121#LOW#007#,#098##224##252#!,EXT#148# ,PULSE ,"#147#AM ",FUEL 270 DATAM#157#SI#129#,#227##206# BAY,E.C.M.#165#,#102##103##187#S,#102##104##187#S,#105# SCOOPS,#137#CAPE POD,#121#BOMB,GA#149#C#151#C #189#,WHICH," P#142#S#146#T",A#118#,LL,"#197#:#000#",#140##251##140#G #106# 280 DATA"#146##144#GY ","LOAD ","#013##252#'S NAME? ","PR#137#S FI#142# #153# SPA#133#,#252#.#013##013#" 290DATA"---- E L I T E ----"," DONE#013#","THE #149##156# #252# HAD #001##013#KI#118#S,& #119#" ================================================ FILE: 1-source-files/original-sources/$.GETBIT.inf ================================================ $.GETBIT 000000 000000 0000A1 ================================================ FILE: 1-source-files/original-sources/$.GETBIT.txt ================================================ 10 *LOAD :2.O.NDIALS 7600 20 *LOAD O.DIALSHP 6800 30 FORJ%=0TO255STEP4:!(J%+&7EC0)=!(J%+&6F00):NEXT 40 *SAVE :2.NDIALS 7600 8000 ================================================ FILE: 1-source-files/original-sources/$.MAKER.inf ================================================ $.MAKER 000000 000000 00023F ================================================ FILE: 1-source-files/original-sources/$.MAKER.txt ================================================ 5 HIMEM=&7A00 10 REM Create an ELITE software protected file set on cassette 12 ON ERROR GOTO 500 20 *DISC 35 MODE 7 40 IF PAGE<>&7000: PAGE=&7000: CHAIN ":2.MAKER" 50 *LOAD :0.ELITE 1900 53 P%=&90:[LDA#13:RTS:] 55 V%=!&210 AND&FFFF:?&210=&90:?&211=0 :REM OSRDCH revectored to RTS 60 *:2.LTAPE 70 *SAVE ELITE 1900+1500 FFFF1D00 FFFF0E00 80 *DISC 90 *LOAD :0.ELTcode 1900 100 *:2.PROTAPE 110 *SAVE ELITEcode 1900+5100 0000 0000 500 !&210=(!&210 AND&FFFF0000)+V%:REPORT:PRINT" on line "ERL:END ================================================ FILE: 1-source-files/original-sources/$.SBLOCK.inf ================================================ $.SBLOCK 000000 000000 0003E1 ================================================ FILE: 1-source-files/original-sources/$.SBLOCK.txt ================================================ 5REM Prepare DEFAULT and UNIV and serve with WORDS9 7MODE0 10NA%=&780:POW=15:K%=&C00:NI%=36 100GOSUB 1000 110INPUT"Insert assembly disk and hit RETURN "A$ 120*SAVE WORDS9 7400 7800 400 400 900END 1000*LOAD WORDS9 7400 1100FORZ=4TO6STEP2 1110O%=&7780:CODE%=O% 1200[OPTZ 1300.NAME EQUS("Default"):EQUB13 1310.QQ0 EQUB20:.QQ1 EQUB173:.QQ21 EQUD&2485A4A:EQUW&B753 \Base seed 1315.CASH EQUD &D0070000 1320.QQ14 EQUB70 fuel 1330.LASER EQUDPOW:EQUW0:.CRGO EQUB16 1350.QQ20 EQUD0:EQUD0:EQUD0:EQUD0 \cargo 1360.ECM EQUB FALSE 1370.BST EQUB FALSE 1400.BOMB EQUB FALSE 1410.GHYP EQUB FALSE 1415.ESCP EQUB FALSE 1420.NOMSL EQUB 3 1425.FIST EQUB FALSE 1430.TALLY EQUW 0 1440.SAVC EQUB 128 1450.CHK EQUB 0 1460] 1480P%=&7E0:O%=&7780+&60 1500FORI%=0TO12:!O%=K%+I%*NI%:O%=O%+2:NEXT 1550NEXT 1600NB%=CHK-NAME:A%=NB%:FORI%=NB%-1TO0STEP-1 1610A%=(A%+(I%?CODE%))EOR(I%?CODE%) 1620NEXT:REM?(CODE%+NB%)=A% 1700RETURN ================================================ FILE: 1-source-files/original-sources/$.SFTPROT.inf ================================================ $.SFTPROT 000000 000000 000215 ================================================ FILE: 1-source-files/original-sources/$.SFTPROT.txt ================================================ 10 REM SOFTWARE PROTECTION 20 REM USING OSFILE 25 FILEV=&212:IRQ2=&206:BFLAG=&3CA:USVIA=&FE60 30 P%=&C00:[ 40.VEC EQUW0 50.RESET LDA#1:ORABFLAG:STABFLAG:LDAUSVIA+4:LDA&FC:RTI 60.START PHP:PHA:SEI:LDA#192:STAUSVIA+14:LDA#(RESET DIV256):STAIRQ2+1:LDA#(RESET MOD256):STAIRQ2:LDA#64:STAUSVIA+11:LDA#255:STAUSVIA+4:STAUSVIA+5:STAUSVIA+6:STAUSVIA+7:PLA:CLI:PLP:JMP(VEC) 90.SET SEI:LDAFILEV:STAVEC:LDAFILEV+1:STAVEC+1:LDA#(START DIV256):STAFILEV+1:LDA#(START MOD256):STAFILEV:CLI:RTS 100] ================================================ FILE: 1-source-files/original-sources/$.SHPPRTE.inf ================================================ $.SHPPRTE 000000 000000 000640 ================================================ FILE: 1-source-files/original-sources/$.SHPPRTE.txt ================================================ 1REM Prepare DIALSHP and SHIPS 2MODE1 5D%=&5490 10HIMEM=&2000 18*LOAD DMPDIAL 20READN%:C%=D%:B%=&7F00 25READ A$,B$,P,Q,R,S,T,U,V,W:!B%=&7F00+2*N%:B%=B%+2 30FORI%=2TON%:READ A$,B$,P,Q,R,S,T,U,V,W:!B%=C%:B%=B%+2:C%=C%+EVAL("&"+B$):NEXT 40RESTORE1010:C%=D% 45READ A$,B$,P,Q,R,S,T,U,V,W:OSCLI("LOAD "+A$+" "+STR$~B%):B%?1=P*P MOD256:B%?2=P*P DIV256:B%?14=Q:B%?15=R:B%?5=S:B%?7=T:B%?19=U:B%?10=V MOD256:B%?11=V DIV256:B%?13=W:B%=B%+EVAL("&"+B$) 46P%=B% 48[OPT2:.PRXS EQUW1:EQUW250:EQUW4000:EQUW5000:EQUW4000:EQUW7500:EQUW1750:EQUW25000:EQUW10000:EQUW50000:] 50FORI%=2TON%:READ A$,B$,P,Q,R,S,T,U,V,W 60OSCLI("LOAD S."+A$+" "+STR$~C%):C%?1=P*P MOD256:C%?2=P*P DIV256:C%?14=Q:C%?15=R:C%?5=S:C%?7=T:C%?19=U:C%?10=V MOD256:C%?11=V DIV256:C%?13=W:C%=C%+EVAL("&"+B$) 80NEXT:PRINT~D% C% PRXS 90INPUT"Insert assembly disk and hit RETURN"A$ 100OSCLI("S.SHIPS "+STR$~D%+" 6000") 110OSCLI("S.DIALSHP 7800 8000") 1000DATA 10 1005REMDATA SHIP5,80, 50,75,10,37,26,0 1010DATA SHIP3,A8, 65,70,37,61,30,0,50,20 1030DATA SHIP1+,DA, 75,100,32,77,42,1,0,23 1040DATA SHIP4,12E, 70,90,30,93,34,1,200,25 1050DATA SHIP2,F2, 80,200,20,85,46,2,250,40 1060DATA CYLON,188, 95,150,28,153,42,3,0,50 1065DATA THAARG,11C, 99,240,39,101,38,5,500,55 1066DATA SPCSTN,11C, 160,240,0,85,54,6,0,120 1070DATA MISSILE,FE, 40,2,44,81,10,0,0,14 1075DATA TETRA,54, 16,1,10,25,22,0,0,8 1080DATA ASTROID,D6, 80,60,40,65,34,0,5,50 2000 REM length,hits rad,energy,vel,4*lines+1,4*(exp nodes)+6,no.missiles,Bounty,Distance at which point ================================================ FILE: 1-source-files/original-sources/$.TOKPRI.inf ================================================ $.TOKPRI 000000 000000 0004B1 ================================================ FILE: 1-source-files/original-sources/$.TOKPRI.txt ================================================ >LIST 100GOSUB1000 110FORA%=96TO125:PRINTA%" ";:CALLTT27:PRINT:NEXT 120FORA%=129TO255:PRINTA%" ";:CALLTT27:PRINT:NEXT 200END 1000DIM CODE &1000 1010FORZ=0TO2STEP2 1020V=&70:QQ17=&72:?QQ17=0 1050P%=CODE 1060[OPTZ 1100.TT27\"Detoken 1110TAX:BMITT43:CMP#&60:BCSex:LDXQQ17:BEQTT74:BMITT41:BITQQ17:BVSTT46:.TT42 1120CMP#65:BCCTT44:CMP#&5B:BCSTT44:ADC#32:.TT44 JMPTT26:.TT41 BITQQ17:BVSTT45:CMP#65:BCCTT74:PHA:TXA:ORA#64:STAQQ17:PLA:JMPTT26 1130.TT45 CPX#255:BEQTT48:CMP#65:BCSTT42:.TT46 PHA:TXA:AND#191:STAQQ17:PLA 1140.TT74 JMPTT26 1150.TT43 CMP#160:BCSTT47:AND#127:BEQTT48:ASLA:TAY:LDAQQ16-2,Y 1160JSRTT27:LDAQQ16-1,Y:CMP#&3F:BEQTT48:JMPTT27 1170.TT47 SBC#160:.ex TAX:LDA#(QQ18 MOD256):STAV:LDA#(QQ18 DIV256):STAV+1:LDY#0:TXA:BEQTT50 1180.TT51 LDA(V),Y:BEQTT49:INY:BNETT51:INCV+1:BNETT51:.TT49 INY:BNETT59:INCV+1:.TT59 DEX:BNETT51:.TT50 1190TYA:PHA:LDAV+1:PHA:LDA(V),Y:EOR#35 1200JSRTT27:PLA:STAV+1:PLA:TAY:INY:BNETT52:INCV+1:.TT52 1210LDA(V),Y:BNETT50:.TT48 RTS 1212.QQ16 EQUS"LEXEGEZACEBISOUSESARMAINDIREA?ERATENBERALAVETIEDORQUANTEISRION" 1220.TT26 JMP&FFEE 1230.QQ18 1280] 1290NEXT 1300OSCLI("LOAD WORDS9 "+STR$~QQ18) 1400RETURN >*SPOOL ================================================ FILE: 1-source-files/original-sources/$.UNPACK.inf ================================================ $.UNPACK 000000 000000 00045D ================================================ FILE: 1-source-files/original-sources/$.UNPACK.txt ================================================ 10 REM Unpack an ELITE security number 20 REM This works for either disc or tape copies 30 REM This program is the property of D.Braben & I.Bell 40 REM and MUST NOT BE GIVEN AWAY UNDER ANY CIRCUMSTANCES 50 60 INPUT"ELITE security number ",A$ 70 B1%=(EVAL(RIGHT$(A$,8)))AND255 80 N%=INT((EVALA$)/256) 90 B2%=N%AND255:B3%=(N%AND&FF00)/256:B4%=(N%AND&FF0000)/65536 100 B%=B4%EOR B2%:IFB%AND128 PRINTCHR$7+'" <<< THIS FILE HAS BEEN TAMPERED WITH >>>"':END 110 PRINT'"File has been used on version(s) for "; 120 IFB%AND2 PRINT"BBC cassette, "; 130 IFB%AND4 PRINT"BBC disc, "; 140 IFB%AND8 PRINT"Electron, "; 145 IFB%AND&70 PRINT"Something else??"; 150 PRINT"only." 160 B%=B2%EOR B3% 170 INPUT"What CASH does this file have",C:C%=C*10:IF B%=(C%AND&FF00)/256 PRINT"Tallies." ELSE PRINTCHR$7+'"MISMATCH."' 180 B%=B3% EOR B1% EOR&5A:PRINT"Commander was ";:IFB%>24 PRINT"One of the ... ELITE.":RUN 190 IFB%>10 PRINT"Deadly.":RUN 200 IFB%>2 PRINT"Dangerous.":RUN 210 IFB% PRINT"Competant.":RUN 220 PRINT"Competant at most.":RUN ================================================ FILE: 1-source-files/original-sources/A.GENTOK.inf ================================================ $.GENTOKA 000000 000000 000B18 ================================================ FILE: 1-source-files/original-sources/A.GENTOK.txt ================================================ 10 REM Generate TOKENS file 20 words=OPENOUT"WORDS9" 30 ONERRORGOTO150 40 REPEATREADA$:FORN%=1TOLENA$:CH%=ASCMID$(A$,N%,1) 50 IFCH%=ASC"#"THENGOSUB100:ELSEbyte=CH% 60 BPUT#words,byte EOR35:NEXT:BPUT#words,0 70 UNTILFALSE 100 byte=VAL(MID$(A$,N%+1,3)):N%=N%+4:RETURN 150 IFERR=42THENCLOSE#words:END ELSE CLOSE#words:PRINT"Line "ERL:REPORT:END 160 DATA#111##017##007#," CH#138#T",GO#150#RNM#146#T,D#145#A#017##003#,#140##150#NT#153#Y#013#,SYS#156#M,P#158##133#,#002# #139#RKET #166#S,#140#D#136#T#158##128#,AG#158#CULTU#148#L 170 DATA#158#CH ,A#150##148##131# ,PO#153# ,#139##140#LY ,UNIT,VIEW ,#154##155##151#TY,#155##138#CHY,FEUD#128#,MUL#151#-#162# 180 DATA#141#CT#145##153##185#,#251#MUN#157#T,C#159#F#152##144#ACY,DEMOC#148#CY,C#153#P#153##145#E #203##145#E,SHIP,PRODUCT," #149#S#144#",HUM#155# COL#159#I#128#,"HYP#144#SPA#133# " 190 DATASH#153#T #202##161#,#141##203##155##133#,POPUL#145#I#159#,GROSS #186#IVITY,EC#159#OMY," LIGHT YE#138#S",#156#CH.#129##150#L,"CASH"," #134##118#I#159#",#122##161##001# 200 DATAT#138##131#T LO#203#,#106# JAMM#152#,R#155##131#,ST,"#176# OF ",SE#118#," C#138#GO#006#",E#154#IP,FOOD,#156#X#151#L#137# 210 DATA#148##141#OAC#151##150#S,S#149##150#S,LI#154##153#/W#140##137#,LUXU#158##137#,N#138#CO#151#CS,#251#PUT#144#S,#139#CH#140##144#Y,#117#OYS,FI#142##138#MS,FURS 220 DATAM#140##144##128#S,GOLD,PL#145##140#UM,#131#M-#203##159##137#,#128#I#146# #127#S,(Y/N)?," CR",L#138##131#,FI#144##133#,S#139##118# 230 DATAG#142##146#,R#152#,YE#118#OW,BLUE,B#149#CK,#022#,SLIMY,BUG-EY#152#,H#153#N#152#,B#159#Y 240 DATAF#145#,FURRY,ROD#146#T,FROG,LI#132#RD,LOB#203##144#,#134#RD,HUM#155#OID,FEL#140#E,#140#SECT 250 DATA#171##148##141##136#,COM,#251#M#155#D#144#," D#137#TROY#152#","BY D.B#148##147#N & I.#147##118#" 260 DATA"#174# #176##013# #186# #174# #166# F#153# SA#129##013##010#",FR#159#T,#142##138#,#129#FT,#158#GHT,#121#LOW#007#,#099##017##252#!,EXT#148# ,PULSE#187#,"#147#AM#187#",FUEL 270 DATAM#157#SI#129#,#227##206# BAY,E.C.M.#165#,#102##103#S,#102##104#S,#105# SCOOPS,#137#CAPE POD,#121#BOMB,#121##174#,#124##140#G #215#,#122# #189#,A#118#,LL,"#197#:#000#",#140##251##140#G #106# 280 DATA"#146##144#GY ",GA#149#C#151#C,"#013##252#'S NAME? ",DOCK 290DATA#005##129#G#128# #203##145##136#:,"#252# #004##013##013##013##006##031# #165##009##002##013##189##165##009##003##013#C#159##141##151##159##009#",I#156#M 300DATA" LOAD NEW #252# #225##013##013#",#006##124##152#,#148##151#NG:," #159# ","#013##008##207#M#146#T:#006#",C#129##155#,OFF#146#D#144#,FUGI#151##150#,H#138#M#129#SS,MO#203#LY #022#,#172#,#171#,ABO#150# #171#,#251#PET#146#T 310DATAD#155##131#RO#136#,DEADLY,"---- E L I T E ----",P#142#S#146#T,"#008#GAME O#150#R","PR#137#S FI#142# #153# SPA#133#,#252#.#013##013#","(C) AC#153#N#135#FT 1984" ================================================ FILE: 1-source-files/original-sources/O.ELITED.inf ================================================ $.ELITEDO 000000 000000 002E8C ================================================ FILE: 1-source-files/original-sources/O.ELITED.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 20REM ELITE 30H%=L%+P%-C%:O%=W% 300[OPTZ 700.tnpr pha:LDX#12:CPXQQ29:BCCkg:.Tml ADCQQ20,X:DEX:BPLTml:CMPCRGO:pla:RTS:.kg LDYQQ29:ADCQQ20,Y:cmp#200:pla:rts 840.TT20 JSRP%+3:JSRP%+3 850.TT54 LDAQQ15:CLC:ADCQQ15+2:TAX:LDAQQ15+1:ADCQQ15+3:TAY 860LDAQQ15+2:STAQQ15:LDAQQ15+3:STAQQ15+1:LDAQQ15+5:STAQQ15+3:LDAQQ15+4:STAQQ15+2:CLC:TXA:ADCQQ15+2:STAQQ15+4:TYA:ADCQQ15+3:STAQQ15+5:RTS 950.TT146 LDAQQ8:ORAQQ8+1:BNETT63:INCYC:RTS:.TT63 LDA#191:JSRTT68 955LDXQQ8:LDYQQ8+1:SEC:JSRpr5:LDA#195:.TT60 JSRTT27:.TTX69 INCYC:.TT69 LDA#128:STAQQ17:.TT67 LDA#13:JMPTT27 990.TT70 LDA#173:JSRTT27:JMPTT72:.spc JSRTT27:JMPTT162 1000.TT25\ DATA 1010\LDA#1:JSRTT66-2:LDA#9:STAXC:LDA#163:JSRTT27:JSRNLIN:JSRTTX69:INCYC:JSRTT146:LDA#194 1030JSRTT68:LDAQQ3:CLC:ADC#1:LSRA:CMP#2:BEQTT70:LDAQQ3:BCCTT71 1040SBC#5:CLC:.TT71 ADC#170:JSRTT27:.TT72 LDAQQ3:LSRA:LSRA:CLC:ADC#168:JSRTT60:LDA#162:JSRTT68:LDAQQ4:CLC:ADC#177:JSRTT60:LDA#196:JSRTT68 1070LDXQQ5:INX:CLC:JSRpr2:JSRTTX69:LDA#192:JSRTT68:SEC:LDXQQ6:JSRpr2:LDA#198:JSRTT60:LDA#&28:JSRTT27:LDAQQ15+4:BMITT75:LDA#188:JSRTT27:JMPTT76:.TT75 LDAQQ15+5 1110LSRA:LSRA:PHA:AND#7:CMP#3:BCSTT205:ADC#227:JSRspc:.TT205 PLA:LSRA:LSRA:LSRA:CMP#6:BCSTT206:ADC#230:JSRspc:.TT206 LDAQQ15+3:EORQQ15+1:AND#7 1116STAQQ19:CMP#6:BCSTT207:ADC#236:JSRspc:.TT207 LDAQQ15+5:AND#3:CLC:ADCQQ19:AND#7:ADC#242:JSRTT27:.TT76 LDA#&53:JSRTT27:LDA#&29:JSRTT60 1127LDA#193:JSRTT68:LDXQQ7:LDYQQ7+1:JSRpr6:JSRTT162:LDA#0:STAQQ17:LDA#&4D:JSRTT27:LDA#226:JSRTT60:LDA#250:JSRTT68:LDAQQ15+5:LDXQQ15+3:AND#15:CLC:ADC#11:TAY 1150JSRpr5:JSRTT162:LDA#&6B:JSRTT26:LDA#&6D:JMPTT26 1200.TT24 1210LDAQQ15+1:AND#7:STAQQ3:LDAQQ15+2:LSRA:LSRA:LSRA:AND#7:STAQQ4:LSRA:BNETT77:LDAQQ3:ORA#2:STAQQ3:.TT77 LDAQQ3:EOR#7:CLC:STAQQ5:LDAQQ15+3:AND#3:ADCQQ5:STAQQ5 1240LDAQQ4:LSRA:ADCQQ5:STAQQ5:ASLA:ASLA:ADCQQ3:ADCQQ4:ADC#1:STAQQ6:LDAQQ3:EOR#7:ADC#3:STAP:LDAQQ4:ADC#4:STAQ:JSRMULTU:LDAQQ6:STAQ:JSRMULTU:ASLP:ROLA:ASLP:ROLA:ASLP:ROLA:STAQQ7+1:LDAP:STAQQ7:RTS 1400.TT22\Lng Sc 1410LDA#64:JSRTT66:LDA#7:STAXC:JSRTT81:LDA#199:JSRTT27:JSRNLIN:LDA#152:JSRNLIN2:JSRTT14 1460LDX#0:.TT83 STXXSAV:LDXQQ15+3:LDYQQ15+4:TYA:ORA#&50:STAZZ 1470LDAQQ15+1:LSRA:CLC:ADC#24:STAXX15+1:JSRPIXEL:JSRTT20:LDXXSAV:INX:BNETT83:LDAQQ9:STAQQ19:LDAQQ10:LSRA:STAQQ19+1:LDA#4:STAQQ19+2 1700.TT15 1705LDA#24:LDXQQ11:BPLP%+4:LDA#0:STAQQ19+5:LDAQQ19:SEC:SBCQQ19+2:BCSTT84:LDA#0:.TT84 STAXX15:LDAQQ19:CLC:ADCQQ19+2:BCCP%+4:LDA#FF:STAXX15+2 1725LDAQQ19+1:CLC:ADCQQ19+5:STAXX15+1:JSRHLOIN:LDAQQ19+1:SEC:SBCQQ19+2:BCSTT86:LDA#0:.TT86 CLC:ADCQQ19+5:STAXX15+1:LDAQQ19+1:CLC:ADCQQ19+2:ADCQQ19+5:CMP#152:BCCTT87 1750LDXQQ11:BMITT87:LDA#151:.TT87 STAXX15+3:LDAQQ19:STAXX15:STAXX15+2:JMPLL30 1800.TT126 LDA#104:STAQQ19:LDA#90:STAQQ19+1:LDA#16:STAQQ19+2:JSRTT15:LDAQQ14:STAK:JMPTT128 2000.TT14\Crcl/+ 2010LDAQQ11:BMITT126:LDAQQ14:LSRA:LSRA:STAK:LDAQQ0:STAQQ19:LDAQQ1:LSRA:STAQQ19+1:LDA#7:STAQQ19+2:JSRTT15:LDAQQ19+1:CLC:ADC#24:STAQQ19+1 2300.TT128 LDAQQ19:STAK3:LDAQQ19+1:STAK4:LDX#0:STXK4+1:STXK3+1:\STXLSX:INX:STXLSP:LDX#2:STXSTP 2310JSRCIRCLE2:\LDA#FFSTALSX:RTS 2650.TT219\Buy 2655\LDA#2:JSRTT66-2:JSRTT163:LDA#128:STAQQ17:\JSRFLKB:LDA#0:STAQQ29 2660.TT220 JSRTT151:LDAQQ25:BNETT224:JMPTT222:.TQ4 LDY#176:.Tc JSRTT162:TYA:JSRprq:.TTX224 JSRdn2:.TT224 2671JSRCLYNS:LDA#204:JSRTT27:LDAQQ29:CLC:ADC#208:JSRTT27:LDA#&2F:JSRTT27:JSRTT152:LDA#&3F:JSRTT27:JSRTT67:LDX#0:STXR:LDX#12:STXT1:.TT223 2700JSRgnum:BCSTQ4:STAP:JSRtnpr:LDY#206:BCSTc:LDAQQ24:STAQ:JSRGCASH:JSRLCASH:LDY#197:BCCTc 2708LDYQQ29:LDAR:PHA:CLC:ADCQQ20,Y:STAQQ20,Y:LDAAVL,Y:SEC:SBCR:STAAVL,Y:PLA:BEQTT222:JSRdn 2710.TT222 LDAQQ29:CLC:ADC#5:STAYC:LDA#0:STAXC:INCQQ29:LDAQQ29:CMP#17:BCSBAY2:JMPTT220:.BAY2 LDA#f9:JMPFRCE 2750.gnum LDX#0:STXR:LDX#12:STXT1:.TT223 JSRTT217:STAQ:SEC:SBC#&30:BCCOUT:CMP#10:BCSBAY2:STAS:LDAR:CMP#26:BCSOUT:ASLA:STAT:ASLA:ASLA:ADCT:ADCS:STAR:CMPQQ25:BEQTT226:BCSOUT:.TT226 LDAQ:JSRTT26:DECT1:BNETT223:.OUT LDAR:RTS 2850.TT208\Sel 2855LDA#4:JSRTT66:LDA#4:STAYC:STAXC:\JSRFLKB:LDA#205:JSRTT27:LDA#206:JSRTT68 2900.TT210\Crgo 2910LDY#0:.TT211 STYQQ29:LDXQQ20,Y:BEQTT212 2912TYA:ASLA:ASLA:TAY:LDAQQ23+1,Y:STAQQ19+1 2915TXA:PHA:JSRTT69:CLC:LDAQQ29:ADC#208 2917JSRTT27:LDA#14:STAXC:PLA:TAX:CLC:JSRpr2:JSRTT152 2922LDAQQ11:CMP#4:BNETT212:LDA#205:JSRTT214 2923BCCTT212:LDAQQ29:LDX#255:STXQQ17:JSRTT151 2925LDYQQ29:LDAQQ20,Y:STAP:LDAQQ24:STAQ:JSRGCASH:JSRMCASH 2935LDA#0:LDYQQ29:STAQQ20,Y:STAQQ17 2940.TT212 LDYQQ29:INY:CPY#17:BCSP%+5:JMPTT211:LDAQQ11:CMP#4:BNEP%+8:JSRdn2:JMPBAY2:RTS 2942.TT213\Invntry 2945LDA#8:JSRTT66:LDA#11:STAXC:LDA#164:JSRTT60:JSRNLIN4:JSRfwl 2950LDACRGO:CMP#26:BCCP%+7:LDA#&6B:JSRTT27:JMPTT210 2965.TT214 PHA:JSRTT162:PLA:.TT221 JSRTT27:LDA#225:JSRTT27 2966JSRTT217:ORA#32:CMP#&79:BEQTT218:LDA#&6E:JMPTT26:.TT218 JSRTT26:SEC:RTS 3000.TT16 TXA:PHA:DEY:TYA:EOR#255:PHA:JSRWSCAN:JSRTT103:PLA:STAQQ19+3 3010LDAQQ10:JSRTT123:LDAQQ19+4:STAQQ10:STAQQ19+1:PLA 3020STAQQ19+3:LDAQQ9:JSRTT123:LDAQQ19+4:STAQQ9:STAQQ19:.TT103 3030LDAQQ11:BMITT105:LDAQQ9:STAQQ19:LDAQQ10:LSRA:STAQQ19+1 3040LDA#4:STAQQ19+2:JMPTT15 3045.TT123 STAQQ19+4:CLC:ADCQQ19+3:LDXQQ19+3:BMITT124:BCCTT125 3047RTS:.TT124 BCCTT180:.TT125 STAQQ19+4:.TT180 RTS 3050.TT105 LDAQQ9:SEC:SBCQQ0:CMP#38:BCCTT179:CMP#230:BCCTT180 3055.TT179 ASLA:ASLA:CLC:ADC#104:STAQQ19 3060LDAQQ10:SEC:SBCQQ1:CMP#38:BCCP%+6:CMP#220:BCCTT180 3065ASLA:CLC:ADC#90:STAQQ19+1:LDA#8:STAQQ19+2:JMPTT15 3300.TT23\ShrtSc 3310LDA#128:JSRTT66:LDA#7:STAXC:LDA#190:JSRNLIN3:JSRTT14:JSRTT103:JSRTT81 3349LDA#0:STAXX20:LDX#24:.EE3 STAINWK,X:DEX:BPLEE3 3350.TT182 LDAQQ15+3:SEC:SBCQQ0:BCSTT184:EOR#FF:ADC#1:.TT184 CMP#20:BCSTT187:LDAQQ15+1:SEC:SBCQQ1:BCSTT186:EOR#FF:ADC#1:.TT186 CMP#38:BCSTT187 3370LDAQQ15+3:SEC:SBCQQ0:ASLA:ASLA:ADC#104:STAXX12:LSRA:LSRA:LSRA:STAXC:INCXC:LDAQQ15+1:SEC:SBCQQ1:ASLA:ADC#90:STAK4:LSRA:LSRA:LSRA 3377TAY:LDXINWK,Y:BEQEE4:INY:LDXINWK,Y:BEQEE4:DEY:DEY:LDXINWK,Y:BNEee1:.EE4 STYYC:CPY#3:BCCTT187:DEX:STXINWK,Y 3380LDA#128:STAQQ17:JSRcpl:.ee1 3390\drawbigstars:LDA#0:STAK3+1:STAK4+1:STAK+1:LDAXX12:STAK3:LDAQQ15+5:AND#1:ADC#2:STAK:JSRFLFLLS:JSRSUN:JSRFLFLLS 3400.TT187 JSRTT20:INCXX20:BEQTT111-1:JMPTT182 3450.TT81 LDX#5:LDAQQ21,X:STAQQ15,X:DEX:BPLTT81+2 3500RTS:.TT111 JSRTT81:LDY#127:STYT:LDA#0:STAU 3510.TT130 LDAQQ15+3:SEC:SBCQQ9:BCSTT132:EOR#FF:ADC#1:.TT132 LSRA:STAS:LDAQQ15+1:SEC:SBCQQ10:BCSTT134:EOR#FF:ADC#1:.TT134 LSRA:CLC:ADCS:CMPT:BCSTT135 3550STAT:LDX#5:.TT136 LDAQQ15,X:STAQQ19,X:DEX:BPLTT136:.TT135 3560JSRTT20:INCU:BNETT130:LDX#5:.TT137 LDAQQ19,X:STAQQ15,X:DEX 3570BPLTT137:LDAQQ15+1:STAQQ10:LDAQQ15+3:STAQQ9 3575SEC:SBCQQ0:BCSTT139:EOR#FF:ADC#1:.TT139 JSRSQUA2:STAK+1:LDAP:STAK:LDAQQ10 3590SEC:SBCQQ1:BCSTT141:EOR#FF:ADC#1:.TT141 LSRA:JSRSQUA2:PHA:LDAP:CLC:ADCK 3610STAQ:PLA:ADCK+1:STAR:JSRLL5:LDAQ:ASLA:LDX#0:STXQQ8+1:ROLQQ8+1:ASLA:ROLQQ8+1:STAQQ8:JMPTT24 4340.hy6 JSRCLYNS:LDA#15:STAXC:JMPTT27 4350.hyp LDAQQ12:BNEhy6:LDAQQ22+1:BNEhy5:JSRCTRL:BMIGhy:LDAQQ11:BEQTTX110:\AND#192:\BEQhy5 4353JSRhm:.TTX111 4355LDAQQ8:ORAQQ8+1:BEQhy5:LDA#7:STAXC:LDA#23:STAYC:LDA#0:STAQQ17:LDA#189:JSRTT27:LDAQQ8+1:BNETT147:LDAQQ14:CMPQQ8:BCCTT147 4380LDA#&2D:JSRTT27:JSRcpl:LDA#15:STAQQ22+1:STAQQ22:TAX:JSRee3:.hy5 RTS 4390.TTX110 JSRTT111:JMPTTX111 4392.Ghy LDXGHYP:BEQhy5:INX:STXQQ8:STXQQ8+1:STXGHYP:STXFIST:INX:STXQQ22+1:LDX#5:STXQQ22:INCGCNT:LDAGCNT:AND#7:STAGCNT:.G1 LDAQQ21,X:ASLA:ROLQQ21,X:DEX:BPLG1:JSRDORND:STAQQ9:STXQQ10:JSRTT110:LDA#116:JSRMESS:.jmp LDAQQ9:STAQQ0:LDAQQ10 4393STAQQ1:.rt RTS 4395.ee3 LDY#1:STYYC:DEY:STYXC::.pr6 CLC:.pr5 LDA#5:JMPTT11 4400.TT147 LDA#202:.prq JSRTT27:LDA#&3F:JMPTT27 5000.TT151\Pmk-A 5010PHA:STAQQ19+4:ASLA:ASLA:STAQQ19:LDA#1:STAXC:PLA:ADC#208 5015JSRTT27:LDA#14:STAXC:LDXQQ19:LDAQQ23+1,X:STAQQ19+1:LDAQQ26:ANDQQ23+3,X:CLC:ADCQQ23,X:STAQQ24:JSRTT152 5050JSRvar:LDAQQ19+1:BMITT155:LDAQQ24:ADCQQ19+3:JMPTT156 5060.TT155 LDAQQ24:SEC:SBCQQ19+3:.TT156 STAQQ24:STAP:LDA#0:JSRGC2 5070SEC:JSRpr5:LDYQQ19+4:LDA#5:LDXAVL,Y:STXQQ25 5100CLC:BEQTT172:JSRpr2+2:JMPTT152:.TT172 LDAXC:ADC#4:STAXC:LDA#&2D:BNETT162+2 5110.TT152 LDAQQ19+1:AND#96:BEQTT160:CMP#32:BEQTT161 5120JSRTT16a:.TT162 LDA#32:JMPTT27 5130.TT160 LDA#&74:JSRTT26:BCCTT162 5140.TT161 LDA#&6B:JSRTT26:.TT16a LDA#&67:JMPTT26 5160.TT163 LDA#17:STAXC:LDA#FF:BNETT162+2 5200.TT167\MktP 5210LDA#16:JSRTT66:LDA#5:STAXC:LDA#167:JSRNLIN3:LDA#3:STAYC:JSRTT163:LDA#0:STAQQ29:.TT168 LDX#128:STXQQ17:JSRTT151:INCYC 5250INCQQ29:LDAQQ29:CMP#17:BCCTT168:RTS 5900.var LDAQQ19+1:AND#31:LDYQQ28:STAQQ19+2:CLC:LDA#0:STAAVL+16:.TT153 DEY:BMITT154:ADCQQ19+2:JMPTT153:.TT154 STAQQ19+3:RTS 5980.hyp1 JSRTT111:JSRjmp:LDX#5:.TT112 LDAQQ15,X:STAQQ2,X:DEX:BPLTT112:INX:STXEV:LDAQQ3:STAQQ28:LDAQQ5:STAtek:LDAQQ4:STAgov:JSRDORND:STAQQ26 5990LDX#0:STXXX4:.hy9 LDAQQ23+1,X:STAQQ19+1:JSRvar:LDAQQ23+3,X:ANDQQ26:CLC:ADCQQ23+2,X:LDYQQ19+1:BMITT157:SEC:SBCQQ19+3:JMPTT158:.TT157 CLC:ADCQQ19+3:.TT158 BPLTT159:LDA#0:.TT159 5994LDYXX4:AND#63:STAAVL,Y:INY:TYA:STAXX4:ASLA:ASLA:TAX:CMP#63:BCChy9:.hyR RTS 5995.GTHG JSRZe:LDA#FF:STAINWK+32:LDA#THG:JSRNWSHP:LDA#TGL:JMPNWSHP 5996.ptg LSRCOK:SEC:ROLCOK 5998.MJP\LDA#1:JSRTT66-2:JSRLL164:JSRRES2:STYMJ:.MJP1 JSRGTHG:LDA#3:CMPMANY+THG:BCSMJP1:STANOSTM:LDX#0:JSRLOOK1:LDAQQ1:EOR#31:STAQQ1:RTS 6000.TT18\HSPC 6005LDAQQ14:SEC:SBCQQ8:STAQQ14:LDAQQ11:BNEee5:JSRTT66:JSRLL164:.ee5 JSRCTRL:ANDPATG:BMIptg:JSRDORND:CMP#253:BCSMJP\JSRTT111:JSRhyp1:JSRRES2:JSRSOLAR 6500LDAQQ11:AND#63:BNEhyR:JSRTTX66:LDAQQ11:BNETT114:INCQQ11:.TT110 LDXQQ12:BEQNLUNCH:JSRLAUN:JSRRES2:JSRTT111:INCINWK+8:JSRSOS1:LDA#128:STAINWK+8:INCINWK+7:JSRNWSPS:LDA#12:STADELTA:JSRBAD:ORAFIST:STAFIST 6510.NLUNCH LDX#0:STXQQ12:JMPLOOK1:.TT114 BMITT115:JMPTT22:.TT115 JMPTT23 6530.LCASH STXT1:LDACASH+3:SEC:SBCT1:STACASH+3:STYT1:LDACASH+2:SBCT1:STACASH+2:LDACASH+1:SBC#0:STACASH+1:LDACASH:SBC#0:STACASH:BCSTT113 6540.MCASH TXA:CLC:ADCCASH+3:STACASH+3:TYA:ADCCASH+2:STACASH+2:LDACASH+1:ADC#0:STACASH+1:LDACASH:ADC#0:STACASH:CLC:.TT113 RTS 6550.GCASH JSRMULTU:.GC2 ASLP:ROLA:ASLP:ROLA:TAY:LDXP:RTS 6690.bay JMPBAY 6700.EQSHP JSRDIALS:LDA#32:JSRTT66:\JSRFLKB:LDA#12:STAXC:LDA#207:JSRspc:LDA#185:JSRNLIN3:LDA#128:STAQQ17:INCYC:LDAtek:CLC:ADC#3:CMP#12:BCCP%+4:LDA#12:STAQ:STAQQ25:INCQ:LDA#70:SEC:SBCQQ14:ASLA:STAPRXS 6710LDX#1:.EQL1 STXXX13:JSRTT67:LDXXX13:CLC:JSRpr2:JSRTT162:LDAXX13:CLC:ADC#&68:JSRTT27:LDAXX13:JSRprx-3:SEC:LDA#25:STAXC:LDA#6:JSRTT11:LDXXX13:INX:CPXQ:BCCEQL1 6720JSRCLYNS:LDA#127:JSRprq:JSRgnum:beqbay:bcsbay:SBC#0:LDX#2:STXXC:INCYC:PHA:JSReq:PLA:BNEet0:STAMCNT:LDX#70:STXQQ14:.et0 CMP#1:BNEet1:LDXNOMSL:INX:LDY#&75:CPX#5:BCSpres 6730STXNOMSL:JSRmsblob:.et1 LDY#&6B:CMP#2:BNEet2:LDX#37:CPXCRGO:BEQpres:STXCRGO:.et2 CMP#3:BNEet3:INY:LDXECM:BNEpres:DECECM:.et3 CMP#4:BNEet4:JSRqv:LDA#4:LDYLASER,X:BEQed4:.ed7 LDY#187:BNEpres:.ed4 LDA#POW:STALASER,X:LDA#4:.et4 6740CMP#5:BNEet5:JSRqv:STXT1:LDA#5:LDYLASER,X:BEQed5:\BPLP%+4:BMIed7:LDA#4:JSRprx:JSRMCASH:.ed5 LDA#POW+128:LDXT1:STALASER,X:.et5 6750LDY#&6F:CMP#6:BNEet6:LDXBST:BEQed9:.pres STYK:JSRprx:JSRMCASH:LDAK:JSRspc:LDA#31:JSRTT27:.err JSRdn2:JMPBAY:.ed9 DECBST:.et6 INY:CMP#7:BNEet7:LDXESCP:BNEpres:DECESCP:.et7 INY:CMP#8:BNEet8:LDXBOMB:BNEpres:LDX#&7F:STXBOMB:.et8 6800INY:CMP#9:BNEetA:LDXENGY:BNEpres:INCENGY:.etA INY:CMP#10:BNEetB:LDXDKCMP:BNEpres:DECDKCMP:.etB:INY:CMP#11:BNEet9:LDXGHYP:BNEpres:DECGHYP:.et9 JSRdn:JMPEQSHP:.dn JSRTT162:LDA#119:JSRspc:.dn2 JSRBEEP:LDY#50:JMPDELAY 6900.eq JSRprx:JSRLCASH:BCSc:LDA#197:JSRprq:JMPerr:SEC:SBC#1:.prx ASLA:TAY:LDXPRXS,Y:LDAPRXS+1,Y:TAY:.c RTS 6910.qv LDY#16:STYYC:.qv1 LDX#12:STXXC:TYA:CLC:ADC#B-16:JSRspc:LDAYC:CLC:ADC#&50:JSRTT27:INCYC:LDYYC:CPY#20:BCCqv1:.qv3 JSRCLYNS:.qv2 LDA#175:JSRprq:JSRTT217:SEC:SBC#&30:CMP#4:BCSqv3:TAX:RTS 9900] 9910IFZ>4OSCLI("S.ELTD "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9920PRINT"D d,";:GOTO10 ================================================ FILE: 1-source-files/original-sources/README.md ================================================ # Original source code for the BBC Micro cassette version of Elite This folder contains the original source code for the BBC Micro cassette version of Elite from Ian Bell's personal website. --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 1-source-files/original-sources/S.BCFS.inf ================================================ S.BCFS 000000 000000 000380 ================================================ FILE: 1-source-files/original-sources/S.BCFS.txt ================================================ 10REM Prepare the Big Code File 20 25REM ELTcode 30 35REM (a provisional name, ahem) 40 50MODE7 100C%=&F40:L%=&1128:D%=&563A:ZP=&70 110IF PAGE<>&6800:PAGE=&6800:CHAIN"S.BCFS" 120P%=&1100:[ .LBL EQUB&6C:LDX#&60:LDA#&B:STAZP+1:LDY#0:STYZP:TYA:INY:.CHK3 CLC:ADC(ZP),Y:INY:BNECHK3:INCZP+1:.CHK4 CLC:ADC(ZP),Y:INY:BPLCHK4:CMP&B00:BEQLBL+2:LDA#&7F:STA&FE4E:JMP(&FFFC) :] 320*L.ELTA 330*L.ELTB 340*L.ELTC 350*L.ELTD 360*L.ELTE 370*L.ELTF 380*L.ELTG 385OSCLI("L.SHIPS "+STR$~(D%+L%-C%)) 390A%=0:FORN%=L%TOL%+&45FF:A%=A%+?N%:NEXT:?(D%+L%-C%-1)=A% 395FORN%=0TO&6000-C%:L%?N%=(L%?N%)EOR(N%MOD256):NEXT 397A%=0:FORN%=&1100TO&1127:A%=A%+?N%:NEXT:PRINT"Checksum 1=";A% 450INPUT"Place Disk in default drive and"'" Press Return"A$ 500OSCLI("S.ELTcode 1100 "+STR$~(L%+&6000-C%)+" "+STR$~L%+" "+STR$~L%) ================================================ FILE: 1-source-files/original-sources/S.GENTOK.inf ================================================ $.GENTOKS 000000 000000 000B1F ================================================ FILE: 1-source-files/original-sources/S.GENTOK.txt ================================================ 10 REM Generate TOKENS file 20 words=OPENOUT"WORDS9" 30 ONERRORGOTO150 40 REPEATREADA$:FORN%=1TOLENA$:CH%=ASCMID$(A$,N%,1) 50 IFCH%=ASC"#"THENGOSUB100:ELSEbyte=CH% 60 BPUT#words,byte EOR35:NEXT:BPUT#words,0 70 UNTILFALSE 100 byte=VAL(MID$(A$,N%+1,3)):N%=N%+4:RETURN 150 IFERR=42THENCLOSE#words:END ELSE CLOSE#words:PRINT"Line "ERL:REPORT:END 160 DATA#111##017##007#," CH#138#T",GO#150#RNM#146#T,D#145#A#017##003#,#140##150#NT#153#Y#013#,SYS#156#M,P#158##133#,#002# #139#RKET #166#S,#140#D#136#T#158##128#,AG#158#CULTU#148#L 170 DATA#158#CH ,A#150##148##131# ,PO#153# ,#139##140#LY ,UNIT,VIEW ,#154##155##151#TY,#155##138#CHY,FEUD#128#,MUL#151#-#162# 180 DATA#141#CT#145##153##185#,#251#MUN#157#T,C#159#F#152##144#ACY,DEMOC#148#CY,C#153#P#153##145#E #203##145#E,SHIP,PRODUCT," #149#S#144#",HUM#155# COL#159#I#128#,"HYP#144#SPA#133# " 190 DATASH#153#T #202##161#,#141##203##155##133#,POPUL#145#I#159#,GROSS #186#IVITY,EC#159#OMY," LIGHT YE#138#S",#156#CH.#129##150#L,"CASH"," #134##118#I#159#",#122##161##001# 200 DATAT#138##131#T LO#203#,#106# JAMM#152#,R#155##131#,ST,"#176# OF ",SE#118#," C#138#GO#006#",E#154#IP,FOOD,#156#X#151#L#137# 210 DATA#148##141#OAC#151##150#S,S#149##150#S,LI#154##153#/W#140##137#,LUXU#158##137#,N#138#CO#151#CS,#251#PUT#144#S,#139#CH#140##144#Y,#117#OYS,FI#142##138#MS,FURS 220 DATAM#140##144##128#S,GOLD,PL#145##140#UM,#131#M-#203##159##137#,#128#I#146# #127#S,(Y/N)?," CR",L#138##131#,FI#144##133#,S#139##118# 230 DATAG#142##146#,R#152#,YE#118#OW,BLUE,B#149#CK,#022#,SLIMY,BUG-EY#152#,H#153#N#152#,B#159#Y 240 DATAF#145#,FURRY,ROD#146#T,FROG,LI#132#RD,LOB#203##144#,#134#RD,HUM#155#OID,FEL#140#E,#140#SECT 250 DATA#171##148##141##136#,COM,#251#M#155#D#144#," D#137#TROY#152#","#013##013# (C) D.B#148##147#N & I.#147##118# 1984" 260 DATA"#174# #176##013# #186# #174# #166# F#153# SA#129##013##010#",FR#159#T,#142##138#,#129#FT,#158#GHT,#121#LOW#007#,#099##017##252#!,EXT#148# ,PULSE#187#,"#147#AM#187#",FUEL 270 DATAM#157#SI#129#,#227##206# BAY,E.C.M.#165#,#102##103#S,#102##104#S,#105# SCOOPS,#137#CAPE POD,#121#BOMB,#121##174#,#124##140#G #215#,#122# #189#,A#118#,LL,"#197#:#000#",#140##251##140#G #106# 280 DATA"#146##144#GY ",GA#149#C#151#C,"#013##252#'S NAME? ",DOCK 290DATA#005##129#G#128# #203##145##136#:,"#252# #004##013##013##013##006##031# #165##009##002##013##189##165##009##003##013#C#159##141##151##159##009#",I#156#M 300DATA" LOAD NEW #252# #225##254#",#006##124##152#,#148##151#NG:," #159# ","#013##008##207#M#146#T:#006#",C#129##155#,OFF#146#D#144#,FUGI#151##150#,H#138#M#129#SS,MO#203#LY #022#,#172#,#171#,ABO#150# #171#,#251#PET#146#T 310DATAD#155##131#RO#136#,DEADLY,"---- E L I T E ----",P#142#S#146#T,"#008#GAME O#150#R","PR#137#S FI#142# #153# SPA#133#,#252#.#254#","AC#153#N#135#FT#013##013#" ================================================ FILE: 1-source-files/original-sources/S.STEST.inf ================================================ $.STEST 000000 000000 0012D3 ================================================ FILE: 1-source-files/original-sources/S.STEST.txt ================================================ 5REM Source Code for Loader 10C%=&F40:S%=C%:L%=&1128:D%=&563A:LC%=&6000-C%:svn=&7FFD 20MOS=S%+8:TRTB%=4 100DIM CODE &1000 1000OSWRCH=&FFEE:OSBYTE=&FFF4:OSWORD=&FFF1:SCLI=&FFF7:IRQ1V=&204 1010ZP=&70:P=&72:Q=&73:YY=&74:T=&75 1020FF=&FF 1030VIA=&FE40:USVIA=VIA:VSCAN=57:VEC=&7FFE 3000FORZ=4TO6STEP2 3010P%=&900:O%=CODE 3015RESTORE:READN% 3020B%=P%:FORI%=0TON%-1:READA:PROCP(A):NEXT 3100E%=P%:FORI%=1TO4:FORJ%=1TO14:READA:PROCP(A):NEXT, 4000[OPTZ 5000.ENTRY LDA#16:LDX#3:JSROSBYTE \ADC 5001LDA#190:LDX#8:JSROSB \8bitADC 5002LDA#200:LDX#3:JSROSB \break,escape 5004LDA#13:LDX#0:JSROSB \otput bffer 5005LDA#144:LDX#255:JSROSB \TV 5006LDA#225:LDX#128:JSROSB \fn keys 5007LDA#13:LDX#2:JSROSB \kybrd buffer 5008LDA#(B% MOD256):STAZP:LDA#(B% DIV256):STAZP+1:LDY#0:.LOOP LDA(ZP),Y:JSROSWRCH:INY:CPY#N%:BNELOOP \set up mode 5010LDA#4:LDX#1:JSROSB \cursor 5020LDA#9:LDX#0:JSROSB \flashing 5030LDA#172:LDX#0:LDY#FF:JSROSBYTE:STXTRTB%:STYTRTB%+1 \int-ascii table 5050JSRPLL1 5100EQUS FNE(0):EQUS FNE(1):EQUS FNE(2):EQUS FNE(3) \envelopes 5110LDX#(MESS2 MOD256):LDY#(MESS2 DIV256):JSRSCLI 5120LDX#(MESS3 MOD256):LDY#(MESS3 DIV256):JSRSCLI 5130LDX#(MESS4 MOD256):LDY#(MESS4 DIV256):JSRSCLI 5140LDX#(MESS5 MOD256):LDY#(MESS5 DIV256):JSRSCLI 5150LDX#(MESS6 MOD256):LDY#(MESS6 DIV256):JSRSCLI 5160LDX#(MESS7 MOD256):LDY#(MESS7 DIV256):JSRSCLI 5170LDX#(MESS8 MOD256):LDY#(MESS8 DIV256):JSRSCLI 5180LDX#(MESS9 MOD256):LDY#(MESS9 DIV256):JSRSCLI 5190LDX#(MESS10 MOD256):LDY#(MESS10 DIV256):JSRSCLI 5200LDX#(MESS11 MOD256):LDY#(MESS11 DIV256):JSRSCLI 5310LDA#140:LDX#12:JSROSBYTE 5320LDA#0:STAsvn 5350LDX#(LC% DIV256):LDA#(L% MOD256):STAZP:LDA#(L% DIV256):STAZP+1:LDA#(C% MOD256):STAP:LDA#(C% DIV256):STAP+1:LDY#0 5360.ML1 LDA(ZP),Y:STA(P),Y:INY:BNEML1:INCZP+1:INCP+1:DEX:BPLML1 5370LDAS%+6:STA&202:LDAS%+7:STA&203:LDAS%+2:STA&20E:LDAS%+3:STA&20F 5380.SETUP SEI:LDAVIA+4:STA1:LDA#&39:STAVIA+&E:LDA#&7F:STA&FE6E:LDAIRQ1V:STAVEC:LDAIRQ1V+1:STAVEC+1:LDAS%+4:STAIRQ1V:LDAS%+5:STAIRQ1V+1:LDA#VSCAN:STAUSVIA+5:CLI 5385LDA#&81:LDY#FF:LDX#1:JSROSBYTE:TXA:EOR#FF:STAMOS \FF if MOS0.1 else 0 5390JMP(S%) 5400.PLL1 LDAVIA+4:STARAND+1:JSRDORND:JSRSQUA2:STAZP+1:LDAP:STAZP:JSRDORND:STAYY:JSRSQUA2:TAX:LDAP:ADCZP:STAZP:TXA:ADCZP+1:BCSPLC1 5410STAZP+1:LDA#1:SBCZP:STAZP:LDA#&40:SBCZP+1:STAZP+1:BCCPLC1:JSRROOT:LDAZP:LSRA:TAX:LDAYY:CMP#128:RORA:JSRPIX 5420.PLC1 DECCNT:BNEPLL1:DECCNT+1:BNEPLL1 5450.PLL2 JSRDORND:TAX:JSRSQUA2:STAZP+1:JSRDORND:STAYY:JSRSQUA2:ADCZP+1:CMP#&11:BCCPLC2:LDAYY:JSRPIX 5460.PLC2 DECCNT2:BNEPLL2:DECCNT2+1:BNEPLL2 5500.PLL3 JSRDORND:STAZP:JSRSQUA2:STAZP+1:JSRDORND:STAYY:JSRSQUA2:STAT 5510ADCZP+1:STAZP+1:LDAZP:CMP#128:RORA:CMP#128:RORA:ADCYY:TAX:JSRSQUA2:TAY:ADCZP+1 5520BCSPLC3:CMP#&50:BCSPLC3:CMP#&20:BCCPLC3:TYA:ADCT:CMP#&10:BCSPL1:LDAZP:BPLPLC3:.PL1 LDAYY:JSRPIX 5550.PLC3 DECCNT3:BNEPLL3:DECCNT3+1:BNEPLL3 5800.DORND LDARAND+1:TAX:ADCRAND+3:STARAND+1:STXRAND+3:LDARAND:TAX:ADCRAND+2:STARAND:STXRAND+2:RTS 5810.RAND EQUD &34785349 5815.SQUA2 BPLSQUA:EOR#FF:CLC:ADC#1 5820.SQUA STAQ:STAP:LDA#0:LDY#8:LSRP:.SQL1 BCCSQ1:CLC:ADCQ:.SQ1 RORA:RORP:DEY:BNESQL1:RTS 5850.PIX TAY:EOR#128:LSRA:LSRA:LSRA:ORA#&60:STAZP+1:TXA:EOR#128:AND#&F8:STAZP:TYA:AND#7:TAY:TXA:AND#7:TAX 5860LDATWOS,X:STA(ZP),Y:RTS 5870.TWOS EQUD &10204080:EQUD&01020408 5880.CNT EQUW&300:.CNT2 EQUW &1DD:.CNT3 EQUW &333 5890.ROOT LDYZP+1:LDAZP:STAQ:LDX#0:STXZP:LDA#8:STAP:.LL6 CPXZP:BCCLL7:BNELL8:CPY#&40:BCCLL7:.LL8 TYA:SBC#&40:TAY:TXA:SBCZP:TAX:.LL7 ROLZP:ASLQ:TYA:ROLA:TAY:TXA:ROLA:TAX:ASLQ:TYA:ROLA:TAY:TXA:ROLA:TAX:DECP:BNELL6:RTS 5900.OSB LDY#0:JMPOSBYTE 6010.MESS2 EQUS("L.ELTA"):EQUB13 6020.MESS3 EQUS("L.ELTB"):EQUB13 6030.MESS4 EQUS("L.ELTC"):EQUB13 6040.MESS5 EQUS("L.ELTD"):EQUB13 6050.MESS6 EQUS("L.ELTE"):EQUB13 6060.MESS7 EQUS("L.ELTF"):EQUB13 6070.MESS8 EQUS("L.ELTG"):EQUB13 6100.MESS9 EQUS("L.SHIPS "+STR$~(D%+L%-C%)):EQUB13 6110.MESS10 EQUS("L.WORDS9"):EQUB13 6120.MESS11 EQUS("L.DIALSHP"):EQUB13 7000] 7020NEXTZ 7100PRINT~CODE O% P% ENTRY 7110INPUT"Insert assembly disk and hit RETURN"A$ 7120OSCLI("S.MCTEST "+STR$~CODE +" "+STR$~O% +" "+STR$~ENTRY +" 900") 7200END 8000DATA67 8100DATA 22,4,28,2,17,15,16 8110DATA 23,0, 6,31,0,0,0,0,0,0 8112DATA 23,0,12,12,0,0,0,0,0,0 8114DATA 23,0,13, 0,0,0,0,0,0,0 8116DATA 23,0, 1,32,0,0,0,0,0,0 8118DATA 23,0, 2,45,0,0,0,0,0,0 8120DATA 23,0,10,32,0,0,0,0,0,0 9100DATA1,1,0,111,-8,4,1,8, 8,-2,0,-1,126,44 9110DATA2,1,14,-18,-1,44,32,50, 6,1,0,-2,120,126 9120DATA3,1,1,-1,-3,17,32,128,1,0,0,-1,1,1 9130DATA4,1,4,-8,44,4,6,8,22,0,0,-127,126,0 10000DEFPROCP(A):?O%=A:O%=O%+1:P%=P%+1:ENDPROC 10100DEF FNE(I%) 10110[OPTZ 10120LDX#((E%+I%*14)MOD256):LDY#((E%+I%*14)DIV256):LDA#8:JSROSWORD 10130] 10140="" ================================================ FILE: 1-source-files/original-sources/text-sources/ELITEA.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 5GOTO120 20REM ELITE 30MODE7:VDU28,0,23,39,19 40LOMEM=&3D70 100C%=&F40:W%=&7200:L%=&1128:HIMEM=W%:Z=0 120D%=&563A:WP=&D40:K%=&900:LS%=WP-1:QQ18=&400:T%=&300 220NOST=18:NOSH=12:COPS=2:SH3=COPS:CYL=7:THG=6:SST=8:MSL=9:AST=10:OIL=11:TGL=12:ESC=13:NI%=36:POW=15:B=&30 1000FF=&FF:OSWRCH=&FFEE:OSBYTE=&FFF4:OSWORD=&FFF1:OSFILE=&FFDD:SCLI=&FFF7:VIA=&FE40:USVIA=VIA:IRQ1V=&204:VSCAN=57:XX21=D% 1020ZP=0:X=128:Y=96:RAND=FNZT(4):TRTB%=FNZ2:T1=FNZ:SC=FNZ2:SCH=SC+1:XX16=FNZT(18):P=FNZT(3) 1060XX0=FNZ2:INF=FNZ2:V=FNZ2:XX=FNZ2:YY=FNZ2:SUNX=FNZ2:BETA=FNZ:BET1=FNZ:XC=FNZ:YC=FNZ:QQ22=FNZ2:ECMA=FNZ 1120XX15=FNZT(6):XX12=FNZT(6):X1=XX15:Y1=X1+1:X2=Y1+1:Y2=X2+1:K=FNZT(4) 1125KL=FNZT(16):LAS=FNZ:MSTG=FNZ 1126f0=&20:f1=&71:f2=&72:f3=&73:f4=&14:f5=&74:f6=&75:f7=&16:f8=&76:f9=&77 1128KY1=KL+1:KY2=KL+2:KY3=KL+3:KY4=KL+4:KY5=KL+5:KY6=KL+6:KY7=KL+7:KY12=KL+8:KY13=KL+9:KY14=KL+10:KY15=KL+11:KY16=KL+12:KY17=KL+13:KY18=KL+14:KY19=KL+15 1130INWK=FNZT(NI%):XX19=INWK+33:XX1=INWK:LSP=FNZ:QQ15=FNZT(6):XX18=FNZT(9):QQ17=XX18:QQ19=QQ17+1:K5=XX18:K6=K5+4:ALP1=FNZ:ALP2=FNZ2 1150BET2=FNZ2:DELTA=FNZ:DELT4=FNZ2:U=FNZ:Q=FNZ:R=FNZ:S=FNZ:XSAV=FNZ:YSAV=FNZ:XX17=FNZ 1160QQ11=FNZ:ZZ=FNZ:XX13=FNZ:MCNT=FNZ:DL=FNZ:TYPE=FNZ:JSTX=FNZ:JSTY=FNZ:ALPHA=FNZ 1195QQ12=FNZ:TGT=FNZ:SWAP=FNZ:COL=FNZ:FLAG=FNZ:CNT=FNZ:CNT2=FNZ:STP=FNZ:XX4=FNZ:XX20=FNZ:XX14=FNZ:RAT=FNZ:RAT2=FNZ:K2=FNZT(4) 1400P%=C%:O%=W%:H%=L%+P%-C% 1410IFZ=4THENZ=6ELSEZ=4 1450FRIN=FNWT(NOSH+1):MANY=FNWT(14):SSPR=MANY+SST 1460ECMP=FNW:MJ=FNW:CABTMP=MANY:LAS2=FNW:MSAR=FNW:VIEW=FNW:LASCT=FNW:GNTMP=FNW:HFX=FNW:EV=FNW:DLY=FNW 1465de=FNW:T=&D1:XX2=&D2:K3=XX2:K4=K3+14:REM16 1470LSO=FNWT(192):LSX=LSO:LSX2=FNWT(78):LSY2=FNWT(78):SY=FNWT(NOST+1):SYL=FNWT(NOST+1):SZ=FNWT(NOST+1):SZL=FNWT(NOST+1) 1480XSAV2=FNW:YSAV2=FNW 1500TP=FNTP:QQ0=FNTP:QQ1=FNTP:QQ21=FNTPT(6):CASH=FNTPT(4):QQ14=FNTP:COK=FNTP:GCNT=FNTP:LASER=FNTPT(6):CRGO=FNTP:QQ20=FNTPT(17):ECM=FNTP:BST=FNTP:BOMB=FNTP:ENGY=FNTP:DKCMP=FNTP:GHYP=FNTP:ESCP=FNTPT(5) 1520NOMSL=FNTP:FIST=FNTP:AVL=FNTPT(17):QQ26=FNTP:TALLY=FNTPT(2):SVC=FNTPT(3):NT%=SVC+2-TP:MCH=FNW 1600SX=T%:SXL=SX+NOST+1:XX3=256:REM&70 1628FSH=FNW:ASH=FNW:ENERGY=FNW:REMFF 1630LASX=FNW:LASY=FNW:COMX=FNW:COMY=FNW:QQ24=FNW:QQ25=FNW:QQ28=FNW:QQ29=FNW:gov=FNW:tek=FNW:SLSP=FNW2:XX24=FNW:ALTIT=FNW:VEC=&7FFE:svn=&7FFD 1650QQ2=FNWT(6):QQ3=FNW:QQ4=FNW:QQ5=FNW:QQ6=FNW2:QQ7=FNW2:QQ8=FNW2:QQ9=FNW:QQ10=FNW:NOSTM=FNW 1800[OPTZ:.S% EQUWTT170:EQUWTT26:EQUWIRQ1:EQUWBR1 1830.COMC brk:.DNOIZ brk:.DAMP brk:.DJD brk:.PATG brk:.FLH brk:.JSTGY brk:.JSTE brk:.JSTK brk 4000.M% LDAK%:STARAND 4020LDXJSTX:JSRcntr:JSRcntr:TXA:EOR#128:TAY:AND#128:STAALP2:STXJSTX:EOR#128:STAALP2+1:TYA:BPLP%+7:EOR#FF:CLC:ADC#1:LSRA:LSRA:CMP#8:BCSP%+4:LSRA:CLC:STAALP1:ORAALP2:STAALPHA 4030LDXJSTY:JSRcntr:TXA:EOR#128:TAY:AND#128:STXJSTY:STABET2+1:EOR#128:STABET2:TYA:BPLP%+4:EOR#FF:ADC#4:LSRA:LSRA:LSRA:LSRA:CMP#3:BCSP%+3:LSRA:STABET1:ORABET2:STABETA 4050LDAKY2:BEQMA17:LDADELTA:CMP#40:BCSMA17:INCDELTA:.MA17 LDAKY1:BEQMA4:DECDELTA:BNEMA4:INCDELTA:.MA4 4060LDAKY15:ANDNOMSL:BEQMA20:LDY#&EE:JSRABORT:LDA#40:JSRNOISE:.MA31 LDA#0:STAMSAR:.MA20 LDAMSTG:BPLMA25:LDAKY14:BEQMA25:LDXNOMSL:BEQMA25:STAMSAR:LDY#&E0:JSRMSBAR:.MA25 4064LDAKY16:BEQMA24:LDAMSTG:BMIMA64:JSRFRMIS:.MA24 LDAKY12:BEQMA76:ASLBOMB:.MA76 4070LDAKY13:ANDESCP:BEQP%+5:JMPESCAPE:LDAKY18:BEQP%+5:JSRWARP:LDAKY17:ANDECM:BEQMA64:LDAECMA:BNEMA64:DECECMP:JSRECBLB2:.MA64 4075LDAKY19:ANDDKCMP:ANDSSPR:BEQMA68:LDAK%+NI%+32:BMIMA68:JMPGOIN:.MA68 4080LDA#0:STALAS:STADELT4:LDADELTA:LSRA:RORDELT4:LSRA:RORDELT4:STADELT4+1 4090LDALASCT:BNEMA3:LDAKY7:BEQMA3:LDAGNTMP:CMP#242:BCSMA3:LDXVIEW:LDALASER,X:BEQMA3:PHA:AND#127:STALAS:STALAS2:LDA#0:JSRNOISE:JSRLASLI:PLA:BPLma1:LDA#0:.ma1 AND#&FA:STALASCT:.MA3 4100LDX#0:.MAL1 4105STXXSAV:LDAFRIN,X:BNEP%+5:JMPMA18:STATYPE:JSRGINF 4110LDY#(NI%-1):.MAL2 LDA(INF),Y:STAINWK,Y:DEY:BPLMAL2:LDATYPE:BMIMA21:ASLA:TAY:LDAXX21-2,Y:STAXX0:LDAXX21-1,Y:STAXX0+1 4115LDABOMB:BPLMA21:CPY#2*SST:BEQMA21:LDAINWK+31:AND#32:BNEMA21:LDAINWK+31:ORA#128:STAINWK+31:JSREXNO2 4130.MA21 JSRMVEIT:LDY#(NI%-1):.MAL3 LDAINWK,Y:STA(INF),Y:DEY:BPLMAL3 4134LDAINWK+31:AND#&A0:JSRMAS4:BNEMA65:LDAINWK:ORAINWK+3:ORAINWK+6:BMIMA65:LDXTYPE:BMIMA65:CPX#SST:BEQISDK:AND#&C0:BNEMA65:CPX#MSL:BEQMA65 4138CPX#OIL:BCSP%+5:JMPMA58:LDABST:ANDINWK+5:BPLMA58:LDA#3:CPX#TGL:BCCoily:BNEslvy2:LDA#16:BNEslvy2 4140.oily JSRDORND:AND#7:.slvy2 STAQQ29:LDA#1:JSRtnpr:LDY#78:BCSMA59:LDYQQ29:ADCQQ20,Y:STAQQ20,Y:TYA:ADC#208:JSRMESS 4141JMPMA60:.MA65 JMPMA26 4142.ISDK LDAK%+NI%+32:BMIMA62:LDAINWK+14:CMP#&D6:BCCMA62:JSRSPS4:LDAXX15+2:BMIMA62:CMP#89:BCCMA62:LDAINWK+16:AND#&7F:CMP#80:BCCMA62:.GOIN LDA#0:STAQQ22+1:LDA#8:JSRLAUN:JSRRES4:JMPBAY:.MA62 LDADELTA:CMP#5:BCCMA67:JMPDEATH 4143.MA59 JSREXNO3:.MA60 ASLINWK+31:SEC:RORINWK+31:.MA61 BNEMA26 4144.MA67 LDA#1:STADELTA:LDA#5:BNEMA63:.MA58 ASLINWK+31:SEC:RORINWK+31:LDAINWK+35:SEC:RORA:.MA63 JSROOPS:JSREXNO3:.MA26 4146LDAQQ11:BNEMA15:JSRPLUT 4150JSRHITCH:BCCMA8:LDAMSAR:BEQMA47:JSRBEEP:LDXXSAV:LDY#&E:JSRABORT2:.MA47 LDALAS:BEQMA8:LDX#15:JSREXNO:LDAINWK+35:SEC:SBCLAS:BCSMA14 4155LDATYPE:CMP#SST:BEQMA14+2:LDAINWK+31:ORA#128:STAINWK+31:BCSMA8:JSRDORND:BPLoh:LDY#0:AND(XX0),Y:STACNT:.um BEQoh:LDX#OIL:LDA#0:JSRSFS1:DECCNT:BPLum:.oh JSREXNO2 4160.MA14 STAINWK+35:LDATYPE:JSRANGRY:.MA8 4180JSRLL9:.MA15 LDY#35:LDAINWK+35:STA(INF),Y 4190LDAINWK+31:BPLMAC1:AND#&20:BEQNBOUN:LDATYPE:CMP#COPS:BNEq2:LDAFIST:ORA#64:STAFIST:.q2 LDADLY:ORAMJ:BNEKS1S:LDY#10:LDA(XX0),Y:BEQKS1S:TAX:INY:LDA(XX0),Y:TAY:JSRMCASH:LDA#0:JSRMESS:.KS1S JMPKS1:.NBOUN 4240.MAC1 LDATYPE:BMIMA27:JSRFAROF:BCCKS1S:.MA27 LDY#31:LDAINWK+31:STA(INF),Y:LDXXSAV:INX:JMPMAL1:.MA18 LDABOMB:BPLMA77:ASLBOMB:JSRWSCAN:LDA#&30:STA&FE21:.MA77 4250LDAMCNT:AND#7:BNEMA22:LDXENERGY:BPLb:LDXASH:JSRSHD:STXASH:LDXFSH:JSRSHD:STXFSH:.b SEC:LDAENGY:ADCENERGY:BCSP%+5:STAENERGY 4260LDAMJ:BNEMA23S:LDAMCNT:AND#31:BNEMA93:LDASSPR:BNEMA23S:TAY:JSRMAS2:BNEMA23S 4270LDX#28:.MAL4 LDAK%,X:STAINWK,X:DEX:BPLMAL4:INX:LDY#9:JSRMAS1:BNEMA23S:LDX#3:LDY#11:JSRMAS1:BNEMA23S:LDX#6:LDY#13:JSRMAS1:BNEMA23S 4280LDA#&C0:JSRFAROF2:BCCMA23S 4290LDAQQ11:BNEP%+5\!:JSRWPLS:JSRNWSPS:.MA23S JMPMA23 4300.MA22 LDAMJ:BNEMA23:LDAMCNT:AND#31:.MA93 CMP#10:BNEMA29:LDA#50:CMPENERGY:BCCP%+6:ASLA:JSRMESS:LDY#FF:STYALTIT:INY:JSRm:BNEMA23:JSRMAS3:BCSMA23:SBC#&24:BCCMA28:STAR:JSRLL5:LDAQ:STAALTIT:BNEMA23:.MA28 JMPDEATH 4310.MA29 CMP#20:BNEMA23:LDA#30:STACABTMP:LDASSPR:BNEMA23:LDY#NI%:JSRMAS2:BNEMA23:JSRMAS3:EOR#FF:ADC#30:STACABTMP:BCSMA28 4320CMP#&E0:BCCMA23:LDABST:BEQMA23:LDADELT4+1:LSRA:ADCQQ14:CMP#70:BCCP%+4:LDA#70:STAQQ14:LDA#160:JSRMESS 4350.MA23 LDALAS2:BEQMA16:LDALASCT:CMP#8:BCSMA16:JSRLASLI2:LDA#0:STALAS2:.MA16 4360LDAECMP:BEQMA69:JSRDENGY:BEQMA70:.MA69 LDAECMA:BEQMA66:DECECMA:BNEMA66:.MA70 JSRECMOF:.MA66 4380LDAQQ11:BNEMA9:JMPSTARS 4900.MAS1 LDAINWK,Y:ASLA:STAK+1:LDAINWK+1,Y:ROLA:STAK+2:LDA#0:RORA:STAK+3:JSRMVT3:STAINWK+2,X:LDYK+1:STYINWK,X:LDYK+2:STYINWK+1,X:AND#127:.MA9 RTS:.m LDA#0:.MAS2 ORAK%+2,Y:ORAK%+5,Y:ORAK%+8,Y:AND#127:RTS 4940.MAS3 LDAK%+1,Y:JSRSQUA2:STAR:LDAK%+4,Y:JSRSQUA2:ADCR:BCSMA30:STAR:LDAK%+7,Y:JSRSQUA2:ADCR:BCCP%+4:.MA30 LDA#FF:RTS 7000.MVEIT LDAINWK+31:AND#&A0:BNEMV30 7011LDAMCNT:EORXSAV:AND#15:BNEMV3:JSRTIDY:.MV3 LDXTYPE:BPLP%+5:JMPMV40:LDAINWK+32:BPLMV30:CPX#MSL:BEQMV26 7014LDAMCNT:EORXSAV:AND#7:BNEMV30:.MV26 JSRTACTICS:.MV30 JSRSCAN 7020LDAINWK+27:ASLA:ASLA:STAQ:LDAINWK+10:AND#127:JSRFMLTU:STAR:LDAINWK+10:LDX#0:JSRMVT1-2 7025LDAINWK+12:AND#127:JSRFMLTU:STAR:LDAINWK+12:LDX#3:JSRMVT1-2:LDAINWK+14:AND#127:JSRFMLTU:STAR:LDAINWK+14:LDX#6:JSRMVT1-2 7030LDAINWK+27:CLC:ADCINWK+28:BPLP%+4:LDA#0:LDY#15:CMP(XX0),Y:BCCP%+4:LDA(XX0),Y:STAINWK+27 7032LDA#0:STAINWK+28 7040LDXALP1:LDAINWK:EOR#FF:STAP:LDAINWK+1:JSRMLTU2-2:STAP+2:LDAALP2+1:EORINWK+2:LDX#3:JSRMVT6 7045STAK2+3:LDAP+1:STAK2+1:EOR#FF:STAP:LDAP+2:STAK2+2\K2=Y-aX 7050LDXBET1:JSRMLTU2-2:STAP+2:LDAK2+3:EORBET2:LDX#6:JSRMVT6:STAINWK+8:LDAP+1:STAINWK+6:EOR#FF:STAP:LDAP+2:STAINWK+7\Z=Z+bK2 7060JSRMLTU2:STAP+2:LDAK2+3:STAINWK+5:EORBET2:EORINWK+8:BPLMV43:LDAP+1:ADCK2+1:STAINWK+3:LDAP+2:ADCK2+2:STAINWK+4:JMPMV44:.MV43 7070LDAK2+1:SBCP+1:STAINWK+3:LDAK2+2:SBCP+2:STAINWK+4:BCSMV44:LDA#1:SBCINWK+3:STAINWK+3:LDA#0:SBCINWK+4:STAINWK+4:LDAINWK+5:EOR#128:STAINWK+5 7080.MV44\Y=K2-bZ:LDXALP1:LDAINWK+3:EOR#FF:STAP:LDAINWK+4:JSRMLTU2-2:STAP+2:LDAALP2:EORINWK+5:LDX#0:JSRMVT6:STAINWK+2:LDAP+2:STAINWK+1:LDAP+1:STAINWK\X=X+aY 7110.MV45 LDADELTA:STAR:LDA#128:LDX#6:JSRMVT1:LDATYPE:AND#&81:CMP#&81:BNEP%+3:RTS \Z=Z-d 7120LDY#9:JSRMVS4:LDY#15:JSRMVS4:LDY#21:JSRMVS4:LDAINWK+30:AND#128:STARAT2:LDAINWK+30:AND#127:BEQMV8:CMP#127:SBC#0:ORARAT2:STAINWK+30 7130LDX#15:LDY#9:JSRMVS5:LDX#17:LDY#11:JSRMVS5:LDX#19:LDY#13:JSRMVS5 7160.MV8 LDAINWK+29:AND#128:STARAT2:LDAINWK+29:AND#127:BEQMV5:CMP#127:SBC#0:ORARAT2:STAINWK+29 7170LDX#15:LDY#21:JSRMVS5:LDX#17:LDY#23:JSRMVS5:LDX#19:LDY#25:JSRMVS5 7210.MV5 LDAINWK+31:AND#&A0:BNEMVD1:LDAINWK+31:ORA#16:STAINWK+31:JMPSCAN:.MVD1 LDAINWK+31:AND#&EF:STAINWK+31:RTS 7300AND#128:.MVT1 ASLA:STAS:LDA#0:RORA:STAT:LSRS:EORINWK+2,X:BMIMV10:LDAR:ADCINWK,X:STAINWK,X:LDAS:ADCINWK+1,X:STAINWK+1,X:LDAINWK+2,X:ADC#0:ORAT:STAINWK+2,X:RTS 7310.MV10 LDAINWK,X:SEC:SBCR:STAINWK,X:LDAINWK+1,X:SBCS:STAINWK+1,X:LDAINWK+2,X:AND#127:SBC#0:ORA#128:EORT:STAINWK+2,X:BCSMV11 7320LDA#1:SBCINWK,X:STAINWK,X:LDA#0:SBCINWK+1,X:STAINWK+1,X:LDA#0:SBCINWK+2,X:AND#127:ORAT:STAINWK+2,X:.MV11 RTS 7400.MVT3 LDAK+3:STAS:AND#128:STAT:EORINWK+2,X:BMIMV13:LDAK+1:CLC:ADCINWK,X:STAK+1:LDAK+2:ADCINWK+1,X:STAK+2:LDAK+3:ADCINWK+2,X:AND#127:ORAT:STAK+3:RTS 7410.MV13 LDAS:AND#127:STAS:LDAINWK,X:SEC:SBCK+1:STAK+1:LDAINWK+1,X:SBCK+2:STAK+2:LDAINWK+2,X:AND#127:SBCS:ORA#128:EORT:STAK+3:BCSMV14 7420LDA#1:SBCK+1:STAK+1:LDA#0:SBCK+2:STAK+2:LDA#0:SBCK+3:AND#127:ORAT:STAK+3:.MV14 RTS 7500.MVS4 LDAALPHA:STAQ:LDXINWK+2,Y:STXR:LDXINWK+3,Y:STXS:LDXINWK,Y:STXP:LDAINWK+1,Y:EOR#128:JSRMAD:STAINWK+3,Y:STXINWK+2,Y:STXP \Y=Y-aX 7520LDXINWK,Y:STXR:LDXINWK+1,Y:STXS:LDAINWK+3,Y:JSRMAD:STAINWK+1,Y:STXINWK,Y:STXP \X=X+aY 7530LDABETA:STAQ:LDXINWK+2,Y:STXR:LDXINWK+3,Y:STXS:LDXINWK+4,Y:STXP:LDAINWK+5,Y:EOR#128:JSRMAD:STAINWK+3,Y:STXINWK+2,Y:STXP\Y=Y-bZ 7540LDXINWK+4,Y:STXR:LDXINWK+5,Y:STXS:LDAINWK+3,Y:JSRMAD:STAINWK+5,Y:STXINWK+4,Y:RTS\Z=Z+bY 7600.MVS5 LDAINWK+1,X:AND#127:LSRA:STAT:LDAINWK,X:SEC:SBCT:STAR:LDAINWK+1,X:SBC#0:STAS:LDAINWK,Y:STAP:LDAINWK+1,Y:AND#128:STAT:LDAINWK+1,Y:AND#127:LSRA:RORP:LSRA:RORP:LSRA:RORP:LSRA:RORP:ORAT:EORRAT2:STXQ:JSRADD:STAK+1:STXK 7610LDXQ:LDAINWK+1,Y:AND#127:LSRA:STAT:LDAINWK,Y:SEC:SBCT:STAR:LDAINWK+1,Y:SBC#0:STAS:LDAINWK,X:STAP:LDAINWK+1,X:AND#128:STAT:LDAINWK+1,X:AND#127:LSRA:RORP:LSRA:RORP:LSRA:RORP:LSRA:RORP:ORAT:EOR#128:EORRAT2 7620STXQ:JSRADD:STAINWK+1,Y:STXINWK,Y:LDXQ:LDAK:STAINWK,X:LDAK+1:STAINWK+1,X:RTS 7650.MVT6 TAY:EORINWK+2,X:BMIMV50:LDAP+1:CLC:ADCINWK,X:STAP+1:LDAP+2:ADCINWK+1,X:STAP+2:TYA:RTS 7660.MV50 LDAINWK,X:SEC:SBCP+1:STAP+1:LDAINWK+1,X:SBCP+2:STAP+2:BCCMV51:TYA:EOR#128:RTS:.MV51 LDA#1:SBCP+1:STAP+1:LDA#0:SBCP+2:STAP+2:TYA:RTS 7700.MV40 LDAALPHA:EOR#128:STAQ:LDAINWK:STAP:LDAINWK+1:STAP+1:LDAINWK+2:JSRMULT3:LDX#3:JSRMVT3\K=Y-aX 7710LDAK+1:STAK2+1:STAP:LDAK+2:STAK2+2:STAP+1:LDABETA:STAQ:LDAK+3:STAK2+3:JSRMULT3:LDX#6:JSRMVT3:LDAK+1:STAP:STAINWK+6:LDAK+2:STAP+1:STAINWK+7:LDAK+3:STAINWK+8\Z=Z+bK2 7720EOR#128:JSRMULT3:LDAK+3:AND#128:STAT:EORK2+3:BMIMV1 7730LDAK:\CLC:ADCK2:LDAK+1:ADCK2+1:STAINWK+3:LDAK+2:ADCK2+2:STAINWK+4:LDAK+3:ADCK2+3:JMPMV2 7740.MV1 LDAK:SEC:SBCK2:LDAK+1:SBCK2+1:STAINWK+3:LDAK+2:SBCK2+2:STAINWK+4:LDAK2+3:AND#127:STAP:LDAK+3:AND#127:SBCP:STAP:BCSMV2 7750LDA#1:SBCINWK+3:STAINWK+3:LDA#0:SBCINWK+4:STAINWK+4:LDA#0:SBCP:ORA#128:.MV2 EORT:STAINWK+5\Y=K2-bZ 7760LDAALPHA:STAQ:LDAINWK+3:STAP:LDAINWK+4:STAP+1:LDAINWK+5:JSRMULT3:LDX#0:JSRMVT3:LDAK+1:STAINWK:LDAK+2:STAINWK+1:LDAK+3:STAINWK+2\X=X+aY 7770JMPMV45:] 9510IFZ>4OSCLI"S.ELTA "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H% 9520PRINT"A d,";:GOTO2 10100DEFFNZ=FNZT(1) 10110DEFFNZ2=FNZT(2) 10120DEFFNZT(N%):ZP=ZP+N%:=ZP-N% 10300DEFFNW=FNWT(1) 10310DEFFNW2=FNWT(2) 10320DEFFNWT(N%):WP=WP+N%:=WP-N% 10400DEFFNTP=FNTPT(1) 10410DEFFNTPT(N%):T%=T%+N%:=T%-N% ================================================ FILE: 1-source-files/original-sources/text-sources/ELITEB.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 20REM ELITE 1000O%=W%:H%=L%+P%-C%:Q%=FALSE 1010J%=O%:[OPTZ 1100.NA% EQUS("JAMESON"):EQUB13:EQUB0 1110EQUB20\QQ0:EQUB173\QQ1:EQUD&2485A4A\QQ21:EQUW&B753 \Base seed 1120EQUD(((&E8030000)AND(NOTQ%))+((&CA9A3B)ANDQ%))\CASH,&80969800 1130EQUB70 fuel 1135EQUB 0 COK-UP 1137EQUB0 GALACTIC COUNT 1140EQUBPOW+(128ANDQ%):EQUB(POW+128)ANDQ%:EQUB0:EQUB0:EQUW0 LASER:EQUB22+(15ANDQ%) \37 CRGO 1150EQUD0:EQUD0:EQUD0:EQUD0:EQUB0\crgo 1160EQUB Q% ECM 1170EQUB Q% BST 1180EQUB Q%AND127 BOMB 1190EQUB Q%AND1 ENGY++ 1200EQUB Q% DCK COMP 1203EQUB Q% GHYP 1205EQUB Q% ESCP 1207EQUD FALSE EXPAND 1210EQUB 3+(Q%AND1) MISSILES 1220EQUB FALSE FIST 1222EQUB16:EQUB15:EQUB17:EQUB0:EQUB3:EQUB28:EQUB14:EQUW0:EQUB10:EQUB0:EQUB17:EQUB58:EQUB7:EQUB9:EQUB8:EQUB0 1224EQUB 0 QQ26 1230EQUW 0 TALLY 1240EQUB 128 SVC 1245]CH%=NT%-2:CY%=0:FORI%=CH%+J%TO1+J%STEP-1:CH%=CH%+CY%+(I%?7):CY%=(CH%>255)AND1:CH%=CH%MOD256:CH%=CH%EOR(I%?8):NEXT:[OPTZ 1247.CHK2 EQUB CH% EOR&A9 1250.CHK EQUB CH% 1300.UNIV:]FORI%=0TO12:!O%=K%+I%*NI%:O%=O%+2:P%=P%+2:NEXT:[OPTZ 1800.TWOS EQUD&10204080:EQUD&01020408:.TWOS2 EQUD&183060C0:EQUD&0303060C:.CTWOS EQUD&11224488:EQUB&88 2000.LL30:.LOIN STYYSAV 2020LDA#128:STAS:ASLA:STASWAP:LDAX2:SBCX1:BCSLI1:EOR#FF:ADC#1:SEC:.LI1 STAP 2030LDAY2:SBCY1:BCSLI2:EOR#FF:ADC#1:.LI2 STAQ:CMPP:BCCSTPX:JMPSTPY 2040.STPX LDXX1:CPXX2:BCCLI3:DECSWAP:LDAX2:STAX1:STXX2:TAX:LDAY2:LDYY1:STAY1:STYY2:.LI3 2050LDAY1:LSRA:LSRA:LSRA:ORA#&60:STASCH:LDAY1:AND#7:TAY:TXA:AND#&F8:STASC 2060TXA:AND#7:TAX:LDATWOS,X:STAR 2064LDAQ:LDX#254:STXQ:.LIL1 ASLA:BCSLI4:CMPP:BCCLI5:.LI4 SBCP:SEC:.LI5 ROLQ:BCSLIL1 2070LDXP:INX:LDAY2:SBCY1:BCSDOWN 2080LDASWAP:BNELI6:DEX:.LIL2 LDAR:EOR(SC),Y:STA(SC),Y 2090.LI6 LSRR:BCCLI7:RORR:LDASC:ADC#8:STASC 2100.LI7 LDAS:ADCQ:STAS:BCCLIC2:DEY:BPLLIC2:DECSCH:LDY#7 2110.LIC2 DEX:BNELIL2:LDYYSAV:RTS 2150.DOWN LDASWAP:BEQLI9:DEX:.LIL3 LDAR:EOR(SC),Y:STA(SC),Y 2160.LI9 LSRR:BCCLI10:RORR:LDASC:ADC#8:STASC 2170.LI10 LDAS:ADCQ:STAS:BCCLIC3:INY:CPY#8:BNELIC3:INCSCH:LDY#0 2180.LIC3 DEX:BNELIL3:LDYYSAV:RTS 2200.STPY LDYY1:TYA:LDXX1:CPYY2:BCSLI15:DECSWAP:LDAX2:STAX1:STXX2:TAX:LDAY2:STAY1:STYY2:TAY 2210.LI15 LSRA:LSRA:LSRA:ORA#&60:STASCH:TXA:AND#&F8:STASC 2214TXA:AND#7:TAX:LDATWOS,X:STAR:LDAY1:AND#7:TAY 2220LDAP:LDX#1:STXP:.LIL4 ASLA:BCSLI13:CMPQ:BCCLI14:.LI13 SBCQ:SEC:.LI14 ROLP:BCCLIL4:LDXQ:INX:LDAX2:SBCX1:BCCLFT 2230CLC:LDASWAP:BEQLI17:DEX:.LIL5 LDAR:EOR(SC),Y:STA(SC),Y:.LI17 DEY:BPLLI16:DECSCH:LDY#7 2240.LI16 LDAS:ADCP:STAS:BCCLIC5:LSRR:BCCLIC5:RORR:LDASC:ADC#8:STASC 2250.LIC5 DEX:BNELIL5:LDYYSAV:RTS 2300.LFT LDASWAP:BEQLI18:DEX:.LIL6 LDAR:EOR(SC),Y:STA(SC),Y:.LI18 DEY:BPLLI19:DECSCH:LDY#7:.LI19 LDAS:ADCP:STAS:BCCLIC6 2310ASLR:BCCLIC6:ROLR:LDASC:SBC#7:STASC:CLC:.LIC6 DEX:BNELIL6:LDYYSAV 2390.HL6 RTS 2392.NLIN3 JSRTT27:.NLIN4 LDA#19:BNENLIN2:.NLIN LDA#23:INCYC:.NLIN2 STAY1:LDX#2:STXX1:LDX#254:STXX2:BNEHLOIN 2395.HLOIN2 JSREDGES:STYY1:LDA#0:STALSO,Y 2400.HLOIN STYYSAV:LDXX1:CPXX2:BEQHL6:BCCHL5:LDAX2:STAX1:STXX2:TAX:.HL5 DECX2 2410LDAY1:LSRA:LSRA:LSRA:ORA#&60:STASCH:LDAY1:AND#7:STASC:TXA:AND#&F8:TAY 2420.HL1 TXA:AND#&F8:STAT:LDAX2:AND#&F8:SEC:SBCT:BEQHL2:LSRA:LSRA:LSRA:STAR 2430LDAX1:AND#7:TAX:LDATWFR,X:EOR(SC),Y:STA(SC),Y:TYA:ADC#8:TAY:LDXR:DEX:BEQHL3 2440CLC:.HLL1 LDA#FF:EOR(SC),Y:STA(SC),Y:TYA:ADC#8:TAY:DEX:BNEHLL1 2450.HL3 LDAX2:AND#7:TAX:LDATWFL,X:EOR(SC),Y:STA(SC),Y:LDYYSAV:RTS 2460.HL2 LDAX1:AND#7:TAX:LDATWFR,X:STAT:LDAX2:AND#7:TAX:LDATWFL,X:ANDT:EOR(SC),Y:STA(SC),Y:LDYYSAV:RTS 2470.TWFL EQUD&F0E0C080:EQUW&FCF8:EQUB&FE:.TWFR EQUD&1F3F7FFF:EQUD&0103070F 2520.PX3 LDATWOS,X:EOR(SC),Y:STA(SC),Y:LDYT1:RTS 2580.PIX1 JSRADD:STAYY+1:TXA:STASYL,Y 2600.PIXEL2 2610LDAX1:BPLPX1:EOR#&7F:CLC:ADC#1:.PX1 EOR#128:TAX:LDAY1:AND#127:CMP#96:BCSPX4:LDAY1:BPLPX2:EOR#&7F:ADC#1:.PX2 STAT:LDA#97:SBCT 2620.PIXEL STYT1:TAY:LSRA:LSRA:LSRA:ORA#&60:STASCH:TXA:AND#&F8:STASC:TYA:AND#7:TAY:TXA:AND#7:TAX 2630LDAZZ:CMP#&90:BCSPX3:LDATWOS2,X:EOR(SC),Y:STA(SC),Y:LDAZZ:CMP#&50:BCSPX13:DEY:BPLPX14:LDY#1:.PX14 LDATWOS2,X:EOR(SC),Y:STA(SC),Y:.PX13 LDYT1:.PX4 RTS 3000.BLINE TXA:ADCK4:STAK6+2:LDAK4+1:ADCT:STAK6+3 3010LDAFLAG:BEQBL1:INCFLAG:.BL5 LDYLSP:LDA#FF:CMPLSY2-1,Y:BEQBL7:STALSY2,Y:INCLSP:BNEBL7:.BL1 LDAK5:STAXX15:LDAK5+1:STAXX15+1 3012LDAK5+2:STAXX15+2:LDAK5+3:STAXX15+3 3014LDAK6:STAXX15+4:LDAK6+1:STAXX15+5 3016LDAK6+2:STAXX12:LDAK6+3:STAXX12+1 3040JSRLL145:BCSBL5:LDASWAP:BEQBL9:LDAX1:LDYX2:STAX2:STYX1:LDAY1:LDYY2:STAY2:STYY1:.BL9 3050LDYLSP:LDALSY2-1,Y:CMP#FF:BNEBL8:LDAX1:STALSX2,Y:LDAY1:STALSY2,Y:INY:.BL8 LDAX2:STALSX2,Y:LDAY2:STALSY2,Y:INY:STYLSP:JSRLOIN 3051LDAXX13:BNEBL5 3052.BL7 LDAK6:STAK5:LDAK6+1:STAK5+1:LDAK6+2:STAK5+2:LDAK6+3:STAK5+3:LDACNT:CLC:ADCSTP:STACNT 3700RTS:.FLIP \LDAMJ\BNEFLIP-1:LDYNOSTM:.FLL1 LDXSY,Y:LDASX,Y:STAY1:STASY,Y:TXA:STAX1:STASX,Y:LDASZ,Y:STAZZ:JSRPIXEL2:DEY:BNEFLL1:RTS 3800.STARS \LDA#FF:\STACOL:LDXVIEW:BEQSTARS1:DEX:BNEST11:JMPSTARS6:.ST11 JMPSTARS2 4000.STARS1 4010LDYNOSTM:.STL1 JSRDV42:LDAR:LSRP:RORA:LSRP:RORA:ORA#1:STAQ 4012LDASZL,Y:SBCDELT4:STASZL,Y:LDASZ,Y:STAZZ:SBCDELT4+1:STASZ,Y 4020JSRMLU1:STAYY+1:LDAP:ADCSYL,Y:STAYY:STAR:LDAY1:ADCYY+1:STAYY+1:STAS 4030LDASX,Y:STAX1:JSRMLU2:STAXX+1:LDAP:ADCSXL,Y:STAXX:LDAX1:ADCXX+1:STAXX+1 4050EORALP2+1:JSRMLS1:JSRADD:STAYY+1:STXYY 4060EORALP2:JSRMLS2:JSRADD:STAXX+1:STXXX 4070LDXBET1:LDAYY+1:EORBET2+1:JSRMULTS-2:STAQ:JSRMUT2:ASLP:ROLA:STAT:LDA#0:RORA:ORAT:JSRADD:STAXX+1:TXA:STASXL,Y 4080LDAYY:STAR:LDAYY+1:STAS:\JSRMADSTASSTXR:LDA#0:STAP:LDABETA:EOR#128 4110JSRPIX1:LDAXX+1:STAX1:STASX,Y:AND#127:CMP#120:BCSKILL1:LDAYY+1:STASY,Y:STAY1:AND#127:CMP#120:BCSKILL1 4130LDASZ,Y:CMP#16:BCCKILL1:STAZZ 4140.STC1 JSRPIXEL2:DEY:BEQP%+5:JMPSTL1:RTS 4150.KILL1 JSRDORND:ORA#4:STAY1:STASY,Y:JSRDORND:ORA#8:STAX1:STASX,Y:JSRDORND:ORA#&90:STASZ,Y:STAZZ:LDAY1:JMPSTC1 4200.STARS6 4210LDYNOSTM:.STL6 JSRDV42:LDAR:LSRP:RORA:LSRP:RORA:ORA#1:STAQ 4220LDASX,Y:STAX1:JSRMLU2:STAXX+1:LDASXL,Y:SBCP:STAXX:LDAX1:SBCXX+1:STAXX+1 4230JSRMLU1:STAYY+1:LDASYL,Y:SBCP:STAYY:STAR:LDAY1:SBCYY+1:STAYY+1:STAS 4240LDASZL,Y:ADCDELT4:STASZL,Y:LDASZ,Y:STAZZ:ADCDELT4+1:STASZ,Y 4250LDAXX+1:EORALP2:JSRMLS1:JSRADD:STAYY+1:STXYY 4260EORALP2+1:JSRMLS2:JSRADD:STAXX+1:STXXX 4270LDAYY+1:EORBET2+1:LDXBET1:JSRMULTS-2:STAQ:LDAXX+1:STAS:EOR#128:JSRMUT1:ASLP:ROLA:STAT:LDA#0:RORA:ORAT:JSRADD:STAXX+1:TXA:STASXL,Y 4280LDAYY:STAR:LDAYY+1:STAS:\EOR#128:\JSRMADSTASSTXR:LDA#0:STAP:LDABETA 4310JSRPIX1:LDAXX+1:STAX1:STASX,Y:LDAYY+1:STASY,Y:STAY1:AND#127:CMP#110:BCSKILL6 4330LDASZ,Y:CMP#160:BCSKILL6:STAZZ 4340.STC6 JSRPIXEL2:DEY:BEQST3:JMPSTL6:.ST3 RTS 4350.KILL6 JSRDORND:AND#127:ADC#10:STASZ,Y:STAZZ:LSRA:BCSST4:LSRA:LDA#&FC:RORA:STAX1:STASX,Y:JSRDORND:STAY1:STASY,Y:JMPSTC6 4360.ST4 JSRDORND:STAX1:STASX,Y:LSRA:LDA#230:RORA:STAY1:STASY,Y:BNESTC6 5000.PRXS EQUW1:EQUW300:EQUW4000:EQUW6000:EQUW4000:EQUW10000:EQUW5250:EQUW10000:EQUW9000:EQUW15000:EQUW10000:EQUW50000 6990.st4 LDX#9:CMP#25:BCSst3:DEX:CMP#10:BCSst3:DEX:CMP#2:BCSst3:DEX:BNEst3 7000.STATUS LDA#8:JSRTT66:JSRTT111:LDA#7:STAXC:LDA#126:JSRNLIN3:LDA#15:LDYQQ12:BNEst6:LDA#230:LDYMANY+AST:LDXFRIN+2,Y:BEQst6:LDYENERGY:CPY#128:ADC#1:.st6 JSRplf:LDA#125:JSRspc:LDA#19:LDYFIST:BEQst5:CPY#50:ADC#1:.st5 JSRplf:LDA#16 7010JSRspc:LDATALLY+1:BNEst4:TAX:LDATALLY:LSRA:LSRA:INX:LSRA:BNEP%-2:.st3 TXA:CLC:ADC#21:JSRplf 7030LDA#18:JSRplf2:LDACRGO:CMP#26:BCCP%+7:LDA#&6B:JSRplf2:LDABST:BEQP%+7:LDA#111:JSRplf2:LDAECM:BEQP%+7:LDA#&6C:JSRplf2:LDA#113:STAXX4:.stqv TAY:LDXBOMB-113,Y:BEQP%+5:JSRplf2:INCXX4:LDAXX4:CMP#117:BCCstqv 7040LDX#0:.st STXCNT:LDYLASER,X:BEQst1:TXA:CLC:ADC#96:JSRspc:LDA#103:LDXCNT:LDYLASER,X:BPLP%+4:LDA#104:JSRplf2:.st1 LDXCNT:INX:CPX#4:BCCst:RTS 7100.plf2 JSRplf:LDX#6:STXXC:RTS 7600.TENS EQUD&E87648 7605.pr2 LDA#3:LDY#0 7610.TT11 STAU:LDA#0:STAK:STAK+1:STYK+2:STXK+3:.BPRNT LDX#11:STXT:PHP:BCCTT30:DECT:DECU 7630.TT30 LDA#11:SEC:STAXX17:SBCU:STAU:INCU:LDY#0:STYS:JMPTT36 7640.TT35 ASLK+3:ROLK+2:ROLK+1:ROLK:ROLS:LDX#3:.tt35 LDAK,X:STAXX15,X:DEX:BPLtt35:LDAS:STAXX15+4 7650ASLK+3:ROLK+2:ROLK+1:ROLK:ROLS:ASLK+3:ROLK+2:ROLK+1:ROLK:ROLS:CLC:LDX#3:.tt36 LDAK,X:ADCXX15,X:STAK,X:DEX:BPLtt36:LDAXX15+4:ADCS:STAS 7660LDY#0:.TT36 LDX#3:SEC:.tt37 LDAK,X:SBCTENS,X:STAXX15,X:DEX:BPLtt37:LDAS:SBC#23:STAXX15+4 7670BCCTT37:LDX#3:.tt38 LDAXX15,X:STAK,X:DEX:BPLtt38:LDAXX15+4:STAS:INY:JMPTT36 7680.TT37 TYA:BNETT32:LDAT:BEQTT32:DECU:BPLTT34:LDA#32:BNEtt34:.TT32 LDY#0:STYT:CLC:ADC#B:.tt34 JSRTT26 7700.TT34 DECT:BPLP%+4:INCT:DECXX17:BMIRR3+1 \!!:BNEP%+10:PLP:BCCP%+7:LDA#&2E:JSRTT26:JMPTT35 8000.BELL LDA#7 8200.TT26 \PRINT 8205STAK3:STYYSAV2:STXXSAV2:LDYQQ17:CPY#FF:BEQRR4 8210CMP#7:BEQR5:CMP#32:BCSRR1:CMP#10:BEQRRX1:LDX#1:STXXC:.RRX1 INCYC:BNERR4 8220.RR1 \LDX#(K3 MOD256)\INX\STXP+1\DEX\LDY#(K3 DIV256)\STYP+2\LDA#10\JSROSWORD 8225TAY:LDX#&BF:ASLA:ASLA:BCCP%+4:LDX#&C1:ASLA:BCCP%+3:INX:STAP+1:STXP+2 8240LDAXC:ASLA:ASLA:ASLA:STASC:LDAYC:CPY#&7F:BNERR2:DECXC:ADC#&5E:TAX:LDY#&F8:JSRZES2:BEQRR4:.RR2 INCXC:\LDAYC:CMP#24:BCCRR3:JSRTTX66:JMPRR4 8250.RR3 ORA#&60:.RREN STASC+1:LDY#7:.RRL1 LDA(P+1),Y:EOR(SC),Y:STA(SC),Y:DEY:BPLRRL1 8260.RR4 LDYYSAV2:LDXXSAV2:LDAK3:CLC:.rT9 RTS 8270.R5 JSRBEEP:JMPRR4 9500.DIALS LDA#&D0:STASC:LDA#&78:STASC+1:JSRPZW:STXK+1:STAK:LDA#14:STAT1:LDADELTA:\LSRA:JSRDIL-1 9502LDA#0:STAR:STAP:LDA#8:STAS:LDAALP1:LSRA:LSRA:ORAALP2:EOR#128:JSRADD:JSRDIL2:LDABETA:LDXBET1:BEQP%+4:SBC#1:JSRADD:JSRDIL2 9503LDAMCNT:AND#3:BNErT9 9504LDY#0:JSRPZW:STXK:STAK+1:LDX#3:STXT1:.DLL23 STYXX12,X:DEX:BPLDLL23:LDX#3:LDAENERGY:LSRA:LSRA:STAQ:.DLL24 SEC:SBC#16:BCCDLL26:STAQ:LDA#16:STAXX12,X:LDAQ:DEX:BPLDLL24:BMIDLL9:.DLL26 9505LDAQ:STAXX12,X:.DLL9 LDAXX12,Y:STYP:JSRDIL:LDYP:INY:CPY#4:BNEDLL9 9506LDA#&78:STASC+1:LDA#16:\"<80<:STASC:LDAFSH:JSRDILX:LDAASH:JSRDILX:LDAQQ14:JSRDILX+2 9510JSRPZW:STXK+1:STAK:LDX#11:STXT1:LDACABTMP:JSRDILX:LDAGNTMP:JSRDILX 9530LDA#&F0:STAT1:STAK+1:LDAALTIT:JSRDILX:JMPCOMPAS 9540.PZW LDX#&F0:LDAMCNT:AND#8:ANDFLH:BEQP%+4:TXA:EQUB&2C:LDA#15:RTS 9690.DILX LSRA:LSRA:LSRA:LSRA 9700.DIL STAQ:LDX#FF:STXR:CMPT1:BCSDL30:LDAK+1:BNEDL31:.DL30 LDAK:.DL31 STACOL:LDY#2:LDX#3:.DL1 LDAQ:CMP#4:BCCDL2:SBC#4:STAQ:LDAR:.DL5 ANDCOL:STA(SC),Y:INY:STA(SC),Y:INY:STA(SC),Y:TYA:CLC:ADC#6:TAY:DEX:BMIDL6:BPLDL1 9710.DL2 EOR#3:STAQ:LDAR:.DL3 ASLA:AND#239:DECQ:BPLDL3:PHA:LDA#0:STAR:LDA#99:STAQ:PLA:JMPDL5:.DL6 INCSC+1:.DL9 RTS 9712.DIL2 LDY#1:STAQ:.DLL10 SEC:LDAQ:SBC#4:BCSDLL11:LDA#FF:LDXQ:STAQ:LDACTWOS,X:AND#&F0:BNEDLL12:.DLL11 STAQ:LDA#0:.DLL12 STA(SC),Y:INY:STA(SC),Y:INY:STA(SC),Y:INY:STA(SC),Y:TYA:CLC:ADC#5:TAY:CPY#30:BCCDLL10:INCSC+1:RTS 9730.TVT1 EQUD&8494C4D4:\TVT2:EQUD&A5B5E5F5:EQUD&26366676:EQUD&A1B1F1E1:\TVT3:EQUD&A0B0E0F0:EQUD&8090C0D0:EQUD&27376777 9740.LINSCN LDA#30:STADL:STAUSVIA+4:LDA#VSCAN:STAUSVIA+5:LDAHFX:BNEVNT1:LDA#8:STA&FE20:.VNT3 LDATVT1+16,Y:STA&FE21:DEY:BPLVNT3:LDALASCT:BEQP%+5:DECLASCT:\VNT4:LDAsvn:BNEjvec:PLA:TAY:LDA&FE41:LDA&FC:RTI 9750.IRQ1 TYA:PHA:LDY#11:LDA#2:BITVIA+&D:BNELINSCN:BVCjvec:ASLA\4:STA&FE20:LDAESCP:BNEVNT1:\VNT2:LDATVT1,Y:STA&FE21:DEY:BPLP%-7:.jvec PLA:TAY:JMP(VEC):.VNT1 LDY#7:LDATVT1+8,Y:STA&FE21:DEY:BPLVNT1+2:BMIjvec 9800.ESCAPE LDAMJ:PHA:JSRRES2:LDX#CYL:STXTYPE:JSRFRS1:LDA#8:STAINWK+27:LDA#&C2:STAINWK+30:LSRA:STAINWK+32:.ESL1 JSRMVEIT:JSRLL9:DECINWK+32:BNEESL1 9810JSRSCAN:JSRRESET:PLA:BEQP%+5:JMPDEATH:LDX#16:.ESL2 STAQQ20,X:DEX:BPLESL2:STAFIST:STAESCP:LDA#70:STAQQ14:JMPBAY 9900] 9910IFZ>4OSCLI("S.ELTB "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9920PRINT"B done,";:GOTO6 ================================================ FILE: 1-source-files/original-sources/text-sources/ELITEC.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 20REM ELITE 1000O%=W%:H%=L%+P%-C% 1010[OPTZ 1880.TA34 LDA#0:JSRMAS4:BEQP%+5:JMPTA21:JSRTA87+3:JSREXNO3:LDA#250:JMPOOPS 1900.TA18\msl 1910LDAECMA:BNETA35:LDAINWK+32:ASLA:BMITA34:LSRA 1915TAX:LDAUNIV,X:STAV:LDAUNIV+1,X:STAV+1:LDY#2:JSRTAS1:LDY#5:JSRTAS1:LDY#8:JSRTAS1 1920LDAK3+2:ORAK3+5:ORAK3+8:AND#127:ORAK3+1:ORAK3+4:ORAK3+7:BNETA64 1930LDAINWK+32:CMP#&82:BEQTA35:LDY#31:LDA(V),Y:BITM32+1:BNETA35:ORA#128:STA(V),Y:.TA35 LDAINWK:ORAINWK+3:ORAINWK+6:BNETA87:LDA#80:JSROOPS:.TA87 JSREXNO2:ASLINWK+31:SEC:RORINWK+31 1940.TA1 RTS 1944.TA64 JSRDORND:CMP#16:BCSTA19:.M32 LDY#32:LDA(V),Y:LSRA:BCCTA19:JMPECBLB2 2000.TACTICS 2005CPX#MSL:BEQTA18:CPX#ESC:BNEP%+8:JSRSPS1:JMPTA15:CPX#SST:BNETA13:JSRDORND:CMP#140:BCCTA14-1:LDAMANY+SH3:CMP#4:BCSTA14-1:LDX#COPS:LDA#&F1:JMPSFS1:.TA13 2008CPX#TGL:BNETA14:LDAMANY+THG:BNETA14:LSRINWK+32:ASLINWK+32:LSRINWK+27:RTS:.TA14 CPX#CYL:BCSTA62:CPX#COPS:BEQTA62:LDASSPR:BEQTA62:LDAINWK+32:AND#129:STAINWK+32 2010.TA62 LDY#14:LDAINWK+35:CMP(XX0),Y:BCSTA21:INCINWK+35:.TA21 2020LDX#8:.TAL1 LDAINWK,X:STAK3,X:DEX:BPLTAL1 2030.TA19 JSRTAS2\XX15=r~96 2040LDY#10:JSRTAS3:STACNT:LDATYPE:CMP#MSL:BNEP%+5:JMPTA20:JSRDORND:CMP#250:BCCTA7:JSRDORND:ORA#&68:STAINWK+29:.TA7\VRol 2100LDY#14:LDA(XX0),Y:LSRA:CMPINWK+35:BCCTA3:LSRA:LSRA:CMPINWK+35:BCCta3:JSRDORND:CMP#230:BCCta3:LDATYPE:CMP#THG:BEQta3:LDA#0:STAINWK+32:JMPSESCP 2102.ta3 LDAINWK+31:AND#7:BEQTA3:STAT:JSRDORND:AND#31:CMPT:BCSTA3:LDAECMA:BNETA3:DECINWK+31:LDATYPE:CMP#THG:BNETA16:LDX#TGL:LDAINWK+32:JMPSFS1:.TA16 JMPSFRMIS:.TA3 2110LDA#0:JSRMAS4:AND#&E0:BNETA4:LDXCNT:CPX#160:BCCTA4:LDAINWK+31:ORA#64:STAINWK+31:CPX#163:BCCTA4 2120LDY#19:LDA(XX0),Y:LSRA:JSROOPS:DECINWK+28:LDAECMA:BNETA10:LDA#8:JMPNOISE:\frLs 2190.TA4 LDAINWK+7:CMP#3:BCSTA5:LDAINWK+1:ORAINWK+4:AND#&FE:BEQTA15:.TA5 JSRDORND:ORA#128:CMPINWK+32:BCSTA15 2194.TA20 LDAXX15:EOR#128:STAXX15:LDAXX15+1:EOR#128:STAXX15+1:LDAXX15+2:EOR#128:STAXX15+2:LDACNT:EOR#128:STACNT 2200.TA15\^XX15 2220LDY#16:JSRTAS3:EOR#128:AND#128:ORA#3:STAINWK+30 2235LDAINWK+29:AND#127:CMP#16:BCSTA6 2240LDY#22:JSRTAS3:EORINWK+30:AND#128:EOR#&85:STAINWK+29 2260.TA6 LDACNT:BMITA9:CMP#22:BCCTA9:LDA#3:STAINWK+28:RTS 2280.TA9 AND#127:CMP#18:BCCTA10:LDA#FF:LDXTYPE:CPX#MSL:BNEP%+3:ASLA:STAINWK+28:.TA10 RTS 2900.TAS1 LDA(V),Y:EOR#128:STAK+3:DEY:LDA(V),Y:STAK+2:DEY:LDA(V),Y:STAK+1:STYU:LDXU:JSRMVT3:LDYU 2910STAK3+2,X:LDAK+2:STAK3+1,X:LDAK+1:STAK3,X:RTS 3000.HITCH CLC:LDAINWK+8:BNEHI1:LDATYPE:BMIHI1:LDAINWK+31:AND#32:ORAINWK+1:ORAINWK+4:BNEHI1 3005LDAINWK:JSRSQUA2:STAS:LDAP:STAR 3010LDAINWK+3:JSRSQUA2:TAX:LDAP:ADCR:STAR:TXA:ADCS:BCSFR1-2:STAS:LDY#2:LDA(XX0),Y:CMPS:BNEHI1:DEY:LDA(XX0),Y:CMPR:.HI1 RTS 3210.FRS1 JSRZINF:LDA#28:STAINWK+3:LSRA:STAINWK+6:LDA#128:STAINWK+5:LDAMSTG:ASLA:ORA#128:STAINWK+32 3220.fq1 LDA#96:STAINWK+14:ORA#128:STAINWK+22:LDADELTA:ROLA:STAINWK+27:TXA:JMPNWSHP 3230.FRMIS LDX#MSL:JSRFRS1:BCCFR1:LDXMSTG:JSRGINF:LDAFRIN,X:JSRANGRY:LDY#0:JSRABORT:DECNOMSL:LDA#48:JMPNOISE 3234.ANGRY CMP#SST:BEQAN2:BCSHI1:CMP#CYL:BNEP%+5:JSRAN2:LDY#32:LDA(INF),Y:BEQHI1:ORA#128:STA(INF),Y:LDY#28:LDA#2:STA(INF),Y:ASLA:LDY#30:STA(INF),Y:RTS 3236.AN2 ASLK%+NI%+32:SEC:RORK%+NI%+32:CLC:RTS:.FR1 LDA#201:JMPMESS 3310.SESCP LDX#ESC:LDA#&FE:.SFS1 STAT1:LDAXX0:PHA:LDAXX0+1:PHA:LDAINF:PHA:LDAINF+1:PHA:LDY#NI%-1:.FRL2 LDAINWK,Y:STAXX3,Y:LDA(INF),Y:STAINWK,Y:DEY:BPLFRL2 3315LDATYPE:CMP#SST:BNErx:TXA:PHA:LDA#32:STAINWK+27:LDX#0:LDAINWK+10:JSRSFS2:LDX#3:LDAINWK+12:JSRSFS2:LDX#6:LDAINWK+14:JSRSFS2:PLA:TAX:.rx 3320LDAT1:STAINWK+32:LSRINWK+29:ASLINWK+29:TXA:CMP#OIL:BNENOIL:JSRDORND:ASLA:STAINWK+30:TXA:AND#15:STAINWK+27:LDA#FF:RORA:STAINWK+29:LDA#OIL:.NOIL JSRNWSHP 3330PLA:STAINF+1:PLA:STAINF:LDX#NI%-1:.FRL3 LDAXX3,X:STAINWK,X:DEX:BPLFRL3:PLA:STAXX0+1:PLA:STAXX0:RTS 3350.SFS2 ASLA:STAR:LDA#0:RORA:JMPMVT1 3400.LL164 LDA#56:JSRNOISE:LDA#1:STAHFX:LDA#4:JSRHFS2:DECHFX:RTS 3410.LAUN LDA#48:JSRNOISE:LDA#8:.HFS2 STASTP:JSRTTX66:JSRHFS1 3510.HFS1 LDA#128:STAK3:LDX#Y:STXK4:ASLA:STAXX4:STAK3+1:STAK4+1:.HFL5 JSRHFL1:INCXX4:LDXXX4:CPX#8:BNEHFL5:RTS 3520.HFL1 LDAXX4:AND#7:CLC:ADC#8:STAK:.HFL2 LDA#1:STALSP:JSRCIRCLE2:ASLK:BCSHF8:LDAK:CMP#160:BCCHFL2:.HF8 RTS 4400.STARS2 LDA#0:CPX#2:RORA:STARAT:EOR#128:STARAT2:JSRST2 4410LDYNOSTM:.STL2 LDASZ,Y:STAZZ:LSRA:LSRA:LSRA:JSRDV41:LDAP:EORRAT2:STAS:LDASXL,Y:STAP:LDASX,Y:STAX1:JSRADD 4420STAS:STXR:LDASY,Y:STAY1:EORBET2:LDXBET1:JSRMULTS-2:JSRADD:STXXX:STAXX+1 4430LDXSYL,Y:STXR:LDXY1:STXS:LDXBET1:EORBET2+1:JSRMULTS-2:JSRADD:STXYY:STAYY+1 4440LDXALP1:EORALP2:JSRMULTS-2:STAQ:LDAXX:STAR:LDAXX+1:STAS:EOR#128:JSRMAD:STAXX+1:TXA:STASXL,Y 4450LDAYY:STAR:LDAYY+1:STAS:JSRMAD:STAS:STXR:LDA#0:STAP:LDAALPHA 4460JSRPIX1:LDAXX+1:STASX,Y:STAX1 4470AND#127:CMP#116:BCSKILL2:LDAYY+1:STASY,Y:STAY1:AND#127:CMP#116:BCSST5:.STC2 JSRPIXEL2:DEY:BEQST2:JMPSTL2 4480.ST2 LDAALPHA:EORRAT:STAALPHA:LDAALP2:EORRAT:STAALP2:EOR#128:STAALP2+1:LDABET2:EORRAT:STABET2:EOR#128:STABET2+1:RTS 4500.KILL2 JSRDORND:STAY1:STASY,Y:LDA#115:ORARAT:STAX1:STASX,Y:BNESTF1 4510.ST5 JSRDORND:STAX1:STASX,Y:LDA#110:ORAALP2+1:STAY1:STASY,Y:.STF1 JSRDORND:ORA#8:STAZZ:STASZ,Y:BNESTC2 4700.SNE:] 4720FORI%=0TO31:N=ABS(SIN(I%/64*2*PI)):IFN>=1 I%?O%=FF:ELSEI%?O%=INT(256*N+.5) 4730NEXT:O%=O%+32:P%=P%+32 4740[OPTZ 6040.MU5 STAK:STAK+1:STAK+2:STAK+3:CLC:RTS 6050.MULT3\K(4)=AP(2)*Q:STAR:AND#127:STAK+2:LDAQ:AND#127:BEQMU5:SEC:SBC#1:STAT:LDAP+1:LSRK+2:RORA:STAK+1:LDAP:RORA:STAK:LDA#0:LDX#24 6060.MUL2 BCCP%+4:ADCT:RORA:RORK+2:RORK+1:RORK:DEX:BNEMUL2:STAT:LDAR:EORQ:AND#128:ORAT:STAK+3:RTS 6070.MLS2 LDXXX:STXR:LDXXX+1:STXS:.MLS1 LDXALP1:STXP 6080.MULTS\AP=A*P(P+<32) 6090TAX:AND#128:STAT:TXA:AND#127:BEQMU6:TAX:DEX:STXT1:LDA#0 6100LSRP:BCCP%+4:ADCT1:RORA:RORP:BCCP%+4:ADCT1:RORA:RORP:BCCP%+4:ADCT1:RORA:RORP:BCCP%+4:ADCT1:RORA:RORP:BCCP%+4:ADCT1:RORA:RORP 6110LSRA:RORP:LSRA:RORP:LSRA:RORP:ORAT:RTS 6112.SQUA\AP=A*ApresQ:AND#127:.SQUA2 STAP:TAX:BNEMU11:.MU1 CLC:STXP:TXA:RTS 6114.MLU1 LDASY,Y:STAY1:.MLU2 AND#127:STAP 6116.MULTU\AP=P*Qunsg 6118LDXQ:BEQMU1:.MU11 DEX:STXT:LDA#0:LDX#8:LSRP:.MUL6 BCCP%+4:ADCT:RORA:RORP:DEX:BNEMUL6:RTS 6119.MU6 STAP+1:STAP:RTS 6120.FMLTU2 AND#31:TAX:LDASNE,X:STAQ:LDAK 6125.FMLTU\A=A*Q/256unsg:EOR#FF:SEC:RORA:STAP:LDA#0:.MUL3 BCSMU7:ADCQ:RORA:LSRP:BNEMUL3:RTS:.MU7 LSRA:LSRP:BNEMUL3:RTS 6130LDXQ:BEQMU1:DEX:STXT:LDA#0:LDX#8:LSRP:.MUL6 BCCP%+4:ADCT:RORA:RORP:DEX:BNEMUL6:RTS 6140STXQ:.MLTU2\AP(2)=AP*Qunsg(EORP) 6142EOR#FF:LSRA:STAP+1:LDA#0:LDX#16:RORP:.MUL7 BCSMU21:ADCQ:RORA:RORP+1:RORP:DEX:BNEMUL7:RTS:.MU21 LSRA:RORP+1:RORP:DEX:BNEMUL7:RTS 6146.MUT3 LDXALP1:STXP:.MUT2 LDXXX+1:STXS 6148.MUT1 LDXXX:STXR 6150.MULT1 \AP=Q*A 6160TAX:AND#127:LSRA:STAP:TXA:EORQ:AND#128:STAT:LDAQ:AND#127:BEQmu10:TAX:DEX:STXT1:LDA#0:LDX#7 6170.MUL4 BCCP%+4:ADCT1:RORA:RORP:DEX:BNEMUL4:LSRA:RORP:ORAT:RTS:.mu10 STAP:RTS 6190.MULT12 JSRMULT1:STAS:LDAP:STAR:RTS 6194.TAS3 LDXINWK,Y:STXQ:LDAXX15:JSRMULT12:LDXINWK+2,Y:STXQ:LDAXX15+1:JSRMAD:STAS:STXR 6196LDXINWK+4,Y:STXQ:LDAXX15+2:.MAD JSRMULT1 6200.ADD\AX=AP+SR 6210STAT1:AND#128:STAT:EORS:BMIMU8:LDAR:CLC:ADCP:TAX:LDAS:ADCT1:ORAT:RTS 6220.MU8 LDAS:AND#127:STAU:LDAP:SEC:SBCR:TAX:LDAT1:AND#127:SBCU:BCSMU9:STAU:TXA:EOR#FF:ADC#1:TAX:LDA#0:SBCU:ORA#128:.MU9 EORT:RTS 6330\DVIDT(A=AP/Q)inF 6345.TIS1 STXQ:EOR#128:JSRMAD 6350.DVID96\A=A/96:TAX:AND#128:STAT:TXA:AND#127:LDX#254:STXT1:.DVL3 ASLA:CMP#96:BCCDV4:SBC#96:.DV4 ROLT1:BCSDVL3:LDAT1:ORAT:RTS 6360.DV42 LDASZ,Y:.DV41 STAQ:LDADELTA 6370.DVID4\P-R=A/Qunsg 6380LDX#8:ASLA:STAP:LDA#0:.DVL4 ROLA:BCSDV8:CMPQ:BCCDV5:.DV8 SBCQ:SEC:.DV5 ROLP:DEX:BNEDVL4:JMPLL28+4 6395.DVID3B2 STAP+2:LDAINWK+6:STAQ:LDAINWK+7:STAR:LDAINWK+8:STAS 6400.DVID3B\K+1(3)-K=P(3)/SRQaprx 6410LDAP:ORA#1:STAP:LDAP+2:EORS:AND#128:STAT:LDY#0:LDAP+2:AND#127:.DVL9 CMP#&40:BCSDV14:ASLP:ROLP+1:ROLA:INY:BNEDVL9 6420.DV14 STAP+2:LDAS:AND#127:BMIDV9:.DVL6 DEY:ASLQ:ROLR:ROLA:BPLDVL6:.DV9 STAQ:LDA#254:STAR:LDAP+2:JSRLL31 6440LDA#0:STAK+1:STAK+2:STAK+3:TYA:BPLDV12:LDAR:.DVL8 ASLA:ROLK+1:ROLK+2:ROLK+3:INY:BNEDVL8:STAK:LDAK+3:ORAT:STAK+3:RTS 6450.DV13 LDAR:STAK:LDAT:STAK+3:RTS 6460.DV12 BEQDV13:LDAR:.DVL10 LSRA:DEY:BNEDVL10:STAK:LDAT:STAK+3:RTS 6500.cntr LDADAMP:BNERE1:TXA:BPLBUMP:DEX:BMIRE1 6530.BUMP INX:BNERE1 6540.REDU DEX:BEQBUMP:.RE1 RTS 6550.BUMP2 STAT:TXA:CLC:ADCT:TAX:BCCRE2:LDX#FF:.RE2 BPLRE3+2:LDAT:RTS 6560.REDU2 STAT:TXA:SEC:SBCT:TAX:BCSRE3:LDX#1:.RE3 BPLRE2+2:LDADJD:BNERE2+2:LDX#128:BMIRE2+2 6800.ARCTAN\A=TAN-1(P/Q) 6810LDAP:EORQ:STAT1:LDAQ:BEQAR2:ASLA:STAQ:LDAP:ASLA:CMPQ:BCSAR1:JSRARS1:SEC:.AR4 LDXT1:BMIAR3:RTS 6830.AR1 LDXQ:STAQ:STXP:TXA:JSRARS1:STAT:LDA#64:SBCT:BCSAR4:.AR2 LDA#63:RTS:.AR3 STAT:LDA#128:\SEC:SBCT:RTS 6845.ARS1 JSRLL28:LDAR:LSRA:LSRA:LSRA:TAX:LDAACT,X:RTS 6850.ACT:]FORI%=0TO31:I%?O%=INT(128/PI*ATN(I%/32)+.5):NEXT:P%=P%+32:O%=O%+32:[OPTZ 6900.WARP LDAMANY+AST:CLC:ADCMANY+ESC:ADCMANY+OIL:TAX:LDAFRIN+2,X:ORASSPR:ORAMJ:BNEWA1:LDYK%+8:BMIWA3:TAY:JSRMAS2:LSRA:BEQWA1:.WA3 LDYK%+NI%+8:BMIWA2:LDY#NI%:JSRm:LSRA:BEQWA1:.WA2 6910LDA#&81:STAS:STAR:STAP:LDAK%+8:JSRADD:STAK%+8:LDAK%+NI%+8:JSRADD:STAK%+NI%+8 6920LDA#1:STAQQ11:STAMCNT:LSRA:STAEV:LDXVIEW:JMPLOOK1:.WA1 LDA#40:JMPNOISE 7000.LASLI JSRDORND:AND#7:ADC#Y-4:STALASY:JSRDORND:AND#7:ADC#X-4:STALASX:LDAGNTMP:ADC#8:STAGNTMP:JSRDENGY 7005.LASLI2 LDAQQ11:BNEPU1-1:LDA#32:LDY#224:JSRlas:LDA#48:LDY#208 7050.las STAX2:LDALASX:STAX1:LDALASY:STAY1:LDA#2*Y-1:STAY2:JSRLOIN:LDALASX:STAX1:LDALASY:STAY1:STYX2:LDA#2*Y-1:STAY2:JMPLOIN 8500.PLUT LDXVIEW:BNEPU1:RTS:.PU1 DEX:BNEPU2 8510LDAINWK+2:EOR#128:STAINWK+2:LDAINWK+8:EOR#128:STAINWK+8:LDAINWK+10:EOR#128:STAINWK+10:LDAINWK+14:EOR#128:STAINWK+14:LDAINWK+16:EOR#128:STAINWK+16 8520LDAINWK+20:EOR#128:STAINWK+20:LDAINWK+22:EOR#128:STAINWK+22:LDAINWK+26:EOR#128:STAINWK+26:RTS 8530.PU2 LDA#0:CPX#2:RORA:STARAT2:EOR#128:STARAT 8540LDAINWK:LDXINWK+6:STAINWK+6:STXINWK:LDAINWK+1:LDXINWK+7:STAINWK+7:STXINWK+1:LDAINWK+2:EORRAT:TAX:LDAINWK+8:EORRAT2:STAINWK+2:STXINWK+8 8550LDY#9:JSRPUS1 8560LDY#15:JSRPUS1 8570LDY#21 8600.PUS1 LDAINWK,Y:LDXINWK+4,Y:STAINWK+4,Y:STXINWK,Y:LDAINWK+1,Y:EORRAT:TAX:LDAINWK+5,Y:EORRAT2:STAINWK+1,Y:STXINWK+5,Y:.LO2 RTS 8990.LQ STXVIEW:JSRTT66:JSRSIGHT:JMPNWSTARS 9000.LOOK1 LDA#0:LDYQQ11:BNELQ:CPXVIEW:BEQLO2:STXVIEW:JSRTT66:JSRFLIP:JSRWPSHPS 9010.SIGHT LDYVIEW:LDALASER,Y:BEQLO2:LDA#128:STAQQ19:LDA#Y-24:STAQQ19+1:LDA#20:STAQQ19+2:JSRTT15:LDA#10:STAQQ19+2:JMPTT15 9400LDA#1:.TT66 STAQQ11:.TTX66 LDA#128:STAQQ17:ASLA:STALAS2:STADLY:STAde:LDX#&60:.BOL1 JSRZES1:INX:CPX#&78:BNEBOL1 9410LDXQQ22+1:BEQBOX:JSRee3:.BOX LDY#1:STYYC:LDAQQ11:BNEtt66:LDY#11:STYXC:LDAVIEW:ORA#&60:JSRTT27:JSRTT162:LDA#175:JSRTT27:.tt66 9420LDX#0:STXX1:STXY1:STXQQ17:DEX:STXX2:JSRHLOIN 9430LDA#2:STAX1:STAX2:JSRBOS2 9440.BOS2 JSRBOS1:.BOS1 LDA#0:STAY1:LDA#2*Y-1:STAY2:DECX1:DECX2:JMPLOIN 9450LDY#2:EQUB&2C:.DEL8 LDY#8:.DELAY JSRWSCAN:DEY:BNEDELAY:RTS 9460.hm JSRTT103:JSRTT111:JSRTT103:LDAQQ11:BEQSC5:.CLYNS LDA#20:STAYC:LDA#&75:STASC+1:LDA#7:STASC:JSRTT67:LDA#0:JSRLYN:INCSC+1:JSRLYN:INCSC+1:INY:STYXC 9470.LYN LDY#233:.EE2 STA(SC),Y:DEY:BNEEE2:.SC5 RTS 9500.SCAN LDAINWK+31:AND#16:BEQSC5:LDATYPE:BMISC5:LDX#FF:\CMP#TGL\BEQSC49:CMP#MSL:BNEP%+4:LDX#&F0:\CMP#AST:\BCCP%+4:\LDX#&F:\SC49:STXCOL:LDAINWK+1:ORAINWK+4:ORAINWK+7:AND#&C0:BNESC5 9510LDAINWK+1:CLC:LDXINWK+2:BPLSC2:EOR#FF:ADC#1:.SC2 ADC#123:STAX1 9520LDAINWK+7:LSRA:LSRA:CLC:LDXINWK+8:BPLSC3:EOR#FF:SEC:.SC3 ADC#35:EOR#FF:STASC 9530LDAINWK+4:LSRA:CLC:LDXINWK+5:BMISCD6:EOR#FF:SEC:.SCD6 ADCSC:BPLld246:CMP#194:BCSP%+4:LDA#194:CMP#247:BCCP%+4:.ld246 LDA#246 9535STAY1:SEC:SBCSC:PHP:\BCSSC48:\EOR#FF:\ADC#1:.SC48 PHA:JSRCPIX4:LDACTWOS+1,X:ANDCOL:STAX1:PLA:PLP:TAX:BEQRTS:BCCRTS+1 9540.VLL1 DEY:BPLVL1:LDY#7:DECSC+1:.VL1 LDAX1:EOR(SC),Y:STA(SC),Y:DEX:BNEVLL1:.RTS RTS 9545INY:CPY#8:BNEP%+6:LDY#0:INCSC+1 9550.VLL2 INY:CPY#8:BNEVL2:LDY#0:INCSC+1:.VL2 LDAX1:EOR(SC),Y:STA(SC),Y:INX:BNEVLL2:RTS 9700.WSCAN LDA#0:STADL:LDADL:BEQP%-2:RTS 9900] 9910IFZ>4OSCLI("S.ELTC "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9920PRINT"C d,";:GOTO8 ================================================ FILE: 1-source-files/original-sources/text-sources/ELITED.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 20REM ELITE 30H%=L%+P%-C%:O%=W% 300[OPTZ 700.tnpr pha:LDX#12:CPXQQ29:BCCkg:.Tml ADCQQ20,X:DEX:BPLTml:CMPCRGO:pla:RTS:.kg LDYQQ29:ADCQQ20,Y:cmp#200:pla:rts 840.TT20 JSRP%+3:JSRP%+3 850.TT54 LDAQQ15:CLC:ADCQQ15+2:TAX:LDAQQ15+1:ADCQQ15+3:TAY 860LDAQQ15+2:STAQQ15:LDAQQ15+3:STAQQ15+1:LDAQQ15+5:STAQQ15+3:LDAQQ15+4:STAQQ15+2:CLC:TXA:ADCQQ15+2:STAQQ15+4:TYA:ADCQQ15+3:STAQQ15+5:RTS 950.TT146 LDAQQ8:ORAQQ8+1:BNETT63:INCYC:RTS:.TT63 LDA#191:JSRTT68 955LDXQQ8:LDYQQ8+1:SEC:JSRpr5:LDA#195:.TT60 JSRTT27:.TTX69 INCYC:.TT69 LDA#128:STAQQ17:.TT67 LDA#13:JMPTT27 990.TT70 LDA#173:JSRTT27:JMPTT72:.spc JSRTT27:JMPTT162 1000.TT25\ DATA 1010JSRTT66-2:LDA#9:STAXC:LDA#163:JSRTT27:JSRNLIN:JSRTTX69:INCYC:JSRTT146:LDA#194 1030JSRTT68:LDAQQ3:CLC:ADC#1:LSRA:CMP#2:BEQTT70:LDAQQ3:BCCTT71 1040SBC#5:CLC:.TT71 ADC#170:JSRTT27:.TT72 LDAQQ3:LSRA:LSRA:CLC:ADC#168:JSRTT60:LDA#162:JSRTT68:LDAQQ4:CLC:ADC#177:JSRTT60:LDA#196:JSRTT68 1070LDXQQ5:INX:CLC:JSRpr2:JSRTTX69:LDA#192:JSRTT68:SEC:LDXQQ6:JSRpr2:LDA#198:JSRTT60:LDA#&28:JSRTT27:LDAQQ15+4:BMITT75:LDA#188:JSRTT27:JMPTT76:.TT75 LDAQQ15+5 1110LSRA:LSRA:PHA:AND#7:CMP#3:BCSTT205:ADC#227:JSRspc:.TT205 PLA:LSRA:LSRA:LSRA:CMP#6:BCSTT206:ADC#230:JSRspc:.TT206 LDAQQ15+3:EORQQ15+1:AND#7 1116STAQQ19:CMP#6:BCSTT207:ADC#236:JSRspc:.TT207 LDAQQ15+5:AND#3:CLC:ADCQQ19:AND#7:ADC#242:JSRTT27:.TT76 LDA#&53:JSRTT27:LDA#&29:JSRTT60 1127LDA#193:JSRTT68:LDXQQ7:LDYQQ7+1:JSRpr6:JSRTT162:LDA#0:STAQQ17:LDA#&4D:JSRTT27:LDA#226:JSRTT60:LDA#250:JSRTT68:LDAQQ15+5:LDXQQ15+3:AND#15:CLC:ADC#11:TAY 1150JSRpr5:JSRTT162:LDA#&6B:JSRTT26:LDA#&6D:JMPTT26 1200.TT24 1210LDAQQ15+1:AND#7:STAQQ3:LDAQQ15+2:LSRA:LSRA:LSRA:AND#7:STAQQ4:LSRA:BNETT77:LDAQQ3:ORA#2:STAQQ3:.TT77 LDAQQ3:EOR#7:CLC:STAQQ5:LDAQQ15+3:AND#3:ADCQQ5:STAQQ5 1240LDAQQ4:LSRA:ADCQQ5:STAQQ5:ASLA:ASLA:ADCQQ3:ADCQQ4:ADC#1:STAQQ6:LDAQQ3:EOR#7:ADC#3:STAP:LDAQQ4:ADC#4:STAQ:JSRMULTU:LDAQQ6:STAQ:JSRMULTU:ASLP:ROLA:ASLP:ROLA:ASLP:ROLA:STAQQ7+1:LDAP:STAQQ7:RTS 1400.TT22\Lng Sc 1410LDA#64:JSRTT66:LDA#7:STAXC:JSRTT81:LDA#199:JSRTT27:JSRNLIN:LDA#152:JSRNLIN2:JSRTT14 1460LDX#0:.TT83 STXXSAV:LDXQQ15+3:LDYQQ15+4:TYA:ORA#&50:STAZZ 1470LDAQQ15+1:LSRA:CLC:ADC#24:STAXX15+1:JSRPIXEL:JSRTT20:LDXXSAV:INX:BNETT83:LDAQQ9:STAQQ19:LDAQQ10:LSRA:STAQQ19+1:LDA#4:STAQQ19+2 1700.TT15 1705LDA#24:LDXQQ11:BPLP%+4:LDA#0:STAQQ19+5:LDAQQ19:SEC:SBCQQ19+2:BCSTT84:LDA#0:.TT84 STAXX15:LDAQQ19:CLC:ADCQQ19+2:BCCP%+4:LDA#FF:STAXX15+2 1725LDAQQ19+1:CLC:ADCQQ19+5:STAXX15+1:JSRHLOIN:LDAQQ19+1:SEC:SBCQQ19+2:BCSTT86:LDA#0:.TT86 CLC:ADCQQ19+5:STAXX15+1:LDAQQ19+1:CLC:ADCQQ19+2:ADCQQ19+5:CMP#152:BCCTT87 1750LDXQQ11:BMITT87:LDA#151:.TT87 STAXX15+3:LDAQQ19:STAXX15:STAXX15+2:JMPLL30 1800.TT126 LDA#104:STAQQ19:LDA#90:STAQQ19+1:LDA#16:STAQQ19+2:JSRTT15:LDAQQ14:STAK:JMPTT128 2000.TT14\Crcl/+ 2010LDAQQ11:BMITT126:LDAQQ14:LSRA:LSRA:STAK:LDAQQ0:STAQQ19:LDAQQ1:LSRA:STAQQ19+1:LDA#7:STAQQ19+2:JSRTT15:LDAQQ19+1:CLC:ADC#24:STAQQ19+1 2300.TT128 LDAQQ19:STAK3:LDAQQ19+1:STAK4:LDX#0:STXK4+1:STXK3+1:\STXLSX:INX:STXLSP:LDX#2:STXSTP 2310JSRCIRCLE2:\LDA#FFSTALSX:RTS 2650.TT219\Buy 2655\LDA#2:JSRTT66-2:JSRTT163:LDA#128:STAQQ17:\JSRFLKB:LDA#0:STAQQ29 2660.TT220 JSRTT151:LDAQQ25:BNETT224:JMPTT222:.TQ4 LDY#176:.Tc JSRTT162:TYA:JSRprq:.TTX224 JSRdn2:.TT224 2671JSRCLYNS:LDA#204:JSRTT27:LDAQQ29:CLC:ADC#208:JSRTT27:LDA#&2F:JSRTT27:JSRTT152:LDA#&3F:JSRTT27:JSRTT67:LDX#0:STXR:LDX#12:STXT1:.TT223 2700JSRgnum:BCSTQ4:STAP:JSRtnpr:LDY#206:BCSTc:LDAQQ24:STAQ:JSRGCASH:JSRLCASH:LDY#197:BCCTc 2708LDYQQ29:LDAR:PHA:CLC:ADCQQ20,Y:STAQQ20,Y:LDAAVL,Y:SEC:SBCR:STAAVL,Y:PLA:BEQTT222:JSRdn 2710.TT222 LDAQQ29:CLC:ADC#5:STAYC:LDA#0:STAXC:INCQQ29:LDAQQ29:CMP#17:BCSBAY2:JMPTT220:.BAY2 LDA#f9:JMPFRCE 2750.gnum LDX#0:STXR:LDX#12:STXT1:.TT223 JSRTT217:STAQ:SEC:SBC#&30:BCCOUT:CMP#10:BCSBAY2:STAS:LDAR:CMP#26:BCSOUT:ASLA:STAT:ASLA:ASLA:ADCT:ADCS:STAR:CMPQQ25:BEQTT226:BCSOUT:.TT226 LDAQ:JSRTT26:DECT1:BNETT223:.OUT LDAR:RTS 2850.TT208\Sel 2855LDA#4:JSRTT66:LDA#4:STAYC:STAXC:\JSRFLKB:LDA#205:JSRTT27:LDA#206:JSRTT68 2900.TT210\Crgo 2910LDY#0:.TT211 STYQQ29:LDXQQ20,Y:BEQTT212 2912TYA:ASLA:ASLA:TAY:LDAQQ23+1,Y:STAQQ19+1 2915TXA:PHA:JSRTT69:CLC:LDAQQ29:ADC#208 2917JSRTT27:LDA#14:STAXC:PLA:TAX:CLC:JSRpr2:JSRTT152 2922LDAQQ11:CMP#4:BNETT212:LDA#205:JSRTT214 2923BCCTT212:LDAQQ29:LDX#255:STXQQ17:JSRTT151 2925LDYQQ29:LDAQQ20,Y:STAP:LDAQQ24:STAQ:JSRGCASH:JSRMCASH 2935LDA#0:LDYQQ29:STAQQ20,Y:STAQQ17 2940.TT212 LDYQQ29:INY:CPY#17:BCSP%+5:JMPTT211:LDAQQ11:CMP#4:BNEP%+8:JSRdn2:JMPBAY2:RTS 2942.TT213\Invntry 2945LDA#8:JSRTT66:LDA#11:STAXC:LDA#164:JSRTT60:JSRNLIN4:JSRfwl 2950LDACRGO:CMP#26:BCCP%+7:LDA#&6B:JSRTT27:JMPTT210 2965.TT214 PHA:JSRTT162:PLA:.TT221 JSRTT27:LDA#225:JSRTT27 2966JSRTT217:ORA#32:CMP#&79:BEQTT218:LDA#&6E:JMPTT26:.TT218 JSRTT26:SEC:RTS 3000.TT16 TXA:PHA:DEY:TYA:EOR#255:PHA:JSRWSCAN:JSRTT103:PLA:STAQQ19+3 3010LDAQQ10:JSRTT123:LDAQQ19+4:STAQQ10:STAQQ19+1:PLA 3020STAQQ19+3:LDAQQ9:JSRTT123:LDAQQ19+4:STAQQ9:STAQQ19:.TT103 3030LDAQQ11:BEQTT180:BMITT105:LDAQQ9:STAQQ19:LDAQQ10:LSRA:STAQQ19+1 3040LDA#4:STAQQ19+2:JMPTT15 3045.TT123 STAQQ19+4:CLC:ADCQQ19+3:LDXQQ19+3:BMITT124:BCCTT125 3047RTS:.TT124 BCCTT180:.TT125 STAQQ19+4:.TT180 RTS 3050.TT105 LDAQQ9:SEC:SBCQQ0:CMP#38:BCCTT179:CMP#230:BCCTT180 3055.TT179 ASLA:ASLA:CLC:ADC#104:STAQQ19 3060LDAQQ10:SEC:SBCQQ1:CMP#38:BCCP%+6:CMP#220:BCCTT180 3065ASLA:CLC:ADC#90:STAQQ19+1:LDA#8:STAQQ19+2:JMPTT15 3300.TT23\ShrtSc 3310LDA#128:JSRTT66:LDA#7:STAXC:LDA#190:JSRNLIN3:JSRTT14:JSRTT103:JSRTT81 3349LDA#0:STAXX20:LDX#24:.EE3 STAINWK,X:DEX:BPLEE3 3350.TT182 LDAQQ15+3:SEC:SBCQQ0:BCSTT184:EOR#FF:ADC#1:.TT184 CMP#20:BCSTT187:LDAQQ15+1:SEC:SBCQQ1:BCSTT186:EOR#FF:ADC#1:.TT186 CMP#38:BCSTT187 3370LDAQQ15+3:SEC:SBCQQ0:ASLA:ASLA:ADC#104:STAXX12:LSRA:LSRA:LSRA:STAXC:INCXC:LDAQQ15+1:SEC:SBCQQ1:ASLA:ADC#90:STAK4:LSRA:LSRA:LSRA 3377TAY:LDXINWK,Y:BEQEE4:INY:LDXINWK,Y:BEQEE4:DEY:DEY:LDXINWK,Y:BNEee1:.EE4 STYYC:CPY#3:BCCTT187:DEX:STXINWK,Y 3380LDA#128:STAQQ17:JSRcpl:.ee1 3390\bigstars:LDA#0:STAK3+1:STAK4+1:STAK+1:LDAXX12:STAK3:LDAQQ15+5:AND#1:ADC#2:STAK:JSRFLFLLS:JSRSUN:JSRFLFLLS 3400.TT187 JSRTT20:INCXX20:BEQTT111-1:JMPTT182 3450.TT81 LDX#5:LDAQQ21,X:STAQQ15,X:DEX:BPLTT81+2 3500RTS:.TT111 JSRTT81:LDY#127:STYT:LDA#0:STAU 3510.TT130 LDAQQ15+3:SEC:SBCQQ9:BCSTT132:EOR#FF:ADC#1:.TT132 LSRA:STAS:LDAQQ15+1:SEC:SBCQQ10:BCSTT134:EOR#FF:ADC#1:.TT134 LSRA:CLC:ADCS:CMPT:BCSTT135 3550STAT:LDX#5:.TT136 LDAQQ15,X:STAQQ19,X:DEX:BPLTT136:.TT135 3560JSRTT20:INCU:BNETT130:LDX#5:.TT137 LDAQQ19,X:STAQQ15,X:DEX 3570BPLTT137:LDAQQ15+1:STAQQ10:LDAQQ15+3:STAQQ9 3575SEC:SBCQQ0:BCSTT139:EOR#FF:ADC#1:.TT139 JSRSQUA2:STAK+1:LDAP:STAK:LDAQQ10 3590SEC:SBCQQ1:BCSTT141:EOR#FF:ADC#1:.TT141 LSRA:JSRSQUA2:PHA:LDAP:CLC:ADCK 3610STAQ:PLA:ADCK+1:STAR:JSRLL5:LDAQ:ASLA:LDX#0:STXQQ8+1:ROLQQ8+1:ASLA:ROLQQ8+1:STAQQ8:JMPTT24 4340.hy6 JSRCLYNS:LDA#15:STAXC:JMPTT27 4350.hyp LDAQQ12:BNEhy6:LDAQQ22+1:BNEzZ+1:JSRCTRL:BMIGhy 4353JSRhm 4355LDAQQ8:ORAQQ8+1:BEQzZ+1:LDA#7:STAXC:LDA#23:STAYC:LDA#0:STAQQ17:LDA#189:JSRTT27:LDAQQ8+1:BNETT147:LDAQQ14:CMPQQ8:BCCTT147 4380LDA#&2D:JSRTT27:JSRcpl:.wW LDA#15:STAQQ22+1:STAQQ22:TAX:JMPee3\hy5 RTS 4392.Ghy JSRTT111:LDXGHYP:BEQhy5:INX:STXQQ8:STXQQ8+1:STXGHYP:STXFIST:JSRwW:LDX#5:INCGCNT:LDAGCNT:AND#7:STAGCNT:.G1 LDAQQ21,X:ASLA:ROLQQ21,X:DEX:BPLG1:\JSRDORND:.zZ LDA#&60:STAQQ9:STAQQ10:JSRTT110:LDA#116:JSRMESS:.jmp LDAQQ9:STAQQ0:LDAQQ10 4393STAQQ1:.hy5 RTS 4395.ee3 LDY#1:STYYC:DEY:STYXC:.pr6 CLC:.pr5 LDA#5:JMPTT11 4400.TT147 LDA#202:.prq JSRTT27:LDA#&3F:JMPTT27 5000.TT151\Pmk-A 5010PHA:STAQQ19+4:ASLA:ASLA:STAQQ19:LDA#1:STAXC:PLA:ADC#208 5015JSRTT27:LDA#14:STAXC:LDXQQ19:LDAQQ23+1,X:STAQQ19+1:LDAQQ26:ANDQQ23+3,X:CLC:ADCQQ23,X:STAQQ24:JSRTT152 5050JSRvar:LDAQQ19+1:BMITT155:LDAQQ24:ADCQQ19+3:JMPTT156 5060.TT155 LDAQQ24:SEC:SBCQQ19+3:.TT156 STAQQ24:STAP:LDA#0:JSRGC2 5070SEC:JSRpr5:LDYQQ19+4:LDA#5:LDXAVL,Y:STXQQ25 5100CLC:BEQTT172:JSRpr2+2:JMPTT152:.TT172 LDAXC:ADC#4:STAXC:LDA#&2D:BNETT162+2 5110.TT152 LDAQQ19+1:AND#96:BEQTT160:CMP#32:BEQTT161 5120JSRTT16a:.TT162 LDA#32:JMPTT27 5130.TT160 LDA#&74:JSRTT26:BCCTT162 5140.TT161 LDA#&6B:JSRTT26:.TT16a LDA#&67:JMPTT26 5160.TT163 LDA#17:STAXC:LDA#FF:BNETT162+2 5200.TT167\MktP 5210LDA#16:JSRTT66:LDA#5:STAXC:LDA#167:JSRNLIN3:LDA#3:STAYC:JSRTT163:LDA#0:STAQQ29:.TT168 LDX#128:STXQQ17:JSRTT151:INCYC 5250INCQQ29:LDAQQ29:CMP#17:BCCTT168:RTS 5900.var LDAQQ19+1:AND#31:LDYQQ28:STAQQ19+2:CLC:LDA#0:STAAVL+16:.TT153 DEY:BMITT154:ADCQQ19+2:JMPTT153:.TT154 STAQQ19+3:RTS 5980.hyp1 JSRTT111:JSRjmp:LDX#5:.TT112 LDAQQ15,X:STAQQ2,X:DEX:BPLTT112:INX:STXEV:LDAQQ3:STAQQ28:LDAQQ5:STAtek:LDAQQ4:STAgov:RTS 5990.GVL JSRDORND:STAQQ26:LDX#0:STXXX4:.hy9 LDAQQ23+1,X:STAQQ19+1:JSRvar:LDAQQ23+3,X:ANDQQ26:CLC:ADCQQ23+2,X:LDYQQ19+1:BMITT157:SEC:SBCQQ19+3:JMPTT158:.TT157 CLC:ADCQQ19+3:.TT158 BPLTT159:LDA#0:.TT159 5994LDYXX4:AND#63:STAAVL,Y:INY:TYA:STAXX4:ASLA:ASLA:TAX:CMP#63:BCChy9:.hyR RTS 5995.GTHG JSRZe:LDA#FF:STAINWK+32:LDA#THG:JSRNWSHP:LDA#TGL:JMPNWSHP 5996.ptg LSRCOK:SEC:ROLCOK 5998.MJP\LDA#1:JSRTT66-2:JSRLL164:JSRRES2:STYMJ:.MJP1 JSRGTHG:LDA#3:CMPMANY+THG:BCSMJP1:STANOSTM:LDX#0:JSRLOOK1:LDAQQ1:EOR#31:STAQQ1:RTS 6000.TT18\HSPC 6005LDAQQ14:SEC:SBCQQ8:STAQQ14:LDAQQ11:BNEee5:JSRTT66:JSRLL164:.ee5 JSRCTRL:ANDPATG:BMIptg:JSRDORND:CMP#253:BCSMJP\JSRTT111:JSRhyp1+3:JSRGVL:JSRRES2:JSRSOLAR 6500LDAQQ11:AND#63:BNEhyR:JSRTTX66:LDAQQ11:BNETT114:INCQQ11:.TT110 LDXQQ12:BEQNLUNCH:JSRLAUN:JSRRES2:JSRTT111:INCINWK+8:JSRSOS1:LDA#128:STAINWK+8:INCINWK+7:JSRNWSPS:LDA#12:STADELTA:JSRBAD:ORAFIST:STAFIST 6510.NLUNCH LDX#0:STXQQ12:JMPLOOK1:.TT114 BMITT115:JMPTT22:.TT115 JMPTT23 6530.LCASH STXT1:LDACASH+3:SEC:SBCT1:STACASH+3:STYT1:LDACASH+2:SBCT1:STACASH+2:LDACASH+1:SBC#0:STACASH+1:LDACASH:SBC#0:STACASH:BCSTT113 6540.MCASH TXA:CLC:ADCCASH+3:STACASH+3:TYA:ADCCASH+2:STACASH+2:LDACASH+1:ADC#0:STACASH+1:LDACASH:ADC#0:STACASH:CLC:.TT113 RTS 6550.GCASH JSRMULTU:.GC2 ASLP:ROLA:ASLP:ROLA:TAY:LDXP:RTS 6690.bay JMPBAY 6700.EQSHP JSRDIALS:LDA#32:JSRTT66:LDA#12:STAXC:LDA#207:JSRspc:LDA#185:JSRNLIN3:LDA#128:STAQQ17:INCYC:LDAtek:CLC:ADC#3:CMP#12:BCCP%+4:LDA#12:STAQ:STAQQ25:INCQ:LDA#70:SEC:SBCQQ14:ASLA:STAPRXS 6710LDX#1:.EQL1 STXXX13:JSRTT67:LDXXX13:CLC:JSRpr2:JSRTT162:LDAXX13:CLC:ADC#&68:JSRTT27:LDAXX13:JSRprx-3:SEC:LDA#25:STAXC:LDA#6:JSRTT11:LDXXX13:INX:CPXQ:BCCEQL1 6720JSRCLYNS:LDA#127:JSRprq:JSRgnum:beqbay:bcsbay:SBC#0:LDX#2:STXXC:INCYC:PHA:JSReq:PLA:BNEet0:STAMCNT:LDX#70:STXQQ14:.et0 CMP#1:BNEet1:LDXNOMSL:INX:LDY#&75:CPX#5:BCSpres 6730STXNOMSL:JSRmsblob:.et1 LDY#&6B:CMP#2:BNEet2:LDX#37:CPXCRGO:BEQpres:STXCRGO:.et2 CMP#3:BNEet3:INY:LDXECM:BNEpres:DECECM:.et3 CMP#4:BNEet4:JSRqv:LDA#4:LDYLASER,X:BEQed4:.ed7 LDY#187:BNEpres:.ed4 LDA#POW:STALASER,X:LDA#4:.et4 6740CMP#5:BNEet5:JSRqv:STXT1:LDA#5:LDYLASER,X:BEQed5:\BPLP%+4:BMIed7:LDA#4:JSRprx:JSRMCASH:.ed5 LDA#POW+128:LDXT1:STALASER,X:.et5 6750LDY#&6F:CMP#6:BNEet6:LDXBST:BEQed9:.pres STYK:JSRprx:JSRMCASH:LDAK:JSRspc:LDA#31:JSRTT27:.err JSRdn2:JMPBAY:.ed9 DECBST:.et6 INY:CMP#7:BNEet7:LDXESCP:BNEpres:DECESCP:.et7 INY:CMP#8:BNEet8:LDXBOMB:BNEpres:LDX#&7F:STXBOMB:.et8 6800INY:CMP#9:BNEetA:LDXENGY:BNEpres:INCENGY:.etA INY:CMP#10:BNEetB:LDXDKCMP:BNEpres:DECDKCMP:.etB:INY:CMP#11:BNEet9:LDXGHYP:BNEpres:DECGHYP:.et9 JSRdn:JMPEQSHP:.dn JSRTT162:LDA#119:JSRspc:.dn2 JSRBEEP:LDY#50:JMPDELAY 6900.eq JSRprx:JSRLCASH:BCSc:LDA#197:JSRprq:JMPerr:SEC:SBC#1:.prx ASLA:TAY:LDXPRXS,Y:LDAPRXS+1,Y:TAY:.c RTS 6910.qv LDY#16:STYYC:.qv1 LDX#12:STXXC:TYA:CLC:ADC#B-16:JSRspc:LDAYC:CLC:ADC#&50:JSRTT27:INCYC:LDYYC:CPY#20:BCCqv1:.qv3 JSRCLYNS:.qv2 LDA#175:JSRprq:JSRTT217:SEC:SBC#&30:CMP#4:BCSqv3:TAX:RTS 9900] 9910IFZ>4OSCLI("S.ELTD "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9920PRINT"D d,";:GOTO10 ================================================ FILE: 1-source-files/original-sources/text-sources/ELITEE.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 11GOTO20 12*L.ELITEF 20REM ELITE 100H%=L%+P%-C%:O%=W%:A$="(C)Bell/Braben1984":B$=STRING$(26," "):B$="":FORI%=1TOLENA$:B$=B$+CHR$(ASC(MID$(A$,I%,1))EOR&A4):NEXT:[OPTZ:EQUSB$ 190.cpl LDX#5:.TT53 LDAQQ15,X:STAQQ19,X:DEX:BPLTT53:LDY#3:BITQQ15:BVSP%+3:DEY:STYT:.TT55 LDAQQ15+5:AND#31:BEQP%+7:ORA#128:JSRTT27:JSRTT54:DECT:BPLTT55:LDX#5:.TT56 LDAQQ19,X:STAQQ15,X:DEX:BPLTT56:RTS 200.cmn LDY#0:.QUL4 LDANA%,Y:CMP#13:BEQypl-1:JSRTT26:INY:BNEQUL4:RTS 300.ypl LDAMJ:BNEcmn-1:JSRTT62:JSRcpl:.TT62 LDX#5:.TT78 LDAQQ15,X:LDYQQ2,X:STAQQ2,X:STYQQ15,X:DEX:BPLTT78:RTS 500.tal CLC:LDXGCNT:INX:JMPpr2:.fwl LDA#105:JSRTT68:LDXQQ14:SEC:JSRpr2:LDA#195:JSRplf:.PCASH LDA#119:BNETT27 510.csh LDX#3:.pc1 LDACASH,X:STAK,X:DEX:BPLpc1:LDA#9:STAU:SEC:JSRBPRNT:LDA#226:.plf JSRTT27:JMPTT67:.TT68 JSRTT27:.TT73 LDA#&3A 600.TT27 TAX:BEQcsh:BMITT43:DEX:BEQtal:DEX:BEQypl:dex:bneP%+5:JMPcpl:dex:beqcmn:dex:beqfwl:dex:bneP%+7:LDA#128:STAQQ17:RTS:DEX:DEX:BNEP%+5:STXQQ17:RTS:dex:beqcrlf:CMP#&60:BCSex:CMP#14:BCCP%+6:CMP#32:BCCqw:LDXQQ17 620BEQTT74:BMITT41:BITQQ17:BVSTT46:.TT42 CMP#65:BCCTT44:CMP#&5B:BCSTT44:ADC#32:.TT44 JMPTT26:.TT41 BITQQ17:BVSTT45:CMP#65:BCCTT74:PHA:TXA:ORA#64:STAQQ17:PLA:BNETT44 630.qw ADC#114:BNEex:.crlf LDA#21:STAXC:BNETT73:.TT45 CPX#FF:BEQTT48:CMP#65:BCSTT42:.TT46 PHA:TXA:AND#191:STAQQ17:PLA:.TT74 JMPTT26:.TT43 CMP#160:BCSTT47:AND#127:ASLA:TAY:LDAQQ16,Y 670JSRTT27:LDAQQ16+1,Y:CMP#63:BEQTT48:JMPTT27:.TT47 SBC#160:.ex TAX:LDA#(QQ18 MOD256):STAV:LDA#(QQ18 DIV256):STAV+1:LDY#0:TXA:BEQTT50 680.TT51 LDA(V),Y:BEQTT49:INY:BNETT51:INCV+1:BNETT51:.TT49 INY:BNETT59:INCV+1:.TT59 DEX:BNETT51:.TT50 693TYA:PHA:LDAV+1:PHA:LDA(V),Y:EOR#35 695JSRTT27:PLA:STAV+1:PLA:TAY:INY:BNEP%+4:INCV+1:LDA(V),Y:BNETT50:.TT48 RTS 1990.EX2 LDAINWK+31:ORA#&A0:STAINWK+31:RTS 2000.DOEXP LDAINWK+31:AND#64:BEQP%+5:JSRPTCLS:LDAINWK+6:STAT:LDAINWK+7:CMP#&20:BCCP%+6:LDA#&FE:BNEyy:ASLT:ROLA:ASLT:ROLA:SEC:ROLA:.yy STAQ:LDY#1:LDA(XX19),Y:ADC#4:BCSEX2 2040STA(XX19),Y:JSRDVID4:LDAP:CMP#&1C:BCCP%+6:LDA#&FE:BNE`_:ASLR:ROLA:ASLR:ROLA:ASLR:ROLA:.`_ DEY:STA(XX19),Y:LDAINWK+31:AND#&BF:STAINWK+31:AND#8:BEQTT48 2050LDY#2:LDA(XX19),Y:TAY:.EXL1 LDAXX3-7,Y:STA(XX19),Y:DEY:CPY#6:BNEEXL1:LDAINWK+31:ORA#64:STAINWK+31 2100.PTCLS LDY#0:LDA(XX19),Y:STAQ:INY:LDA(XX19),Y:BPLP%+4:EOR#FF:LSRA:LSRA:LSRA:ORA#1:STAU:INY:LDA(XX19),Y:STATGT:LDARAND+1:PHA 2110LDY#6:.EXL5 LDX#3:.EXL3 INY:LDA(XX19),Y:STAK3,X:DEX:BPLEXL3:STYCNT:LDY#2:.EXL2 INY:LDA(XX19),Y:EORCNT:STARAND-3,Y:CPY#6:BNEEXL2:LDYU 2140.EXL4 JSRDORND2:STAZZ:LDAK3+1:STAR:LDAK3:JSREXS1:BNEEX11:CPX#2*Y-1:BCSEX11:STXY1:LDAK3+3:STAR:LDAK3+2:JSREXS1:BNEEX4:LDAY1:JSRPIXEL:.EX4 DEY:BPLEXL4:LDYCNT:CPYTGT:BCCEXL5 2180PLA:STARAND+1:LDAK%+6:STARAND+3:RTS:.EX11 JSRDORND2:JMPEX4 2200.EXS1 STAS:JSRDORND2:ROLA:BCSEX5:JSRFMLTU:ADCR:TAX:LDAS:ADC#0:RTS 2210.EX5 JSRFMLTU:STAT:LDAR:SBCT:TAX:LDAS:SBC#0:RTS 3008.SOS1 JSRmsblob:LDA#127:STAINWK+29:STAINWK+30:LDAtek:AND#2:ORA#128:JMPNWSHP 3010.SOLAR LSRFIST:JSRZINF:LDAQQ15+1:AND#7:ADC#6:LSRA:STAINWK+8:RORA:STAINWK+2:STAINWK+5 3020JSRSOS1:LDAQQ15+3:AND#7:ORA#129:STAINWK+8:LDAQQ15+5:AND#3:STAINWK+2:STAINWK+1:LDA#0:STAINWK+29:STAINWK+30:LDA#&81:JSRNWSHP 3600.NWSTARS LDAQQ11:\ORAMJ:BNEWPSHPS:.nWq LDYNOSTM:.SAL4 JSRDORND:ORA#8:STASZ,Y:STAZZ:JSRDORND:STASX,Y:STAX1:JSRDORND:STASY,Y:STAY1:JSRPIXEL2:DEY:BNESAL4 3710.WPSHPS LDX#0:.WSL1 LDAFRIN,X:BEQWS2:BMIWS1:STATYPE:JSRGINF:LDY#31 3730.WSL2 LDA(INF),Y:STAINWK,Y:DEY:BPLWSL2:STXXSAV:JSRSCAN:LDXXSAV:LDY#31:LDA(INF),Y:AND#&A7:STA(INF),Y:.WS1 INX:BNEWSL1:.WS2 LDX#FF:STXLSX2:STXLSY2 3740.FLFLLS LDY#2*Y-1:LDA#0:.SAL6 STALSO,Y:DEY:BNESAL6:DEY:STYLSX:RTS 3810.DET1 LDA#6:SEI:STA&FE00:STX&FE01:CLI:RTS 3900DEX:RTS:.SHD INX:BEQSHD-2:.DENGY DECENERGY:PHP:BNEP%+5:INCENERGY:PLP:RTS 4000.COMPAS JSRDOT:LDASSPR:BNESP1:JSRSPS1:JMPSP2:.SPS2 ASLA:TAX:LDA#0:RORA:TAY:LDA#20 \14:STAQ:TXA:JSRDVID4:LDXP 4080TYA:BMILL163:LDY#0:RTS:.LL163 LDY#FF:TXA:EOR#FF:TAX:INX:RTS 4090.SPS4 LDX#8:.SPL1 LDAK%+NI%,X:STAK3,X:DEX:BPLSPL1:JMPTAS2 4100.SP1 JSRSPS4:.SP2 LDAXX15:JSRSPS2:TXA:ADC#195\X-1:STACOMX:LDAXX15+1:JSRSPS2:STXT:LDA#204:SBCT:STACOMY 4130LDA#&F0:LDXXX15+2:BPLP%+4:LDA#FF:STACOMC 4200.DOT LDACOMY:STAY1:LDACOMX:STAX1:LDACOMC:STACOL:CMP#&F0:BNECPIX2:.CPIX4 JSRCPIX2:DECY1:.CPIX2 LDAY1 4250\.CPIX:TAY:LSRA:LSRA:LSRA:ORA#&60:STASCH:LDAX1:AND#&F8:STASC:TYA:AND#7:TAY:LDAX1:AND#6:LSRA:TAX:LDACTWOS,X:ANDCOL:EOR(SC),Y:STA(SC),Y 4260LDACTWOS+1,X:BPLCP1:LDASC:ADC#8:STASC:LDACTWOS+1,X:.CP1 ANDCOL:EOR(SC),Y:STA(SC),Y:RTS 4300.OOPS STAT:LDY#8:LDX#0:LDA(INF),Y:BMIOO1:LDAFSH:SBCT:BCCOO2:STAFSH:RTS:.OO2 \LDX#0:STXFSH:BCCOO3:.OO1 LDAASH:SBCT:BCCOO5:STAASH:RTS:.OO5 \LDX#0:STXASH:.OO3 ADCENERGY:STAENERGY:BEQP%+4:BCSP%+5:JMPDEATH:JSREXNO3:JMPOUCH 4410.SPS3 LDAK%+1,X:STAK3,X:LDAK%+2,X:TAY:AND#127:STAK3+1,X:TYA:AND#128:STAK3+2,X:RTS 4450.GINF TXA:ASLA:TAY:LDAUNIV,Y:STAINF:LDAUNIV+1,Y:STAINF+1:RTS 4480.NWSPS JSRSPBLB:LDX#1:STXINWK+32:DEX:STXINWK+30:\STXINWK+31:STXFRIN+1:DEX:STXINWK+29:LDX#10:JSRNwS1:JSRNwS1:JSRNwS1 4490LDA#(LSO MOD256):STAINWK+33:LDA#(LSO DIV256):STAINWK+34:LDA#SST 4500.NWSHP STAT:LDX#0:.NWL1 LDAFRIN,X:BEQNW1:INX:CPX#NOSH:BCCNWL1:.NW3 CLC:RTS 4510.NW1 JSRGINF:LDAT:BMINW2:ASLA:TAY:LDAXX21-2,Y:STAXX0:LDAXX21-1,Y:STAXX0+1:CPY#2*SST:BEQNW6:LDY#5:LDA(XX0),Y:STAT1:LDASLSP:SEC:SBCT1:STAINWK+33:LDASLSP+1:SBC#0:STAINWK+34 4530LDAINWK+33:\SEC:SBCINF:TAY:LDAINWK+34:SBCINF+1:BCCNW3+1:BNENW4:CPY#NI%:BCCNW3+1:.NW4 4550LDAINWK+33:STASLSP:LDAINWK+34:STASLSP+1:.NW6 LDY#14:LDA(XX0),Y:STAINWK+35:LDY#19:LDA(XX0),Y:AND#7:STAINWK+31 4560LDAT:.NW2 STAFRIN,X:TAX:BMIP%+5:INCMANY,X:LDY#(NI%-1):.NWL3 LDAINWK,Y:STA(INF),Y:DEY:BPLNWL3:SEC:RTS 4600.NwS1 LDAINWK,X:EOR#128:STAINWK,X:INX:INX:RTS 4710.ABORT LDX#FF:.ABORT2 STXMSTG:LDXNOMSL:JSRMSBAR:STYMSAR:RTS 4730.ECBLB2 LDA#32:STAECMA:ASLA:JSRNOISE:.ECBLB LDA#7*8:\" <<120<":LDX#(ECBT MOD256):LDY#(ECBT DIV256):BNEBULB-2 4740.SPBLB LDA#24*8:\"<<128<":LDX#(SPBT MOD256):LDY#(SPBT DIV256):.BULB STASC:STXP+1:STYP+2:LDA#&7D:JMPRREN 4800.ECBT EQUW&E0E0:EQUB&80:.SPBT EQUD&E080E0E0:EQUD&E0E020E0 4900.MSBAR TXA:ASLA:ASLA:ASLA:STAT:LDA#49\113:SBCT:STASC:LDA#&7E:STASCH:TYA:LDY#5:.MBL1 STA(SC),Y:DEY:BNEMBL1:RTS 5000.PROJ LDAINWK:STAP:LDAINWK+1:STAP+1:LDAINWK+2:JSRPLS6:BCSPL2-1:LDAK:ADC#X:STAK3:TXA:ADC#0:STAK3+1 5010LDAINWK+3:STAP:LDAINWK+4:STAP+1:LDAINWK+5:EOR#128:JSRPLS6:BCSPL2-1:LDAK:ADC#Y:STAK4:TXA:ADC#0:STAK4+1:CLC:RTS 5020.PL2 LDATYPE:LSRA:BCSP%+5:JMPWPLS2:JMPWPLS 5040.PLANET LDAINWK+8:BMIPL2:CMP#48:BCSPL2:ORAINWK+7:BEQPL2:JSRPROJ:BCSPL2 5090LDA#96:STAP+1:LDA#0:STAP:JSRDVID3B2:LDAK+1:BEQPL82:LDA#&F8:STAK:.PL82 5110LDATYPE:LSRA:BCCPL9:JMPSUN:.PL9 JSRWPLS2:JSRCIRCLE:BCSPL20:LDAK+1:BEQPL25:.PL20 RTS 5160.PL25 LDATYPE:CMP#&80:BNEPL26:LDAK:CMP#6:BCCPL20:LDAINWK+14:EOR#128:STAP:LDAINWK+20:JSRPLS4:LDX#9:JSRPLS1:STAK2:STYXX16:JSRPLS1:STAK2+1:STYXX16+1:LDX#15:JSRPLS5 5230JSRPLS2:LDAINWK+14:EOR#128:STAP:LDAINWK+26:JSRPLS4 5240LDX#21:JSRPLS5:JMPPLS2 5270.PL26\crtr:LDAINWK+20:BMIPL20 5280LDX#15:JSRPLS3:CLC:ADCK3:STAK3:TYA:ADCK3+1:STAK3+1:JSRPLS3:STAP:LDAK4:SEC:SBCP:STAK4:STYP:LDAK4+1:SBCP:STAK4+1 5300LDX#9:JSRPLS1:LSRA:STAK2:STYXX16:JSRPLS1:LSRA:STAK2+1:STYXX16+1 5310LDX#21:JSRPLS1:LSRA:STAK2+2:STYXX16+2:JSRPLS1:LSRA:STAK2+3:STYXX16+3 5320LDA#64:STATGT:LDA#0:STACNT2:JMPPLS22 5330.PLS1 LDAINWK,X:STAP:LDAINWK+1,X:AND#127:STAP+1:LDAINWK+1,X:AND#128 5340JSRDVID3B2:LDAK:LDYK+1:BEQP%+4:LDA#&FE:LDYK+3:INX:INX:RTS 5350.PLS2 LDA#31:STATGT:.PLS22 LDX#0:STXCNT:DEX:STXFLAG:.PLL4 5360LDACNT2:AND#31:TAX:LDASNE,X:STAQ:LDAK2+2:JSRFMLTU:STAR:LDAK2+3:JSRFMLTU:STAK:LDXCNT2:CPX#33:LDA#0:RORA:STAXX16+5 5370LDACNT2:CLC:ADC#16:AND#31:TAX:LDASNE,X:STAQ:LDAK2+1:JSRFMLTU:STAK+2:LDAK2:JSRFMLTU:STAP:LDACNT2:ADC#15:AND#63:CMP#33:LDA#0:RORA:STAXX16+4 5380LDAXX16+5:EORXX16+2:STAS:LDAXX16+4:EORXX16:JSRADD:STAT:BPLPL42:TXA:EOR#FF:CLC:ADC#1:TAX:LDAT:EOR#&7F:ADC#0:STAT:.PL42:TXA:ADCK3:STAK6:LDAT:ADCK3+1:STAK6+1 5390LDAK:STAR:LDAXX16+5:EORXX16+3:STAS:LDAK+2:STAP:LDAXX16+4:EORXX16+1:JSRADD:EOR#128:STAT:BPLPL43:TXA:EOR#FF:CLC:ADC#1:TAX:LDAT:EOR#&7F:ADC#0:STAT:.PL43 5400JSRBLINE:CMPTGT:BEQP%+4:BCSPL40:LDACNT2:CLC:ADCSTP:AND#63:STACNT2:JMPPLL4:.PL40 RTS 5410JMPWPLS:.PLF3 TXA:EOR#FF:CLC:ADC#1:TAX:.PLF17 LDA#FF:JMPPLF5 5430.SUN LDA#1:STALSX:JSRCHKON:BCSPLF3-3:LDA#0:LDXK:CPX#&60:ROLA:CPX#&28:ROLA:CPX#&10:ROLA 5450.PLF18 STACNT:LDA#2*Y-1:LDXP+2:BNEPLF2:CMPP+1:BCCPLF2:LDAP+1:BNEPLF2:LDA#1:.PLF2 STATGT 5460LDA#2*Y-1:SEC:SBCK4:TAX:LDA#0:SBCK4+1:BMIPLF3:BNEPLF4:INX:DEX:BEQPLF17:CPXK:BCCPLF5:.PLF4 LDXK:LDA#0:.PLF5 STXV:STAV+1 5470LDAK:JSRSQUA2:STAK2+1:LDAP:STAK2:LDY#2*Y-1:LDASUNX:STAYY:LDASUNX+1:STAYY+1:.PLFL2 CPYTGT:BEQPLFL:LDALSO,Y:BEQPLF13:JSRHLOIN2:.PLF13 DEY:BNEPLFL2 5480.PLFL LDAV:JSRSQUA2:STAT:LDAK2:SEC:SBCP:STAQ:LDAK2+1:SBCT:STAR:STYY1:JSRLL5:LDYY1:JSRDORND:ANDCNT:CLC:ADCQ:BCCPLF44:LDA#FF:.PLF44 5490LDXLSO,Y:STALSO,Y:BEQPLF11:LDASUNX:STAYY:LDASUNX+1:STAYY+1:TXA:JSREDGES:LDAX1:STAXX:LDAX2:STAXX+1 5500LDAK3:STAYY:LDAK3+1:STAYY+1:LDALSO,Y:JSREDGES:BCSPLF23:LDAX2:LDXXX:STXX2:STAXX:JSRHLOIN:.PLF23 LDAXX:STAX1:LDAXX+1:STAX2:.PLF16 JSRHLOIN:.PLF6 5530DEY:BEQPLF8:LDAV+1:BNEPLF10:DECV:BNEPLFL:DECV+1:.PLFLS JMPPLFL 5535.PLF11 LDXK3:STXYY:LDXK3+1:STXYY+1:JSREDGES:BCCPLF16:LDA#0:STALSO,Y:BEQPLF6 5540.PLF10 LDXV:INX:STXV:CPXK:BCCPLFLS:BEQPLFLS:LDASUNX:STAYY:LDASUNX+1:STAYY+1:.PLFL3 LDALSO,Y:BEQPLF9:JSRHLOIN2 5550.PLF9 DEY:BNEPLFL3:.PLF8 CLC:LDAK3:STASUNX:LDAK3+1:STASUNX+1:.RTS2 RTS 5600.CIRCLE JSRCHKON:BCSRTS2 5610LDA#0:STALSX2 5700LDXK:LDA#8:CPX#8:BCCPL89:LSRA:CPX#60:BCCPL89:LSRA:.PL89 STASTP:.CIRCLE2 LDX#FF:STXFLAG:INX:STXCNT:.PLL3 5710LDACNT:JSRFMLTU2:LDX#0:STXT:LDXCNT:CPX#33:BCCPL37:EOR#FF:ADC#0:TAX:LDA#FF:ADC#0:STAT:TXA:CLC 5720.PL37 ADCK3:STAK6:LDAK3+1:ADCT:STAK6+1 5730LDACNT:CLC:ADC#16:JSRFMLTU2:TAX:LDA#0:STAT:LDACNT:ADC#15:AND#63:CMP#33:BCCPL38:TXA:EOR#FF:ADC#0:TAX:LDA#FF:ADC#0:STAT:CLC 5740.PL38 JSRBLINE:CMP#65:BCSP%+5:JMPPLL3:CLC:RTS 5750.WPLS2 LDYLSX2:BNEWP1:.WPL1 CPYLSP:BCSWP1:LDALSY2,Y:CMP#FF:BEQWP2:STAY2:LDALSX2,Y:STAX2:JSRLOIN:INY:LDASWAP:BNEWPL1 5760LDAX2:STAX1:LDAY2:STAY1:JMPWPL1:.WP2 INY:LDALSX2,Y:STAX1:LDALSY2,Y:STAY1:INY:JMPWPL1:.WP1 LDA#1:STALSP:LDA#FF:STALSX2:RTS 5790.WPLS LDALSX:BMIWPLS-1:LDASUNX:STAYY:LDASUNX+1:STAYY+1:LDY#2*Y-1:.WPL2 LDALSO,Y:BEQP%+5:JSRHLOIN2:DEY:BNEWPL2:DEY:STYLSX:RTS 5800.EDGES STAT:CLC:ADCYY:STAX2:LDAYY+1:ADC#0:BMIED1:BEQP%+6:LDA#254:STAX2 5810LDAYY:SEC:SBCT:STAX1:LDAYY+1:SBC#0:BNEED3:CLC:RTS 5820.ED3 BPLED1:LDA#2:STAX1:CLC:RTS:.ED1 LDA#0:STALSO,Y:SEC:RTS 5850.CHKON LDAK3:CLC:ADCK:LDAK3+1:ADC#0:BMIPL21:LDAK3:SEC:SBCK:LDAK3+1:SBC#0:BMIPL31:BNEPL21:.PL31 5860LDAK4:CLC:ADCK:STAP+1:LDAK4+1:ADC#0:BMIPL21:STAP+2:LDAK4:SEC:SBCK:TAX:LDAK4+1:SBC#0:BMIPL44:BNEPL21:CPX#2*Y-1:RTS:.PL21 SEC:RTS 5900.PLS3 JSRPLS1:STAP:LDA#222:STAQ:STXU:JSRMULTU:LDXU:LDYK+3:BPLPL12:EOR#FF:CLC:ADC#1:BEQPL12:LDY#FF:RTS:.PL12 LDY#0:RTS 5910.PLS4 STAQ:JSRARCTAN:LDXINWK+14:BMIP%+4:EOR#128:LSRA:LSRA:STACNT2:RTS 5920.PLS5 JSRPLS1:STAK2+2:STYXX16+2:JSRPLS1:STAK2+3:STYXX16+3:RTS 5930.PLS6 JSRDVID3B2:LDAK+3:AND#127:ORAK+2:BNEPL21:LDXK+1:CPX#4:BCSPL6:LDAK+3:\CLC:BPLPL6:LDAK:EOR#FF:ADC#1:STAK:TXA:EOR#FF:ADC#0:TAX:.PL44 CLC:.PL6 RTS 7200.TT17 JSRDOKEY:LDAJSTK:BEQTJ1:LDAJSTX:EOR#FF:JSRTJS1:TYA:TAX 7210LDAJSTY:.TJS1 TAY:LDA#0:CPY#&10:SBC#0:\CPY#&20SBC#0:CPY#&40:SBC#0:CPY#&C0:ADC#0:CPY#&E0:ADC#0:\CPY#&F0ADC#0 7220TAY:LDAKL:RTS 7250.TJ1 LDAKL:LDX#0:LDY#0:CMP#&19:BNEP%+3:DEX:CMP#&79:BNEP%+3:INX:CMP#&39:BNEP%+3:INY:CMP#&29:BNEP%+3:DEY:RTS 7550.ping LDX#1:.pl1 LDAQQ0,X:STAQQ9,X:DEX:BPLpl1:RTS 9500]PRINT"E d,"; 9710IFZ>4OSCLI("S.ELTE "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9720GOTO12 ================================================ FILE: 1-source-files/original-sources/text-sources/ELITEF.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 11GOTO20 12*L.ELITEF 13GOTO20 14*L.ELITEG 20REM ELITE 100 H%=L%+P%-C%:O%=W% 900[OPTZ 1000.KS3 LDAP:STASLSP:LDAP+1:STASLSP+1:RTS:.KS1 LDXXSAV:JSRKILLSHP:LDXXSAV:JMPMAL1 1010.KS4 JSRZINF:JSRFLFLLS:STAFRIN+1:STASSPR:JSRSPBLB:LDA#6:STAINWK+5:LDA#&81:JMPNWSHP 1020.KS2 LDX#FF:.KSL4 INX:LDAFRIN,X:BEQKS3:CMP#MSL:BNEKSL4:TXA:ASLA:TAY:LDAUNIV,Y:STASC:LDAUNIV+1,Y:STASC+1 1030LDY#32:LDA(SC),Y:BPLKSL4:AND#&7F:LSRA:CMPXX4:BCCKSL4:BEQKS6:SBC#1:ASLA:ORA#128:STA(SC),Y:BNEKSL4:.KS6 LDA#0:STA(SC),Y:BEQKSL4 1050.KILLSHP STXXX4:CPXMSTG:BNEKS5 \<<**:LDY#&EE:JSRABORT:LDA#200:JSRMESS:.KS5 LDYXX4:LDXFRIN,Y:CPX#SST:BEQKS4:DECMANY,X:LDXXX4 1060LDY#5:LDA(XX0),Y:LDY#33:CLC:ADC(INF),Y:STAP:INY:LDA(INF),Y:ADC#0:STAP+1 1070.KSL1 INX:LDAFRIN,X:STAFRIN-1,X:BEQKS2:ASLA:TAY:LDAXX21-2,Y:STASC:LDAXX21-1,Y:STASC+1:LDY#5:LDA(SC),Y:STAT:LDAP:SEC:SBCT:STAP:LDAP+1:SBC#0:STAP+1 1080TXA:ASLA:TAY:LDAUNIV,Y:STASC:LDAUNIV+1,Y:STASC+1:LDY#35:LDA(SC),Y:STA(INF),Y:DEY 1090LDA(SC),Y:STAK+1:LDAP+1:STA(INF),Y:DEY:LDA(SC),Y:STAK:LDAP:STA(INF),Y:DEY:.KSL2 LDA(SC),Y:STA(INF),Y:DEY:BPLKSL2:LDASC:STAINF:LDASC+1:STAINF+1 1100LDYT:.KSL3 DEY:LDA(K),Y:STA(P),Y:TYA:BNEKSL3:BEQKSL1 1500.SFX EQUS FNS("12010010"):EQUS FNS("12022C08"):EQUS FNS("1103F018"):EQUS FNS("10F1071A") 1510EQUS FNS("03F1BC01"):EQUS FNS("13F40C08"):EQUS FNS("10F1060C"):EQUS FNS("10026010") HYP:EQUS FNS("1304C2FF"):EQUS FNS("13000000") 3000.RESET \"<<<<":JSRZERO:LDX#6:.SAL3 STABETA,X:DEX:BPLSAL3:STXQQ12:.RES4 LDA#FF:LDX#2:.REL5 STAFSH,X:DEX:BPLREL5 3002.RES2 LDA#NOST:STANOSTM:LDX#FF:STXLSX2:STXLSY2:STXMSTG:LDA#128:STAJSTY:STAALP2:STABET2:ASLA:STAALP2+1:STABET2+1:STAMCNT:LDA#3:STADELTA:STAALPHA:STAALP1 3005LDASSPR:BEQP%+5:JSRSPBLB:LDAECMA:BEQyu:JSRECMOF:.yu JSRWPSHPS:JSRZERO:LDA#(LS%MOD256):STASLSP:LDA#(LS%DIV256):STASLSP+1:JSRDIALS 3006.ZINF LDY#NI%-1:LDA#0:.ZI1 STAINWK,Y:DEY:BPLZI1:LDA#96:STAINWK+18:STAINWK+22:ORA#128:STAINWK+14:RTS 3007.msblob LDX#4:.ss CPXNOMSL:BEQSAL8:LDY#0:JSRMSBAR:DEX:BNEss:RTS:.SAL8 LDY#&EE:JSRMSBAR:DEX:BNESAL8:RTS 3890.me2 LDAMCH:JSRMESS:LDA#0:STADLY:JMPme3 3900.Ze JSRZINF:JSRDORND:STAT1:AND#128:STAINWK+2:TXA:AND#128:STAINWK+5:LDA#32:STAINWK+1:STAINWK+4:STAINWK+7:TXA:CMP#245:ROLA:ORA#&C0:STAINWK+32 3904.DORND2 CLC:.DORND LDARAND:ROLA:TAX:ADCRAND+2:STARAND:STXRAND+2:LDARAND+1:TAX:ADCRAND+3:STARAND+1:STXRAND+3:RTS 3910.MTT4 LSRA:STAINWK+32:STAINWK+29:ROLINWK+31:AND#31:ORA#16:STAINWK+27:LDA#CYL:JSRNWSHP 4000.TT100 JSRM%:DECDLY:BEQme2:BPLme3:INCDLY:.me3 DECMCNT:BEQP%+5:.ytq JMPMLOOP:LDAMJ:BNEytq 4020JSRDORND:CMP#35:BCSMTT1:LDAMANY+AST:CMP#3:BCSMTT1:JSRZINF:LDA#38:STAINWK+7:JSRDORND:STAINWK:STXINWK+3:AND#128:STAINWK+2:TXA:AND#128:STAINWK+5:ROLINWK+1:ROLINWK+1 4022JSRDORND:BVSMTT4:ORA#&6F:STAINWK+29:LDASSPR:BNEMTT1:TXA:BCSMTT2:AND#31:ORA#16:STAINWK+27:BCCMTT3 4025.MTT2 ORA#127:STAINWK+30:.MTT3 JSRDORND:CMP#5:LDA#AST:BCSP%+4:LDA#OIL:JSRNWSHP 4030.MTT1 4040LDASSPR:BNEMLOOP:JSRBAD:ASLA:LDXMANY+COPS:BEQP%+5:ORAFIST:STAT:JSRZe:CMPT:BCSP%+7:LDA#COPS:JSRNWSHP:LDAMANY+COPS:BNEMLOOP:DECEV:BPLMLOOP:INCEV:JSRDORND:LDYgov:BEQ`:CMP#90:BCSMLOOP:AND#7:CMPgov:BCCMLOOP:.` 4050JSRZe:CMP#200:BCSmt1:INCEV:AND#3:ADC#3:TAY:TXA:CMP#200:ROLA:ORA#&C0:CPY#6:BEQtha:STAINWK+32:TYA:JSRNWSHP:.mj1 JMPMLOOP:.mt1 AND#3:STAEV:STAXX13:.mt3 JSRDORND:AND#3:ORA#1:JSRNWSHP 4100DECXX13:BPLmt3:.MLOOP LDA#1:STAVIA+&E:LDX#FF:TXS:LDXGNTMP:BEQEE20:DECGNTMP:.EE20 JSRDIALS:LDAQQ11:BEQP%+11:ANDPATG:LSRA:BCSP%+5:JSRDELAY-5 4200JSRTT17:.FRCE JSRTT102:LDAQQ12:BNEMLOOP:JMPTT100 4250.tha JSRDORND:CMP#200:BCCP%+5:JSRGTHG:JMPMLOOP 4500.TT102 CMP#f8:BNEP%+5:JMPSTATUS:CMP#f4:BNEP%+5:JMPTT22:CMP#f5:BNEP%+5:JMPTT23:CMP#f6:BNETT92:JSRTT111:JMPTT25:.TT92 CMP#f9:BNEP%+5:JMPTT213:CMP#f7:BNEP%+5:JMPTT167:CMP#f0:BNEfvw:JMPTT110:.fvw BITQQ12 4505BPLINSP:CMP#f3:BNEP%+5:JMPEQSHP:CMP#f1:BNEP%+5:JMPTT219:CMP#&47:BNEP%+5:JMPSVE 4510CMP#f2:BNE``:JMPTT208:.INSP CMP#&71:BCC``:CMP#&74:BCS``:AND#3:TAX:JMPLOOK1:.`` CMP#&54:BNEP%+5:JMPhyp:CMP#&32:BEQT95:STAT1:LDAQQ11:AND#192:BEQTT107:LDAQQ22+1:BNETT107:LDAT1:CMP#&36:BNEee2:JSRTT103:JSRping 4520JSRTT103:.ee2 JSRTT16:.TT107:LDAQQ22+1:BEQt95:DECQQ22:BNEt95:LDXQQ22+1:DEX:JSRee3:LDA#5:STAQQ22:LDXQQ22+1:JSRee3:DECQQ22+1:BNEt95:JMPTT18:.t95 RTS 4550.T95 LDAQQ11:AND#192:BEQt95:JSRhm:STAQQ17:JSRcpl:LDA#128:STAQQ17:LDA#1:STAXC:INCYC:JMPTT146 4800.BAD LDAQQ20+3:CLC:ADCQQ20+6:ASLA:ADCQQ20+10:RTS 4850.FAROF LDA#&E0:.FAROF2 CMPINWK+1:BCCMA34:CMPINWK+4:BCCMA34:CMPINWK+7:.MA34 RTS:.MAS4 ORAINWK+1:ORAINWK+4:ORAINWK+7:RTS 4900.DEATH JSREXNO3:JSRRES2:ASLDELTA:ASLDELTA:LDX#24:JSRDET1:JSRTT66:JSRBOX:JSRnWq:LDA#12:STAYC:STAXC:LDA#146:JSRex:.D1 JSRZe:LSRA:LSRA:STAINWK:LDY#0:STYQQ11:STYINWK+1:STYINWK+4:STYINWK+7:STYINWK+32:DEY:STYMCNT:STYLASCT:EOR#42 4905STAINWK+3:ORA#80:STAINWK+6:TXA:AND#&8F:STAINWK+29 4910RORA:AND#&87:STAINWK+30:PHP:LDX#OIL:JSRfq1:PLP:LDA#0:RORA:LDY#31:STA(INF),Y:LDAFRIN+3:BEQD1:JSRU%:STADELTA:.D2 JSRM%:LDALASCT:BNED2:LDX#31:JSRDET1:.DEATH2 JSRRES2 5000.TT170 LDX#FF:TXS 5010.BR1 LDX#3:STXXC:JSRFX200:LDX#CYL:LDA#128:JSRTITLE:CMP#&44:BNEQU5:\BR1 LDX#3STXXCJSRFX200LDA#1JSRTT66JSRFLKB 5015\LDA#14JSRTT214BCCQU5:JSRGTNME:JSRLOD:JSRTRNME:JSRTTX66 5020.QU5 \JSRTTX66:LDX#NT%:.QUL1 LDANA%+7,X:STATP-1,X:DEX:BNEQUL1:STXQQ11:JSRCHECK:CMPCHK:BNEP%-6:EOR#&A9:TAX:LDACOK:CPXCHK2:BEQtZ:ORA#128:.tZ ORA#2:STACOK:JSRmsblob:LDA#147:LDX#3:JSRTITLE:JSRping:JSRhyp1 5021.BAY LDA#FF:STAQQ12:LDA#f8:JMPFRCE 5110.TITLE PHA:STXTYPE:JSRRESET:LDA#1:JSRTT66:DECQQ11:LDA#96:STAINWK+14 5120\LSRA:STAINWK+7:LDX#127:STXINWK+29:STXINWK+30:INX:STXQQ17 5130LDATYPE:JSRNWSHP 5140LDY#6:STYXC:JSRDELAY:LDA#30:JSRplf:LDY#6:STYXC:INCYC:LDAPATG:BEQawe:LDA#254:JSRTT27:.awe JSRCLYNS:STYDELTA:STYJSTK:PLA:JSRex:LDA#148:LDX#7:STXXC:JSRex 5150.TLL2 LDAINWK+7:CMP#1:BEQTL1:DECINWK+7:.TL1 JSRMVEIT:LDA#128:STAINWK+6:ASLA:STAINWK:STAINWK+3:JSRLL9:DECMCNT:LDA&FE40:AND#16:\TAX:BEQTL2:JSRRDKEY:BEQTLL2:RTS:.TL2 DECJSTK:RTS 5200.CHECK LDX#NT%-2:CLC:TXA:.QUL2 ADCNA%+7,X:EORNA%+8,X:DEX:BNEQUL2:RTS 5250.TRNME LDX#7:.GTL1 LDAINWK,X:STANA%,X:DEX:BPLGTL1:.TR1 LDX#7:.GTL2 LDANA%,X:STAINWK,X:DEX:BPLGTL2:RTS 5300.GTNME LDA#1:JSRTT66:LDA#123:JSRTT27:JSRDEL8:LDA#&81:STAVIA+&E:LDA#15:TAX:JSROSBYTE:LDX#(RLINE MOD256):LDY#(RLINE DIV256):LDA#0:JSROSWORD\LDA#1STAVIA+&E:BCSTR1:TYA:BEQTR1:JMPTT67 5350.RLINE EQUWINWK:EQUB7:EQUB33:EQUB&7A 5400.ZERO LDX#&D:.ZEL JSRZES1:DEX:CPX#9:BNEZEL 5410.ZES1 LDY#0:STYSC:.ZES2 LDA#0:STXSC+1:.ZEL1 STA(SC),Y:INY:BNEZEL1:RTS 5500.SVE JSRGTNME:JSRTRNME:JSRZERO:LSRSVC:LDX#NT%:.SVL1 LDATP,X:STA&B00,X:STANA%+8,X:DEX:BPLSVL1:JSRCHECK:STACHK:PHA:ORA#128:STAK:EORCOK:STAK+2:EORCASH+2:STAK+1:EOR#&5A:EORTALLY+1:STAK+3:JSRBPRNT:JSRTT67:JSRTT67:PLA:STA&B00+NT%:EOR#&A9 5501STACHK2:STA&AFF+NT%:LDY#&B:STY&C0B:INY:STY&C0F 5510LDA#&81:STAVIA+&E:INCsvn:LDA#0:JSRQUS1:LDX#0\STXVIA+&EDEX:STXsvn:JMPBAY 5520.QUS1 LDX#INWK:STX&C00:LDX#0:JMPOSFILE 5600.LOD LDX#2:JSRFX200:JSRZERO:LDY#&B:STY&C03:INC&C0B:INY:LDA#FF:JSRQUS1:LDA&B00:BMISPS1+1:LDX#NT%:.LOL1 LDA&B00,X:STANA%+8,X:DEX:BPLLOL1:LDX#3 5620.FX200\MOS:LDY#0:LDA#200:JMPOSBYTE 6500RTS:.SPS1 LDX#0:JSRSPS3:LDX#3:JSRSPS3:LDX#6:JSRSPS3 6600.TAS2 LDAK3:ORAK3+3:ORAK3+6:ORA#1:STAK3+9:LDAK3+1:ORAK3+4:ORAK3+7 6610.TAL2 ASLK3+9:ROLA:BCSTA2:ASLK3:ROLK3+1:ASLK3+3:ROLK3+4:ASLK3+6:ROLK3+7:BCCTAL2 6620.TA2 LDAK3+1:LSRA:ORAK3+2:STAXX15:LDAK3+4:LSRA:ORAK3+5:STAXX15+1:LDAK3+7:LSRA:ORAK3+8:STAXX15+2 6700.NORM 6705LDAXX15:JSRSQUA:STAR:LDAP:STAQ:LDAXX15+1:JSRSQUA:STAT:LDAP:ADCQ:STAQ:LDAT:ADCR:STAR:LDAXX15+2:JSRSQUA:STAT:LDAP:ADCQ:STAQ:LDAT:ADCR:STAR 6710JSRLL5 6720LDAXX15:JSRTIS2:STAXX15 \*96/Q 6730LDAXX15+1:JSRTIS2:STAXX15+1 6740LDAXX15+2:JSRTIS2:STAXX15+2:.NO1 RTS 6800.RDKEY \OSBYTE7A:LDX#16:.Rd1 JSRDKS4:BMIRd2:INX:BPLRd1:TXA:.Rd2 EOR#128:TAX:RTS 7000.ECMOF LDA#0:STAECMA:STAECMP:JSRECBLB:LDA#72:BNENOISE 7001.EXNO3 LDA#16:JSRNOISE:LDA#24:BNENOISE 7003.SFRMIS LDX#MSL:JSRSFS1-2:BCCNO1:LDA#&78:JSRMESS:LDA#48:BNENOISE 7004.EXNO2 INCTALLY:BNEEXNO-2:INCTALLY+1:LDA#101:JSRMESS:LDX#7 \15:.EXNO STXT:LDA#24:JSRNOS1:LDAINWK+7:LSRA:LSRA:ANDT:ORA#&F1:STAXX16+2:JSRNO3:LDA#16 7006EQUB&2C:.BEEP LDA#32 7010.NOISE JSRNOS1:.NO3 LDXDNOIZ:BNENO1:LDX#(XX16 MOD256):LDY#(XX16 DIV256):LDA#7:JMPOSWORD 7015.NOS1 LSRA:ADC#3:TAY:LDX#7:.NOL1 LDA#0:STAXX16,X:DEX:LDASFX,Y:STAXX16,X:DEY:DEX:BPLNOL1 7020.KYTB RTS:EQUB&E8:EQUB&E2:EQUB&E6:EQUB&E7:EQUB&C2:EQUB&D1:EQUB&C1:EQUD&35237060:EQUW&2265:EQUB&45:EQUB&52 \? <>XSA.FBRLtabescTUMEJC 7030.DKS1 LDXKYTB,Y:JSRDKS4:BPLDKS2-1:LDX#FF:STXKL,Y:RTS 7032.CTRL LDX#1:.DKS4 LDA#3:SEI:STA&FE40:LDA#&7F:STA&FE43:STX&FE4F:LDX&FE4F:LDA#&B:STA&FE40:CLI:TXA 7035RTS:.DKS2 LDA#&80:JSROSBYTE:TYA:EORJSTE 7037RTS:.DKS3 STYT:CPXT:BNEDk3:LDADAMP-&40,X:EOR#FF:STADAMP-&40,X:JSRBELL:JSRDELAY:LDYT:.Dk3 RTS 7040.DKJ1 LDY#1:JSRDKS1:INY:JSRDKS1 7050LDA&FE40:TAX:AND#16:EOR#16:STAKL+7:LDX#1:JSRDKS2:ORA#1:STAJSTX:LDX#2:JSRDKS2:EORJSTGY:STAJSTY:JMPDK4 7065.U% LDA#0:LDY#15:.DKL3 STAKL,Y:DEY:BNEDKL3:RTS 7070.DOKEY JSRU%:LDAJSTK:BNEDKJ1 7080LDY#7:.DKL2 JSRDKS1:DEY:BNEDKL2 7090LDXJSTX:LDA#7:LDYKL+3:BEQP%+5:JSRBUMP2:LDYKL+4:BEQP%+5:JSRREDU2:STXJSTX 7100ASLA:LDXJSTY:LDYKL+5:BEQP%+5:JSRREDU2:LDYKL+6:BEQP%+5:JSRBUMP2:STXJSTY 7110.DK4 JSRRDKEY:STXKL:CPX#&69:BNEDK2:.FREEZE JSRWSCAN:JSRRDKEY:CPX#&51:BNEDK6:LDA#0:STADNOIZ 7114.DK6 LDY#&40:.DKL4 JSRDKS3:INY:CPY#&47:BNEDKL4:.DK55 CPX#&10:BNEDK7:STXDNOIZ:.DK7 CPX#&70:BNEP%+5:JMPDEATH2:CPX#&59:BNEFREEZE:.DK2 LDAQQ11:BNEDK5:LDY#15:LDA#FF 7120.DKL1 LDXKYTB,Y:CPXKL:BNEDK1:STAKL,Y:.DK1 DEY:CPY#7:BNEDKL1 7130.DK5 RTS 7140.TT217 STYYSAV:.t JSRDELAY-5:JSRRDKEY:BNEt:.t2 JSRRDKEY:BEQt2:TAY:LDA(TRTB%),Y:LDYYSAV:TAX:.out RTS 7190.me1 STXDLY:PHA:LDAMCH:JSRmes9:PLA:EQUB&2C:.ou2 lda#108:EQUB&2C:.ou3 lda#111 7200.MESS LDX#0:STXQQ17:LDY#9:STYXC:LDY#22:STYYC:CPXDLY:BNEme1:STYDLY:STAMCH:.mes9 JSRTT27:LSRde:BCCout:LDA#253:JMPTT27 7300.OUCH JSRDORND:BMIout:CPX#22:BCSout:LDAQQ20,X:BEQout:LDADLY:BNEout:LDY#3:STYde:STAQQ20,X:CPX#17:BCSou1:TXA:ADC#208:BNEMESS:.ou1 7310BEQou2:CPX#18:BEQou3:TXA:ADC#113-20:BNEMESS 7410.QQ16 EQUS"ALLEXEGEZACEBISOUSESARMAINDIREA?ERATENBERALAVETIEDORQUANTEISRION" 7420.QQ23\Prxs:EQUD&1068213:EQUD&30A8114:EQUD&7028341\Food 7430EQUD&1FE28528:EQUD&FFB8553:EQUD&33608C4:EQUD &78081DEB \slvs.. 7440EQUD&3380E9A:EQUD&7280675:EQUD&1F11014E:EQUD&71D0D7C \comps 7450EQUD&3FDC89B0:EQUD&03358120:EQUD&742A161:EQUD&1F37A2AB \pltnm 7460EQUD&FFAC12D:EQUD&7C00F35 \Gms. 8000.TI2 TYA:LDY#2:JSRTIS3:STAINWK+20\Uz=-(FxUx+FyUy)/Fz:JMPTI3 8010.TI1 TAX:LDAXX15+1:AND#&60:BEQTI2:LDA#2:JSRTIS3:STAINWK+18:JMPTI3 8020.TIDY LDAINWK+10:STAXX15:LDAINWK+12:STAXX15+1:LDAINWK+14:STAXX15+2:JSRNORM:LDAXX15:STAINWK+10:LDAXX15+1:STAINWK+12:LDAXX15+2:STAINWK+14 8030LDY#4:LDAXX15:AND#&60:BEQTI1:LDX#2:LDA#0:JSRTIS3:STAINWK+16 8040.TI3 LDAINWK+16:STAXX15:LDAINWK+18:STAXX15+1:LDAINWK+20:STAXX15+2:JSRNORM:LDAXX15:STAINWK+16:LDAXX15+1:STAINWK+18:LDAXX15+2:STAINWK+20 8050LDAINWK+12:STAQ:LDAINWK+20:JSRMULT12:LDXINWK+14:LDAINWK+18:JSRTIS1:EOR#128:STAINWK+22 8060LDAINWK+16:JSRMULT12:LDXINWK+10:LDAINWK+20:JSRTIS1:EOR#128:STAINWK+24 8070LDAINWK+18:JSRMULT12:LDXINWK+12:LDAINWK+16:JSRTIS1:EOR#128:STAINWK+26 \FxU/96(LHS) 8080LDA#0:LDX#14:.TIL1 STAINWK+9,X:DEX:DEX:BPLTIL1:RTS 8100.TIS2 TAY:AND#127:CMPQ:BCSTI4:LDX#254:STXT:.TIL2 ASLA:CMPQ:BCCP%+4:SBCQ:ROLT:BCSTIL2:LDAT 8110LSRA:LSRA:STAT:LSRA:ADCT:STAT:TYA:AND#128:ORAT:RTS:.TI4 TYA:AND#128:ORA#96:RTS 8130.TIS3 STAP+2:LDAINWK+10,X:STAQ:LDAINWK+16,X:JSRMULT12:LDXINWK+10,Y:STXQ:LDAINWK+16,Y:JSRMAD 8140STXP:LDYP+2:LDXINWK+10,Y:STXQ:EOR#128 8150.DVIDT\A=AP/Q:STAP+1:EORQ:AND#128:STAT:LDA#0:LDX#16:ASLP:ROLP+1:ASLQ:LSRQ:.DVL2 ROLA:CMPQ:BCCP%+4:SBCQ:ROLP:ROLP+1:DEX:BNEDVL2:LDAP:ORAT:RTS 9000]:PRINT"F d,"; 9710IFZ>4OSCLI("S.ELTF "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9720GOTO14 10200DEFFNS(A$):N%=LEN(A$)DIV2:FORI%=0TON%-1:I%?O%=EVAL("&"+MID$(A$,2*I%+1,2)):NEXT:P%=P%+N%:O%=O%+N%:="" ================================================ FILE: 1-source-files/original-sources/text-sources/ELITEG.txt ================================================ 1GOTO20 2*L.ELITEB 3GOTO20 4*L.ELITEA 6*L.ELITEC 7GOTO20 8*L.ELITED 9GOTO20 10*L.ELITEE 11GOTO20 12*L.ELITEF 13GOTO20 14*L.ELITEG 20REM ELITE 100H%=L%+P%-C%:O%=W% 1000[OPTZ 7000.SHPPT JSREE51:JSRPROJ:ORAK3+1:BNEnono:LDAK4:CMP#Y*2-2:BCSnono:LDY#2:jsrShpt:ldy#6:ldaK4:ADC#1:jsrShpt:LDA#8:ORAXX1+31:STAXX1+31:LDA#8:JMPLL81+2:PLA:PLA:.nono lda#&F7:andXX1+31:staXX1+31:RTS 7010.Shpt STA(XX19),Y:iny:iny:STA(XX19),Y:LDAK3:DEY:STA(XX19),Y:ADC#3:BCSnono-2:dey:dey:STA(XX19),Y:rts 8040.LL5 \2BSQRT Q=SQR(RQ) 8045LDYR:LDAQ:STAS:LDX#0:STXQ:LDA#8:STAT:.LL6 CPXQ:BCCLL7:BNELL8:CPY#&40:BCCLL7:.LL8 TYA:SBC#&40:TAY:TXA:SBCQ:TAX:.LL7 ROLQ:ASLS:TYA:ROLA:TAY:TXA:ROLA:TAX:ASLS:TYA:ROLA:TAY:TXA:ROLA:TAX:DECT:BNELL6:RTS 8065.LL28 \BFRDIV R=A*256/Q 8070CMPQ:BCSLL2:LDX#254:STXR:.LL31 ASLA:BCSLL29:CMPQ:BCCP%+4:SBCQ:ROLR:BCSLL31:RTS:.LL29 SBCQ:SEC:ROLR:BCSLL31:RTS:.LL2 LDA#FF:STAR:RTS 8085.LL38 \BADD(S)A=R+Q(SA) 8090EORS:BMILL39:LDAQ:CLC:ADCR:RTS:.LL39 LDAR:SEC:SBCQ 8095BCCP%+4:CLC:RTS:PHA:LDAS:EOR#128:STAS:PLA:EOR#255:ADC#1:RTS 8100.LL51 \XX12=XX15.XX16 8105LDX#0:LDY#0:.ll51 LDAXX15:STAQ:LDAXX16,X:JSRFMLTU:STAT:LDAXX15+1:EORXX16+1,X:STAS:LDAXX15+2 8115STAQ:LDAXX16+2,X:JSRFMLTU:STAQ:LDAT:STAR:LDAXX15+3 8120EORXX16+3,X:JSRLL38:STAT:LDAXX15+4:STAQ:LDAXX16+4,X:JSRFMLTU:STAQ:LDAT:STAR:LDAXX15+5:EORXX16+5,X 8130JSRLL38:STAXX12,Y:LDAS:STAXX12+1,Y:INY:INY:TXA:CLC:ADC#6:TAX:CMP#17:BCCll51:RTS 8132.LL25 JMPPLANET 8135.LL9 \ ENTRY 8137LDATYPE:BMILL25 8140LDA#31:STAXX4:LDA#32:BITXX1+31:BNEEE28 8144BPLEE28:ORAXX1+31:AND#&3F:STAXX1+31:LDA#0:LDY#28:STA(INF),Y:LDY#30:STA(INF),Y:JSREE51:LDY#1:LDA#18:STA(XX19),Y:LDY#7:LDA(XX0),Y:LDY#2:STA(XX19),Y 8146\LDAXX1+32\AND#&7F\STAXX1+32:.EE55 INY:JSRDORND:STA(XX19),Y:CPY#6:BNEEE55:.EE28 8150LDAXX1+8:.EE49 BPLLL10:.LL14 LDAXX1+31:AND#32:BEQEE51:LDAXX1+31:AND#&F7:STAXX1+31:JMPDOEXP:.EE51 8155LDA#8:BITXX1+31:BEQLL10-1:EORXX1+31:STAXX1+31:JMPLL155:\LL24 8165RTS:.LL10 8175LDAXX1+7:CMP#&C0:BCSLL14:LDAXX1:CMPXX1+6:LDAXX1+1:SBCXX1+7:BCSLL14:LDAXX1+3:CMPXX1+6:LDAXX1+4:SBCXX1+7:BCSLL14 8205LDY#6:LDA(XX0),Y:TAX:LDA#255:STAXX3,X:STAXX3+1,X 8215LDAXX1+6:STAT:LDAXX1+7:LSRA:RORT:LSRA:RORT:LSRA:RORT:LSRA:BNELL13:LDAT:RORA:LSRA:LSRA:LSRA:STAXX4 8225BPLLL17:.LL13 LDY#13:LDA(XX0),Y:CMPXX1+7:BCSLL17:LDA#32:ANDXX1+31:BNELL17:JMPSHPPT:.LL17 8275LDX#5:.LL15 LDAXX1+21,X:STAXX16,X:LDAXX1+15,X:STAXX16+6,X:LDAXX1+9,X:STAXX16+12,X:DEX:BPLLL15 8290LDA#197 \NORM:STAQ:LDY#16:.LL21 LDAXX16,Y:ASLA:LDAXX16+1,Y 8295ROLA:JSRLL28:LDXR:STXXX16,Y:DEY:DEY:BPLLL21 8300LDX#8:.ll91 LDAXX1,X:STAXX18,X:DEX:BPLll91 8315LDA#255:STAXX2+15 8320LDY#12:LDAXX1+31:AND#32:BEQEE29:LDA(XX0),Y:LSRA:LSRA:TAX:LDA#FF:.EE30 STAXX2,X:DEX:BPLEE30:INX:STXXX4:.LL41 JMPLL42:.EE29 LDA(XX0),Y:BEQLL41:STAXX20 8330\DtProd^XX2 8335LDY#18:LDA(XX0),Y:TAX:LDAXX18+7:.LL90 TAY:BEQLL91:INX:LSRXX18+4:RORXX18+3:LSRXX18+1:RORXX18:LSRA:RORXX18+6:TAY:BNELL90+3:.LL91 STXXX17:LDAXX18+8 8350STAXX15+5:LDAXX18:STAXX15:LDAXX18+2:STAXX15+1:LDAXX18+3:STAXX15+2:LDAXX18+5:STAXX15+3:LDAXX18+6:STAXX15+4:JSRLL51:LDAXX12:STAXX18:LDAXX12+1:STAXX18+2:LDAXX12+2 8365STAXX18+3:LDAXX12+3:STAXX18+5:LDAXX12+4:STAXX18+6:LDAXX12+5:STAXX18+8 8375LDY#4:LDA(XX0),Y:CLC:ADCXX0:STAV:LDY#17:LDA(XX0),Y:ADCXX0+1:STAV+1:LDY#0 8385.LL86 LDA(V),Y:STAXX12+1:AND#31:CMPXX4:BCSLL87 8390TYA:LSRA:LSRA:TAX:LDA#255:STAXX2,X:TYA:ADC#4 8395TAY:JMPLL88:.LL87 LDAXX12+1:ASLA:STAXX12+3:ASLA:STAXX12+5 8400INY:LDA(V),Y:STAXX12:INY:LDA(V),Y:STAXX12+2:INY:LDA(V),Y 8405STAXX12+4:LDXXX17:CPX#4:BCCLL92:.LL143 8410\Face offset<255 9090TXA:CLC:ADCXX15+2:STAXX15+2:TYA:ADCXX15+3:STAXX15+3 9095LDX#FF:STXXX15:INX:STXXX15+1 9100.LL134 LDAXX15+3:BPLLL135:STAS:LDAXX15+2:STAR \ Y1<0 9105JSRLL123:TXA:CLC:ADCXX15:STAXX15:TYA:ADCXX15+1:STAXX15+1 9110LDA#0:STAXX15+2:STAXX15+3 9115.LL135 \BNELL139:LDAXX15+2:SEC:SBC#Y*2:STAR \ Y1>191 9120LDAXX15+3:SBC#0:STAS:BCCLL136:.LL139 JSRLL123:TXA:CLC:ADCXX15 9130STAXX15:TYA:ADCXX15+1:STAXX15+1:LDA#Y*2-1:STAXX15+2:LDA#0:STAXX15+3:.LL136 RTS 9140\ YX=SR*M/256 9142.LL120 LDAXX15:STAR 9145\.LL120:JSRLL129:PHA:LDXT:BNELL121:.LL122 9160LDA#0:TAX:TAY:LSRS:RORR:ASLQ:BCCLL126:.LL125 TXA:CLC 9165ADCR:TAX:TYA:ADCS:TAY:.LL126 LSRS:RORR:ASLQ:BCSLL125 9170BNELL126:PLA:BPLLL133:RTS 9180\ YX=SR*256/M (M=grad.) 9185.LL123 JSRLL129:PHA:LDXT:BNELL122:.LL121 9200LDA#255:TAY:ASLA:TAX:.LL130 ASLR:ROLS:LDAS:BCSLL131 9205CMPQ:BCCLL132:.LL131 SBCQ:STAS:LDAR:SBC#0:STAR:SEC 9210.LL132 TXA:ROLA:TAX:TYA:ROLA:TAY:BCSLL130:PLA:BMILL128 9215.LL133 TXA:EOR#FF:\CLC:ADC#1:TAX:TYA:EOR#FF:ADC#0:TAY:.LL128 RTS 9216.LL129 LDXXX12+2:STXQ:LDAS:BPLLL127:LDA#0:SEC:SBCR:STAR:LDAS:PHA:EOR#255:ADC#0:STAS:PLA:.LL127 EORXX12+3:RTS 9300.LL145 \CLIP 9305LDA#0:STASWAP 9310LDAXX15+5:.LL147 LDX#Y*2-1:ORAXX12+1:BNELL107:CPXXX12 9315BCCLL107:LDX#0:.LL107 STXXX13:LDAXX15+1:ORAXX15+3:BNELL83 9320LDA#Y*2-1:CMPXX15+2:BCCLL83 9325LDAXX13:BNELL108:.LL146 LDAXX15+2 9330STAXX15+1:LDAXX15+4:STAXX15+2:LDAXX12:STAXX15+3:CLC:RTS 9335.LL109 SEC:RTS:.LL108 LSRXX13:.LL83 9340LDAXX13:BPLLL115 9345LDAXX15+1:ANDXX15+5:BMILL109:LDAXX15+3:ANDXX12+1:BMILL109 9350LDXXX15+1:DEX:TXA:LDXXX15+5:DEX:STXXX12+2:ORAXX12+2 9355BPLLL109:LDAXX15+2:CMP#Y*2:LDAXX15+3:SBC#0:STAXX12+2 9360LDAXX12:CMP#Y*2:LDAXX12+1:SBC#0:ORAXX12+2:BPLLL109 9365.LL115 TYA:PHA:LDAXX15+4:SEC:SBCXX15:STAXX12+2:LDAXX15+5 9370SBCXX15+1:STAXX12+3:LDAXX12:SEC:SBCXX15+2:STAXX12+4 9375LDAXX12+1:SBCXX15+3:STAXX12+5:EORXX12+3:STAS 9380LDAXX12+5:BPLLL110:LDA#0:SEC:SBCXX12+4:STAXX12+4:LDA#0:SBCXX12+5:STAXX12+5 9385.LL110 LDAXX12+3:BPLLL111:SEC:LDA#0:SBCXX12+2:STAXX12+2:LDA#0:SBCXX12+3 9390\GETgrad 9395.LL111 TAX:BNELL112:LDXXX12+5:BEQLL113:.LL112 LSRA:RORXX12+2 9400LSRXX12+5:RORXX12+4:JMPLL111:.LL113 STXT:LDAXX12+2 9405CMPXX12+4:BCCLL114:STAQ:LDAXX12+4:JSRLL28 9410 \ Use Y/X grad. 9415JMPLL116:.LL114 LDAXX12+4:STAQ:LDAXX12+2:JSRLL28 9420 \ Use X/Y grad. 9425DECT:.LL116 LDAR:STAXX12+2:LDAS:STAXX12+3 9430LDAXX13:BEQLL138:BPLLLX117:.LL138 JSRLL118 9435LDAXX13:BPLLL124 9440.LL117 LDAXX15+1:ORAXX15+3:BNELL137:LDAXX15+2:CMP#Y*2 9445BCSLL137:.LLX117 LDXXX15:LDAXX15+4:STAXX15:STXXX15+4:LDAXX15+5 9450LDXXX15+1:STXXX15+5:STAXX15+1:LDXXX15+2:LDAXX12:STAXX15+2 9455STXXX12:LDAXX12+1:LDXXX15+3:STXXX12+1:STAXX15+3:JSRLL118 9460DECSWAP 9465.LL124 PLA:TAY:JMPLL146:.LL137 PLA:TAY:SEC:RTS 9520] 9530F%=P%:PRINT"G d." 9710IFZ>4OSCLI("SAVE ELTG "+STR$~W%+" "+STR$~O%+" "+STR$~L%+" "+STR$~H%) 9720IFZ=4GOTO4 9730 PRINT~C% F% S%,D%-F% ================================================ FILE: 2-build-files/README.md ================================================ # Build files for the BBC Micro cassette version of Elite This folder contains support scripts for building the BBC Micro cassette version of Elite. * [crc32.py](crc32.py) calculates checksums during the verify stage and compares the results with the relevant binaries in the [4-reference-binaries](../4-reference-binaries) folder * [elite-checksum.py](elite-checksum.py) adds checksums and encryption to the assembled output * [elite-decrypt.py](elite-decrypt.py) decrypts an encrypted game binary by doing the opposite to the elite-checksum.py script (this is not used in the build process, but is useful when trying to decrypt any new releases that might be found) * mktibet.php and tibetuef.php are used to create UEFs from files. It also contains the `make.exe` executable for Windows, plus the required DLL files. --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 2-build-files/crc32.py ================================================ #!/usr/bin/env python # # ****************************************************************************** # # ELITE VERIFICATION SCRIPT # # Written by Kieran Connell, extended by Mark Moxon # # This script performs checksums on the compiled files from the build process, # and checks them against the extracted files from the original source disc # # ****************************************************************************** from __future__ import print_function import sys import os import os.path import zlib def main(): if len(sys.argv) <= 2: # Do CRC on single folder folder = sys.argv[1] if len(sys.argv) == 2 else "." names = sorted(os.listdir(folder)) print() print('Checksum Size Filename') print('------------------------------------------') for name in names: if name.endswith(".bin"): full_name = os.path.join(folder, name) if not os.path.isfile(full_name): continue with open(full_name, 'rb') as f: data = f.read() print('%08x %5d %s' % ( zlib.crc32(data) & 0xffffffff, len(data), full_name) ) print() else: # Do CRC on two folders folder1 = sys.argv[1] names1 = sorted(os.listdir(folder1)) folder2 = sys.argv[2] names2 = sorted(os.listdir(folder2)) names = list(names1) names.extend(x for x in names2 if x not in names) if '4-reference-binaries' in folder1: src = '[--originals--]' elif 'output' in folder1: src = '[---output----]' else: src = '[{0: ^13}]'.format(folder1[0:13]).replace(' ', '-') if '4-reference-binaries' in folder2: dest = '[--originals--]' elif 'output' in folder2: dest = '[---output----]' else: dest = '[{0: ^13}]'.format(folder2[0:13]).replace(' ', '-') print('Results for variant: ' + os.path.basename(folder1)) print(src + ' ' + dest) print('Checksum Size Checksum Size Match Filename') print('-----------------------------------------------------------') for name in names: if name.endswith(".bin"): full_name1 = os.path.join(folder1, name) full_name2 = os.path.join(folder2, name) if name in names1 and name in names2 and os.path.isfile(full_name1) and os.path.isfile(full_name2): with open(full_name1, 'rb') as f: data1 = f.read() with open(full_name2, 'rb') as f: data2 = f.read() crc1 = zlib.crc32(data1) & 0xffffffff crc2 = zlib.crc32(data2) & 0xffffffff match = ' Yes ' if crc1 == crc2 and len(data1) == len(data2) else ' No ' print('%08x %5d %08x %5d %s %s' % ( crc1, len(data1), crc2, len(data2), match, name) ) elif name in names1 and os.path.isfile(full_name1): with open(full_name1, 'rb') as f: data = f.read() print('%08x %5d %s %s %s %s' % ( zlib.crc32(data) & 0xffffffff, len(data), '- ', ' -', ' - ', name) ) elif name in names2 and os.path.isfile(full_name2): with open(full_name2, 'rb') as f: data = f.read() print('%s %s %08x %5d %s %s' % ( '- ', ' -', zlib.crc32(data) & 0xffffffff, len(data), ' - ', name) ) print() if __name__ == '__main__': main() ================================================ FILE: 2-build-files/elite-checksum.py ================================================ #!/usr/bin/env python # # ****************************************************************************** # # CASSETTE ELITE CHECKSUM SCRIPT # # Written by Kieran Connell and Mark Moxon # # This script applies encryption, checksums and obfuscation to the compiled # binaries for the main game and the loader. The script has two parts: # # * The first part generates an encrypted version of the main game's "ELTcode" # binary, based on the code in the original "S.BCFS" BASIC source program # # * The second part generates an encrypted version of the main game's "ELITE" # binary, based on the code in the original "ELITES" BASIC source program # # ****************************************************************************** from __future__ import print_function import sys argv = sys.argv argc = len(argv) encrypt = True disc = True prot = False release = 1 for arg in argv[1:]: if arg == "-u": encrypt = False if arg == "-t": disc = False if arg == "-p": prot = True if arg == "-rel1": release = 1 if arg == "-rel2": release = 2 if arg == "-rel3": release = 3 print("Cassette Elite Checksum") print("Encryption = ", encrypt) print("Build for disc = ", disc) print("Add tape protection = ", prot) # Configuration variables for scrambling code and calculating checksums # # Values must match those in 3-assembled-output/compile.txt # # If you alter the source code, then you should extract the correct values for # the following variables and plug them into the following, otherwise the game # will fail the checksum process and will hang on loading # # You can find the correct values for these variables by building your updated # source, and then searching compile.txt for "elite-checksum.py", where the new # values will be listed if release == 1 or release == 2: BLOCK_offset = 0x14B0 ENDBLOCK_offset = 0x1530 MAINSUM_offset = 0x1335 TUT_offset = 0x13E1 CHECKbyt_offset = 0x1334 CODE_offset = 0x0F86 elif release == 3: if disc: BLOCK_offset = 0x14B0 ENDBLOCK_offset = 0x1530 MAINSUM_offset = 0x1335 TUT_offset = 0x13E1 CHECKbyt_offset = 0x1334 CODE_offset = 0x0F86 else: if prot: BLOCK_offset = 0x14E1 ENDBLOCK_offset = 0x1567 MAINSUM_offset = 0x134A TUT_offset = 0x13F6 CHECKbyt_offset = 0x1349 CODE_offset = 0x0F86 else: BLOCK_offset = 0x14BB ENDBLOCK_offset = 0x153B MAINSUM_offset = 0x1346 TUT_offset = 0x13F2 CHECKbyt_offset = 0x1345 CODE_offset = 0x0F86 # Load assembled code files that make up big code file data_block = bytearray() eliteb_offset = 0 # Append all assembled code files elite_names = ("ELThead", "ELTA", "ELTB", "ELTC", "ELTD", "ELTE", "ELTF", "ELTG") for file_name in elite_names: print(str(len(data_block)), file_name) if file_name == "ELTB": eliteb_offset = len(data_block) elite_file = open("3-assembled-output/" + file_name + ".bin", "rb") data_block.extend(elite_file.read()) elite_file.close() # Commander data checksum commander_offset = 0x52 CH = 0x4B - 2 CY = 0 for i in range(CH, 0, -1): CH = CH + CY + data_block[eliteb_offset + i + 7] CY = (CH > 255) & 1 CH = CH % 256 CH = CH ^ data_block[eliteb_offset + i + 8] print("Commander checksum = ", hex(CH)) data_block[eliteb_offset + commander_offset] = CH ^ 0xA9 data_block[eliteb_offset + commander_offset + 1] = CH # Skip one byte for checksum0 checksum0_offset = len(data_block) data_block.append(0) # Append SHIPS file ships_file = open("3-assembled-output/SHIPS.bin", "rb") data_block.extend(ships_file.read()) ships_file.close() print("3-assembled-output/SHIPS.bin file read") # Calculate checksum0 checksum0 = 0 for n in range(0x0, 0x4600): checksum0 += data_block[n + 0x28] print("checksum 0 = ", hex(checksum0)) if encrypt: data_block[checksum0_offset] = checksum0 % 256 # Encrypt data block if encrypt: for n in range(0x0, len(data_block) - 0x28): data_block[n + 0x28] ^= (n % 256) # Calculate checksum1 checksum1 = 0 for n in range(0x0, 0x28): checksum1 += data_block[n] print("checksum 1 = ", hex(checksum1)) # Write output file for ELTcode output_file = open("3-assembled-output/ELTcode.bin", "wb") output_file.write(data_block) output_file.close() print("3-assembled-output/ELTcode.bin file saved") output_file = None data_block = None # Start again but for loader print("Elite Loader Checksums") loader_block = bytearray() loader_file = open("3-assembled-output/ELITE.unprot.bin", "rb") loader_block.extend(loader_file.read()) loader_file.close() # Reverse bytes between BLOCK and ENDBLOCK for i in range(0, int((ENDBLOCK_offset - BLOCK_offset) / 2)): temp = loader_block[BLOCK_offset + i] loader_block[BLOCK_offset + i] = loader_block[ENDBLOCK_offset - i - 1] loader_block[ENDBLOCK_offset - i - 1] = temp # Compute MAINSUM MAINSUM = 0 for i in range(0, 0x400): MAINSUM += loader_block[i] print("MAINSUM = ", hex(MAINSUM)) if encrypt: loader_block[MAINSUM_offset + 1] = MAINSUM % 256 # Compute CHECKbyt CHECKbyt = 0 for i in range(1, 384): CHECKbyt += loader_block[CHECKbyt_offset + i] print("CHECKbyt = ", hex(CHECKbyt)) if encrypt: loader_block[CHECKbyt_offset] = CHECKbyt % 256 if encrypt: print("Encypting...") # EOR code in BLOCK to ENDBLOCK for i in range(0, ENDBLOCK_offset - BLOCK_offset): loader_block[TUT_offset + i] ^= loader_block[BLOCK_offset + i] # EOR checksum code from CHECKbyt to end of loader # See Elite loader (Part 3 of 6) for decryption routine where we # EOR 2 pages for Ian Bell's variants, and 3 pages for STH variant if release == 1 or release == 2: for i in range(0, 2): for j in range(0, 256): if (j + i * 256 + CHECKbyt_offset) < len(loader_block): loader_block[j + i * 256 + CHECKbyt_offset] ^= loader_block[j + CODE_offset] elif release == 3: for i in range(0, 3): for j in range(0, 256): if (j + i * 256 + CHECKbyt_offset) < len(loader_block): loader_block[j + i * 256 + CHECKbyt_offset] ^= loader_block[j + CODE_offset] # EOR 15 pages of data at beginning of loader for i in range(0, 0xf): for j in range(0, 256): loader_block[j + i * 256] ^= loader_block[j + CODE_offset] # Write output file for ELITE output_file = open("3-assembled-output/ELITE.bin", "wb") output_file.write(loader_block) output_file.close() print("3-assembled-output/ELITE.bin file saved") ================================================ FILE: 2-build-files/elite-decrypt.py ================================================ #!/usr/bin/env python # # ****************************************************************************** # # CASSETTE ELITE DECRYPTION SCRIPT # # Written by Mark Moxon # # This script removes encryption and checksums from the compiled binaries for # the main game code. It reads the encrypted "ELTcode.bin" binary and generates # a decrypted version as "ELTcode.decrypt.bin" # # Files are saved using the decrypt.bin suffix so they don't overwrite any # existing unprot.bin files, so they can be compared if required # # Run this script by changing directory to the repository's root folder and # running the script with "python 2-build-files/elite-decrypt.py" # # You can decrypt specific releases by adding the following arguments, as in # "python 2-build-files/elite-decrypt.py -rel1" for example: # # -rel1 Decrypt the source discs from Ian Bell's site # -rel2 Decrypt the text source discs from Ian Bell's site # -rel3 Decrypt the Stairway to Hell release # # If unspecified, the default is rel3 # # ****************************************************************************** from __future__ import print_function import sys print() print("BBC cassette Elite decryption") argv = sys.argv release = 3 folder = "sth" for arg in argv[1:]: if arg == "-rel1": release = 1 folder = "source-disc" if arg == "-rel2": release = 2 folder = "text-sources" if arg == "-rel3": release = 3 folder = "sth" # Configuration variables if release == 1 or release == 2: BLOCK_offset = 0x14B0 ENDBLOCK_offset = 0x1530 MAINSUM_offset = 0x1335 TUT_offset = 0x13E1 CHECKbyt_offset = 0x1334 CODE_offset = 0x0F86 checksum0_offset = 0x4721 elif release == 3: BLOCK_offset = 0x14B0 ENDBLOCK_offset = 0x1530 MAINSUM_offset = 0x1335 TUT_offset = 0x13E1 CHECKbyt_offset = 0x1334 CODE_offset = 0x0F86 if release == 1: checksum0_offset = 0x4721 elif release == 2: checksum0_offset = 0x471F # Decrypt ELTcode data_block = bytearray() # Load assembled code file elite_file = open("4-reference-binaries/" + folder + "/ELTcode.bin", "rb") data_block.extend(elite_file.read()) elite_file.close() print() print("[ Read ] 4-reference-binaries/" + folder + "/ELTcode.bin") # Do decryption for n in range(0x0, len(data_block) - 0x28): data_block[n + 0x28] ^= (n % 256) if release == 1 or release == 2: data_block[checksum0_offset] = 0 if release == 2: data_block.append(0) data_block.append(0) print("[ Decrypt ] 4-reference-binaries/" + folder + "/ELTcode.bin") # Write output file for ELTcode.decrypt output_file = open("4-reference-binaries/" + folder + "/ELTcode.decrypt.bin", "wb") output_file.write(data_block) output_file.close() print("[ Save ] 4-reference-binaries/" + folder + "/ELTcode.decrypt.bin") # Configuration variables for ELITE loader_block = bytearray() # Load assembled code file elite_file = open("4-reference-binaries/" + folder + "/ELITE.bin", "rb") loader_block.extend(elite_file.read()) elite_file.close() print() print("[ Read ] 4-reference-binaries/" + folder + "/ELITE.bin") # Do decryption # EOR 15 pages of data at beginning of loader for i in range(0xe, -1, -1): for j in range(255, -1, -1): loader_block[j + i * 256] ^= loader_block[j + CODE_offset] # EOR checksum code from CHECKbyt to end of loader # See Elite loader (Part 3 of 6) for decryption routine where we # EOR 2 pages for Ian Bell's variants, and 3 pages for STH variant if release == 1 or release == 2: for i in range(1, -1, -1): for j in range(255, -1, -1): if (j + i * 256 + CHECKbyt_offset) < len(loader_block): loader_block[j + i * 256 + CHECKbyt_offset] ^= loader_block[j + CODE_offset] elif release == 3: for i in range(2, -1, -1): for j in range(255, -1, -1): if (j + i * 256 + CHECKbyt_offset) < len(loader_block): loader_block[j + i * 256 + CHECKbyt_offset] ^= loader_block[j + CODE_offset] # EOR code in BLOCK to ENDBLOCK for i in range(ENDBLOCK_offset - BLOCK_offset - 1, -1, -1): loader_block[TUT_offset + i] ^= loader_block[BLOCK_offset + i] # Reverse bytes between BLOCK and ENDBLOCK for i in range(0, int((ENDBLOCK_offset - BLOCK_offset) / 2)): temp = loader_block[BLOCK_offset + i] loader_block[BLOCK_offset + i] = loader_block[ENDBLOCK_offset - i - 1] loader_block[ENDBLOCK_offset - i - 1] = temp # Zero two checksum bytes to match assembled code loader_block[CHECKbyt_offset] = 0 loader_block[MAINSUM_offset + 1] = 0 print("[ Decrypt ] 4-reference-binaries/" + folder + "/ELITE.bin") # Write output file for ELITE.decrypt output_file = open("4-reference-binaries/" + folder + "/ELITE.decrypt.bin", "wb") output_file.write(loader_block) output_file.close() print("[ Save ] 4-reference-binaries/" + folder + "/ELITE.decrypt.bin") print() ================================================ FILE: 2-build-files/mktibet-0.3.php ================================================ =7, reduce stupidity declare (strict_types=1); define ("MKT_E_OK", 0); define ("MKT_E_CLI", 1); define ("MKT_E_LOAD", 2); define ("MKT_E_LARGE_FILE", 3); define ("MKT_E_SAVE", 4); define ("CLI_STATE_IDLE", 0); define ("CLI_STATE_LOAD", 1); define ("CLI_STATE_EXEC", 2); define ("CLI_STATE_NAME", 3); define ("CLI_STATE_TIBET", 4); define ("CLI_STATE_BAUD", 5); define ("MAX_FILE_SIZE", 32 * 1024); define ("DURATION_PRE_GAP_S", 2.0); define ("DURATION_MID_GAP_S", 1.0); define ("DURATION_POST_GAP_S", 2.0); define ("DURATION_LEADER_S", 1.0); define ("TIBET_VERSION", 0.4); define ("MKTIBET_VERSION", 0.3); define ("DURATION_LEADER_CYCS", (int) (DURATION_LEADER_S * 2400.0)); $argv = $_SERVER['argv']; print "\n$argv[0] v".MKTIBET_VERSION."\n\n"; $e = process($argv); return $e; class FileOpts { var $load; var $exec; var $baud; var $prepend_dummy_byte; // 0.3 var $have_load; var $have_exec; var $have_baud; var $have_no_dummy; // 0.3 function __construct() { $this->load = 0xffff1900; $this->exec = 0xffff8023; $this->baud = 1200; $this->prepend_dummy_byte = TRUE; // 0.3 $this->have_load = 0; $this->have_exec = 0; $this->have_baud = 0; $this->have_no_dummy = 0; // 0.3 } function to_string() : string { $s="("; $s .= sprintf("load &%x; ", $this->load); $s .= sprintf("exec &%x; ", $this->exec); $s .= "baud ".$this->baud."; "; $s .= "prepend_dummy $this->prepend_dummy_byte"; // 0.3 $s .= ")"; return $s; } } class TibetFile { var $mos_name; var $path_to_src; var $opts; var $data; var $have_mos_name; function __construct (int $baud) { $this->mos_name=NULL; $this->data=""; $this->path_to_src = ""; $this->have_mos_name = 0; $this->opts = new FileOpts; $this->opts->baud = $baud; $this->opts->prepend_dummy_byte = TRUE; // v0.3: BeebEm fail } function to_string() : string { $s=""; $s .= "MOS: \"$this->mos_name\", "; //$s .= "path: \"$this->path_to_src\", "; $s .= $this->opts->to_string(); return $s; } } function process(array $argv) { $files = array(); $tibet_fn="tibet.tibet"; $e = parse_cli ($argv, $files, $tibet_fn); // files, tibet_fn populated if (MKT_E_OK != $e) { usage($argv[0]); return $e; } $e = fill_missing_names ($files); if (MKT_E_OK != $e) { return $e; } $e = load_files ($files); if (MKT_E_OK != $e) { return $e; } foreach ($files as $k=>$v) { print $v->path_to_src."\n"; print " ".$v->to_string(); print "\n"; } $tibet_s = ""; $e = build_tibet ($files, $tibet_s); if (MKT_E_OK != $e) { return $e; } if (FALSE === @file_put_contents ($tibet_fn, $tibet_s)) { print "E: Could not write output file: $tibet_fn\n"; return MKT_E_SAVE; } print "Wrote ".strlen($tibet_s)." bytes: $tibet_fn\n"; return MKT_E_OK; } function build_tibet (array $files, string &$out) : int { $out .= "tibet ".TIBET_VERSION."\n\n"; $out .= "silence ".DURATION_PRE_GAP_S."\n\n"; $num_files = count($files); $prev_baud = 0; for ($n=0; $n < $num_files; $n++) { $f = $files[$n]; $d = $f->data; $len = strlen($d); // v0.3: Maddeningly, BeebEm misses the start of the first block unless you // send some dummy data first, because ... no, I've no idea why on earth it would do this if ($f->opts->prepend_dummy_byte) { $out .= "leader ".DURATION_LEADER_CYCS."\n"; $out .= "data\n----..--..--..--....\nend\n"; // standard MOS 1.2 &AA dummy byte $out .= "leader ".DURATION_LEADER_CYCS."\n\n"; } // split into blocks for ($i=0, $rem=$len, $bn=0; $i < $len; $i += 256, $rem -= 256, $bn++) { if ($rem < 256) { $blklen = $rem; } else { $blklen = 256; } $blk_payload = substr ($d, $i, $blklen); $blk_built = ""; $e = build_block ($bn, $rem <= 256, FALSE, $blk_payload, $f, $blk_built); if (MKT_E_OK != $e) { return $e; } $blk_encoded = ""; $e = tibet_encode ($blk_built, $f->opts->baud, $prev_baud != $f->opts->baud, // baud changed? $blk_encoded); if (MKT_E_OK != $e) { return $e; } $leader_cycs = DURATION_LEADER_CYCS; $out .= "leader ".$leader_cycs."\n\n"; $out .= $blk_encoded; //printf("%02x len %u\n", $bn, strlen($blk)); $prev_baud = $f->opts->baud; } $out .= "leader ".DURATION_LEADER_CYCS."\n\n"; if ($n < ($num_files - 1)) { $out .= "silence ".DURATION_MID_GAP_S."\n\n"; } } $out .= "silence ".DURATION_POST_GAP_S."\n\n"; return MKT_E_OK; } function tibet_encode (string $in, int $baud, bool $baud_changed, string &$out) : int { $out = ""; if ($baud_changed) { $out .= "/baud ".$baud."\n"; } $out .= "data\n"; $len = strlen($in); $one = ($baud == 1200) ? ".." : "........"; $zero = ($baud == 1200) ? "--" : "--------"; $newline_limit = ($baud == 1200) ? 3 : 0; for ($n=0, $x=0; $n < $len; $n++, $x++) { $c = ord($in[$n]); $out .= $zero; // start bit for ($i=0; $i < 8; $i++) { $out .= ($c&1) ? $one : $zero; $c = ($c >> 1) & 0x7f; } $out .= $one; // stop bit if ($x == $newline_limit) { $out .= "\n"; $x = -1; } } if ($x!=0) { $out .= "\n"; } $out .= "end\n\n"; return MKT_E_OK; } function build_block (int $bn, bool $final, bool $locked, string $payload, TibetFile $tf, string &$out) : int { $len = strlen($payload); $flags = ($final ? 0x80 : 0) | (($len == 0) ? 0x40 : 0) | ($locked ? 1 : 0); $hdr = $tf->mos_name. "\x00". to_le32($tf->opts->load). to_le32($tf->opts->exec). to_le16($bn). to_le16($len). chr($flags). "\x00\x00\x00\x00"; $hcrc = acorn_crc($hdr); $out = "*" . $hdr . to_be16($hcrc); if ($len > 0) { $dcrc = acorn_crc($payload); $out .= $payload . to_be16($dcrc); } return MKT_E_OK; } function acorn_crc (string $s) : int { $crc = 0; for ($n=0; $n < strlen($s); $n++) { //u8_t i; //u32_t c; //u16_t h; $b = ord($s[$n]); $c = $crc; $h = ($c>>8) & 0xff; $h = $b ^ $h; $c = ($c & 0x00ff) | (($h << 8) & 0xff00); for ($i=0; $i<8; $i++) { //u32_t t; $t = 0; if ($c & 0x8000) { $c = $c ^ 0x810; $t = 1; } $c = 0xffff & ($t | (($c<<1) & 0xfffe)); } $crc = $c; } return $crc; } function to_be16 (int $i) : string { $s = ""; $s .= chr(($i >> 8) & 0xff); $s .= chr($i & 0xff); return $s; } function to_le16 (int $i) : string { $s = ""; $s .= chr($i & 0xff); $s .= chr(($i >> 8) & 0xff); return $s; } function to_le32 (int $i) : string { $s = ""; $s .= chr($i & 0xff); $s .= chr(($i >> 8) & 0xff); $s .= chr(($i >> 16) & 0xff); $s .= chr(($i >> 24) & 0xff); return $s; } function load_files (array &$files) : int { foreach ($files as $k=>$file) { $p = $file->path_to_src; $f = @file_get_contents($p); if (FALSE === $f) { print "E: Could not load file: $p\n"; return MKT_E_LOAD; } if (strlen($f) > MAX_FILE_SIZE) { print "E: File was too large: $p\n"; return MKT_E_LARGE_FILE; } $file->data = $f; $files[$k] = $file; } return MKT_E_OK; } function fill_missing_names (array &$a) : int { foreach ($a as $k=>$file) { if ( ! isset($file->mos_name) ) { $basename = basename($file->path_to_src); $e = check_mos_filename($basename); if (MKT_E_OK != $e) { return $e; } $file->mos_name = $basename; $a[$k] = $file; // replace in array } } return MKT_E_OK; } function parse_cli (array $argv, array &$files, string &$tibet_fn) : int { $opts_done = 0; $state = 0; $argc = count($argv) - 1; $have_tibet_filename = 0; // current working file $f = new TibetFile(1200); $state = CLI_STATE_IDLE; for ($n=1; $n <= $argc; $n++) { $v = $argv[$n]; if ($state == CLI_STATE_IDLE) { if ($v[0] == "+") { // opt if ($v == "+x") { // execution address if ($f->opts->have_exec) { print "E: Cannot specify exec address twice.\n"; return MKT_E_CLI; } $f->opts->have_exec = 1; $state = CLI_STATE_EXEC; } else if ($v == "+d") { // load address if ($f->opts->have_load) { print "E: Cannot specify load address twice.\n"; return MKT_E_CLI; } $f->opts->have_load = 1; $state = CLI_STATE_LOAD; } else if ($v == "+b") { // baud if ($f->opts->have_baud) { print "E: Cannot specify baud rate twice.\n"; return MKT_E_CLI; } $f->opts->have_baud = 1; $state = CLI_STATE_BAUD; } else if ($v == "+n") { // overridden MOS filename if ($f->have_mos_name) { print "E: Cannot specify MOS filename twice.\n"; return MKT_E_CLI; } $f->have_mos_name = 1; $state = CLI_STATE_NAME; } else if ($v == "+t") { // TIBET filename if ($have_tibet_filename) { print "E: Cannot specify TIBET filename twice.\n"; return MKT_E_CLI; } $have_tibet_filename = 1; $state = CLI_STATE_TIBET; } else if ($v == "+no-dummy") { if ($f->opts->have_no_dummy) { print "E: Cannot specify no-dummy twice.\n"; return MKT_E_CLI; } $f->have_no_dummy = 1; $f->opts->prepend_dummy_byte = FALSE; } else { print "E: unknown option $v\n"; $e = MKT_E_CLI; return $e; } } else { // no '+' => filename, completes file $f->path_to_src = $v; $files[] = $f; // start a new one, but persist the baud from previous one $f = new TibetFile($f->opts->baud); } } else if ($state == CLI_STATE_LOAD) { $i=0; $e = cli_parse_x32($v, $i); if (MKT_E_OK != $e) { return $e; } $f->opts->load = $i; $state = CLI_STATE_IDLE; } else if ($state == CLI_STATE_EXEC) { $i=0; $e = cli_parse_x32($v, $i); if (MKT_E_OK != $e) { return $e; } $f->opts->exec = $i; $state = CLI_STATE_IDLE; } else if ($state == CLI_STATE_BAUD) { $i=0; $e = cli_parse_baud($v, $i); if (MKT_E_OK != $e) { return $e; } $f->opts->baud = $i; $state = CLI_STATE_IDLE; } else if ($state == CLI_STATE_NAME) { $e = check_mos_filename($v); if (MKT_E_OK != $e) { return $e; } $f->mos_name = $v; $state = CLI_STATE_IDLE; } else if ($state == CLI_STATE_TIBET) { $tibet_fn = $v; $state = CLI_STATE_IDLE; } } // next arg if ( ! $have_tibet_filename ) { print "\nE: Must specify output TIBET filename with +t.\n"; return MKT_E_CLI; } return MKT_E_OK; } function check_mos_filename (string $v) : int { if (strlen($v) > 10) { print "E: overridden MOS filename is too long (max 10 chars): $v\n"; return MKT_E_CLI; } else if (strlen($v) == 0) { print "E: overridden MOS filename is empty: $v\n"; return MKT_E_CLI; } $len = strlen($v); for ($n=0; $n < $len; $n++) { if ($v[$n] == "\x00") { print "E: overridden MOS filename contains null byte\n"; return MKT_E_CLI; } } return MKT_E_OK; } function cli_parse_baud (string $v, int &$baud_out) : int { if ($v == "300") { $baud_out = 300; } else if ($v == "1200") { $baud_out = 1200; } else { print "E: Illegal baud: $v\n"; return MKT_E_CLI; } return MKT_E_OK; } function cli_parse_x32 (string $v, int &$out) : int { $len = strlen($v); if ($len == 0) { print "E: illegal 32-bit hex: $v\n"; return MKT_E_CLI; } // removed because it causes backgrounding on Unix! //if ($v[0]=="&") { // $v = substr($v, 1); //} if (($v[0]=="0") && (($v[1]=="x") || ($v[1]=="X"))) { $v = substr($v, 2); } $len = strlen($v); if ($len > 8) { print "E: illegal 32-bit hex: $v\n"; return MKT_E_CLI; } for ($n=0; $n < $len; $n++) { if ( ! ctype_xdigit($v[$n]) ) { print "E: illegal 32-bit hex: $v\n"; return MKT_E_CLI; } } $i=0; $e = sscanf($v, "%x", $i); if (FALSE === $e) { print "E: illegal 32-bit hex: $v\n"; return MKT_E_CLI; } $out = $i; return MKT_E_OK; } function usage (string $argv0) { print "\n\nUsage:\n\n"; print " php -f $argv0 +t [opts] [opts] [opts] ...\n\n"; print "where each per-file [opts] may be:\n\n"; print " +x specify execute address for next file\n"; print " +d specify load address for next file\n"; print " +b <1200|300> specify baud rate for next file\n"; print " +n override MOS filename for next file\n"; print " +no-dummy disable prepending &AA byte before next file\n"; print "\n"; } ?> ================================================ FILE: 2-build-files/tibetuef-0.8.php ================================================ =7, reduce stupidity declare (strict_types=1); define ("APPNAME", "tibetuef.php"); define ("TIBETUEF_VERSION", "0.8"); //define ("TIBET_VERSION_STG", "0.4"); define ("TIBET_MAJOR_VERSION", "0"); define ("TBT_E_OK", 0); define ("TBT_E_USAGE", 1); define ("TBT_E_LOAD", 2); define ("TBT_E_IPFN_MATCHES_OPFN", 3); define ("TBT_E_PARSE_VERSION", 4); define ("TBT_E_BAD_VERSION", 5); define ("TBT_E_PARSE_BAD_LINE", 6); define ("TBT_E_PARSE_SILENCE", 7); define ("TBT_E_BAD_SILENCE", 8); define ("TBT_E_PARSE_LEADER", 9); define ("TBT_E_BAD_LEADER", 10); define ("TBT_E_PARSE_DATA", 11); define ("TBT_E_BAD_PHASE", 12); define ("TBT_E_PARSE_CYCLES", 13); define ("TBT_E_BUG", 14); define ("TBT_E_WRITE_FILE", 15); define ("TBT_E_PARSE_HINT", 16); define ("TBT_E_BAD_FRAMING", 17); define ("TBT_E_PARSE_DUP_VERSION", 18); define ("TBT_E_BAD_INT", 19); define ("TBT_E_BAD_FLOAT", 20); define ("TBT_E_GZIP", 21); // 0.7: handle void chunks define ("TBT_E_ZL_CHUNK", 22); // 0.8: major version mismatch define ("TBT_E_INCOMPATIBLE", 23); define ("STATE_VERSION", 0); define ("STATE_IDLE", 1); define ("STATE_CYCLES", 2); class Span { var $linenum; var $span_ix; } class TimeHint extends Span { var $timestamp; } class ParsedTibet { var $version; var $spans; function __construct() { $this->spans = array(); $this->version = ""; } } class TibetSilence extends Span { var $secs; } class TibetLeader extends Span { var $cycles; } class DataFraming extends Span { var $framelen; // 7 or 8: FIXME: rename to wordlen var $parity; // string; "N", "O", "E" var $stops; // 1 or 2 //var $autodetected; function to_string() : string { return "$this->framelen$this->parity$this->stops"; } function __construct() { // defaults $this->framelen = 8; $this->parity = "N"; $this->stops = 1; } } class BaudRate extends Span { var $rate; function to_string() : string { return "$this->rate"; } function __construct() { // default $this->rate = 1200; } } class TibetData extends Span { var $squawk; var $cycles; // array var $bits; var $framing; // DataFraming function __construct() { $this->cycles = array(); // TibetCycles $this->bits = array(); // also TibetCycles ... $this->squawk = 0; } } class TibetCycle extends Span { var $value; } class DummyByte extends Span { var $pre_leader_cycs; var $post_leader_cycs; var $byte_value; } $e = tbt_main ($_SERVER['argc'], $_SERVER['argv']); if (TBT_E_USAGE == $e) { usage($_SERVER['argv'][0]); } return $e; die(); function tbt_main ($argc, $argv) : int { print "\ntibetuef.php ".TIBETUEF_VERSION."\n\n"; $insert_timestamps = 0; $use_chunk_102 = 0; //$use_chunk_102b = 0; $use_chunk_104 = 0; $use_chunk_114 = 0; // 0.8: option to use &112 for silence $use_chunk_112_for_silence = 0; $have_nz = 0; $have_no_117 = 0; // 0.6 if ($argc < 3) { // PHP filename, ipfn, opfn return TBT_E_USAGE; } $chunk_change_count = 0; // -2 for ipfn, opfn for ($i=1, $dupe=0; $i < ($argc - 2); $i++) { $a = $argv[$i]; if ($a[0] != "+") { break; } //if (CLI_STATE_IDLE == $state) { //if ($a == "+f") { // if ($autodetect_framings) { return TBT_E_USAGE; } // dup // $autodetect_framings = 1; //} else if ($a == "+t") { if ($insert_timestamps) { $dupe = 1; } // dup $insert_timestamps = 1; } else if ($a == "+102") { if ($use_chunk_102) { $dupe = 1; } $use_chunk_102 = 1; $chunk_change_count++; //} else if ($a == "+102b") { // if ($use_chunk_102b) { $dupe = 1; } // $use_chunk_102b = 1; // $chunk_change_count++; } else if ($a == "+104") { if ($use_chunk_104) { $dupe = 1; } $use_chunk_104 = 1; $chunk_change_count++; } else if ($a == "+114") { if ($use_chunk_114) { $dupe = 1; } $use_chunk_114 = 1; $chunk_change_count++; } else if ($a == "+112") { // 0.8 if ($use_chunk_112_for_silence) { $dupe = 1; } $use_chunk_112_for_silence = 1; } else if ($a == "+nz") { if ($have_nz) { $dupe = 1; } $have_nz = 1; } else if ($a == "+no-117") { // 0.6 if ($have_no_117) { $dupe = 1; } $have_no_117 = 1; } else { print "E: Unknown option $a\n\n"; return TBT_E_USAGE; } if ($dupe) { print "E: Duplicate option $a specified.\n\n"; return TBT_E_USAGE; } } if ($chunk_change_count > 1) { print "E: Can only supply one of +102, +104 and +114.\n\n"; return TBT_E_USAGE; } $ipfn = $argv[$argc - 2]; $opfn = $argv[$argc - 1]; print "Input file: $ipfn\n"; print "Output file: $opfn\n"; if ($insert_timestamps) { print "Inserting &120 chunks for /time hints.\n"; } // 0.8 if ($use_chunk_112_for_silence) { print "Using &112 for silence instead of &116.\n"; } //$chunk_102_interpretation = -1; $chunk_to_use_for_data = 0x100; if ($use_chunk_102) { // || $use_chunk_102b) { $chunk_to_use_for_data = 0x102; //$chunk_102_interpretation = $use_chunk_102b; } else if ($use_chunk_104) { $chunk_to_use_for_data = 0x104; } else if ($use_chunk_114) { $chunk_to_use_for_data = 0x114; } if ($chunk_change_count > 0) { print "Using chunk type &".sprintf("%x", $chunk_to_use_for_data)." for data.\n"; } if ($have_nz) { print "Will not compress output UEF file.\n"; } //if ($autodetect_framings) { // print "Autodetecting framings.\n"; //} else { // print "Taking framings from TIBET file.\n"; //} print "\n"; if ($ipfn == $opfn) { print "E: Input and output filenames cannot match.\n"; return TBT_E_IPFN_MATCHES_OPFN; } if (FALSE === ($ip = file_get_contents($ipfn))) { print "E: Could not load file: $ipfn\n"; return TBT_E_LOAD; } $len = strlen($ip); print "Loaded $len bytes.\n"; // try gzdecode $ip_unz = @gzdecode($ip); if (FALSE === $ip_unz) { print "Input TIBET was uncompressed.\n"; } else { print "Decompressed input TIBET: ".strlen($ip)." -> ".strlen($ip_unz)." bytes.\n"; $ip = $ip_unz; } $tbt = new ParsedTibet; $e = tbt_process ($ip, ($insert_timestamps == 1), $tbt); // tbt populated if (TBT_E_OK != $e) { return $e; } $e = cycles_to_bits ($tbt); // tbt modified if (TBT_E_OK != $e) { return $e; } //if ($autodetect_framings) { // override framings that may have been read from the TIBET file earlier //$e = autopopulate_framings($tbt); // tbt modified //if (TBT_E_OK != $e) { return $e; } //} else { //$e = populate_framings_from_tibet ($tbt); // tbt modified //if (TBT_E_OK != $e) { return $e; } //} // 0.4 $e = spans_fix_up_long_leader($tbt); if (TBT_E_OK != $e) { return $e; } // 0.4 $e = spans_detect_and_convert_dummy_bits($tbt); if (TBT_E_OK != $e) { return $e; } $uef = ""; $msg = ""; $e = build_uef ($tbt, $chunk_to_use_for_data, $use_chunk_112_for_silence, // 0.8 //$chunk_102_interpretation, $have_no_117, // 0.6 $uef, $msg); if (TBT_E_OK != $e) { return $e; } print "\nChunks: (type-len)\n"; print_chunk_messages($msg); print "\n"; if ( ! $have_nz ) { $uef_z = gzencode($uef, 9, FORCE_GZIP); if (FALSE === $uef_z) { print "E: Could not compress output UEF.\n"; return TBT_E_GZIP; } print "Compressed output UEF: ".strlen($uef)." -> ".strlen($uef_z)." bytes.\n"; $uef = $uef_z; } if (FALSE === file_put_contents($opfn, $uef)) { print "E: Could not write file: $opfn\n"; return TBT_E_WRITE_FILE; } return TBT_E_OK; } // 0.4 function spans_fix_up_long_leader (ParsedTibet &$tbt) : int { $spans_new = array(); foreach ($tbt->spans as $k=>$span) { if ((get_class($span) != "TibetLeader") || ($span->cycles <= 0xffff)) { $spans_new[] = $span; continue; } for ($rem = $span->cycles; $rem > 0; $rem -= 0xffff) { $num_cycs = $rem; if ($num_cycs > 0xffff) { $num_cycs = 0xffff; } $new_span = new TibetLeader; $new_span->linenum = $span->linenum; $new_span->span_ix = $span->span_ix; // preserve this $new_span->cycles = $num_cycs; $spans_new[] = $new_span; //~ print "M: L$span->linenum, span $span->span_ix: Leader: $num_cycs cycs\n"; } } $tbt->spans = $spans_new; //foreach ($tbt->spans as $k=>$v) { if ("TibetLeader"==get_class($v)) { print "L: $v->cycles\n"; } } return TBT_E_OK; } function print_chunk_messages ($msg) { print wordwrap($msg); } function cycles_to_bits (ParsedTibet &$tbt) : int { $current_baud = 1200; foreach ($tbt->spans as $sn => $span) { if (gettype($span) != "object") { print "B: cycles_to_bits: Bad span type: \"".gettype($span)."\"\n"; return TBT_E_BUG; } $type = get_class($span); if ("BaudRate" == $type) { print "span #$span->span_ix: Baud rate change: $current_baud -> $span->rate\n"; $current_baud = $span->rate; } if ("TibetData" != $type) { continue; } //print count($tbd->cycles)." cycles in span\n"; $span->bits = array(); $i=0; //print_r($span); die(); $bitlen = 2; if ($current_baud == 300) { $bitlen = 8; } $num_atoms = count($span->cycles); //for ($i=0; $i < (count($span->cycles) - 1); $i+=2) { for ($i=0; $i < ($num_atoms - ($bitlen - 1)); $i += $bitlen) { //$atoms = array(); $ln = $span->cycles[$i]->linenum; $zeros = 0; $ones = 0; for ($j=0; ($j < $bitlen) && (($i + $j) < $num_atoms); $j++) { //$atoms[$j] = $span->cycles[$i + $j]; if ($span->cycles[$i + $j]->value) { $ones++; } else { $zeros++; } } if ($j != $bitlen) { print "W: cycles_to_bits: line $ln, span #$span->span_ix: Partial bit\n"; $atom = $span->cycles[$i]; // partial bit: use the first atom's value } else { /* for ($j=0; $j < $bitlen; $j++) { if ($span->cycles[$i + $j]->value) { $ones++; } else { $zeros++; } } */ if (($ones == $bitlen) || ($zeros == $bitlen)) { // unanimous $atom = $span->cycles[$i]; } else { // bad bit print "W: cycles_to_bits: line $ln, span #$span->span_ix: Fuzzy bit\n"; // skip one atom and resynchronise $i -= ($bitlen - 1); continue; } // this is the old code that allowed voting on // 300 baud bits; it now violates the TIBET // specification on decode, so it's been replaced // with the simple skip-one-atom-and-resync logic from the spec /* } else { print "W: cycles_to_bits: line $ln, span #$span->span_ix: Fuzzy bit\n"; if ($ones > $zeros) { // find first one for ($j=0; $j < $bitlen; $j++) { if ($span->cycles[$i + $j]->value) { $atom = $span->cycles[$i]; } } } else if ($ones < $zeros) { // find first zero for ($j=0; $j < $bitlen; $j++) { if ( ! $span->cycles[$i + $j]->value ) { $atom = $span->cycles[$i]; } } } else { // it's a tie, just use first atom $atom = $span->cycles[$i]; } } */ } // at this point we should have an atom //$a = $span->cycles[$i]->value; //$b = $span->cycles[$i+1]->value; /* if ($a != $b) { print "W: cycles_to_bits: L$ln, span #$span->span_ix: Cycle pair mismatch\n"; // skip one and resynchronise $i--; continue; } $span->bits[] = $span->cycles[$i]; */ $span->bits[] = $atom; } //print count($bits)." bits in span\n"; } // next span return TBT_E_OK; } function populate_framings_from_tibet (ParsedTibet &$tbt) : int { // use "framing ..." lines to set framings on subsequent data spans $framing = new DataFraming; // 8N1 default foreach ($tbt->spans as $sn => $span) { if (gettype($span) != "object") { print "B: populate_framings_from_tibet: Bad span type: \"".gettype($span)."\"\n"; return TBT_E_BUG; } $type = get_class($span); if ("TibetData" == $type) { // note that this means the framing field on the data span // is itself a span, with a span_ix and a line number, which // will be the originating span where this framing was programmed. $tbt->spans[$sn]->framing = $framing; } else if ("DataFraming" == $type) { $framing = $span; } } return TBT_E_OK; } /* function autopopulate_framings (ParsedTibet &$tbt) : int { // default to 8N1 framing, since BASIC always needs this to load $prev_framing = new DataFraming; foreach ($tbt->spans as $sn => $span) { if (gettype($span) != "object") { print "B: autopopulate_framings: Bad span type: \"".gettype($span)."\"\n"; return TBT_E_BUG; } $type = get_class($span); if ("TibetData" != $type) { continue; } if ($span->squawk) { continue; } // need to identify framing format // "For the BBC/Electron, the following formats may be encountered: // 7E1, 7E2, 7O1, 7O2, 8E1, 8N2, 8O1. // Format 8N1 would produce the same output as chunk &0100." // 7E1/7O1: 0xxxxxxxP1 } // 8N1: 0xxxxxxxx1 } "short" // ^ short_stops_score counts these // 7E2/7O2: 0xxxxxxxP11 } "long" // 8N2: 0xxxxxxxx11 } // 8E1/8O1: 0xxxxxxxxP1 } // ^ long_stops_score counts these // ^ double_stop_score counts these $bits = $span->bits; $nb = count($bits); if ($nb < 1000) { print "W: L$span->linenum, span #$span->span_ix, $nb bits: too short to derive framing, using previous ".$prev_framing->to_string()."\n"; $span->framing = $prev_framing; continue; } // find first start bit (should be right at the start) for ($i=0; $i < $nb; $i++) { $b = $bits[$i]; if (0 == $b->value) { break; } } if ($i != 0) { print "W: autopopulate_framings: L$b->linenum, span #$b->span_ix, $nb bits: Late start bit (i=$i)\n"; } $i++; // first data bit $short_stops_score = 0; $short_odd_score = 0; $short_even_score = 0; // assume frame len of 10 for ($j=$i; $j < ($nb - 9); $j += 10) { $short_stops_score += $bits[$j+8]->value; $ones = 0; // check all data bits, plus the parity bit (8 bits); count the ones for ($k=$j; $k < $j+8; $k++) { $ones += $bits[$k]->value; } if ($ones & 1) { $short_odd_score++; } else { $short_even_score++; } } $long_stops_score = 0; $double_stop_score = 0; $long_7bit_odd_score = 0; $long_7bit_even_score = 0; $long_8bit_odd_score = 0; $long_8bit_even_score = 0; // now assume frame len of 11 for ($j=$i; $j < ($nb - 10); $j+=11) { $long_stops_score += $bits[$j+9]->value; $double_stop_score += $bits[$j+8]->value; $ones = 0; // check all data bits, plus the potential parity bit (8 bits); count the ones for ($k=$j+1; $k < $j+9; $k++) { $ones += $bits[$k]->value; } if ($ones & 1) { $long_7bit_odd_score++; } else { $long_7bit_even_score++; } // do it again but include an extra bit, another potential parity bit $ones += $bits[$j+9]->value; if ($ones & 1) { $long_8bit_odd_score++; } else { $long_8bit_even_score++; } } //print "short_stops_score = $short_stops_score\n"; //print "short_even_score = $short_even_score\n"; //print "short_odd_score = $short_odd_score\n"; //print "long_stops_score = $long_stops_score\n"; //print "double_stop_score = $double_stop_score\n"; // if short_stops_score > long_stops_score // 7E1, 7O1, 8N1 // else // if double_stop_score ~= long_stops_score // 7E2, 7O2, 8N2 // else // 8E1, 8O1 $framelen = 0; $parity = ""; $stops = 0; // $epsilon is "approximately zero" $epsilon = $nb / 320; if ($short_stops_score > ($long_stops_score * 1.1)) { // 7E1/7O1: 0xxxxxxxP1 } // 8N1: 0xxxxxxxx1 } "short" // for a perfect signal, // 7E1: short_odd_score = 0, short_even_score = lots // 7O1: short_odd_score = lots, short_even_score = 0 // 8N1: short_odd_score = some, short_even_score = some $stops = 1; if ($short_odd_score < $epsilon) { // 7E1 $framelen = 7; $parity = "E"; } else if ($short_even_score < $epsilon) { // 7O1 $framelen = 7; $parity = "O"; } else { // 8N1 $framelen = 8; $parity = "N"; } } else if (abs($double_stop_score - $long_stops_score) < $epsilon) { // 7E2/7O2: 0xxxxxxxP11 } "long" // 8N2: 0xxxxxxxx11 } $stops = 2; if ($long_7bit_odd_score < $epsilon) { // 7E2 $framelen = 7; $parity = "E"; } else if ($long_7bit_even_score < $epsilon) { // 7O2 $framelen = 7; $parity = "O"; } else { // 8N2 $framelen = 8; $parity = "N"; } } else { // 8E1/8O1: 0xxxxxxxxP1 $stops = 1; $framelen = 8; if ($long_8bit_odd_score < $epsilon) { // 8E1 $parity = "E"; } else { // 8O1 $parity = "O"; } } $framing = new DataFraming; $framing->stops = $stops; $framing->framelen = $framelen; $framing->parity = $parity; //$framing->autodetected = TRUE; $tbt->spans[$sn]->framing = $framing; $prev_framing = $framing; print "Framing: L$b->linenum, span #$b->span_ix, $nb bits: ".$span->framing->to_string()."\n"; } return TBT_E_OK; } */ function spans_detect_and_convert_dummy_bits (ParsedTibet &$tbt) : int { $dummies = array(); // for a dummy bit span, we need , // so we start at 1 and end at N-2 for ($i=1; $i < (count($tbt->spans) - 1); $i++) { $prev = $tbt->spans[$i-1]; $cur = $tbt->spans[$i]; $next = $tbt->spans[$i+1]; if ( (get_class($prev) != "TibetLeader") || (get_class($cur) != "TibetData") || (get_class($next) != "TibetLeader")) { continue; // nope } $num_bits = count($cur->bits); if ($num_bits < 10) { continue; // nope } // candidate span may have some leader tone following the // data burst, so we need to ignore that. for ($end=($num_bits - 1); ($end>=0) && ($cur->bits[$end]->value == 1); $end--) { } // $end should now point to the last zero in the chunk if ($end != 7) { continue; // nope } // OK, expect &AA $bits = $cur->bits; if ( !$bits[0]->value && !$bits[1]->value && $bits[2]->value && !$bits[3]->value && $bits[4]->value && !$bits[5]->value && $bits[6]->value && !$bits[7]->value) { print "M: line $cur->linenum: Dummy byte detected.\n"; $dummies[] = $i; } } // rather than mess about trying to delete elements from // the spans list, which would mess up the numbering in // dummies, we'll just set them to NULL. foreach ($dummies as $k=>$span_ix) { $tdb = new DummyByte; $tdb->linenum = $tbt->spans[$span_ix]->linenum; $tdb->pre_leader_cycs = $tbt->spans[$span_ix-1]->cycles; $tdb->post_leader_cycs = $tbt->spans[$span_ix+1]->cycles; $tdb->value = 0xAA; $tbt->spans[$span_ix] = $tdb; // delete the formerly leader spans: $tbt->spans[$span_ix - 1] = NULL; $tbt->spans[$span_ix + 1] = NULL; } $spans_new = array(); for ($i=0; $i < count($tbt->spans); $i++) { // DON'T rewrite the span indices. We want these to reflect // the original lineup in the TIBET file, so // will end up with a pair of discontinuities: ... N-3, N-2, N, N+2, N+3 ... if (isset($tbt->spans[$i])) { // now skip the NULLs $spans_new[] = $tbt->spans[$i]; } } //print "orig: ".count($tbt->spans).", final: ".count($spans_new)."\n"; $tbt->spans = $spans_new; // replace orig array return TBT_E_OK; } function build_uef (ParsedTibet $tbt, int $chunk_to_use_for_data, int $use_chunk_112_for_silence, int $omit_chunk_117, // 0.6 string &$uef, string &$msg) : int { // header, versions $uef = "UEF File!\x00\x0a\x00"; // origin chunk $origin = "Created with ".APPNAME." v".TIBETUEF_VERSION."\0"; $orglen = strlen($origin); $uef .= "\x00\x00".le32($orglen).$origin; $limit = count($tbt->spans); $framing = new DataFraming; $cycs_to_steal = 0; // 0.5 $cur_active_baud = 1200; foreach ($tbt->spans as $sn => $span) { if (gettype($span) != "object") { print "B: Bad span type: \"".gettype($span)."\"\n"; return TBT_E_BUG; } $type = get_class($span); $chunkbuf=""; $chunktype = 0; if ("TibetLeader" == $type) { // we (maybe) stole some 1-cycles from this leader to pad the // preceding data cycle $span->cycles -= $cycs_to_steal; } $cycs_to_steal = 0; if ("TibetLeader" == $type) { $chunktype = 0x110; // may need multiple chunks // 0.4 -- not any more -- we handle this earlier now, // in a separate span-processing pass, // because there's a potential problem with chunk &111 // which amalgamates leader spans /* for ($rem = $span->cycles; $rem > 0; $rem -= 0xffff) { $num_cycs = $rem; if ($num_cycs > 0xffff) { $num_cycs = 0xffff; } //~ print "M: L$span->linenum, span $span->span_ix: Leader: $num_cycs cycs\n"; $e = build_uef_leader ($num_cycs, $chunkbuf); if (TBT_E_OK != $e) { return $e; } $uef .= wrap_chunk ($chunktype, $chunkbuf, $msg); } */ $e = build_uef_leader ($span->cycles, $chunkbuf); if (TBT_E_OK != $e) { return $e; } $uef .= wrap_chunk ($chunktype, $chunkbuf, $msg); } else if ("TibetSilence" == $type) { // 0.8 if ($use_chunk_112_for_silence) { // complicated: multiple chunks may be needed $e = build_uef_silence_112($span, $uef, $msg); } else { $e = build_uef_silence_116($span, $chunkbuf); $uef .= wrap_chunk (0x116, $chunkbuf, $msg); } if (TBT_E_OK != $e) { return $e; } } else if ("TibetData" == $type) { if (count($span->cycles) > 0) { $span->framing = $framing; // assign current framing value $trailing_1_cycles = 0; if ($span->squawk) { $chunktype = 0x114; $e = build_uef_squawk($span, $chunkbuf, $trailing_1_cycles); } else { $e = build_uef_data ($span, $cur_active_baud, // 0.5 $chunkbuf, $chunktype, $cycs_to_steal, // 0.7: can be -ve now, => same as trailing_1_cycles $chunk_to_use_for_data); } // 0.7: error handling for chunk &114: if (TBT_E_OK == $e) { // do not create chunk on error, or void-chunk condition $uef .= wrap_chunk ($chunktype, $chunkbuf, $msg); } // trap & nullify void-chunk error: if (TBT_E_ZL_CHUNK == $e) { $e = TBT_E_OK; } // abort on any other error: if (TBT_E_OK != $e) { return $e; } // assign unused trailing 1-cycles to subsequent leader cycle // FIXME: consider doing this in prior separate pass, in separate function // 0.7 if ($cycs_to_steal < 0) { // negative cycs_to_steal is same as trailing_1_cycles $trailing_1_cycles = -$cycs_to_steal; $cycs_to_steal = 0; } //if ($span->squawk && ($sn+1 < $limit) && (get_class($tbt->spans[$sn+1]) == "TibetLeader")) { if (($trailing_1_cycles > 0) && ($sn+1 < $limit) && (get_class($tbt->spans[$sn+1]) == "TibetLeader")) { print "M: Assign $trailing_1_cycles trailing 1-cycles to subsequent leader\n"; $tbt->spans[$sn+1]->cycles += $trailing_1_cycles; } } else { print "W: skipped zero-length data section\n"; } } else if ("DataFraming" == $type) { $framing = $span; } else if ("BaudRate" == $type) { if ($span->rate != $cur_active_baud) { // 0.6: if ( $omit_chunk_117 ) { print "W: Omitting chunk &117 (baud rate) as instructed.\n"; } else { $baudrate = $span; $baud_uef = ""; build_uef_baud($baudrate->rate, $baud_uef); $uef .= wrap_chunk (0x117, $baud_uef, $msg); // 0.5: $cur_active_baud = $baudrate->rate; } } } else if ("TimeHint" == $type) { // paste this text into the UEF $chunkbuf = sprintf("time: %f seconds\0", $span->timestamp); $uef .= wrap_chunk (0x120, $chunkbuf, $msg); } else if ("DummyByte" == $type) { $dummy_byte=""; build_dummy_byte($span, $dummy_byte); // dummy_byte populated $uef .= wrap_chunk (0x111, $dummy_byte, $msg); } else { print "B: Bad span class: \"$type\"\n"; return TBT_E_BUG; } } return TBT_E_OK; } function build_dummy_byte (DummyByte $db, string &$chunkbuf) : int { $chunkbuf = le16($db->pre_leader_cycs).le16($db->post_leader_cycs); return TBT_E_OK; } function build_uef_baud (int $baud, string &$chunkbuf) : int { $chunkbuf = le16($baud); return TBT_E_OK; } function build_uef_leader (int $num_cycs, string &$chunkbuf) : int { $chunkbuf = le16($num_cycs); return TBT_E_OK; } function build_uef_silence_116 (TibetSilence $tbs, string &$chunkbuf) : int { $chunkbuf = uef_float($tbs->secs); return TBT_E_OK; } // 0.8 // more complicated than the others, as it may generate multiple chunks // $uef is passed in function build_uef_silence_112 (TibetSilence $tbs, string &$uef, string &$msg) : int { // chunk 112 expresses silence as equivalent 2403.8 Hz cycles // if gap is large, multiple chunks will be needed ... // two byte field, so maximum gap in a single chunk is (65535 / 2403.8) = 27.263 seconds // not very long! $num_cycs = (int) round($tbs->secs * (2000000.0 / 832.0)); // correct frequency value if ($num_cycs == 0) { print "W: silence as &112: tiny gap (".$tbs->secs." s); round up to 1/2400\n"; $num_cycs = 1; } // multiple chunks needed for ( $rem = $num_cycs; $rem > 0; $rem -= 65535 ) { $chunkbuf = le16(($rem > 65535) ? 65535 : $rem); $uef .= wrap_chunk(0x112, $chunkbuf, $msg); } return TBT_E_OK; } function build_uef_squawk (TibetData $tbd, string &$chunkbuf, int &$trailing_unused_1_cycles) : int { $num_cycles = 0.0; $cycs_buf = ""; $bitcount=0; $b=0; $cycle_count=0; $zero_half_cycle_count = 0; // determine length of trailing leader section // e.g., count=2, one trailing 2400 // 01 // ^ count-1 // ^ limit //print "cyc_count = ".count($tbd->cycles)."\n"; // count down from num cycles to 0, expecting cycle value of 1 // (i.e. trailing 1-cycles which should be leader instead); // stop when first 0-cycle is found; this becomes the limit for ($limit = count($tbd->cycles) - 1; $limit >= 0; $limit--) { if (0 == $tbd->cycles[$limit]->value) { break; } } // and what remains at the end is the trailing unused 1-cycles // to be returned to the caller $trailing_unused_1_cycles = count($tbd->cycles) - (1 + $limit); // 0.7: prevent void squawk chunks from happening if ($limit == -1) { print "W: squawk: all cycles are 1-cycles! no actual squawk data! ". "do not create chunk &114\n"; return TBT_E_ZL_CHUNK; } //print "M: L#$tbd->linenum, span $tbd->span_ix: Squawk: "; for ($i=0; $i <= $limit; $i++) { if (0 == $tbd->cycles[$i]->value) { $zero_half_cycle_count++; // number of '-' chars in TIBET } // a cycle is either two '-'s or one '.' if ((2 == $zero_half_cycle_count) || (1 == $tbd->cycles[$i]->value)) { // cycle available //print $tbd->cycles[$i]->value ? "S" : "L"; $zero_half_cycle_count = 0; // reset $b <<= 1; $b |= $tbd->cycles[$i]->value; $bitcount++; $cycle_count++; if (8 == $bitcount) { // bit complete $cycs_buf .= chr($b); $b = 0; $bitcount = 0; } } } //print "\n"; if ($zero_half_cycle_count != 0) { $ln = $tbd->cycles[$i-1]->linenum; $span_ix = $tbd->cycles[$i-1]->span_ix; print "W: line $ln, span $span_ix: ". "finished squawk with zero_half_cycle_count=$zero_half_cycle_count (want 0)\n"; } if ($bitcount != 0) { // there are bits remaining; add them to the buffer $b <<= (8 - $bitcount); $cycs_buf .= chr($b); } //print "build_uef_squawk: num_cycles = $num_cycles\n"; //for ($i=0; $i < strlen($cycs_buf); $i++) { // printf ("%02x ", ord($cycs_buf[$i])); //} //print "\n"; // fix in v0.4: cycle count field incorrectly contained byte count $chunkbuf = le24($cycle_count)."WW".$cycs_buf; return TBT_E_OK; } function build_uef_data (TibetData $tbd, int $baud, // 0.5: baud, for chunk &114 string &$chunkbuf, int &$chunktype_used, int &$cycs_to_steal, int $chunk_to_use_for_data) { //int $chunk_102_interpretation) : int { $cycs_to_steal = 0; $e = TBT_E_OK; //~ print "build_uef_data: framing is ".$tbd->framing->to_string()."\n"; // If chunk &100 is requested but framing is incompatible, // use chunk &104 instead. if ($tbd->framing->to_string() != "8N1") { /* cannot use chunk &100 */ if (0x100 == $chunk_to_use_for_data) { $chunk_to_use_for_data = 0x104; } } // 0.7: sanity check for zero-length chunk errors $chunkbuf_local = ""; // Otherwise just use whatever chunk type was requested. if (0x100 == $chunk_to_use_for_data) { $e = build_uef_data_100($tbd, $chunkbuf_local, $cycs_to_steal); } else if (0x102 == $chunk_to_use_for_data) { $e = build_uef_data_102($tbd, $chunkbuf_local, $cycs_to_steal); //, $chunk_102_interpretation); } else if (0x104 == $chunk_to_use_for_data) { $e = build_uef_data_104($tbd, $chunkbuf_local, $cycs_to_steal); } else if (0x114 == $chunk_to_use_for_data) { $e = build_uef_data_114($tbd, $baud, $chunkbuf_local, $cycs_to_steal); // 0.5: baud } // 0.7: suppress zero-length generated chunk, it's probably all 1-bits // (not sure why this happens, something to do with concatenating TIBETs) if (strlen($chunkbuf_local) == 0) { printf("W: Zero-length data chunk, type &%x\n", $chunk_to_use_for_data); //print "count(bits) = ".count($tbd->bits).", cycs_to_steal = $cycs_to_steal\n"; //print_r($tbd->bits); $e = TBT_E_ZL_CHUNK; // this "zero-length chunk" problem happens when // the entire chunk is 1-cycles. // So, we have the *opposite* of a "cycs to steal" // situation here; this is a "cycs to donate" situation. if (0 != $cycs_to_steal) { print "E: Impossible? Zero-length chunk, but nonzero cycs to steal from subsequent leader?!\n"; return TBT_E_BUG; } // OK, so actually we probably have some 1-cycles to donate. // Sanity check that all bits are 1s. (Still don't know why this happens.) for ($i=0; $i < count($tbd->bits); $i++) { if ($tbd->bits[$i]->value != 1) { print "E: Checking empty chunk data: should be all 1s, but found a 0 in here!\n"; return TBT_E_BUG; } } $cycs_to_steal = -count($tbd->bits) * 2; print "W: donating ".(count($tbd->bits) * 2). " 1-cycles from empty chunk (chunk was all 1s somehow)\n"; } else { $chunkbuf .= $chunkbuf_local; } $chunktype_used = $chunk_to_use_for_data; // out return $e; } function build_uef_data_114 (TibetData $tbd, int $baud, // 0.5 string &$chunkbuf, int &$cycs_to_steal) : int { $bits = $tbd->bits; $nb = count($bits); $chunkbuf=" WW"; for ($i=0, $total_cycs=0, $bitpos=0, $v=0, $cycs_to_add=0; $i < $nb; $i++) { $b = $bits[$i]; $cycs_to_add = ($b->value == 1) ? 2 : 1; // 0.5 if ($baud == 300) { $cycs_to_add *= 4; } for ($n=0; $n < $cycs_to_add; $n++) { $v <<= 1; $v |= ($b->value == 1) ? 1 : 0; $bitpos++; $total_cycs++; if ($bitpos == 8) { // end of UEF byte; 8 cycles inserted $chunkbuf .= chr($v); $bitpos = 0; } } } if ($bitpos != 0) { // rem bits $v <<= (8 - $bitpos); $chunkbuf .= chr($v); } // rewrite total cycs in chunk header $chunkbuf[0] = chr($total_cycs & 0xff); $chunkbuf[1] = chr(($total_cycs >> 8 ) & 0xff); $chunkbuf[2] = chr(($total_cycs >> 16) & 0xff); return TBT_E_OK; } function build_uef_data_100 (TibetData $tbd, string &$chunkbuf, int &$cycs_to_steal) : int { // cycs will be double this $bits = $tbd->bits; $nb = count($bits); $s = ""; $bitnum = -1; // expecting start bit $late_start_bit = 0; $bits_to_steal = 0; for ($i=0; $i < $nb; $i++) { $b = $bits[$i]; if ($bitnum == -1) { if ($b->value != 0) { if ( ! $late_start_bit ) { print "W: build_uef_data_100: line $b->linenum, span #$b->span_ix, bit $i: Late start bit\n"; } $late_start_bit = 1; // latch, to avoid error message spam continue; } $late_start_bit = 0; // unlatch $bitnum++; // bitnum = 0 $v = 0; // byte value } else if (($bitnum >= 0) && ($bitnum <= 7)) { $v >>= 1; $v |= (($bits[$i]->value) << 7) & 0x80; $bitnum++; } else { // bitnum = 8 // byte finished $s .= chr($v); // expect stop bit if ($bits[$i]->value != 1) { print "W: build_uef_data_100: line $b->linenum, span #$b->span_ix, bit $i: Bad stop bit\n"; } $bitnum = -1; // go back to expecting start bit } } if ($bitnum != -1) { // byte unfinished // polish it off by stealing 1-bits from subsequent leader tone $rem = (8 - $bitnum); //print "rem = $rem\n"; for ($i=0; $i < $rem; $i++) { $v >>= 1; $v |= 0x80; } $s .= chr($v); // store final byte $bits_to_steal += $rem + 1; // +1 for stop bit } $chunkbuf = $s; $cycs_to_steal = $bits_to_steal * 2; return TBT_E_OK; } function build_uef_data_104 (TibetData $tbd, string &$chunkbuf, int &$cycs_to_steal) : int { /* The first byte holds the number of data bits per packet, not counting start/stop/parity bits. The second byte holds the ascii code for 'N', 'E' or 'O', which specifies that parity is not present, even or odd. The third byte holds information concerning stop bits. If it is a positive number then it is a count of stop bits. If it is a negative number then it is a negatived count of stop bits to which an extra short wave should be added. */ $frame7 = ($tbd->framing->framelen == 7) ? 1 : 0; $stops1 = ($tbd->framing->stops == 1) ? 1 : 0; $parity = ($tbd->framing->parity != "N") ? 1 : 0; //print_r($tbd->framing->stops); print "\n"; //print "stops = $tbd->framing->stops \n"; $s = chr($tbd->framing->framelen). $tbd->framing->parity. chr($tbd->framing->stops); $bits = $tbd->bits; $nb = count($bits); $wordlen = $tbd->framing->framelen; $framelen = $wordlen + (($tbd->framing->parity == "N") ? 0 : 1) + $tbd->framing->stops; $late_start_bit = 0; $bitnum = -1; $bits_to_steal = 0; // 7E1/7O1: 0xxxxxxxP1 // 8N1: 0xxxxxxxx1 // 7E2/7O2: 0xxxxxxxP11 // 8N2: 0xxxxxxxx11 // 8E1/8O1: 0xxxxxxxxP1 for ($i=0; $i < $nb; $i++) { $b = $bits[$i]; if ($bitnum == -1) { if ($b->value != 0) { if ( ! $late_start_bit ) { print "W: build_uef_data_104: line $b->linenum, span #$b->span_ix, bit $i: Late start bit\n"; } $late_start_bit = 1; // latch, to avoid error message spam continue; } $late_start_bit = 0; // unlatch //$bitnum++; // bitnum = 0 $v = 0; // byte value } else if (($bitnum >= 0) && ($bitnum <= ($wordlen - 1))) { //die(); $v >>= 1; $v |= (($bits[$i]->value) << 7) & 0x80; //$bitnum++; } else if ($bitnum == $wordlen) { // byte finished if ($wordlen == 7) { // extra shift needed for 7-bit word $v >>= 1; $v &= 0x7f; } $s .= chr($v); //$bitnum++; } //print "?\n"; die(); //print "bitnum=$bitnum\n"; //print "parity=$parity , frame7=$frame7 \n"; if ($bitnum == 7) { if ($parity && $frame7) { // 7E1, 7O1, 7E2, 7O2 // parity bit if ( ! check_parity ($v, $bits[$i]->value, $tbd->framing->parity) ) { print "W: build_uef_data_104: line $b->linenum, span #$b->span_ix, bit $i: Bad parity bit\n"; } } } else if ($bitnum == 8) { if ($parity && ! $frame7) { // 8E1, 8O1 // parity bit if ( ! check_parity ($v, $bits[$i]->value, $tbd->framing->parity) ) { print "W: build_uef_data_104: line $b->linenum, span #$b->span_ix, bit $i: Bad parity bit\n"; } } else { // 7E1, 7O1, 8N1, 7E2, 7O2, 8N2 // first stop bit if ($bits[$i]->value != 1) { print "W: build_uef_data_104: line $b->linenum, span #$b->span_ix, bit $i: Bad stop bit\n"; } // if 7E1, 7O1, 8N1, byte is now over if ($frame7 && $parity) { // 7E1, 7O1 $bitnum = -2; } else if (! $frame7 && ! $parity && $stops1) { // 8N1 $bitnum = -2; } } } else if ($bitnum == 9) { // 7E2, 7O2, 8N2, 8E1, 8O1 // second stop bit if ($bits[$i]->value != 1) { print "W: build_uef_data_104: line $b->linenum, span #$b->span_ix, bit $i: Bad stop bit\n"; } $bitnum = -2; } $bitnum++; } // next bit if ($bitnum != -1) { // byte unfinished // polish it off by stealing 1-bits from subsequent leader tone $rem = ($wordlen - $bitnum); //print "rem = $rem\n"; for ($i=0; $i < $rem; $i++) { $v >>= 1; $v |= 0x80; } if ($wordlen == 7) { // extra shift needed for 7-bit word $v >>= 1; $v &= 0x7f; } $s .= chr($v); // store final byte $bits_to_steal += $rem + $parity + ($stops1 ? 1 : 2); } $chunkbuf = $s; $cycs_to_steal = $bits_to_steal * 2; // out return TBT_E_OK; } function build_uef_data_102 (TibetData $tbd, string &$chunkbuf, int &$cycs_to_steal) : int { //int $chunk_102_interpretation) : int { $bits = $tbd->bits; $nb = count($bits); // regregex's argument for how this should be implemented was compelling: // https://stardot.org.uk/forums/viewtopic.php?f=4&t=26822 // --- // Chunk &0102 is a raw representation of data bits stored on // cassette. Unlike chunk &0100 there are no implicit start/stop // bits. // The first byte of this chunk is used to calculate chunk length // at the bit level. Only the first // (chunk length [1] * 8) - (value of first byte) // bits are used in this chunk. // --- // Let's assume there are 15 bits of data in the chunk. We need // two bytes of data to hold 15 bits, with one bit spare. Hence the // chunk is going to look like this (bits): // ZZZZZZZZ YYYYYYYY xYYYYYYY // Interpretation B ($chunk_102_interpretation = 1): // If "chunk length" refers to all three bytes of the chunk, then // we need: // (3 * 8) - Z = 15 // 24 - 15 = Z // Z = 9 // When reading a chunk &102 (which we obviously don't do here), it // should be possible to auto-detect which interpretation was used // by examining that first byte; if it's < 8 then interpretation A // was used; if it's >= 8 then B was used. This isn't watertight // because it is possible to encode a pathological chunk &102 that // has, say, three unused bytes at the end, all of which are // "switched off" by that first byte (Z=24 or Z=32), but hey ho. $rem = $nb % 8; if ($rem > 0) { $first_byte = 8 - $rem; } else { $first_byte = 0; } //if ($chunk_102_interpretation == 1) { $first_byte += 8; //} $chunkbuf .= chr($first_byte); for ($i=0, $bitnum=0, $b=0; $i < $nb; $i++, $bitnum++) { $b >>= 1; $b |= ($bits[$i]->value ? 0x80 : 0); if ($bitnum == 7) { $chunkbuf .= chr($b); $bitnum = -1; $b = 0; } } // we may have some bits not yet sent. // we'll use 1-bits as filler, so that in case the decoder doesn't // respect the first byte and carries on sending bits right up to // the end of the chunk, they will be leader bits, which is most // likely to work. if ($bitnum != 0) { for (; $bitnum < 8; $bitnum++) { $b >>= 1; $b |= 0x80; } $chunkbuf .= chr($b); } // we can have an arbitrary number of bits, so we don't need to // steal filler bits from subsequent leader to complete bytes, // as we do for the other data chunk types. $cycs_to_steal = 0; return TBT_E_OK; } /* function my_hexdump (array $mem, bool $include_offset) { $s=""; //$start_of_line = 1; if (!isset($mem) || (count($mem)==0)) { return; } $l=count($mem); if (defined("HEXDUMP_MAX") && $l>HEXDUMP_MAX) { $l=HEXDUMP_MAX; } $sbuf=""; for ($i=0;$i<$l;$i++) { if (!($i%16)) { if ($include_offset) { $s.=sprintf ("%02x ", $i); } else { $s.=" "; } } $s.=sprintf ("%02x ", $z=ord($mem[$i])); if (!ctype_print($w=($mem[$i]))||$z>127||$w==="\r"||$w==="\n") { $sbuf.="."; } else { $sbuf.=$w; } if ($i%16 == 15) { // append text bit yet? $s .= " ".$sbuf."\n"; $sbuf=""; $start_of_line = 1; } } // ending // append any remaining text bit if ($i%16!=0) { for ($i=(16-$i%16);$i;$i--) { // pad up to start of text bit $s.= " "; } $s.= " ".$sbuf."\n"; } return $s; } */ function check_parity (int $word, int $parity_bit, string $parity_mode) : bool { $num_ones = 0; // include bit 7 even if in 7-bit mode, it'll be zero in 7-bit mode so it doesn't matter for ($i=0; $i < 8; $i++) { $num_ones += ($word & 1); $word >>= 1; } $num_ones += ($parity_bit ? 1 : 0); return ($parity_mode == "E") XOR ($num_ones & 1); } function frexp ( $f, &$exponent) { $exponent = ( floor(log($f, 2)) + 1 ); return ( $f * pow(2, -$exponent) ); } function uef_float (float $f) : string { $a = array(); $a[3] = 0; // sign bit if ($f < 0) { $f = -$f; $a[3] = 0x80; } // decode mantissa and exponent $mantissa = (float) frexp ($f, $exponent); $exponent += 126; // store mantissa $im = (int) ($mantissa * (1 << 24)); // hmm. was cast to u32_t. problem? $a[0] = $im&0xff; $a[1] = ($im >> 8)&0xff; $a[2] = ($im >> 16)&0x7f; // store exponent $a[3] |= $exponent >> 1; $a[2] |= ($exponent&1) << 7; $buf = ""; $buf .= chr($a[0]); $buf .= chr($a[1]); $buf .= chr($a[2]); $buf .= chr($a[3]); return $buf; } function wrap_chunk (int $type, string $in, string &$msg) : string { $out = ""; $len = strlen($in); $out .= le16($type); $out .= le32($len); $out .= $in; //printf("Chunk: 0x%04x, payload len 0x%x\n", $type, $len); //~ $msg .= sprintf("[_&%03x_len_&%x_] ", $type, $len); $msg .= sprintf("0x%03x-0x%04x ", $type, $len); return $out; } function le16 (int $i) : string { $s = ""; $s .= chr($i & 0xff); $s .= chr(($i >> 8) & 0xff); return $s; } function le32 (int $i) : string { $s = ""; $s .= chr($i & 0xff); $s .= chr(($i >> 8) & 0xff); $s .= chr(($i >> 16) & 0xff); $s .= chr(($i >> 24) & 0xff); return $s; } function le24 (int $i) : string { $s = ""; $s .= chr($i & 0xff); $s .= chr(($i >> 8) & 0xff); $s .= chr(($i >> 16) & 0xff); return $s; } function process_line (int $ln, string $line, int &$state, int &$span_ix, bool $insert_timestamps, ParsedTibet &$tbt) : int { // FIXME: doesn't quite meet TIBET specifications // more checking needed ... // eliminate comments $line_tmp = explode("#", $line); $line = $line_tmp[0]; // split by space $words_tmp = explode(" ", $line); $words = array(); // remove any blank words foreach ($words_tmp as $tmp=>$w) { $w = trim($w); if (strlen($w) > 0) { $words[] = $w; } } $wc = count($words); // skip empty lines if ($wc == 0) { return TBT_E_OK; } $e = TBT_E_OK; $w0 = $words[0]; // the default state at the start of a parse is STATE_VERSION ... if (STATE_VERSION == $state) { // version line must be the first non-comment, non-blank // line in the file. // any subsequent version lines will simply be ignored. // (this is deliberate and makes concatenating files easy) $e = parse_version ($words, $ln, $tbt->version, $line); $state = STATE_IDLE; } else if (STATE_IDLE == $state) { // this is a whitelist; we could ignore unknown keywords // instead, but we'll leave it like this for now if ($w0 == "tibet") { // duplicate version line; just check it for validity $dummy = ""; $e = parse_version ($words, $ln, $dummy, $line); if ($dummy != $tbt->version) { print "E: line $ln, span $span_ix: Mismatched duplicate version: $line\n"; return TBT_E_PARSE_DUP_VERSION; } // TIBET 0.4: reset framing and baud hints for file concatenation $df = new DataFraming; // constructor defaults to 8N1 $df->linenum = $ln; $df->span_ix = $span_ix; $tbt->spans[] = $df; // token rather than span $br = new BaudRate; // constructor defaults to 1200 $br->linenum = $ln; $br->span_ix = $span_ix; $tbt->spans[] = $br; // token rather than span } else if ($w0 == "silence") { if ($wc != 2) { print "E: line $ln, span $span_ix: Bad silence line: $line\n"; return TBT_E_PARSE_SILENCE; } $silence = new TibetSilence; $silence->linenum = $ln; $f = 0.0; $e = parse_float ($words[1], $f); // f populated if (TBT_E_OK != $e) { return $e; } $silence->secs = $f; //(float) $words[1]; $silence->span_ix = $span_ix; $span_ix++; if (($silence->secs <= 0.0) || ($silence->secs > 1000000.0)) { print "E: line $ln, span $span_ix: Illegal silence length: $words[1]\n"; return TBT_E_BAD_SILENCE; } $tbt->spans[] = $silence; } else if ($w0 == "leader") { if ($wc != 2) { print "E: line $ln: Bad leader line: $line\n"; return TBT_E_PARSE_LEADER; } $leader = new TibetLeader; $leader->linenum = $ln; $num_cycs = 0; $e = parse_int($words[1], $num_cycs); // $num_cycs populated if (TBT_E_OK != $e) { print "E: line $ln, span $span_ix: Non-integer leader cycles count: $words[1]\n"; return $e; } $leader->cycles = $num_cycs; //(int) $words[1]; $leader->span_ix = $span_ix; $span_ix++; if (($leader->cycles < 1) || ($leader->cycles > 30000000)) { print "E: line $ln, span $span_ix: Illegal leader length: $words[1]\n"; return TBT_E_BAD_LEADER; } $tbt->spans[] = $leader; } else if (($w0 == "squawk") || ($w0 == "data")) { if ($wc != 1) { print "E: line $ln, span $span_ix: Illegal $w0 line: $line\n"; return TBT_E_PARSE_DATA; } $data = new TibetData; $data->linenum = $ln; $data->span_ix = $span_ix; $data->squawk = ($w0 == "squawk"); $span_ix++; $state = STATE_CYCLES; $tbt->spans[] = $data; } else if ($w0 == "/phase") { // don't care; it's partially a function of playback, // so I disagree that it should be regarded } else if ($w0 == "/speed") { // don't care; again, it's a function of playback, // not of the source } else if ($w0 == "/time") { if ($insert_timestamps) { $timehint = new TimeHint; $timestamp = 0.0; $e = parse_float($words[1], $timestamp); // timestamp populated if (TBT_E_OK != $e) { print "E: line $ln, span $span_ix: Illegal /time hint: $line\n"; return $e; } $timehint->timestamp = $timestamp; //(float) $words[1]; $timehint->linenum = $ln; $timehint->span_ix = $span_ix; $tbt->spans[] = $timehint; // token rather than span } } else if ($w0 == "/framing") { // quadbike doesn't export this, as it can't detect framing, // but it could be added by manually editing a TIBET file. // UEF chunk 104 needs to know about non-standard framings, and // if they e.g. change in the middle of a block, we stand no // chance of detecting them automatically, so $df = new DataFraming; $df->linenum = $ln; $df->span_ix = $span_ix; $e = parse_framing ($words[1], $df); // df populated if (TBT_E_OK != $e) { return $e; } $tbt->spans[] = $df; // token rather than span } else if ($w0 == "/baud") { // again, not exported by QB $br = new BaudRate; $br->linenum = $ln; $br->span_ix = $span_ix; $e = parse_baudrate ($words[1], $br); // br populated if (TBT_E_OK != $e) { return $e; } $tbt->spans[] = $br; // token rather than span } else { print "E: line $ln, span $span_ix: Unrecognised: $line\n"; return TBT_E_PARSE_BAD_LINE; } } else if (STATE_CYCLES == $state) { if ($w0 == "end") { $state = STATE_IDLE; } else { $len = strlen($words[0]); for ($i=0; $i < $len; $i++) { $span_ix = count($tbt->spans) - 1; $span = $tbt->spans[$span_ix]; // TibetData if ($words[0][$i] == "-") { $cyc = new TibetCycle; $cyc->value = 0; $cyc->linenum = $ln; //$span->linenum; $cyc->span_ix = $span->span_ix; $span->cycles[] = $cyc; } else if ($words[0][$i] == ".") { $cyc = new TibetCycle; $cyc->value = 1; $cyc->linenum = $ln; //$span->linenum; $cyc->span_ix = $span->span_ix; $span->cycles[] = $cyc; } else if ($words[0][$i] == "P") { // P cannot be turned into a bit, so decoders just skip it. } else { print "E: line $ln, span $span_ix: Bad cycle line: $line\n"; return TBT_E_PARSE_CYCLES; } $tbt->spans[$span_ix] = $span; // replace the modified value } } } if (TBT_E_OK != $e) { return $e; } //print "\n"; return TBT_E_OK; } function parse_float (string $w, float &$f) : int { $len = strlen($w); $dp_count=0; if ($len > 50) { return TBT_E_BAD_FLOAT; } for ($i=0; $i < $len; $i++) { $c = $w[$i]; if ($c == ".") { if ($dp_count != 0) { // only one decimal point allowed return TBT_E_BAD_FLOAT; } else if ($i == ($len - 1)) { // decimal point may not be the final character return TBT_E_BAD_FLOAT; } $dp_count++; } else if ( ! ctype_digit ($c) ) { // chars other than digits and decimal point are illegal return TBT_E_BAD_FLOAT; } } $f = (float) $w; return TBT_E_OK; } function parse_int (string $w, int &$i) : int { $len = strlen($w); if ($len > 19) { return TBT_E_BAD_INT; } for ($j=0; $j < $len; $j++) { $v = $w[$j]; if (!ctype_digit($v)) { return TBT_E_BAD_INT; } } $i = (int) $w; return TBT_E_OK; } function parse_framing (string $w, DataFraming &$f) : int { if (strlen($w) != 3) { return FALSE; } if (($w[0] != "7") && ($w[0] != "8")) { return FALSE; } if (($w[1] != "N") && ($w[1] != "O") && ($w[1] != "E")) { return FALSE; } if (($w[2] != "1") && ($w[2] != "2")) { return FALSE; } $framelen = 0; $e = parse_int ($w[0], $framelen); // framelen populated if (TBT_E_OK != $e) { return $e; } $f->framelen = $framelen; $f->parity = $w[1]; $num_stops = 0; $e = parse_int ($w[2], $num_stops); // num_stops populated if (TBT_E_OK != $e) { return $e; } $f->stops = $num_stops; return TBT_E_OK; } function parse_baudrate (string $w, BaudRate &$r) : int { $i = 0; $e = parse_int ($w, $i); // i populated if (TBT_E_OK != $e) { return $e; } $r->rate = $i; return TBT_E_OK; } function parse_version (array $words, int $ln, string &$tbt_version, string $line) : int { $wc = count($words); if ($words[0] != "tibet") { print "E: Version line not found: $line\n"; return TBT_E_PARSE_VERSION; } if ($wc != 2) { print "E: line $ln: Bad version line: $line\n"; return TBT_E_PARSE_VERSION; } // 0.8: switched to major/minor version paradigm $tbt_version = $words[1]; $v = explode(".", $tbt_version); if (count($v) != 2) { print "E: line $ln: Bad version: $tbt_version\n"; return TBT_E_BAD_VERSION; } //if (TIBET_VERSION_STG != $tbt_version) { if ($v[0] != TIBET_MAJOR_VERSION) { print "E: line $ln: Incompatible TIBET version: $tbt_version\n"; return TBT_E_INCOMPATIBLE; } return TBT_E_OK; } function tbt_process (string $ip, bool $insert_timestamps, ParsedTibet &$tbt) : int { $state = STATE_VERSION; $lines = explode ("\n", $ip); $span_ix = 0; print count($lines)." lines.\n"; foreach ($lines as $ln=>$v) { $ln++; // linenum; 1-indexed $e = process_line ($ln, $v, $state, $span_ix, $insert_timestamps, $tbt); // state, tbt, span_ix modified if (TBT_E_OK != $e) { return $e; } } if ((STATE_IDLE != $state) && (STATE_DATA != $state)) { print "W: Finished in unexpected state $state\n"; } print "TIBET version: $tbt->version\n"; return TBT_E_OK; } function usage(string $argv0) { print "Usage:\n\n"; print " php -f $argv0 [options] \n\n"; print "where [options] may be:\n\n"; //print " +f activates automatic framing detection\n"; //print " (overrides all framing lines in input)\n\n"; print " +t use \"/time\" hints in TIBET file to insert &120 label chunks into UEF\n"; print " (currently breaks beebjit)\n\n"; print " +102 use chunk &102 for data\n"; //print " +102b (interpretation B)\n"; print " +104 use chunk &104 for data\n"; print " +114 use chunk &114 for data\n\n"; print " +112 use chunk &112 instead of &116 for silence\n\n"; print " +no-117 omit baud rate chunk &117 (Elkulator compatibility)\n\n"; print " +nz do not compress output UEF file\n"; print "\n"; } ?> ================================================ FILE: 3-assembled-output/README.md ================================================ # Assembled output for the BBC Micro cassette version of Elite This folder contains the output binaries from the build process for the BBC Micro cassette version of Elite. It also contains [compile.txt](compile.txt), which contains the output from the assembly process. This is very useful when debugging the build process. --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 3-assembled-output/README.txt ================================================ --------------------------------------- Acornsoft Elite Version: BBC Micro cassette Variant: Stairway to Hell cassette Product: Acornsoft SBG38 See www.bbcelite.com for details --------------------------------------- ================================================ FILE: 3-assembled-output/compile.txt ================================================ .ZP 0000 .RAND 0000 .TRTB% 0004 .T1 0006 .SC 0007 .SCH 0008 .XX16 0009 .P 001B .XX0 001E .INF 0020 .V 0022 .XX 0024 .YY 0026 .SUNX 0028 .BETA 002A .BET1 002B .XC 002C .YC 002D .QQ22 002E .ECMA 0030 .XX15 0031 .X1 0031 .Y1 0032 .X2 0033 .Y2 0034 0035 .XX12 0037 .K 003D .KL 0041 .KY1 0042 .KY2 0043 .KY3 0044 .KY4 0045 .KY5 0046 .KY6 0047 .KY7 0048 .KY12 0049 .KY13 004A .KY14 004B .KY15 004C .KY16 004D .KY17 004E .KY18 004F .KY19 0050 .LAS 0051 .MSTG 0052 .XX1 0053 .INWK 0053 .XX19 0074 .LSP 0077 .QQ15 0078 .K5 007E .XX18 007E .QQ17 007E .QQ19 007F .K6 0082 .ALP1 0087 .ALP2 0088 .BET2 008A .DELTA 008C .DELT4 008D .U 008F .Q 0090 .R 0091 .S 0092 .XSAV 0093 .YSAV 0094 .XX17 0095 .QQ11 0096 .ZZ 0097 .XX13 0098 .MCNT 0099 .DL 009A .TYPE 009B .JSTX 009C .JSTY 009D .ALPHA 009E .QQ12 009F .TGT 00A0 .SWAP 00A1 .COL 00A2 .FLAG 00A3 .CNT 00A4 .CNT2 00A5 .STP 00A6 .XX4 00A7 .XX20 00A8 .XX14 00A9 .RAT 00AA .RAT2 00AB .K2 00AC .T 00D1 .K3 00D2 .XX2 00D2 .K4 00E0 ZP workspace from &0 to &E1 inclusive .XX3 0100 .T% 0300 .TP 0300 .QQ0 0301 .QQ1 0302 .QQ21 0303 .CASH 0309 .QQ14 030D .COK 030E .GCNT 030F .LASER 0310 0314 .CRGO 0316 .QQ20 0317 .ECM 0328 .BST 0329 .BOMB 032A .ENGY 032B .DKCMP 032C .GHYP 032D .ESCP 032E 032F .NOMSL 0333 .FIST 0334 .AVL 0335 .QQ26 0346 .TALLY 0347 .SVC 0349 034A .SX 034C .SXL 035F T% workspace from &300 to &371 inclusive .QQ18 Macro RTOK: 0400 4C End macro RTOK Macro RTOK: 0401 32 End macro RTOK Macro CONT: 0402 24 End macro CONT 0403 00 Macro CHAR: 0404 03 End macro CHAR Macro CHAR: 0405 60 End macro CHAR Macro CHAR: 0406 6B End macro CHAR Macro TWOK: 0407 A9 End macro TWOK Macro CHAR: 0408 77 End macro CHAR 0409 00 Macro CHAR: 040A 64 End macro CHAR Macro CHAR: 040B 6C End macro CHAR Macro TWOK: 040C B5 End macro TWOK Macro CHAR: 040D 71 End macro CHAR Macro CHAR: 040E 6D End macro CHAR Macro CHAR: 040F 6E End macro CHAR Macro TWOK: 0410 B1 End macro TWOK Macro CHAR: 0411 77 End macro CHAR 0412 00 Macro CHAR: 0413 67 End macro CHAR Macro TWOK: 0414 B2 End macro TWOK Macro CHAR: 0415 62 End macro CHAR Macro RTOK: 0416 32 End macro RTOK Macro CONT: 0417 20 End macro CONT 0418 00 Macro TWOK: 0419 AF End macro TWOK Macro TWOK: 041A B5 End macro TWOK Macro CHAR: 041B 6D End macro CHAR Macro CHAR: 041C 77 End macro CHAR Macro TWOK: 041D BA End macro TWOK Macro CHAR: 041E 7A End macro CHAR Macro CONT: 041F 2E End macro CONT 0420 00 Macro CHAR: 0421 70 End macro CHAR Macro CHAR: 0422 7A End macro CHAR Macro CHAR: 0423 70 End macro CHAR Macro TWOK: 0424 BF End macro TWOK Macro CHAR: 0425 6E End macro CHAR 0426 00 Macro CHAR: 0427 73 End macro CHAR Macro TWOK: 0428 BD End macro TWOK Macro TWOK: 0429 A6 End macro TWOK 042A 00 Macro CONT: 042B 21 End macro CONT Macro CHAR: 042C 03 End macro CHAR Macro TWOK: 042D A8 End macro TWOK Macro CHAR: 042E 71 End macro CHAR Macro CHAR: 042F 68 End macro CHAR Macro CHAR: 0430 66 End macro CHAR Macro CHAR: 0431 77 End macro CHAR Macro CHAR: 0432 03 End macro CHAR Macro RTOK: 0433 85 End macro RTOK Macro CHAR: 0434 70 End macro CHAR 0435 00 Macro TWOK: 0436 AF End macro TWOK Macro CHAR: 0437 67 End macro CHAR Macro TWOK: 0438 AB End macro TWOK Macro CHAR: 0439 77 End macro CHAR Macro TWOK: 043A BD End macro TWOK Macro TWOK: 043B A3 End macro TWOK 043C 00 Macro CHAR: 043D 62 End macro CHAR Macro CHAR: 043E 64 End macro CHAR Macro TWOK: 043F BD End macro TWOK Macro CHAR: 0440 60 End macro CHAR Macro CHAR: 0441 76 End macro CHAR Macro CHAR: 0442 6F End macro CHAR Macro CHAR: 0443 77 End macro CHAR Macro CHAR: 0444 76 End macro CHAR Macro TWOK: 0445 B7 End macro TWOK Macro CHAR: 0446 6F End macro CHAR 0447 00 Macro TWOK: 0448 BD End macro TWOK Macro CHAR: 0449 60 End macro CHAR Macro CHAR: 044A 6B End macro CHAR Macro CHAR: 044B 03 End macro CHAR 044C 00 Macro CHAR: 044D 62 End macro CHAR Macro TWOK: 044E B5 End macro TWOK Macro TWOK: 044F B7 End macro TWOK Macro TWOK: 0450 A0 End macro TWOK Macro CHAR: 0451 03 End macro CHAR 0452 00 Macro CHAR: 0453 73 End macro CHAR Macro CHAR: 0454 6C End macro CHAR Macro TWOK: 0455 BA End macro TWOK Macro CHAR: 0456 03 End macro CHAR 0457 00 Macro TWOK: 0458 A8 End macro TWOK Macro TWOK: 0459 AF End macro TWOK Macro CHAR: 045A 6F End macro CHAR Macro CHAR: 045B 7A End macro CHAR Macro CHAR: 045C 03 End macro CHAR 045D 00 Macro CHAR: 045E 76 End macro CHAR Macro CHAR: 045F 6D End macro CHAR Macro CHAR: 0460 6A End macro CHAR Macro CHAR: 0461 77 End macro CHAR 0462 00 Macro CHAR: 0463 75 End macro CHAR Macro CHAR: 0464 6A End macro CHAR Macro CHAR: 0465 66 End macro CHAR Macro CHAR: 0466 74 End macro CHAR Macro CHAR: 0467 03 End macro CHAR 0468 00 Macro TWOK: 0469 B9 End macro TWOK Macro TWOK: 046A B8 End macro TWOK Macro TWOK: 046B B4 End macro TWOK Macro CHAR: 046C 77 End macro CHAR Macro CHAR: 046D 7A End macro CHAR 046E 00 Macro TWOK: 046F B8 End macro TWOK Macro TWOK: 0470 A9 End macro TWOK Macro CHAR: 0471 60 End macro CHAR Macro CHAR: 0472 6B End macro CHAR Macro CHAR: 0473 7A End macro CHAR 0474 00 Macro CHAR: 0475 65 End macro CHAR Macro CHAR: 0476 66 End macro CHAR Macro CHAR: 0477 76 End macro CHAR Macro CHAR: 0478 67 End macro CHAR Macro TWOK: 0479 A3 End macro TWOK 047A 00 Macro CHAR: 047B 6E End macro CHAR Macro CHAR: 047C 76 End macro CHAR Macro CHAR: 047D 6F End macro CHAR Macro TWOK: 047E B4 End macro TWOK Macro CHAR: 047F 0E End macro CHAR Macro RTOK: 0480 81 End macro RTOK 0481 00 Macro TWOK: 0482 AE End macro TWOK Macro CHAR: 0483 60 End macro CHAR Macro CHAR: 0484 77 End macro CHAR Macro TWOK: 0485 B2 End macro TWOK Macro TWOK: 0486 BA End macro TWOK Macro RTOK: 0487 9A End macro RTOK 0488 00 Macro RTOK: 0489 D8 End macro RTOK Macro CHAR: 048A 6E End macro CHAR Macro CHAR: 048B 76 End macro CHAR Macro CHAR: 048C 6D End macro CHAR Macro TWOK: 048D BE End macro TWOK Macro CHAR: 048E 77 End macro CHAR 048F 00 Macro CHAR: 0490 60 End macro CHAR Macro TWOK: 0491 BC End macro TWOK Macro CHAR: 0492 65 End macro CHAR Macro TWOK: 0493 BB End macro TWOK Macro TWOK: 0494 B3 End macro TWOK Macro CHAR: 0495 62 End macro CHAR Macro CHAR: 0496 60 End macro CHAR Macro CHAR: 0497 7A End macro CHAR 0498 00 Macro CHAR: 0499 67 End macro CHAR Macro CHAR: 049A 66 End macro CHAR Macro CHAR: 049B 6E End macro CHAR Macro CHAR: 049C 6C End macro CHAR Macro CHAR: 049D 60 End macro CHAR Macro TWOK: 049E B7 End macro TWOK Macro CHAR: 049F 60 End macro CHAR Macro CHAR: 04A0 7A End macro CHAR 04A1 00 Macro CHAR: 04A2 60 End macro CHAR Macro TWOK: 04A3 BA End macro TWOK Macro CHAR: 04A4 73 End macro CHAR Macro TWOK: 04A5 BA End macro TWOK Macro TWOK: 04A6 B2 End macro TWOK Macro CHAR: 04A7 66 End macro CHAR Macro CHAR: 04A8 03 End macro CHAR Macro RTOK: 04A9 E8 End macro RTOK Macro TWOK: 04AA B2 End macro TWOK Macro CHAR: 04AB 66 End macro CHAR 04AC 00 Macro CHAR: 04AD 70 End macro CHAR Macro CHAR: 04AE 6B End macro CHAR Macro CHAR: 04AF 6A End macro CHAR Macro CHAR: 04B0 73 End macro CHAR 04B1 00 Macro CHAR: 04B2 73 End macro CHAR Macro CHAR: 04B3 71 End macro CHAR Macro CHAR: 04B4 6C End macro CHAR Macro CHAR: 04B5 67 End macro CHAR Macro CHAR: 04B6 76 End macro CHAR Macro CHAR: 04B7 60 End macro CHAR Macro CHAR: 04B8 77 End macro CHAR 04B9 00 Macro CHAR: 04BA 03 End macro CHAR Macro TWOK: 04BB B6 End macro TWOK Macro CHAR: 04BC 70 End macro CHAR Macro TWOK: 04BD B3 End macro TWOK 04BE 00 Macro CHAR: 04BF 6B End macro CHAR Macro CHAR: 04C0 76 End macro CHAR Macro CHAR: 04C1 6E End macro CHAR Macro TWOK: 04C2 B8 End macro TWOK Macro CHAR: 04C3 03 End macro CHAR Macro CHAR: 04C4 60 End macro CHAR Macro CHAR: 04C5 6C End macro CHAR Macro CHAR: 04C6 6F End macro CHAR Macro TWOK: 04C7 BC End macro TWOK Macro CHAR: 04C8 6A End macro CHAR Macro TWOK: 04C9 A3 End macro TWOK 04CA 00 Macro CHAR: 04CB 6B End macro CHAR Macro CHAR: 04CC 7A End macro CHAR Macro CHAR: 04CD 73 End macro CHAR Macro TWOK: 04CE B3 End macro TWOK Macro CHAR: 04CF 70 End macro CHAR Macro CHAR: 04D0 73 End macro CHAR Macro CHAR: 04D1 62 End macro CHAR Macro TWOK: 04D2 A6 End macro TWOK Macro CHAR: 04D3 03 End macro CHAR 04D4 00 Macro CHAR: 04D5 70 End macro CHAR Macro CHAR: 04D6 6B End macro CHAR Macro TWOK: 04D7 BA End macro TWOK Macro CHAR: 04D8 77 End macro CHAR Macro CHAR: 04D9 03 End macro CHAR Macro RTOK: 04DA E9 End macro RTOK Macro RTOK: 04DB 82 End macro RTOK 04DC 00 Macro TWOK: 04DD AE End macro TWOK Macro RTOK: 04DE E8 End macro RTOK Macro TWOK: 04DF B8 End macro TWOK Macro TWOK: 04E0 A6 End macro TWOK 04E1 00 Macro CHAR: 04E2 73 End macro CHAR Macro CHAR: 04E3 6C End macro CHAR Macro CHAR: 04E4 73 End macro CHAR Macro CHAR: 04E5 76 End macro CHAR Macro CHAR: 04E6 6F End macro CHAR Macro TWOK: 04E7 B2 End macro TWOK Macro CHAR: 04E8 6A End macro CHAR Macro TWOK: 04E9 BC End macro TWOK 04EA 00 Macro CHAR: 04EB 64 End macro CHAR Macro CHAR: 04EC 71 End macro CHAR Macro CHAR: 04ED 6C End macro CHAR Macro CHAR: 04EE 70 End macro CHAR Macro CHAR: 04EF 70 End macro CHAR Macro CHAR: 04F0 03 End macro CHAR Macro RTOK: 04F1 99 End macro RTOK Macro CHAR: 04F2 6A End macro CHAR Macro CHAR: 04F3 75 End macro CHAR Macro CHAR: 04F4 6A End macro CHAR Macro CHAR: 04F5 77 End macro CHAR Macro CHAR: 04F6 7A End macro CHAR 04F7 00 Macro CHAR: 04F8 66 End macro CHAR Macro CHAR: 04F9 60 End macro CHAR Macro TWOK: 04FA BC End macro TWOK Macro CHAR: 04FB 6C End macro CHAR Macro CHAR: 04FC 6E End macro CHAR Macro CHAR: 04FD 7A End macro CHAR 04FE 00 Macro CHAR: 04FF 03 End macro CHAR Macro CHAR: 0500 6F End macro CHAR Macro CHAR: 0501 6A End macro CHAR Macro CHAR: 0502 64 End macro CHAR Macro CHAR: 0503 6B End macro CHAR Macro CHAR: 0504 77 End macro CHAR Macro CHAR: 0505 03 End macro CHAR Macro CHAR: 0506 7A End macro CHAR Macro CHAR: 0507 66 End macro CHAR Macro TWOK: 0508 A9 End macro TWOK Macro CHAR: 0509 70 End macro CHAR 050A 00 Macro TWOK: 050B BF End macro TWOK Macro CHAR: 050C 60 End macro CHAR Macro CHAR: 050D 6B End macro CHAR Macro CHAR: 050E 0D End macro CHAR Macro TWOK: 050F A2 End macro TWOK Macro TWOK: 0510 B5 End macro TWOK Macro CHAR: 0511 6F End macro CHAR 0512 00 Macro CHAR: 0513 60 End macro CHAR Macro CHAR: 0514 62 End macro CHAR Macro CHAR: 0515 70 End macro CHAR Macro CHAR: 0516 6B End macro CHAR 0517 00 Macro CHAR: 0518 03 End macro CHAR Macro TWOK: 0519 A5 End macro TWOK Macro RTOK: 051A 55 End macro RTOK Macro CHAR: 051B 6A End macro CHAR Macro TWOK: 051C BC End macro TWOK 051D 00 Macro RTOK: 051E 59 End macro RTOK Macro RTOK: 051F 82 End macro RTOK Macro CONT: 0520 22 End macro CONT 0521 00 Macro CHAR: 0522 77 End macro CHAR Macro TWOK: 0523 A9 End macro TWOK Macro TWOK: 0524 A0 End macro TWOK Macro CHAR: 0525 77 End macro CHAR Macro CHAR: 0526 03 End macro CHAR Macro CHAR: 0527 6F End macro CHAR Macro CHAR: 0528 6C End macro CHAR Macro RTOK: 0529 E8 End macro RTOK 052A 00 Macro RTOK: 052B 49 End macro RTOK Macro CHAR: 052C 03 End macro CHAR Macro CHAR: 052D 69 End macro CHAR Macro CHAR: 052E 62 End macro CHAR Macro CHAR: 052F 6E End macro CHAR Macro CHAR: 0530 6E End macro CHAR Macro TWOK: 0531 BB End macro TWOK 0532 00 Macro CHAR: 0533 71 End macro CHAR Macro TWOK: 0534 B8 End macro TWOK Macro TWOK: 0535 A0 End macro TWOK 0536 00 Macro CHAR: 0537 70 End macro CHAR Macro CHAR: 0538 77 End macro CHAR 0539 00 Macro RTOK: 053A 93 End macro RTOK Macro CHAR: 053B 03 End macro CHAR Macro CHAR: 053C 6C End macro CHAR Macro CHAR: 053D 65 End macro CHAR Macro CHAR: 053E 03 End macro CHAR 053F 00 Macro CHAR: 0540 70 End macro CHAR Macro CHAR: 0541 66 End macro CHAR Macro RTOK: 0542 55 End macro RTOK 0543 00 Macro CHAR: 0544 03 End macro CHAR Macro CHAR: 0545 60 End macro CHAR Macro TWOK: 0546 A9 End macro TWOK Macro CHAR: 0547 64 End macro CHAR Macro CHAR: 0548 6C End macro CHAR Macro CONT: 0549 25 End macro CONT 054A 00 Macro CHAR: 054B 66 End macro CHAR Macro TWOK: 054C B9 End macro TWOK Macro CHAR: 054D 6A End macro CHAR Macro CHAR: 054E 73 End macro CHAR 054F 00 Macro CHAR: 0550 65 End macro CHAR Macro CHAR: 0551 6C End macro CHAR Macro CHAR: 0552 6C End macro CHAR Macro CHAR: 0553 67 End macro CHAR 0554 00 Macro TWOK: 0555 BF End macro TWOK Macro CHAR: 0556 7B End macro CHAR Macro TWOK: 0557 B4 End macro TWOK Macro CHAR: 0558 6F End macro CHAR Macro TWOK: 0559 AA End macro TWOK 055A 00 Macro TWOK: 055B B7 End macro TWOK Macro TWOK: 055C AE End macro TWOK Macro CHAR: 055D 6C End macro CHAR Macro CHAR: 055E 62 End macro CHAR Macro CHAR: 055F 60 End macro CHAR Macro TWOK: 0560 B4 End macro TWOK Macro TWOK: 0561 B5 End macro TWOK Macro CHAR: 0562 70 End macro CHAR 0563 00 Macro CHAR: 0564 70 End macro CHAR Macro TWOK: 0565 B6 End macro TWOK Macro TWOK: 0566 B5 End macro TWOK Macro CHAR: 0567 70 End macro CHAR 0568 00 Macro CHAR: 0569 6F End macro CHAR Macro CHAR: 056A 6A End macro CHAR Macro TWOK: 056B B9 End macro TWOK Macro TWOK: 056C BA End macro TWOK Macro CHAR: 056D 0C End macro CHAR Macro CHAR: 056E 74 End macro CHAR Macro TWOK: 056F AF End macro TWOK Macro TWOK: 0570 AA End macro TWOK 0571 00 Macro CHAR: 0572 6F End macro CHAR Macro CHAR: 0573 76 End macro CHAR Macro CHAR: 0574 7B End macro CHAR Macro CHAR: 0575 76 End macro CHAR Macro TWOK: 0576 BD End macro TWOK Macro TWOK: 0577 AA End macro TWOK 0578 00 Macro CHAR: 0579 6D End macro CHAR Macro TWOK: 057A A9 End macro TWOK Macro CHAR: 057B 60 End macro CHAR Macro CHAR: 057C 6C End macro CHAR Macro TWOK: 057D B4 End macro TWOK Macro CHAR: 057E 60 End macro CHAR Macro CHAR: 057F 70 End macro CHAR 0580 00 Macro RTOK: 0581 D8 End macro RTOK Macro CHAR: 0582 73 End macro CHAR Macro CHAR: 0583 76 End macro CHAR Macro CHAR: 0584 77 End macro CHAR Macro TWOK: 0585 B3 End macro TWOK Macro CHAR: 0586 70 End macro CHAR 0587 00 Macro TWOK: 0588 A8 End macro TWOK Macro CHAR: 0589 60 End macro CHAR Macro CHAR: 058A 6B End macro CHAR Macro TWOK: 058B AF End macro TWOK Macro TWOK: 058C B3 End macro TWOK Macro CHAR: 058D 7A End macro CHAR 058E 00 Macro RTOK: 058F 56 End macro RTOK Macro CHAR: 0590 6C End macro CHAR Macro CHAR: 0591 7A End macro CHAR Macro CHAR: 0592 70 End macro CHAR 0593 00 Macro CHAR: 0594 65 End macro CHAR Macro CHAR: 0595 6A End macro CHAR Macro TWOK: 0596 AD End macro TWOK Macro TWOK: 0597 A9 End macro TWOK Macro CHAR: 0598 6E End macro CHAR Macro CHAR: 0599 70 End macro CHAR 059A 00 Macro CHAR: 059B 65 End macro CHAR Macro CHAR: 059C 76 End macro CHAR Macro CHAR: 059D 71 End macro CHAR Macro CHAR: 059E 70 End macro CHAR 059F 00 Macro CHAR: 05A0 6E End macro CHAR Macro TWOK: 05A1 AF End macro TWOK Macro TWOK: 05A2 B3 End macro TWOK Macro TWOK: 05A3 A3 End macro TWOK Macro CHAR: 05A4 70 End macro CHAR 05A5 00 Macro CHAR: 05A6 64 End macro CHAR Macro CHAR: 05A7 6C End macro CHAR Macro CHAR: 05A8 6F End macro CHAR Macro CHAR: 05A9 67 End macro CHAR 05AA 00 Macro CHAR: 05AB 73 End macro CHAR Macro CHAR: 05AC 6F End macro CHAR Macro TWOK: 05AD B2 End macro TWOK Macro TWOK: 05AE AF End macro TWOK Macro CHAR: 05AF 76 End macro CHAR Macro CHAR: 05B0 6E End macro CHAR 05B1 00 Macro TWOK: 05B2 A0 End macro TWOK Macro CHAR: 05B3 6E End macro CHAR Macro CHAR: 05B4 0E End macro CHAR Macro RTOK: 05B5 E8 End macro RTOK Macro TWOK: 05B6 BC End macro TWOK Macro TWOK: 05B7 AA End macro TWOK 05B8 00 Macro TWOK: 05B9 A3 End macro TWOK Macro CHAR: 05BA 6A End macro CHAR Macro TWOK: 05BB B1 End macro TWOK Macro CHAR: 05BC 03 End macro CHAR Macro RTOK: 05BD 5C End macro RTOK Macro CHAR: 05BE 70 End macro CHAR 05BF 00 Macro CHAR: 05C0 0B End macro CHAR Macro CHAR: 05C1 7A End macro CHAR Macro CHAR: 05C2 0C End macro CHAR Macro CHAR: 05C3 6D End macro CHAR Macro CHAR: 05C4 0A End macro CHAR Macro CHAR: 05C5 1C End macro CHAR 05C6 00 Macro CHAR: 05C7 03 End macro CHAR Macro CHAR: 05C8 60 End macro CHAR Macro CHAR: 05C9 71 End macro CHAR 05CA 00 Macro CHAR: 05CB 6F End macro CHAR Macro TWOK: 05CC A9 End macro TWOK Macro TWOK: 05CD A0 End macro TWOK 05CE 00 Macro CHAR: 05CF 65 End macro CHAR Macro CHAR: 05D0 6A End macro CHAR Macro TWOK: 05D1 B3 End macro TWOK Macro TWOK: 05D2 A6 End macro TWOK 05D3 00 Macro CHAR: 05D4 70 End macro CHAR Macro TWOK: 05D5 A8 End macro TWOK Macro RTOK: 05D6 55 End macro RTOK 05D7 00 Macro CHAR: 05D8 64 End macro CHAR Macro TWOK: 05D9 AD End macro TWOK Macro TWOK: 05DA B1 End macro TWOK 05DB 00 Macro CHAR: 05DC 71 End macro CHAR Macro TWOK: 05DD BB End macro TWOK 05DE 00 Macro CHAR: 05DF 7A End macro CHAR Macro CHAR: 05E0 66 End macro CHAR Macro RTOK: 05E1 55 End macro RTOK Macro CHAR: 05E2 6C End macro CHAR Macro CHAR: 05E3 74 End macro CHAR 05E4 00 Macro CHAR: 05E5 61 End macro CHAR Macro CHAR: 05E6 6F End macro CHAR Macro CHAR: 05E7 76 End macro CHAR Macro CHAR: 05E8 66 End macro CHAR 05E9 00 Macro CHAR: 05EA 61 End macro CHAR Macro TWOK: 05EB B6 End macro TWOK Macro CHAR: 05EC 60 End macro CHAR Macro CHAR: 05ED 68 End macro CHAR 05EE 00 Macro RTOK: 05EF 35 End macro RTOK 05F0 00 Macro CHAR: 05F1 70 End macro CHAR Macro CHAR: 05F2 6F End macro CHAR Macro CHAR: 05F3 6A End macro CHAR Macro CHAR: 05F4 6E End macro CHAR Macro CHAR: 05F5 7A End macro CHAR 05F6 00 Macro CHAR: 05F7 61 End macro CHAR Macro CHAR: 05F8 76 End macro CHAR Macro CHAR: 05F9 64 End macro CHAR Macro CHAR: 05FA 0E End macro CHAR Macro CHAR: 05FB 66 End macro CHAR Macro CHAR: 05FC 7A End macro CHAR Macro TWOK: 05FD BB End macro TWOK 05FE 00 Macro CHAR: 05FF 6B End macro CHAR Macro TWOK: 0600 BA End macro TWOK Macro CHAR: 0601 6D End macro CHAR Macro TWOK: 0602 BB End macro TWOK 0603 00 Macro CHAR: 0604 61 End macro CHAR Macro TWOK: 0605 BC End macro TWOK Macro CHAR: 0606 7A End macro CHAR 0607 00 Macro CHAR: 0608 65 End macro CHAR Macro TWOK: 0609 B2 End macro TWOK 060A 00 Macro CHAR: 060B 65 End macro CHAR Macro CHAR: 060C 76 End macro CHAR Macro CHAR: 060D 71 End macro CHAR Macro CHAR: 060E 71 End macro CHAR Macro CHAR: 060F 7A End macro CHAR 0610 00 Macro CHAR: 0611 71 End macro CHAR Macro CHAR: 0612 6C End macro CHAR Macro CHAR: 0613 67 End macro CHAR Macro TWOK: 0614 B1 End macro TWOK Macro CHAR: 0615 77 End macro CHAR 0616 00 Macro CHAR: 0617 65 End macro CHAR Macro CHAR: 0618 71 End macro CHAR Macro CHAR: 0619 6C End macro CHAR Macro CHAR: 061A 64 End macro CHAR 061B 00 Macro CHAR: 061C 6F End macro CHAR Macro CHAR: 061D 6A End macro CHAR Macro TWOK: 061E A7 End macro TWOK Macro CHAR: 061F 71 End macro CHAR Macro CHAR: 0620 67 End macro CHAR 0621 00 Macro CHAR: 0622 6F End macro CHAR Macro CHAR: 0623 6C End macro CHAR Macro CHAR: 0624 61 End macro CHAR Macro RTOK: 0625 E8 End macro RTOK Macro TWOK: 0626 B3 End macro TWOK 0627 00 Macro TWOK: 0628 A5 End macro TWOK Macro CHAR: 0629 71 End macro CHAR Macro CHAR: 062A 67 End macro CHAR 062B 00 Macro CHAR: 062C 6B End macro CHAR Macro CHAR: 062D 76 End macro CHAR Macro CHAR: 062E 6E End macro CHAR Macro TWOK: 062F B8 End macro TWOK Macro CHAR: 0630 6C End macro CHAR Macro CHAR: 0631 6A End macro CHAR Macro CHAR: 0632 67 End macro CHAR 0633 00 Macro CHAR: 0634 65 End macro CHAR Macro CHAR: 0635 66 End macro CHAR Macro CHAR: 0636 6F End macro CHAR Macro TWOK: 0637 AF End macro TWOK Macro CHAR: 0638 66 End macro CHAR 0639 00 Macro TWOK: 063A AF End macro TWOK Macro CHAR: 063B 70 End macro CHAR Macro CHAR: 063C 66 End macro CHAR Macro CHAR: 063D 60 End macro CHAR Macro CHAR: 063E 77 End macro CHAR 063F 00 Macro RTOK: 0640 88 End macro RTOK Macro TWOK: 0641 B7 End macro TWOK Macro TWOK: 0642 AE End macro TWOK Macro TWOK: 0643 AB End macro TWOK 0644 00 Macro CHAR: 0645 60 End macro CHAR Macro CHAR: 0646 6C End macro CHAR Macro CHAR: 0647 6E End macro CHAR 0648 00 Macro RTOK: 0649 D8 End macro RTOK Macro CHAR: 064A 6E End macro CHAR Macro TWOK: 064B B8 End macro TWOK Macro CHAR: 064C 67 End macro CHAR Macro TWOK: 064D B3 End macro TWOK 064E 00 Macro CHAR: 064F 03 End macro CHAR Macro CHAR: 0650 67 End macro CHAR Macro TWOK: 0651 AA End macro TWOK Macro CHAR: 0652 77 End macro CHAR Macro CHAR: 0653 71 End macro CHAR Macro CHAR: 0654 6C End macro CHAR Macro CHAR: 0655 7A End macro CHAR Macro TWOK: 0656 BB End macro TWOK 0657 00 Macro CHAR: 0658 61 End macro CHAR Macro CHAR: 0659 7A End macro CHAR Macro CHAR: 065A 03 End macro CHAR Macro CHAR: 065B 67 End macro CHAR Macro CHAR: 065C 0D End macro CHAR Macro CHAR: 065D 61 End macro CHAR Macro TWOK: 065E B7 End macro TWOK Macro TWOK: 065F B0 End macro TWOK Macro CHAR: 0660 6D End macro CHAR Macro CHAR: 0661 03 End macro CHAR Macro CHAR: 0662 05 End macro CHAR Macro CHAR: 0663 03 End macro CHAR Macro CHAR: 0664 6A End macro CHAR Macro CHAR: 0665 0D End macro CHAR Macro TWOK: 0666 B0 End macro TWOK Macro RTOK: 0667 55 End macro RTOK 0668 00 Macro RTOK: 0669 8D End macro RTOK Macro CHAR: 066A 03 End macro CHAR Macro CHAR: 066B 03 End macro CHAR Macro RTOK: 066C 93 End macro RTOK Macro CONT: 066D 2E End macro CONT Macro CHAR: 066E 03 End macro CHAR Macro RTOK: 066F 99 End macro RTOK Macro CHAR: 0670 03 End macro CHAR Macro CHAR: 0671 03 End macro CHAR Macro CHAR: 0672 03 End macro CHAR Macro RTOK: 0673 8D End macro RTOK Macro CHAR: 0674 03 End macro CHAR Macro RTOK: 0675 85 End macro RTOK Macro CHAR: 0676 03 End macro CHAR Macro CHAR: 0677 65 End macro CHAR Macro TWOK: 0678 BA End macro TWOK Macro CHAR: 0679 03 End macro CHAR Macro CHAR: 067A 70 End macro CHAR Macro CHAR: 067B 62 End macro CHAR Macro TWOK: 067C A2 End macro TWOK Macro CONT: 067D 2E End macro CONT Macro CONT: 067E 29 End macro CONT 067F 00 Macro CHAR: 0680 65 End macro CHAR Macro CHAR: 0681 71 End macro CHAR Macro TWOK: 0682 BC End macro TWOK Macro CHAR: 0683 77 End macro CHAR 0684 00 Macro TWOK: 0685 AD End macro TWOK Macro TWOK: 0686 A9 End macro TWOK 0687 00 Macro TWOK: 0688 A2 End macro TWOK Macro CHAR: 0689 65 End macro CHAR Macro CHAR: 068A 77 End macro CHAR 068B 00 Macro TWOK: 068C BD End macro TWOK Macro CHAR: 068D 64 End macro CHAR Macro CHAR: 068E 6B End macro CHAR Macro CHAR: 068F 77 End macro CHAR 0690 00 Macro RTOK: 0691 5A End macro RTOK Macro CHAR: 0692 6F End macro CHAR Macro CHAR: 0693 6C End macro CHAR Macro CHAR: 0694 74 End macro CHAR Macro CONT: 0695 24 End macro CONT 0696 00 Macro RTOK: 0697 40 End macro RTOK Macro RTOK: 0698 32 End macro RTOK Macro RTOK: 0699 DF End macro RTOK Macro CHAR: 069A 02 End macro CHAR 069B 00 Macro CHAR: 069C 66 End macro CHAR Macro CHAR: 069D 7B End macro CHAR Macro CHAR: 069E 77 End macro CHAR Macro TWOK: 069F B7 End macro TWOK Macro CHAR: 06A0 03 End macro CHAR 06A1 00 Macro CHAR: 06A2 73 End macro CHAR Macro CHAR: 06A3 76 End macro CHAR Macro CHAR: 06A4 6F End macro CHAR Macro CHAR: 06A5 70 End macro CHAR Macro CHAR: 06A6 66 End macro CHAR Macro RTOK: 06A7 98 End macro RTOK 06A8 00 Macro TWOK: 06A9 B0 End macro TWOK Macro CHAR: 06AA 62 End macro CHAR Macro CHAR: 06AB 6E End macro CHAR Macro RTOK: 06AC 98 End macro RTOK 06AD 00 Macro CHAR: 06AE 65 End macro CHAR Macro CHAR: 06AF 76 End macro CHAR Macro CHAR: 06B0 66 End macro CHAR Macro CHAR: 06B1 6F End macro CHAR 06B2 00 Macro CHAR: 06B3 6E End macro CHAR Macro TWOK: 06B4 BE End macro TWOK Macro CHAR: 06B5 70 End macro CHAR Macro CHAR: 06B6 6A End macro CHAR Macro TWOK: 06B7 A2 End macro TWOK 06B8 00 Macro RTOK: 06B9 C0 End macro RTOK Macro RTOK: 06BA ED End macro RTOK Macro CHAR: 06BB 03 End macro CHAR Macro CHAR: 06BC 61 End macro CHAR Macro CHAR: 06BD 62 End macro CHAR Macro CHAR: 06BE 7A End macro CHAR 06BF 00 Macro CHAR: 06C0 66 End macro CHAR Macro CHAR: 06C1 0D End macro CHAR Macro CHAR: 06C2 60 End macro CHAR Macro CHAR: 06C3 0D End macro CHAR Macro CHAR: 06C4 6E End macro CHAR Macro CHAR: 06C5 0D End macro CHAR Macro RTOK: 06C6 86 End macro RTOK 06C7 00 Macro RTOK: 06C8 45 End macro RTOK Macro RTOK: 06C9 44 End macro RTOK Macro CHAR: 06CA 70 End macro CHAR 06CB 00 Macro RTOK: 06CC 45 End macro RTOK Macro RTOK: 06CD 4B End macro RTOK Macro CHAR: 06CE 70 End macro CHAR 06CF 00 Macro RTOK: 06D0 4A End macro RTOK Macro CHAR: 06D1 03 End macro CHAR Macro CHAR: 06D2 70 End macro CHAR Macro CHAR: 06D3 60 End macro CHAR Macro CHAR: 06D4 6C End macro CHAR Macro CHAR: 06D5 6C End macro CHAR Macro CHAR: 06D6 73 End macro CHAR Macro CHAR: 06D7 70 End macro CHAR 06D8 00 Macro TWOK: 06D9 AA End macro TWOK Macro CHAR: 06DA 60 End macro CHAR Macro CHAR: 06DB 62 End macro CHAR Macro CHAR: 06DC 73 End macro CHAR Macro CHAR: 06DD 66 End macro CHAR Macro CHAR: 06DE 03 End macro CHAR Macro CHAR: 06DF 73 End macro CHAR Macro CHAR: 06E0 6C End macro CHAR Macro CHAR: 06E1 67 End macro CHAR 06E2 00 Macro RTOK: 06E3 5A End macro RTOK Macro CHAR: 06E4 61 End macro CHAR Macro CHAR: 06E5 6C End macro CHAR Macro CHAR: 06E6 6E End macro CHAR Macro CHAR: 06E7 61 End macro CHAR 06E8 00 Macro RTOK: 06E9 5A End macro RTOK Macro RTOK: 06EA 8D End macro RTOK 06EB 00 Macro RTOK: 06EC 5F End macro RTOK Macro TWOK: 06ED AF End macro TWOK Macro CHAR: 06EE 64 End macro CHAR Macro CHAR: 06EF 03 End macro CHAR Macro RTOK: 06F0 F4 End macro RTOK 06F1 00 Macro RTOK: 06F2 59 End macro RTOK Macro CHAR: 06F3 03 End macro CHAR Macro RTOK: 06F4 9E End macro RTOK 06F5 00 Macro CHAR: 06F6 62 End macro CHAR Macro RTOK: 06F7 55 End macro RTOK 06F8 00 Macro CHAR: 06F9 6F End macro CHAR Macro CHAR: 06FA 6F End macro CHAR 06FB 00 Macro RTOK: 06FC E6 End macro RTOK Macro CHAR: 06FD 19 End macro CHAR Macro CONT: 06FE 23 End macro CONT 06FF 00 Macro TWOK: 0700 AF End macro TWOK Macro RTOK: 0701 D8 End macro RTOK Macro TWOK: 0702 AF End macro TWOK Macro CHAR: 0703 64 End macro CHAR Macro CHAR: 0704 03 End macro CHAR Macro RTOK: 0705 49 End macro RTOK 0706 00 Macro TWOK: 0707 B1 End macro TWOK Macro TWOK: 0708 B3 End macro TWOK Macro CHAR: 0709 64 End macro CHAR Macro CHAR: 070A 7A End macro CHAR Macro CHAR: 070B 03 End macro CHAR 070C 00 Macro CHAR: 070D 64 End macro CHAR Macro CHAR: 070E 62 End macro CHAR Macro TWOK: 070F B6 End macro TWOK Macro CHAR: 0710 60 End macro CHAR Macro TWOK: 0711 B4 End macro TWOK Macro CHAR: 0712 60 End macro CHAR 0713 00 Macro CONT: 0714 2E End macro CONT Macro RTOK: 0715 DF End macro RTOK Macro CHAR: 0716 04 End macro CHAR Macro CHAR: 0717 70 End macro CHAR Macro CHAR: 0718 03 End macro CHAR Macro CHAR: 0719 6D End macro CHAR Macro CHAR: 071A 62 End macro CHAR Macro CHAR: 071B 6E End macro CHAR Macro CHAR: 071C 66 End macro CHAR Macro CHAR: 071D 1C End macro CHAR Macro CHAR: 071E 03 End macro CHAR 071F 00 Macro CHAR: 0720 67 End macro CHAR Macro CHAR: 0721 6C End macro CHAR Macro CHAR: 0722 60 End macro CHAR Macro CHAR: 0723 68 End macro CHAR 0724 00 Macro CONT: 0725 26 End macro CONT Macro TWOK: 0726 A2 End macro TWOK Macro CHAR: 0727 64 End macro CHAR Macro TWOK: 0728 A3 End macro TWOK Macro CHAR: 0729 03 End macro CHAR Macro RTOK: 072A E8 End macro RTOK Macro TWOK: 072B B2 End macro TWOK Macro TWOK: 072C AB End macro TWOK Macro CHAR: 072D 19 End macro CHAR 072E 00 Macro RTOK: 072F DF End macro RTOK Macro CHAR: 0730 03 End macro CHAR Macro CONT: 0731 27 End macro CONT Macro CONT: 0732 2E End macro CONT Macro CONT: 0733 2E End macro CONT Macro CONT: 0734 2E End macro CONT Macro CONT: 0735 25 End macro CONT Macro RTOK: 0736 3C End macro RTOK Macro CHAR: 0737 03 End macro CHAR Macro RTOK: 0738 86 End macro RTOK Macro CONT: 0739 2A End macro CONT Macro CONT: 073A 21 End macro CONT Macro CONT: 073B 2E End macro CONT Macro RTOK: 073C 9E End macro RTOK Macro RTOK: 073D 86 End macro RTOK Macro CONT: 073E 2A End macro CONT Macro CONT: 073F 20 End macro CONT Macro CONT: 0740 2E End macro CONT Macro CHAR: 0741 60 End macro CHAR Macro TWOK: 0742 BC End macro TWOK Macro TWOK: 0743 AE End macro TWOK Macro TWOK: 0744 B4 End macro TWOK Macro TWOK: 0745 BC End macro TWOK Macro CONT: 0746 2A End macro CONT 0747 00 Macro CHAR: 0748 6A End macro CHAR Macro TWOK: 0749 BF End macro TWOK Macro CHAR: 074A 6E End macro CHAR 074B 00 Macro CHAR: 074C 03 End macro CHAR Macro CHAR: 074D 03 End macro CHAR Macro CHAR: 074E 6F End macro CHAR Macro CHAR: 074F 6C End macro CHAR Macro CHAR: 0750 62 End macro CHAR Macro CHAR: 0751 67 End macro CHAR Macro CHAR: 0752 03 End macro CHAR Macro CHAR: 0753 6D End macro CHAR Macro CHAR: 0754 66 End macro CHAR Macro CHAR: 0755 74 End macro CHAR Macro CHAR: 0756 03 End macro CHAR Macro RTOK: 0757 DF End macro RTOK Macro CHAR: 0758 03 End macro CHAR Macro RTOK: 0759 C2 End macro RTOK Macro CONT: 075A 2E End macro CONT Macro CONT: 075B 2E End macro CONT 075C 00 Macro CONT: 075D 25 End macro CONT Macro RTOK: 075E 5F End macro RTOK Macro TWOK: 075F BB End macro TWOK 0760 00 Macro TWOK: 0761 B7 End macro TWOK Macro TWOK: 0762 B4 End macro TWOK Macro CHAR: 0763 6D End macro CHAR Macro CHAR: 0764 64 End macro CHAR Macro CHAR: 0765 19 End macro CHAR 0766 00 Macro CHAR: 0767 03 End macro CHAR Macro TWOK: 0768 BC End macro TWOK Macro CHAR: 0769 03 End macro CHAR 076A 00 Macro CONT: 076B 2E End macro CONT Macro CONT: 076C 2B End macro CONT Macro RTOK: 076D EC End macro RTOK Macro CHAR: 076E 6E End macro CHAR Macro TWOK: 076F B1 End macro TWOK Macro CHAR: 0770 77 End macro CHAR Macro CHAR: 0771 19 End macro CHAR Macro CONT: 0772 25 End macro CONT 0773 00 Macro CHAR: 0774 60 End macro CHAR Macro TWOK: 0775 A2 End macro TWOK Macro TWOK: 0776 B8 End macro TWOK 0777 00 Macro CHAR: 0778 6C End macro CHAR Macro CHAR: 0779 65 End macro CHAR Macro CHAR: 077A 65 End macro CHAR Macro TWOK: 077B B1 End macro TWOK Macro CHAR: 077C 67 End macro CHAR Macro TWOK: 077D B3 End macro TWOK 077E 00 Macro CHAR: 077F 65 End macro CHAR Macro CHAR: 0780 76 End macro CHAR Macro CHAR: 0781 64 End macro CHAR Macro CHAR: 0782 6A End macro CHAR Macro TWOK: 0783 B4 End macro TWOK Macro TWOK: 0784 B5 End macro TWOK 0785 00 Macro CHAR: 0786 6B End macro CHAR Macro TWOK: 0787 A9 End macro TWOK Macro CHAR: 0788 6E End macro CHAR Macro TWOK: 0789 A2 End macro TWOK Macro CHAR: 078A 70 End macro CHAR Macro CHAR: 078B 70 End macro CHAR 078C 00 Macro CHAR: 078D 6E End macro CHAR Macro CHAR: 078E 6C End macro CHAR Macro RTOK: 078F E8 End macro RTOK Macro CHAR: 0790 6F End macro CHAR Macro CHAR: 0791 7A End macro CHAR Macro CHAR: 0792 03 End macro CHAR Macro RTOK: 0793 35 End macro RTOK 0794 00 Macro RTOK: 0795 8F End macro RTOK 0796 00 Macro RTOK: 0797 88 End macro RTOK 0798 00 Macro CHAR: 0799 62 End macro CHAR Macro CHAR: 079A 61 End macro CHAR Macro CHAR: 079B 6C End macro CHAR Macro TWOK: 079C B5 End macro TWOK Macro CHAR: 079D 03 End macro CHAR Macro RTOK: 079E 88 End macro RTOK 079F 00 Macro RTOK: 07A0 D8 End macro RTOK Macro CHAR: 07A1 73 End macro CHAR Macro CHAR: 07A2 66 End macro CHAR Macro CHAR: 07A3 77 End macro CHAR Macro TWOK: 07A4 B1 End macro TWOK Macro CHAR: 07A5 77 End macro CHAR 07A6 00 Macro CHAR: 07A7 67 End macro CHAR Macro TWOK: 07A8 B8 End macro TWOK Macro TWOK: 07A9 A0 End macro TWOK Macro CHAR: 07AA 71 End macro CHAR Macro CHAR: 07AB 6C End macro CHAR Macro TWOK: 07AC AB End macro TWOK 07AD 00 Macro CHAR: 07AE 67 End macro CHAR Macro CHAR: 07AF 66 End macro CHAR Macro CHAR: 07B0 62 End macro CHAR Macro CHAR: 07B1 67 End macro CHAR Macro CHAR: 07B2 6F End macro CHAR Macro CHAR: 07B3 7A End macro CHAR 07B4 00 Macro CHAR: 07B5 0E End macro CHAR Macro CHAR: 07B6 0E End macro CHAR Macro CHAR: 07B7 0E End macro CHAR Macro CHAR: 07B8 0E End macro CHAR Macro CHAR: 07B9 03 End macro CHAR Macro CHAR: 07BA 66 End macro CHAR Macro CHAR: 07BB 03 End macro CHAR Macro CHAR: 07BC 6F End macro CHAR Macro CHAR: 07BD 03 End macro CHAR Macro CHAR: 07BE 6A End macro CHAR Macro CHAR: 07BF 03 End macro CHAR Macro CHAR: 07C0 77 End macro CHAR Macro CHAR: 07C1 03 End macro CHAR Macro CHAR: 07C2 66 End macro CHAR Macro CHAR: 07C3 03 End macro CHAR Macro CHAR: 07C4 0E End macro CHAR Macro CHAR: 07C5 0E End macro CHAR Macro CHAR: 07C6 0E End macro CHAR Macro CHAR: 07C7 0E End macro CHAR 07C8 00 Macro CHAR: 07C9 73 End macro CHAR Macro TWOK: 07CA AD End macro TWOK Macro CHAR: 07CB 70 End macro CHAR Macro TWOK: 07CC B1 End macro TWOK Macro CHAR: 07CD 77 End macro CHAR 07CE 00 Macro CONT: 07CF 2B End macro CONT Macro CHAR: 07D0 64 End macro CHAR Macro CHAR: 07D1 62 End macro CHAR Macro CHAR: 07D2 6E End macro CHAR Macro CHAR: 07D3 66 End macro CHAR Macro CHAR: 07D4 03 End macro CHAR Macro CHAR: 07D5 6C End macro CHAR Macro TWOK: 07D6 B5 End macro TWOK Macro CHAR: 07D7 71 End macro CHAR 07D8 00 Macro CHAR: 07D9 73 End macro CHAR Macro CHAR: 07DA 71 End macro CHAR Macro TWOK: 07DB AA End macro TWOK Macro CHAR: 07DC 70 End macro CHAR Macro CHAR: 07DD 03 End macro CHAR Macro CHAR: 07DE 65 End macro CHAR Macro CHAR: 07DF 6A End macro CHAR Macro TWOK: 07E0 AD End macro TWOK Macro CHAR: 07E1 03 End macro CHAR Macro TWOK: 07E2 BA End macro TWOK Macro CHAR: 07E3 03 End macro CHAR Macro CHAR: 07E4 70 End macro CHAR Macro CHAR: 07E5 73 End macro CHAR Macro CHAR: 07E6 62 End macro CHAR Macro TWOK: 07E7 A6 End macro TWOK Macro CHAR: 07E8 0F End macro CHAR Macro RTOK: 07E9 DF End macro RTOK Macro CHAR: 07EA 0D End macro CHAR Macro CONT: 07EB 2E End macro CONT Macro CONT: 07EC 2E End macro CONT 07ED 00 Macro CHAR: 07EE 0B End macro CHAR Macro CHAR: 07EF 60 End macro CHAR Macro CHAR: 07F0 0A End macro CHAR Macro CHAR: 07F1 03 End macro CHAR Macro CHAR: 07F2 62 End macro CHAR Macro CHAR: 07F3 60 End macro CHAR Macro TWOK: 07F4 BA End macro TWOK Macro CHAR: 07F5 6D End macro CHAR Macro TWOK: 07F6 A4 End macro TWOK Macro CHAR: 07F7 65 End macro CHAR Macro CHAR: 07F8 77 End macro CHAR Macro CHAR: 07F9 03 End macro CHAR Macro CHAR: 07FA 12 End macro CHAR Macro CHAR: 07FB 1A End macro CHAR Macro CHAR: 07FC 1B End macro CHAR Macro CHAR: 07FD 17 End macro CHAR 07FE 00 WORDS9 Assembled at &400 Ends at &7FF Code size is &3FF Execute at &1100 Reload at &1100 S.WORDS9 &400 &7FF &1100 &1100 Saving file '3-assembled-output/WORDS9.bin' .K% 0900 K% workspace from &900 to &AAF inclusive .WP 0D40 .FRIN 0D40 .CABTMP 0D4D .MANY 0D4D .SSPR 0D55 .ECMP 0D5B .MJ 0D5C .LAS2 0D5D .MSAR 0D5E .VIEW 0D5F .LASCT 0D60 .GNTMP 0D61 .HFX 0D62 .EV 0D63 .DLY 0D64 .de 0D65 .LSX 0D66 .LSO 0D66 .LSX2 0E26 .LSY2 0E74 .SY 0EC2 .SYL 0ED5 .SZ 0EE8 .SZL 0EFB .XSAV2 0F0E .YSAV2 0F0F .MCH 0F10 .FSH 0F11 .ASH 0F12 .ENERGY 0F13 .LASX 0F14 .LASY 0F15 .COMX 0F16 .COMY 0F17 .QQ24 0F18 .QQ25 0F19 .QQ28 0F1A .QQ29 0F1B .gov 0F1C .tek 0F1D .SLSP 0F1E .XX24 0F20 .ALTIT 0F21 .QQ2 0F22 .QQ3 0F28 .QQ4 0F29 .QQ5 0F2A .QQ6 0F2B .QQ7 0F2D .QQ8 0F2F .QQ9 0F31 .QQ10 0F32 .NOSTM 0F33 WP workspace from &D40 to &F33 inclusive .S% 0F40 F5 46 0F42 81 1F 0F44 A6 21 0F46 F8 46 .COMC 0F48 .DNOIZ 0F49 .DAMP 0F4A .DJD 0F4B .PATG 0F4C .FLH 0F4D .JSTGY 0F4E .JSTE 0F4F .JSTK 0F50 S% workspace from &F40 to &F50 inclusive .M% 0F51 AD 00 09 LDA &0900 0F54 85 00 STA &00 0F56 A6 9C LDX &9C 0F58 20 5F 29 JSR &295F 0F5B 20 5F 29 JSR &295F 0F5E 8A TXA 0F5F 49 80 EOR #&80 0F61 A8 TAY 0F62 29 80 AND #&80 0F64 85 88 STA &88 0F66 86 9C STX &9C 0F68 49 80 EOR #&80 0F6A 85 89 STA &89 0F6C 98 TYA 0F6D 10 05 BPL &0F74 0F6F 49 FF EOR #&FF 0F71 18 CLC 0F72 69 01 ADC #&01 0F74 4A LSR A 0F75 4A LSR A 0F76 C9 08 CMP #&08 0F78 B0 02 BCS &0F7C 0F7A 4A LSR A 0F7B 18 CLC 0F7C 85 87 STA &87 0F7E 05 88 ORA &88 0F80 85 9E STA &9E 0F82 A6 9D LDX &9D 0F84 20 5F 29 JSR &295F 0F87 8A TXA 0F88 49 80 EOR #&80 0F8A A8 TAY 0F8B 29 80 AND #&80 0F8D 86 9D STX &9D 0F8F 85 8B STA &8B 0F91 49 80 EOR #&80 0F93 85 8A STA &8A 0F95 98 TYA 0F96 10 02 BPL &0F9A 0F98 49 FF EOR #&FF 0F9A 69 04 ADC #&04 0F9C 4A LSR A 0F9D 4A LSR A 0F9E 4A LSR A 0F9F 4A LSR A 0FA0 C9 03 CMP #&03 0FA2 B0 01 BCS &0FA5 0FA4 4A LSR A 0FA5 85 2B STA &2B 0FA7 05 8A ORA &8A 0FA9 85 2A STA &2A 0FAB A5 43 LDA &43 0FAD F0 08 BEQ &0FB7 0FAF A5 8C LDA &8C 0FB1 C9 28 CMP #&28 0FB3 B0 02 BCS &0FB7 0FB5 E6 8C INC &8C .MA17 0FB7 A5 42 LDA &42 0FB9 F0 06 BEQ &0FC1 0FBB C6 8C DEC &8C 0FBD D0 02 BNE &0FC1 0FBF E6 8C INC &8C .MA4 0FC1 A5 4C LDA &4C 0FC3 2D 33 03 AND &0333 0FC6 F0 0F BEQ &0FD7 0FC8 A0 EE LDY #&EE 0FCA 20 07 3D JSR &3D07 0FCD A9 28 LDA #&28 0FCF 20 CD 49 JSR &49CD .MA31 0FD2 A9 00 LDA #&00 0FD4 8D 5E 0D STA &0D5E .MA20 0FD7 A5 52 LDA &52 0FD9 10 11 BPL &0FEC 0FDB A5 4B LDA &4B 0FDD F0 0D BEQ &0FEC 0FDF AE 33 03 LDX &0333 0FE2 F0 08 BEQ &0FEC 0FE4 8D 5E 0D STA &0D5E 0FE7 A0 E0 LDY #&E0 0FE9 20 41 3D JSR &3D41 .MA25 0FEC A5 4D LDA &4D 0FEE F0 07 BEQ &0FF7 0FF0 A5 52 LDA &52 0FF2 30 2C BMI &1020 0FF4 20 8C 24 JSR &248C .MA24 0FF7 A5 49 LDA &49 0FF9 F0 03 BEQ &0FFE 0FFB 0E 2A 03 ASL &032A .MA76 0FFE A5 4A LDA &4A 1000 2D 2E 03 AND &032E 1003 F0 03 BEQ &1008 1005 4C D7 21 JMP &21D7 1008 A5 4F LDA &4F 100A F0 03 BEQ &100F 100C 20 FD 29 JSR &29FD 100F A5 4E LDA &4E 1011 2D 28 03 AND &0328 1014 F0 0A BEQ &1020 1016 A5 30 LDA &30 1018 D0 06 BNE &1020 101A CE 5B 0D DEC &0D5B 101D 20 15 3D JSR &3D15 .MA64 1020 A5 50 LDA &50 1022 2D 2C 03 AND &032C 1025 2D 55 0D AND &0D55 1028 F0 08 BEQ &1032 102A AD 44 09 LDA &0944 102D 30 03 BMI &1032 102F 4C 43 11 JMP &1143 .MA68 1032 A9 00 LDA #&00 1034 85 51 STA &51 1036 85 8D STA &8D 1038 A5 8C LDA &8C 103A 4A LSR A 103B 66 8D ROR &8D 103D 4A LSR A 103E 66 8D ROR &8D 1040 85 8E STA &8E 1042 AD 60 0D LDA &0D60 1045 D0 2D BNE &1074 1047 A5 48 LDA &48 1049 F0 29 BEQ &1074 104B AD 61 0D LDA &0D61 104E C9 F2 CMP #&F2 1050 B0 22 BCS &1074 1052 AE 5F 0D LDX &0D5F 1055 BD 10 03 LDA &0310,X 1058 F0 1A BEQ &1074 105A 48 PHA 105B 29 7F AND #&7F 105D 85 51 STA &51 105F 8D 5D 0D STA &0D5D 1062 A9 00 LDA #&00 1064 20 CD 49 JSR &49CD 1067 20 5B 2A JSR &2A5B 106A 68 PLA 106B 10 02 BPL &106F 106D A9 00 LDA #&00 .ma1 106F 29 FA AND #&FA 1071 8D 60 0D STA &0D60 .MA3 1074 A2 00 LDX #&00 .MAL1 1076 86 93 STX &93 1078 BD 40 0D LDA &0D40,X 107B D0 03 BNE &1080 107D 4C 29 12 JMP &1229 1080 85 9B STA &9B 1082 20 4F 3C JSR &3C4F 1085 A0 23 LDY #&23 .MAL2 1087 B1 20 LDA (&20),Y 1089 99 53 00 STA &0053,Y 108C 88 DEY 108D 10 F8 BPL &1087 108F A5 9B LDA &9B 1091 30 24 BMI &10B7 1093 0A ASL A 1094 A8 TAY 1095 B9 38 56 LDA &5638,Y 1098 85 1E STA &1E 109A B9 39 56 LDA &5639,Y 109D 85 1F STA &1F 109F AD 2A 03 LDA &032A 10A2 10 13 BPL &10B7 10A4 C0 10 CPY #&10 10A6 F0 0F BEQ &10B7 10A8 A5 72 LDA &72 10AA 29 20 AND #&20 10AC D0 09 BNE &10B7 10AE A5 72 LDA &72 10B0 09 80 ORA #&80 10B2 85 72 STA &72 10B4 20 A5 49 JSR &49A5 .MA21 10B7 20 A9 13 JSR &13A9 10BA A0 23 LDY #&23 .MAL3 10BC B9 53 00 LDA &0053,Y 10BF 91 20 STA (&20),Y 10C1 88 DEY 10C2 10 F8 BPL &10BC 10C4 A5 72 LDA &72 10C6 29 A0 AND #&A0 10C8 20 78 46 JSR &4678 10CB D0 55 BNE &1122 10CD A5 53 LDA &53 10CF 05 56 ORA &56 10D1 05 59 ORA &59 10D3 30 4D BMI &1122 10D5 A6 9B LDX &9B 10D7 30 49 BMI &1122 10D9 E0 08 CPX #&08 10DB F0 48 BEQ &1125 10DD 29 C0 AND #&C0 10DF D0 41 BNE &1122 10E1 E0 09 CPX #&09 10E3 F0 3D BEQ &1122 10E5 E0 0B CPX #&0B 10E7 B0 03 BCS &10EC 10E9 4C 6D 11 JMP &116D 10EC AD 29 03 LDA &0329 10EF 25 58 AND &58 10F1 10 7A BPL &116D 10F3 A9 03 LDA #&03 10F5 E0 0C CPX #&0C 10F7 90 06 BCC &10FF 10F9 D0 09 BNE &1104 10FB A9 10 LDA #&10 10FD D0 05 BNE &1104 .oily 10FF 20 57 44 JSR &4457 1102 29 07 AND #&07 .slvy2 1104 8D 1B 0F STA &0F1B 1107 A9 01 LDA #&01 1109 20 C8 2C JSR &2CC8 110C A0 4E LDY #&4E 110E B0 4B BCS &115B 1110 AC 1B 0F LDY &0F1B 1113 79 17 03 ADC &0317,Y 1116 99 17 03 STA &0317,Y 1119 98 TYA 111A 69 D0 ADC #&D0 111C 20 29 4B JSR &4B29 111F 4C 5E 11 JMP &115E .MA65 1122 4C 7C 11 JMP &117C .ISDK 1125 AD 44 09 LDA &0944 1128 30 28 BMI &1152 112A A5 61 LDA &61 112C C9 D6 CMP #&D6 112E 90 22 BCC &1152 1130 20 7D 3B JSR &3B7D 1133 A5 33 LDA &33 1135 30 1B BMI &1152 1137 C9 59 CMP #&59 1139 90 17 BCC &1152 113B A5 63 LDA &63 113D 29 7F AND #&7F 113F C9 50 CMP #&50 1141 90 0F BCC &1152 .GOIN 1143 A9 00 LDA #&00 1145 85 2F STA &2F 1147 A9 08 LDA #&08 1149 20 76 25 JSR &2576 114C 20 A7 43 JSR &43A7 114F 4C 4D 47 JMP &474D .MA62 1152 A5 8C LDA &8C 1154 C9 05 CMP #&05 1156 90 0D BCC &1165 1158 4C 7F 46 JMP &467F .MA59 115B 20 8C 49 JSR &498C .MA60 115E 06 72 ASL &72 1160 38 SEC 1161 66 72 ROR &72 .MA61 1163 D0 17 BNE &117C .MA67 1165 A9 01 LDA #&01 1167 85 8C STA &8C 1169 A9 05 LDA #&05 116B D0 09 BNE &1176 .MA58 116D 06 72 ASL &72 116F 38 SEC 1170 66 72 ROR &72 1172 A5 76 LDA &76 1174 38 SEC 1175 6A ROR A .MA63 1176 20 01 3C JSR &3C01 1179 20 8C 49 JSR &498C .MA26 117C A5 96 LDA &96 117E D0 5A BNE &11DA 1180 20 AF 2A JSR &2AAF 1183 20 27 24 JSR &2427 1186 90 4F BCC &11D7 1188 AD 5E 0D LDA &0D5E 118B F0 0A BEQ &1197 118D 20 CB 49 JSR &49CB 1190 A6 93 LDX &93 1192 A0 0E LDY #&0E 1194 20 09 3D JSR &3D09 .MA47 1197 A5 51 LDA &51 1199 F0 3C BEQ &11D7 119B A2 0F LDX #&0F 119D 20 B4 49 JSR &49B4 11A0 A5 76 LDA &76 11A2 38 SEC 11A3 E5 51 SBC &51 11A5 B0 29 BCS &11D0 11A7 A5 9B LDA &9B 11A9 C9 08 CMP #&08 11AB F0 25 BEQ &11D2 11AD A5 72 LDA &72 11AF 09 80 ORA #&80 11B1 85 72 STA &72 11B3 B0 22 BCS &11D7 11B5 20 57 44 JSR &4457 11B8 10 13 BPL &11CD 11BA A0 00 LDY #&00 11BC 31 1E AND (&1E),Y 11BE 85 A4 STA &A4 .um 11C0 F0 0B BEQ &11CD 11C2 A2 0B LDX #&0B 11C4 A9 00 LDA #&00 11C6 20 E0 24 JSR &24E0 11C9 C6 A4 DEC &A4 11CB 10 F3 BPL &11C0 .oh 11CD 20 A5 49 JSR &49A5 .MA14 11D0 85 76 STA &76 11D2 A5 9B LDA &9B 11D4 20 AB 24 JSR &24AB .MA8 11D7 20 2F 4E JSR &4E2F .MA15 11DA A0 23 LDY #&23 11DC A5 76 LDA &76 11DE 91 20 STA (&20),Y 11E0 A5 72 LDA &72 11E2 10 30 BPL &1214 11E4 29 20 AND #&20 11E6 F0 2C BEQ &1214 11E8 A5 9B LDA &9B 11EA C9 02 CMP #&02 11EC D0 08 BNE &11F6 11EE AD 34 03 LDA &0334 11F1 09 40 ORA #&40 11F3 8D 34 03 STA &0334 .q2 11F6 AD 64 0D LDA &0D64 11F9 0D 5C 0D ORA &0D5C 11FC D0 13 BNE &1211 11FE A0 0A LDY #&0A 1200 B1 1E LDA (&1E),Y 1202 F0 0D BEQ &1211 1204 AA TAX 1205 C8 INY 1206 B1 1E LDA (&1E),Y 1208 A8 TAY 1209 20 18 36 JSR &3618 120C A9 00 LDA #&00 120E 20 29 4B JSR &4B29 .KS1S 1211 4C 81 42 JMP &4281 .NBOUN .MAC1 1214 A5 9B LDA &9B 1216 30 05 BMI &121D 1218 20 6B 46 JSR &466B 121B 90 F4 BCC &1211 .MA27 121D A0 1F LDY #&1F 121F A5 72 LDA &72 1221 91 20 STA (&20),Y 1223 A6 93 LDX &93 1225 E8 INX 1226 4C 76 10 JMP &1076 .MA18 1229 AD 2A 03 LDA &032A 122C 10 0B BPL &1239 122E 0E 2A 03 ASL &032A 1231 20 BF 2C JSR &2CBF 1234 A9 30 LDA #&30 1236 8D 21 FE STA &FE21 .MA77 1239 A5 99 LDA &99 123B 29 07 AND #&07 123D D0 71 BNE &12B0 123F AE 13 0F LDX &0F13 1242 10 12 BPL &1256 1244 AE 12 0F LDX &0F12 1247 20 43 3B JSR &3B43 124A 8E 12 0F STX &0F12 124D AE 11 0F LDX &0F11 1250 20 43 3B JSR &3B43 1253 8E 11 0F STX &0F11 .b 1256 38 SEC 1257 AD 2B 03 LDA &032B 125A 6D 13 0F ADC &0F13 125D B0 03 BCS &1262 125F 8D 13 0F STA &0F13 1262 AD 5C 0D LDA &0D5C 1265 D0 46 BNE &12AD 1267 A5 99 LDA &99 1269 29 1F AND #&1F 126B D0 4C BNE &12B9 126D AD 55 0D LDA &0D55 1270 D0 3B BNE &12AD 1272 A8 TAY 1273 20 7C 13 JSR &137C 1276 D0 35 BNE &12AD 1278 A2 1C LDX #&1C .MAL4 127A BD 00 09 LDA &0900,X 127D 95 53 STA &53,X 127F CA DEX 1280 10 F8 BPL &127A 1282 E8 INX 1283 A0 09 LDY #&09 1285 20 59 13 JSR &1359 1288 D0 23 BNE &12AD 128A A2 03 LDX #&03 128C A0 0B LDY #&0B 128E 20 59 13 JSR &1359 1291 D0 1A BNE &12AD 1293 A2 06 LDX #&06 1295 A0 0D LDY #&0D 1297 20 59 13 JSR &1359 129A D0 11 BNE &12AD 129C A9 C0 LDA #&C0 129E 20 6D 46 JSR &466D 12A1 90 0A BCC &12AD 12A3 A5 96 LDA &96 12A5 D0 03 BNE &12AA 12A7 20 36 41 JSR &4136 12AA 20 5D 3C JSR &3C5D .MA23S 12AD 4C 29 13 JMP &1329 .MA22 12B0 AD 5C 0D LDA &0D5C 12B3 D0 74 BNE &1329 12B5 A5 99 LDA &99 12B7 29 1F AND #&1F .MA93 12B9 C9 0A CMP #&0A 12BB D0 2E BNE &12EB 12BD A9 32 LDA #&32 12BF CD 13 0F CMP &0F13 12C2 90 04 BCC &12C8 12C4 0A ASL A 12C5 20 29 4B JSR &4B29 12C8 A0 FF LDY #&FF 12CA 8C 21 0F STY &0F21 12CD C8 INY 12CE 20 7A 13 JSR &137A 12D1 D0 56 BNE &1329 12D3 20 88 13 JSR &1388 12D6 B0 51 BCS &1329 12D8 E9 24 SBC #&24 12DA 90 0C BCC &12E8 12DC 85 91 STA &91 12DE 20 5B 4D JSR &4D5B 12E1 A5 90 LDA &90 12E3 8D 21 0F STA &0F21 12E6 D0 41 BNE &1329 .MA28 12E8 4C 7F 46 JMP &467F .MA29 12EB C9 14 CMP #&14 12ED D0 3A BNE &1329 12EF A9 1E LDA #&1E 12F1 8D 4D 0D STA &0D4D 12F4 AD 55 0D LDA &0D55 12F7 D0 30 BNE &1329 12F9 A0 24 LDY #&24 12FB 20 7C 13 JSR &137C 12FE D0 29 BNE &1329 1300 20 88 13 JSR &1388 1303 49 FF EOR #&FF 1305 69 1E ADC #&1E 1307 8D 4D 0D STA &0D4D 130A B0 DC BCS &12E8 130C C9 E0 CMP #&E0 130E 90 19 BCC &1329 1310 AD 29 03 LDA &0329 1313 F0 14 BEQ &1329 1315 A5 8E LDA &8E 1317 4A LSR A 1318 6D 0D 03 ADC &030D 131B C9 46 CMP #&46 131D 90 02 BCC &1321 131F A9 46 LDA #&46 1321 8D 0D 03 STA &030D 1324 A9 A0 LDA #&A0 1326 20 29 4B JSR &4B29 .MA23 1329 AD 5D 0D LDA &0D5D 132C F0 0F BEQ &133D 132E AD 60 0D LDA &0D60 1331 C9 08 CMP #&08 1333 B0 08 BCS &133D 1335 20 7A 2A JSR &2A7A 1338 A9 00 LDA #&00 133A 8D 5D 0D STA &0D5D .MA16 133D AD 5B 0D LDA &0D5B 1340 F0 05 BEQ &1347 1342 20 46 3B JSR &3B46 1345 F0 08 BEQ &134F .MA69 1347 A5 30 LDA &30 1349 F0 07 BEQ &1352 134B C6 30 DEC &30 134D D0 03 BNE &1352 .MA70 134F 20 7E 49 JSR &497E .MA66 1352 A5 96 LDA &96 1354 D0 23 BNE &1379 1356 4C D2 1B JMP &1BD2 .MAS1 1359 B9 53 00 LDA &0053,Y 135C 0A ASL A 135D 85 3E STA &3E 135F B9 54 00 LDA &0054,Y 1362 2A ROL A 1363 85 3F STA &3F 1365 A9 00 LDA #&00 1367 6A ROR A 1368 85 40 STA &40 136A 20 AA 15 JSR &15AA 136D 95 55 STA &55,X 136F A4 3E LDY &3E 1371 94 53 STY &53,X 1373 A4 3F LDY &3F 1375 94 54 STY &54,X 1377 29 7F AND #&7F .MA9 1379 60 RTS .m 137A A9 00 LDA #&00 .MAS2 137C 19 02 09 ORA &0902,Y 137F 19 05 09 ORA &0905,Y 1382 19 08 09 ORA &0908,Y 1385 29 7F AND #&7F 1387 60 RTS .MAS3 1388 B9 01 09 LDA &0901,Y 138B 20 6F 27 JSR &276F 138E 85 91 STA &91 1390 B9 04 09 LDA &0904,Y 1393 20 6F 27 JSR &276F 1396 65 91 ADC &91 1398 B0 0C BCS &13A6 139A 85 91 STA &91 139C B9 07 09 LDA &0907,Y 139F 20 6F 27 JSR &276F 13A2 65 91 ADC &91 13A4 90 02 BCC &13A8 .MA30 13A6 A9 FF LDA #&FF 13A8 60 RTS .MVEIT 13A9 A5 72 LDA &72 13AB 29 A0 AND #&A0 13AD D0 25 BNE &13D4 13AF A5 99 LDA &99 13B1 45 93 EOR &93 13B3 29 0F AND #&0F 13B5 D0 03 BNE &13BA 13B7 20 1C 4C JSR &4C1C .MV3 13BA A6 9B LDX &9B 13BC 10 03 BPL &13C1 13BE 4C 2E 17 JMP &172E 13C1 A5 73 LDA &73 13C3 10 0F BPL &13D4 13C5 E0 09 CPX #&09 13C7 F0 08 BEQ &13D1 13C9 A5 99 LDA &99 13CB 45 93 EOR &93 13CD 29 07 AND #&07 13CF D0 03 BNE &13D4 .MV26 13D1 20 9F 22 JSR &229F .MV30 13D4 20 20 2C JSR &2C20 13D7 A5 6E LDA &6E 13D9 0A ASL A 13DA 0A ASL A 13DB 85 90 STA &90 13DD A5 5D LDA &5D 13DF 29 7F AND #&7F 13E1 20 A9 27 JSR &27A9 13E4 85 91 STA &91 13E6 A5 5D LDA &5D 13E8 A2 00 LDX #&00 13EA 20 53 15 JSR &1553 13ED A5 5F LDA &5F 13EF 29 7F AND #&7F 13F1 20 A9 27 JSR &27A9 13F4 85 91 STA &91 13F6 A5 5F LDA &5F 13F8 A2 03 LDX #&03 13FA 20 53 15 JSR &1553 13FD A5 61 LDA &61 13FF 29 7F AND #&7F 1401 20 A9 27 JSR &27A9 1404 85 91 STA &91 1406 A5 61 LDA &61 1408 A2 06 LDX #&06 140A 20 53 15 JSR &1553 140D A5 6E LDA &6E 140F 18 CLC 1410 65 6F ADC &6F 1412 10 02 BPL &1416 1414 A9 00 LDA #&00 1416 A0 0F LDY #&0F 1418 D1 1E CMP (&1E),Y 141A 90 02 BCC &141E 141C B1 1E LDA (&1E),Y 141E 85 6E STA &6E 1420 A9 00 LDA #&00 1422 85 6F STA &6F 1424 A6 87 LDX &87 1426 A5 53 LDA &53 1428 49 FF EOR #&FF 142A 85 1B STA &1B 142C A5 54 LDA &54 142E 20 D9 27 JSR &27D9 1431 85 1D STA &1D 1433 A5 89 LDA &89 1435 45 55 EOR &55 1437 A2 03 LDX #&03 1439 20 F9 16 JSR &16F9 143C 85 AF STA &AF 143E A5 1C LDA &1C 1440 85 AD STA &AD 1442 49 FF EOR #&FF 1444 85 1B STA &1B 1446 A5 1D LDA &1D 1448 85 AE STA &AE 144A A6 2B LDX &2B 144C 20 D9 27 JSR &27D9 144F 85 1D STA &1D 1451 A5 AF LDA &AF 1453 45 8A EOR &8A 1455 A2 06 LDX #&06 1457 20 F9 16 JSR &16F9 145A 85 5B STA &5B 145C A5 1C LDA &1C 145E 85 59 STA &59 1460 49 FF EOR #&FF 1462 85 1B STA &1B 1464 A5 1D LDA &1D 1466 85 5A STA &5A 1468 20 DB 27 JSR &27DB 146B 85 1D STA &1D 146D A5 AF LDA &AF 146F 85 58 STA &58 1471 45 8A EOR &8A 1473 45 5B EOR &5B 1475 10 0F BPL &1486 1477 A5 1C LDA &1C 1479 65 AD ADC &AD 147B 85 56 STA &56 147D A5 1D LDA &1D 147F 65 AE ADC &AE 1481 85 57 STA &57 1483 4C A6 14 JMP &14A6 .MV43 1486 A5 AD LDA &AD 1488 E5 1C SBC &1C 148A 85 56 STA &56 148C A5 AE LDA &AE 148E E5 1D SBC &1D 1490 85 57 STA &57 1492 B0 12 BCS &14A6 1494 A9 01 LDA #&01 1496 E5 56 SBC &56 1498 85 56 STA &56 149A A9 00 LDA #&00 149C E5 57 SBC &57 149E 85 57 STA &57 14A0 A5 58 LDA &58 14A2 49 80 EOR #&80 14A4 85 58 STA &58 .MV44 14A6 A6 87 LDX &87 14A8 A5 56 LDA &56 14AA 49 FF EOR #&FF 14AC 85 1B STA &1B 14AE A5 57 LDA &57 14B0 20 D9 27 JSR &27D9 14B3 85 1D STA &1D 14B5 A5 88 LDA &88 14B7 45 58 EOR &58 14B9 A2 00 LDX #&00 14BB 20 F9 16 JSR &16F9 14BE 85 55 STA &55 14C0 A5 1D LDA &1D 14C2 85 54 STA &54 14C4 A5 1C LDA &1C 14C6 85 53 STA &53 .MV45 14C8 A5 8C LDA &8C 14CA 85 91 STA &91 14CC A9 80 LDA #&80 14CE A2 06 LDX #&06 14D0 20 55 15 JSR &1555 14D3 A5 9B LDA &9B 14D5 29 81 AND #&81 14D7 C9 81 CMP #&81 14D9 D0 01 BNE &14DC 14DB 60 RTS 14DC A0 09 LDY #&09 14DE 20 06 16 JSR &1606 14E1 A0 0F LDY #&0F 14E3 20 06 16 JSR &1606 14E6 A0 15 LDY #&15 14E8 20 06 16 JSR &1606 14EB A5 71 LDA &71 14ED 29 80 AND #&80 14EF 85 AB STA &AB 14F1 A5 71 LDA &71 14F3 29 7F AND #&7F 14F5 F0 1D BEQ &1514 14F7 C9 7F CMP #&7F 14F9 E9 00 SBC #&00 14FB 05 AB ORA &AB 14FD 85 71 STA &71 14FF A2 0F LDX #&0F 1501 A0 09 LDY #&09 1503 20 6D 16 JSR &166D 1506 A2 11 LDX #&11 1508 A0 0B LDY #&0B 150A 20 6D 16 JSR &166D 150D A2 13 LDX #&13 150F A0 0D LDY #&0D 1511 20 6D 16 JSR &166D .MV8 1514 A5 70 LDA &70 1516 29 80 AND #&80 1518 85 AB STA &AB 151A A5 70 LDA &70 151C 29 7F AND #&7F 151E F0 1D BEQ &153D 1520 C9 7F CMP #&7F 1522 E9 00 SBC #&00 1524 05 AB ORA &AB 1526 85 70 STA &70 1528 A2 0F LDX #&0F 152A A0 15 LDY #&15 152C 20 6D 16 JSR &166D 152F A2 11 LDX #&11 1531 A0 17 LDY #&17 1533 20 6D 16 JSR &166D 1536 A2 13 LDX #&13 1538 A0 19 LDY #&19 153A 20 6D 16 JSR &166D .MV5 153D A5 72 LDA &72 153F 29 A0 AND #&A0 1541 D0 09 BNE &154C 1543 A5 72 LDA &72 1545 09 10 ORA #&10 1547 85 72 STA &72 1549 4C 20 2C JMP &2C20 .MVD1 154C A5 72 LDA &72 154E 29 EF AND #&EF 1550 85 72 STA &72 1552 60 RTS 1553 29 80 AND #&80 .MVT1 1555 0A ASL A 1556 85 92 STA &92 1558 A9 00 LDA #&00 155A 6A ROR A 155B 85 D1 STA &D1 155D 46 92 LSR &92 155F 55 55 EOR &55,X 1561 30 15 BMI &1578 1563 A5 91 LDA &91 1565 75 53 ADC &53,X 1567 95 53 STA &53,X 1569 A5 92 LDA &92 156B 75 54 ADC &54,X 156D 95 54 STA &54,X 156F B5 55 LDA &55,X 1571 69 00 ADC #&00 1573 05 D1 ORA &D1 1575 95 55 STA &55,X 1577 60 RTS .MV10 1578 B5 53 LDA &53,X 157A 38 SEC 157B E5 91 SBC &91 157D 95 53 STA &53,X 157F B5 54 LDA &54,X 1581 E5 92 SBC &92 1583 95 54 STA &54,X 1585 B5 55 LDA &55,X 1587 29 7F AND #&7F 1589 E9 00 SBC #&00 158B 09 80 ORA #&80 158D 45 D1 EOR &D1 158F 95 55 STA &55,X 1591 B0 16 BCS &15A9 1593 A9 01 LDA #&01 1595 F5 53 SBC &53,X 1597 95 53 STA &53,X 1599 A9 00 LDA #&00 159B F5 54 SBC &54,X 159D 95 54 STA &54,X 159F A9 00 LDA #&00 15A1 F5 55 SBC &55,X 15A3 29 7F AND #&7F 15A5 05 D1 ORA &D1 15A7 95 55 STA &55,X .MV11 15A9 60 RTS .MVT3 15AA A5 40 LDA &40 15AC 85 92 STA &92 15AE 29 80 AND #&80 15B0 85 D1 STA &D1 15B2 55 55 EOR &55,X 15B4 30 18 BMI &15CE 15B6 A5 3E LDA &3E 15B8 18 CLC 15B9 75 53 ADC &53,X 15BB 85 3E STA &3E 15BD A5 3F LDA &3F 15BF 75 54 ADC &54,X 15C1 85 3F STA &3F 15C3 A5 40 LDA &40 15C5 75 55 ADC &55,X 15C7 29 7F AND #&7F 15C9 05 D1 ORA &D1 15CB 85 40 STA &40 15CD 60 RTS .MV13 15CE A5 92 LDA &92 15D0 29 7F AND #&7F 15D2 85 92 STA &92 15D4 B5 53 LDA &53,X 15D6 38 SEC 15D7 E5 3E SBC &3E 15D9 85 3E STA &3E 15DB B5 54 LDA &54,X 15DD E5 3F SBC &3F 15DF 85 3F STA &3F 15E1 B5 55 LDA &55,X 15E3 29 7F AND #&7F 15E5 E5 92 SBC &92 15E7 09 80 ORA #&80 15E9 45 D1 EOR &D1 15EB 85 40 STA &40 15ED B0 16 BCS &1605 15EF A9 01 LDA #&01 15F1 E5 3E SBC &3E 15F3 85 3E STA &3E 15F5 A9 00 LDA #&00 15F7 E5 3F SBC &3F 15F9 85 3F STA &3F 15FB A9 00 LDA #&00 15FD E5 40 SBC &40 15FF 29 7F AND #&7F 1601 05 D1 ORA &D1 1603 85 40 STA &40 .MV14 1605 60 RTS .MVS4 1606 A5 9E LDA &9E 1608 85 90 STA &90 160A B6 55 LDX &55,Y 160C 86 91 STX &91 160E B6 56 LDX &56,Y 1610 86 92 STX &92 1612 B6 53 LDX &53,Y 1614 86 1B STX &1B 1616 B9 54 00 LDA &0054,Y 1619 49 80 EOR #&80 161B 20 5C 28 JSR &285C 161E 99 56 00 STA &0056,Y 1621 96 55 STX &55,Y 1623 86 1B STX &1B 1625 B6 53 LDX &53,Y 1627 86 91 STX &91 1629 B6 54 LDX &54,Y 162B 86 92 STX &92 162D B9 56 00 LDA &0056,Y 1630 20 5C 28 JSR &285C 1633 99 54 00 STA &0054,Y 1636 96 53 STX &53,Y 1638 86 1B STX &1B 163A A5 2A LDA &2A 163C 85 90 STA &90 163E B6 55 LDX &55,Y 1640 86 91 STX &91 1642 B6 56 LDX &56,Y 1644 86 92 STX &92 1646 B6 57 LDX &57,Y 1648 86 1B STX &1B 164A B9 58 00 LDA &0058,Y 164D 49 80 EOR #&80 164F 20 5C 28 JSR &285C 1652 99 56 00 STA &0056,Y 1655 96 55 STX &55,Y 1657 86 1B STX &1B 1659 B6 57 LDX &57,Y 165B 86 91 STX &91 165D B6 58 LDX &58,Y 165F 86 92 STX &92 1661 B9 56 00 LDA &0056,Y 1664 20 5C 28 JSR &285C 1667 99 58 00 STA &0058,Y 166A 96 57 STX &57,Y 166C 60 RTS .MVS5 166D B5 54 LDA &54,X 166F 29 7F AND #&7F 1671 4A LSR A 1672 85 D1 STA &D1 1674 B5 53 LDA &53,X 1676 38 SEC 1677 E5 D1 SBC &D1 1679 85 91 STA &91 167B B5 54 LDA &54,X 167D E9 00 SBC #&00 167F 85 92 STA &92 1681 B9 53 00 LDA &0053,Y 1684 85 1B STA &1B 1686 B9 54 00 LDA &0054,Y 1689 29 80 AND #&80 168B 85 D1 STA &D1 168D B9 54 00 LDA &0054,Y 1690 29 7F AND #&7F 1692 4A LSR A 1693 66 1B ROR &1B 1695 4A LSR A 1696 66 1B ROR &1B 1698 4A LSR A 1699 66 1B ROR &1B 169B 4A LSR A 169C 66 1B ROR &1B 169E 05 D1 ORA &D1 16A0 45 AB EOR &AB 16A2 86 90 STX &90 16A4 20 5F 28 JSR &285F 16A7 85 3E STA &3E 16A9 86 3D STX &3D 16AB A6 90 LDX &90 16AD B9 54 00 LDA &0054,Y 16B0 29 7F AND #&7F 16B2 4A LSR A 16B3 85 D1 STA &D1 16B5 B9 53 00 LDA &0053,Y 16B8 38 SEC 16B9 E5 D1 SBC &D1 16BB 85 91 STA &91 16BD B9 54 00 LDA &0054,Y 16C0 E9 00 SBC #&00 16C2 85 92 STA &92 16C4 B5 53 LDA &53,X 16C6 85 1B STA &1B 16C8 B5 54 LDA &54,X 16CA 29 80 AND #&80 16CC 85 D1 STA &D1 16CE B5 54 LDA &54,X 16D0 29 7F AND #&7F 16D2 4A LSR A 16D3 66 1B ROR &1B 16D5 4A LSR A 16D6 66 1B ROR &1B 16D8 4A LSR A 16D9 66 1B ROR &1B 16DB 4A LSR A 16DC 66 1B ROR &1B 16DE 05 D1 ORA &D1 16E0 49 80 EOR #&80 16E2 45 AB EOR &AB 16E4 86 90 STX &90 16E6 20 5F 28 JSR &285F 16E9 99 54 00 STA &0054,Y 16EC 96 53 STX &53,Y 16EE A6 90 LDX &90 16F0 A5 3D LDA &3D 16F2 95 53 STA &53,X 16F4 A5 3E LDA &3E 16F6 95 54 STA &54,X 16F8 60 RTS .MVT6 16F9 A8 TAY 16FA 55 55 EOR &55,X 16FC 30 0F BMI &170D 16FE A5 1C LDA &1C 1700 18 CLC 1701 75 53 ADC &53,X 1703 85 1C STA &1C 1705 A5 1D LDA &1D 1707 75 54 ADC &54,X 1709 85 1D STA &1D 170B 98 TYA 170C 60 RTS .MV50 170D B5 53 LDA &53,X 170F 38 SEC 1710 E5 1C SBC &1C 1712 85 1C STA &1C 1714 B5 54 LDA &54,X 1716 E5 1D SBC &1D 1718 85 1D STA &1D 171A 90 04 BCC &1720 171C 98 TYA 171D 49 80 EOR #&80 171F 60 RTS .MV51 1720 A9 01 LDA #&01 1722 E5 1C SBC &1C 1724 85 1C STA &1C 1726 A9 00 LDA #&00 1728 E5 1D SBC &1D 172A 85 1D STA &1D 172C 98 TYA 172D 60 RTS .MV40 172E A5 9E LDA &9E 1730 49 80 EOR #&80 1732 85 90 STA &90 1734 A5 53 LDA &53 1736 85 1B STA &1B 1738 A5 54 LDA &54 173A 85 1C STA &1C 173C A5 55 LDA &55 173E 20 E4 26 JSR &26E4 1741 A2 03 LDX #&03 1743 20 AA 15 JSR &15AA 1746 A5 3E LDA &3E 1748 85 AD STA &AD 174A 85 1B STA &1B 174C A5 3F LDA &3F 174E 85 AE STA &AE 1750 85 1C STA &1C 1752 A5 2A LDA &2A 1754 85 90 STA &90 1756 A5 40 LDA &40 1758 85 AF STA &AF 175A 20 E4 26 JSR &26E4 175D A2 06 LDX #&06 175F 20 AA 15 JSR &15AA 1762 A5 3E LDA &3E 1764 85 1B STA &1B 1766 85 59 STA &59 1768 A5 3F LDA &3F 176A 85 1C STA &1C 176C 85 5A STA &5A 176E A5 40 LDA &40 1770 85 5B STA &5B 1772 49 80 EOR #&80 1774 20 E4 26 JSR &26E4 1777 A5 40 LDA &40 1779 29 80 AND #&80 177B 85 D1 STA &D1 177D 45 AF EOR &AF 177F 30 17 BMI &1798 1781 A5 3D LDA &3D 1783 65 AC ADC &AC 1785 A5 3E LDA &3E 1787 65 AD ADC &AD 1789 85 56 STA &56 178B A5 3F LDA &3F 178D 65 AE ADC &AE 178F 85 57 STA &57 1791 A5 40 LDA &40 1793 65 AF ADC &AF 1795 4C CB 17 JMP &17CB .MV1 1798 A5 3D LDA &3D 179A 38 SEC 179B E5 AC SBC &AC 179D A5 3E LDA &3E 179F E5 AD SBC &AD 17A1 85 56 STA &56 17A3 A5 3F LDA &3F 17A5 E5 AE SBC &AE 17A7 85 57 STA &57 17A9 A5 AF LDA &AF 17AB 29 7F AND #&7F 17AD 85 1B STA &1B 17AF A5 40 LDA &40 17B1 29 7F AND #&7F 17B3 E5 1B SBC &1B 17B5 85 1B STA &1B 17B7 B0 12 BCS &17CB 17B9 A9 01 LDA #&01 17BB E5 56 SBC &56 17BD 85 56 STA &56 17BF A9 00 LDA #&00 17C1 E5 57 SBC &57 17C3 85 57 STA &57 17C5 A9 00 LDA #&00 17C7 E5 1B SBC &1B 17C9 09 80 ORA #&80 .MV2 17CB 45 D1 EOR &D1 17CD 85 58 STA &58 17CF A5 9E LDA &9E 17D1 85 90 STA &90 17D3 A5 56 LDA &56 17D5 85 1B STA &1B 17D7 A5 57 LDA &57 17D9 85 1C STA &1C 17DB A5 58 LDA &58 17DD 20 E4 26 JSR &26E4 17E0 A2 00 LDX #&00 17E2 20 AA 15 JSR &15AA 17E5 A5 3E LDA &3E 17E7 85 53 STA &53 17E9 A5 3F LDA &3F 17EB 85 54 STA &54 17ED A5 40 LDA &40 17EF 85 55 STA &55 17F1 4C C8 14 JMP &14C8 ELITE A Assembled at &F40 Ends at &17F4 Code size is &8B4 Execute at &1128 Reload at &1128 S.ELTA &F40 &17F4 &1128 &1128 Saving file '3-assembled-output/ELTA.bin' .NA% 17F4 4A 41 4D ... 17FB 0D 17FC 00 17FD 14 17FE AD 17FF 4A 5A 1801 48 02 1803 53 B7 1805 00 00 03 E8 1809 46 180A 00 180B 00 180C 0F 180D 00 180E 00 180F 00 1810 00 00 1812 16 1813 00 1814 00 1815 00 1816 00 1817 00 1818 00 1819 00 181A 00 181B 00 181C 00 181D 00 181E 00 181F 00 1820 00 1821 00 1822 00 1823 00 1824 00 1825 00 1826 00 1827 00 1828 00 1829 00 182A 00 182B 00 00 00 00 182F 03 1830 00 1831 10 1832 0F 1833 11 1834 00 1835 03 1836 1C 1837 0E 1838 00 1839 00 183A 0A 183B 00 183C 11 183D 3A 183E 07 183F 09 1840 08 1841 00 1842 00 1843 00 00 1845 80 .CHK2 1846 AA .CHK 1847 03 .UNIV 1848 00 09 184A 24 09 184C 48 09 184E 6C 09 1850 90 09 1852 B4 09 1854 D8 09 1856 FC 09 1858 20 0A 185A 44 0A 185C 68 0A 185E 8C 0A 1860 B0 0A .TWOS 1862 80 1863 40 1864 20 1865 10 1866 08 1867 04 1868 02 1869 01 .TWOS2 186A C0 186B 60 186C 30 186D 18 186E 0C 186F 06 1870 03 1871 03 .CTWOS 1872 88 1873 44 1874 22 1875 11 1876 88 .LL30 1877 .LOIN 1877 84 94 STY &94 1879 A9 80 LDA #&80 187B 85 92 STA &92 187D 0A ASL A 187E 85 A1 STA &A1 1880 A5 33 LDA &33 1882 E5 31 SBC &31 1884 B0 05 BCS &188B 1886 49 FF EOR #&FF 1888 69 01 ADC #&01 188A 38 SEC .LI1 188B 85 1B STA &1B 188D A5 34 LDA &34 188F E5 32 SBC &32 1891 B0 04 BCS &1897 1893 49 FF EOR #&FF 1895 69 01 ADC #&01 .LI2 1897 85 90 STA &90 1899 C5 1B CMP &1B 189B 90 03 BCC &18A0 189D 4C 4A 19 JMP &194A .STPX 18A0 A6 31 LDX &31 18A2 E4 33 CPX &33 18A4 90 11 BCC &18B7 18A6 C6 A1 DEC &A1 18A8 A5 33 LDA &33 18AA 85 31 STA &31 18AC 86 33 STX &33 18AE AA TAX 18AF A5 34 LDA &34 18B1 A4 32 LDY &32 18B3 85 32 STA &32 18B5 84 34 STY &34 .LI3 18B7 A5 32 LDA &32 18B9 4A LSR A 18BA 4A LSR A 18BB 4A LSR A 18BC 09 60 ORA #&60 18BE 85 08 STA &08 18C0 A5 32 LDA &32 18C2 29 07 AND #&07 18C4 A8 TAY 18C5 8A TXA 18C6 29 F8 AND #&F8 18C8 85 07 STA &07 18CA 8A TXA 18CB 29 07 AND #&07 18CD AA TAX 18CE BD 62 18 LDA &1862,X 18D1 85 91 STA &91 18D3 A5 90 LDA &90 18D5 A2 FE LDX #&FE 18D7 86 90 STX &90 .LIL1 18D9 0A ASL A 18DA B0 04 BCS &18E0 18DC C5 1B CMP &1B 18DE 90 03 BCC &18E3 .LI4 18E0 E5 1B SBC &1B 18E2 38 SEC .LI5 18E3 26 90 ROL &90 18E5 B0 F2 BCS &18D9 18E7 A6 1B LDX &1B 18E9 E8 INX 18EA A5 34 LDA &34 18EC E5 32 SBC &32 18EE B0 2C BCS &191C 18F0 A5 A1 LDA &A1 18F2 D0 07 BNE &18FB 18F4 CA DEX .LIL2 18F5 A5 91 LDA &91 18F7 51 07 EOR (&07),Y 18F9 91 07 STA (&07),Y .LI6 18FB 46 91 LSR &91 18FD 90 08 BCC &1907 18FF 66 91 ROR &91 1901 A5 07 LDA &07 1903 69 08 ADC #&08 1905 85 07 STA &07 .LI7 1907 A5 92 LDA &92 1909 65 90 ADC &90 190B 85 92 STA &92 190D 90 07 BCC &1916 190F 88 DEY 1910 10 04 BPL &1916 1912 C6 08 DEC &08 1914 A0 07 LDY #&07 .LIC2 1916 CA DEX 1917 D0 DC BNE &18F5 1919 A4 94 LDY &94 191B 60 RTS .DOWN 191C A5 A1 LDA &A1 191E F0 07 BEQ &1927 1920 CA DEX .LIL3 1921 A5 91 LDA &91 1923 51 07 EOR (&07),Y 1925 91 07 STA (&07),Y .LI9 1927 46 91 LSR &91 1929 90 08 BCC &1933 192B 66 91 ROR &91 192D A5 07 LDA &07 192F 69 08 ADC #&08 1931 85 07 STA &07 .LI10 1933 A5 92 LDA &92 1935 65 90 ADC &90 1937 85 92 STA &92 1939 90 09 BCC &1944 193B C8 INY 193C C0 08 CPY #&08 193E D0 04 BNE &1944 1940 E6 08 INC &08 1942 A0 00 LDY #&00 .LIC3 1944 CA DEX 1945 D0 DA BNE &1921 1947 A4 94 LDY &94 1949 60 RTS .STPY 194A A4 32 LDY &32 194C 98 TYA 194D A6 31 LDX &31 194F C4 34 CPY &34 1951 B0 10 BCS &1963 1953 C6 A1 DEC &A1 1955 A5 33 LDA &33 1957 85 31 STA &31 1959 86 33 STX &33 195B AA TAX 195C A5 34 LDA &34 195E 85 32 STA &32 1960 84 34 STY &34 1962 A8 TAY .LI15 1963 4A LSR A 1964 4A LSR A 1965 4A LSR A 1966 09 60 ORA #&60 1968 85 08 STA &08 196A 8A TXA 196B 29 F8 AND #&F8 196D 85 07 STA &07 196F 8A TXA 1970 29 07 AND #&07 1972 AA TAX 1973 BD 62 18 LDA &1862,X 1976 85 91 STA &91 1978 A5 32 LDA &32 197A 29 07 AND #&07 197C A8 TAY 197D A5 1B LDA &1B 197F A2 01 LDX #&01 1981 86 1B STX &1B .LIL4 1983 0A ASL A 1984 B0 04 BCS &198A 1986 C5 90 CMP &90 1988 90 03 BCC &198D .LI13 198A E5 90 SBC &90 198C 38 SEC .LI14 198D 26 1B ROL &1B 198F 90 F2 BCC &1983 1991 A6 90 LDX &90 1993 E8 INX 1994 A5 33 LDA &33 1996 E5 31 SBC &31 1998 90 2D BCC &19C7 199A 18 CLC 199B A5 A1 LDA &A1 199D F0 07 BEQ &19A6 199F CA DEX .LIL5 19A0 A5 91 LDA &91 19A2 51 07 EOR (&07),Y 19A4 91 07 STA (&07),Y .LI17 19A6 88 DEY 19A7 10 04 BPL &19AD 19A9 C6 08 DEC &08 19AB A0 07 LDY #&07 .LI16 19AD A5 92 LDA &92 19AF 65 1B ADC &1B 19B1 85 92 STA &92 19B3 90 0C BCC &19C1 19B5 46 91 LSR &91 19B7 90 08 BCC &19C1 19B9 66 91 ROR &91 19BB A5 07 LDA &07 19BD 69 08 ADC #&08 19BF 85 07 STA &07 .LIC5 19C1 CA DEX 19C2 D0 DC BNE &19A0 19C4 A4 94 LDY &94 19C6 60 RTS .LFT 19C7 A5 A1 LDA &A1 19C9 F0 07 BEQ &19D2 19CB CA DEX .LIL6 19CC A5 91 LDA &91 19CE 51 07 EOR (&07),Y 19D0 91 07 STA (&07),Y .LI18 19D2 88 DEY 19D3 10 04 BPL &19D9 19D5 C6 08 DEC &08 19D7 A0 07 LDY #&07 .LI19 19D9 A5 92 LDA &92 19DB 65 1B ADC &1B 19DD 85 92 STA &92 19DF 90 0D BCC &19EE 19E1 06 91 ASL &91 19E3 90 09 BCC &19EE 19E5 26 91 ROL &91 19E7 A5 07 LDA &07 19E9 E9 07 SBC #&07 19EB 85 07 STA &07 19ED 18 CLC .LIC6 19EE CA DEX 19EF D0 DB BNE &19CC 19F1 A4 94 LDY &94 .HL6 19F3 60 RTS .NLIN3 19F4 20 B6 38 JSR &38B6 .NLIN4 19F7 A9 13 LDA #&13 19F9 D0 04 BNE &19FF .NLIN 19FB A9 17 LDA #&17 19FD E6 2D INC &2D .NLIN2 19FF 85 32 STA &32 1A01 A2 02 LDX #&02 1A03 86 31 STX &31 1A05 A2 FE LDX #&FE 1A07 86 33 STX &33 1A09 D0 0A BNE &1A15 .HLOIN2 1A0B 20 55 41 JSR &4155 1A0E 84 32 STY &32 1A10 A9 00 LDA #&00 1A12 99 66 0D STA &0D66,Y .HLOIN 1A15 84 94 STY &94 1A17 A6 31 LDX &31 1A19 E4 33 CPX &33 1A1B F0 D6 BEQ &19F3 1A1D 90 07 BCC &1A26 1A1F A5 33 LDA &33 1A21 85 31 STA &31 1A23 86 33 STX &33 1A25 AA TAX .HL5 1A26 C6 33 DEC &33 1A28 A5 32 LDA &32 1A2A 4A LSR A 1A2B 4A LSR A 1A2C 4A LSR A 1A2D 09 60 ORA #&60 1A2F 85 08 STA &08 1A31 A5 32 LDA &32 1A33 29 07 AND #&07 1A35 85 07 STA &07 1A37 8A TXA 1A38 29 F8 AND #&F8 1A3A A8 TAY .HL1 1A3B 8A TXA 1A3C 29 F8 AND #&F8 1A3E 85 D1 STA &D1 1A40 A5 33 LDA &33 1A42 29 F8 AND #&F8 1A44 38 SEC 1A45 E5 D1 SBC &D1 1A47 F0 37 BEQ &1A80 1A49 4A LSR A 1A4A 4A LSR A 1A4B 4A LSR A 1A4C 85 91 STA &91 1A4E A5 31 LDA &31 1A50 29 07 AND #&07 1A52 AA TAX 1A53 BD A2 1A LDA &1AA2,X 1A56 51 07 EOR (&07),Y 1A58 91 07 STA (&07),Y 1A5A 98 TYA 1A5B 69 08 ADC #&08 1A5D A8 TAY 1A5E A6 91 LDX &91 1A60 CA DEX 1A61 F0 0E BEQ &1A71 1A63 18 CLC .HLL1 1A64 A9 FF LDA #&FF 1A66 51 07 EOR (&07),Y 1A68 91 07 STA (&07),Y 1A6A 98 TYA 1A6B 69 08 ADC #&08 1A6D A8 TAY 1A6E CA DEX 1A6F D0 F3 BNE &1A64 .HL3 1A71 A5 33 LDA &33 1A73 29 07 AND #&07 1A75 AA TAX 1A76 BD 9B 1A LDA &1A9B,X 1A79 51 07 EOR (&07),Y 1A7B 91 07 STA (&07),Y 1A7D A4 94 LDY &94 1A7F 60 RTS .HL2 1A80 A5 31 LDA &31 1A82 29 07 AND #&07 1A84 AA TAX 1A85 BD A2 1A LDA &1AA2,X 1A88 85 D1 STA &D1 1A8A A5 33 LDA &33 1A8C 29 07 AND #&07 1A8E AA TAX 1A8F BD 9B 1A LDA &1A9B,X 1A92 25 D1 AND &D1 1A94 51 07 EOR (&07),Y 1A96 91 07 STA (&07),Y 1A98 A4 94 LDY &94 1A9A 60 RTS .TWFL 1A9B 80 1A9C C0 1A9D E0 1A9E F0 1A9F F8 1AA0 FC 1AA1 FE .TWFR 1AA2 FF 1AA3 7F 1AA4 3F 1AA5 1F 1AA6 0F 1AA7 07 1AA8 03 1AA9 01 .PX3 1AAA BD 62 18 LDA &1862,X 1AAD 51 07 EOR (&07),Y 1AAF 91 07 STA (&07),Y 1AB1 A4 06 LDY &06 1AB3 60 RTS .PIX1 1AB4 20 5F 28 JSR &285F 1AB7 85 27 STA &27 1AB9 8A TXA 1ABA 99 D5 0E STA &0ED5,Y .PIXEL2 1ABD A5 31 LDA &31 1ABF 10 05 BPL &1AC6 1AC1 49 7F EOR #&7F 1AC3 18 CLC 1AC4 69 01 ADC #&01 .PX1 1AC6 49 80 EOR #&80 1AC8 AA TAX 1AC9 A5 32 LDA &32 1ACB 29 7F AND #&7F 1ACD C9 60 CMP #&60 1ACF B0 46 BCS &1B17 1AD1 A5 32 LDA &32 1AD3 10 04 BPL &1AD9 1AD5 49 7F EOR #&7F 1AD7 69 01 ADC #&01 .PX2 1AD9 85 D1 STA &D1 1ADB A9 61 LDA #&61 1ADD E5 D1 SBC &D1 .PIXEL 1ADF 84 06 STY &06 1AE1 A8 TAY 1AE2 4A LSR A 1AE3 4A LSR A 1AE4 4A LSR A 1AE5 09 60 ORA #&60 1AE7 85 08 STA &08 1AE9 8A TXA 1AEA 29 F8 AND #&F8 1AEC 85 07 STA &07 1AEE 98 TYA 1AEF 29 07 AND #&07 1AF1 A8 TAY 1AF2 8A TXA 1AF3 29 07 AND #&07 1AF5 AA TAX 1AF6 A5 97 LDA &97 1AF8 C9 90 CMP #&90 1AFA B0 AE BCS &1AAA 1AFC BD 6A 18 LDA &186A,X 1AFF 51 07 EOR (&07),Y 1B01 91 07 STA (&07),Y 1B03 A5 97 LDA &97 1B05 C9 50 CMP #&50 1B07 B0 0C BCS &1B15 1B09 88 DEY 1B0A 10 02 BPL &1B0E 1B0C A0 01 LDY #&01 .PX14 1B0E BD 6A 18 LDA &186A,X 1B11 51 07 EOR (&07),Y 1B13 91 07 STA (&07),Y .PX13 1B15 A4 06 LDY &06 .PX4 1B17 60 RTS .BLINE 1B18 8A TXA 1B19 65 E0 ADC &E0 1B1B 85 84 STA &84 1B1D A5 E1 LDA &E1 1B1F 65 D1 ADC &D1 1B21 85 85 STA &85 1B23 A5 A3 LDA &A3 1B25 F0 12 BEQ &1B39 1B27 E6 A3 INC &A3 .BL5 1B29 A4 77 LDY &77 1B2B A9 FF LDA #&FF 1B2D D9 73 0E CMP &0E73,Y 1B30 F0 68 BEQ &1B9A 1B32 99 74 0E STA &0E74,Y 1B35 E6 77 INC &77 1B37 D0 61 BNE &1B9A .BL1 1B39 A5 7E LDA &7E 1B3B 85 31 STA &31 1B3D A5 7F LDA &7F 1B3F 85 32 STA &32 1B41 A5 80 LDA &80 1B43 85 33 STA &33 1B45 A5 81 LDA &81 1B47 85 34 STA &34 1B49 A5 82 LDA &82 1B4B 85 35 STA &35 1B4D A5 83 LDA &83 1B4F 85 36 STA &36 1B51 A5 84 LDA &84 1B53 85 37 STA &37 1B55 A5 85 LDA &85 1B57 85 38 STA &38 1B59 20 13 55 JSR &5513 1B5C B0 CB BCS &1B29 1B5E A5 A1 LDA &A1 1B60 F0 10 BEQ &1B72 1B62 A5 31 LDA &31 1B64 A4 33 LDY &33 1B66 85 33 STA &33 1B68 84 31 STY &31 1B6A A5 32 LDA &32 1B6C A4 34 LDY &34 1B6E 85 34 STA &34 1B70 84 32 STY &32 .BL9 1B72 A4 77 LDY &77 1B74 B9 73 0E LDA &0E73,Y 1B77 C9 FF CMP #&FF 1B79 D0 0B BNE &1B86 1B7B A5 31 LDA &31 1B7D 99 26 0E STA &0E26,Y 1B80 A5 32 LDA &32 1B82 99 74 0E STA &0E74,Y 1B85 C8 INY .BL8 1B86 A5 33 LDA &33 1B88 99 26 0E STA &0E26,Y 1B8B A5 34 LDA &34 1B8D 99 74 0E STA &0E74,Y 1B90 C8 INY 1B91 84 77 STY &77 1B93 20 77 18 JSR &1877 1B96 A5 98 LDA &98 1B98 D0 8F BNE &1B29 .BL7 1B9A A5 82 LDA &82 1B9C 85 7E STA &7E 1B9E A5 83 LDA &83 1BA0 85 7F STA &7F 1BA2 A5 84 LDA &84 1BA4 85 80 STA &80 1BA6 A5 85 LDA &85 1BA8 85 81 STA &81 1BAA A5 A4 LDA &A4 1BAC 18 CLC 1BAD 65 A6 ADC &A6 1BAF 85 A4 STA &A4 1BB1 60 RTS .FLIP 1BB2 AC 33 0F LDY &0F33 .FLL1 1BB5 BE C2 0E LDX &0EC2,Y 1BB8 B9 4C 03 LDA &034C,Y 1BBB 85 32 STA &32 1BBD 99 C2 0E STA &0EC2,Y 1BC0 8A TXA 1BC1 85 31 STA &31 1BC3 99 4C 03 STA &034C,Y 1BC6 B9 E8 0E LDA &0EE8,Y 1BC9 85 97 STA &97 1BCB 20 BD 1A JSR &1ABD 1BCE 88 DEY 1BCF D0 E4 BNE &1BB5 1BD1 60 RTS .STARS 1BD2 AE 5F 0D LDX &0D5F 1BD5 F0 09 BEQ &1BE0 1BD7 CA DEX 1BD8 D0 03 BNE &1BDD 1BDA 4C CD 1C JMP &1CCD .ST11 1BDD 4C BB 25 JMP &25BB .STARS1 1BE0 AC 33 0F LDY &0F33 .STL1 1BE3 20 BE 28 JSR &28BE 1BE6 A5 91 LDA &91 1BE8 46 1B LSR &1B 1BEA 6A ROR A 1BEB 46 1B LSR &1B 1BED 6A ROR A 1BEE 09 01 ORA #&01 1BF0 85 90 STA &90 1BF2 B9 FB 0E LDA &0EFB,Y 1BF5 E5 8D SBC &8D 1BF7 99 FB 0E STA &0EFB,Y 1BFA B9 E8 0E LDA &0EE8,Y 1BFD 85 97 STA &97 1BFF E5 8E SBC &8E 1C01 99 E8 0E STA &0EE8,Y 1C04 20 79 27 JSR &2779 1C07 85 27 STA &27 1C09 A5 1B LDA &1B 1C0B 79 D5 0E ADC &0ED5,Y 1C0E 85 26 STA &26 1C10 85 91 STA &91 1C12 A5 32 LDA &32 1C14 65 27 ADC &27 1C16 85 27 STA &27 1C18 85 92 STA &92 1C1A B9 4C 03 LDA &034C,Y 1C1D 85 31 STA &31 1C1F 20 7E 27 JSR &277E 1C22 85 25 STA &25 1C24 A5 1B LDA &1B 1C26 79 5F 03 ADC &035F,Y 1C29 85 24 STA &24 1C2B A5 31 LDA &31 1C2D 65 25 ADC &25 1C2F 85 25 STA &25 1C31 45 89 EOR &89 1C33 20 28 27 JSR &2728 1C36 20 5F 28 JSR &285F 1C39 85 27 STA &27 1C3B 86 26 STX &26 1C3D 45 88 EOR &88 1C3F 20 20 27 JSR &2720 1C42 20 5F 28 JSR &285F 1C45 85 25 STA &25 1C47 86 24 STX &24 1C49 A6 2B LDX &2B 1C4B A5 27 LDA &27 1C4D 45 8B EOR &8B 1C4F 20 2A 27 JSR &272A 1C52 85 90 STA &90 1C54 20 00 28 JSR &2800 1C57 06 1B ASL &1B 1C59 2A ROL A 1C5A 85 D1 STA &D1 1C5C A9 00 LDA #&00 1C5E 6A ROR A 1C5F 05 D1 ORA &D1 1C61 20 5F 28 JSR &285F 1C64 85 25 STA &25 1C66 8A TXA 1C67 99 5F 03 STA &035F,Y 1C6A A5 26 LDA &26 1C6C 85 91 STA &91 1C6E A5 27 LDA &27 1C70 85 92 STA &92 1C72 A9 00 LDA #&00 1C74 85 1B STA &1B 1C76 A5 2A LDA &2A 1C78 49 80 EOR #&80 1C7A 20 B4 1A JSR &1AB4 1C7D A5 25 LDA &25 1C7F 85 31 STA &31 1C81 99 4C 03 STA &034C,Y 1C84 29 7F AND #&7F 1C86 C9 78 CMP #&78 1C88 B0 20 BCS &1CAA 1C8A A5 27 LDA &27 1C8C 99 C2 0E STA &0EC2,Y 1C8F 85 32 STA &32 1C91 29 7F AND #&7F 1C93 C9 78 CMP #&78 1C95 B0 13 BCS &1CAA 1C97 B9 E8 0E LDA &0EE8,Y 1C9A C9 10 CMP #&10 1C9C 90 0C BCC &1CAA 1C9E 85 97 STA &97 .STC1 1CA0 20 BD 1A JSR &1ABD 1CA3 88 DEY 1CA4 F0 03 BEQ &1CA9 1CA6 4C E3 1B JMP &1BE3 1CA9 60 RTS .KILL1 1CAA 20 57 44 JSR &4457 1CAD 09 04 ORA #&04 1CAF 85 32 STA &32 1CB1 99 C2 0E STA &0EC2,Y 1CB4 20 57 44 JSR &4457 1CB7 09 08 ORA #&08 1CB9 85 31 STA &31 1CBB 99 4C 03 STA &034C,Y 1CBE 20 57 44 JSR &4457 1CC1 09 90 ORA #&90 1CC3 99 E8 0E STA &0EE8,Y 1CC6 85 97 STA &97 1CC8 A5 32 LDA &32 1CCA 4C A0 1C JMP &1CA0 .STARS6 1CCD AC 33 0F LDY &0F33 .STL6 1CD0 20 BE 28 JSR &28BE 1CD3 A5 91 LDA &91 1CD5 46 1B LSR &1B 1CD7 6A ROR A 1CD8 46 1B LSR &1B 1CDA 6A ROR A 1CDB 09 01 ORA #&01 1CDD 85 90 STA &90 1CDF B9 4C 03 LDA &034C,Y 1CE2 85 31 STA &31 1CE4 20 7E 27 JSR &277E 1CE7 85 25 STA &25 1CE9 B9 5F 03 LDA &035F,Y 1CEC E5 1B SBC &1B 1CEE 85 24 STA &24 1CF0 A5 31 LDA &31 1CF2 E5 25 SBC &25 1CF4 85 25 STA &25 1CF6 20 79 27 JSR &2779 1CF9 85 27 STA &27 1CFB B9 D5 0E LDA &0ED5,Y 1CFE E5 1B SBC &1B 1D00 85 26 STA &26 1D02 85 91 STA &91 1D04 A5 32 LDA &32 1D06 E5 27 SBC &27 1D08 85 27 STA &27 1D0A 85 92 STA &92 1D0C B9 FB 0E LDA &0EFB,Y 1D0F 65 8D ADC &8D 1D11 99 FB 0E STA &0EFB,Y 1D14 B9 E8 0E LDA &0EE8,Y 1D17 85 97 STA &97 1D19 65 8E ADC &8E 1D1B 99 E8 0E STA &0EE8,Y 1D1E A5 25 LDA &25 1D20 45 88 EOR &88 1D22 20 28 27 JSR &2728 1D25 20 5F 28 JSR &285F 1D28 85 27 STA &27 1D2A 86 26 STX &26 1D2C 45 89 EOR &89 1D2E 20 20 27 JSR &2720 1D31 20 5F 28 JSR &285F 1D34 85 25 STA &25 1D36 86 24 STX &24 1D38 A5 27 LDA &27 1D3A 45 8B EOR &8B 1D3C A6 2B LDX &2B 1D3E 20 2A 27 JSR &272A 1D41 85 90 STA &90 1D43 A5 25 LDA &25 1D45 85 92 STA &92 1D47 49 80 EOR #&80 1D49 20 04 28 JSR &2804 1D4C 06 1B ASL &1B 1D4E 2A ROL A 1D4F 85 D1 STA &D1 1D51 A9 00 LDA #&00 1D53 6A ROR A 1D54 05 D1 ORA &D1 1D56 20 5F 28 JSR &285F 1D59 85 25 STA &25 1D5B 8A TXA 1D5C 99 5F 03 STA &035F,Y 1D5F A5 26 LDA &26 1D61 85 91 STA &91 1D63 A5 27 LDA &27 1D65 85 92 STA &92 1D67 A9 00 LDA #&00 1D69 85 1B STA &1B 1D6B A5 2A LDA &2A 1D6D 20 B4 1A JSR &1AB4 1D70 A5 25 LDA &25 1D72 85 31 STA &31 1D74 99 4C 03 STA &034C,Y 1D77 A5 27 LDA &27 1D79 99 C2 0E STA &0EC2,Y 1D7C 85 32 STA &32 1D7E 29 7F AND #&7F 1D80 C9 6E CMP #&6E 1D82 B0 13 BCS &1D97 1D84 B9 E8 0E LDA &0EE8,Y 1D87 C9 A0 CMP #&A0 1D89 B0 0C BCS &1D97 1D8B 85 97 STA &97 .STC6 1D8D 20 BD 1A JSR &1ABD 1D90 88 DEY 1D91 F0 03 BEQ &1D96 1D93 4C D0 1C JMP &1CD0 .ST3 1D96 60 RTS .KILL6 1D97 20 57 44 JSR &4457 1D9A 29 7F AND #&7F 1D9C 69 0A ADC #&0A 1D9E 99 E8 0E STA &0EE8,Y 1DA1 85 97 STA &97 1DA3 4A LSR A 1DA4 B0 14 BCS &1DBA 1DA6 4A LSR A 1DA7 A9 FC LDA #&FC 1DA9 6A ROR A 1DAA 85 31 STA &31 1DAC 99 4C 03 STA &034C,Y 1DAF 20 57 44 JSR &4457 1DB2 85 32 STA &32 1DB4 99 C2 0E STA &0EC2,Y 1DB7 4C 8D 1D JMP &1D8D .ST4 1DBA 20 57 44 JSR &4457 1DBD 85 31 STA &31 1DBF 99 4C 03 STA &034C,Y 1DC2 4A LSR A 1DC3 A9 E6 LDA #&E6 1DC5 6A ROR A 1DC6 85 32 STA &32 1DC8 99 C2 0E STA &0EC2,Y 1DCB D0 C0 BNE &1D8D .PRXS 1DCD 01 00 1DCF 2C 01 1DD1 A0 0F 1DD3 70 17 1DD5 A0 0F 1DD7 10 27 1DD9 82 14 1DDB 10 27 1DDD 28 23 1DDF 98 3A 1DE1 10 27 1DE3 50 C3 .st4 1DE5 A2 09 LDX #&09 1DE7 C9 19 CMP #&19 1DE9 B0 5F BCS &1E4A 1DEB CA DEX 1DEC C9 0A CMP #&0A 1DEE B0 5A BCS &1E4A 1DF0 CA DEX 1DF1 C9 02 CMP #&02 1DF3 B0 55 BCS &1E4A 1DF5 CA DEX 1DF6 D0 52 BNE &1E4A .STATUS 1DF8 A9 08 LDA #&08 1DFA 20 7B 2B JSR &2B7B 1DFD 20 A4 32 JSR &32A4 1E00 A9 07 LDA #&07 1E02 85 2C STA &2C 1E04 A9 7E LDA #&7E 1E06 20 F4 19 JSR &19F4 1E09 A9 0F LDA #&0F 1E0B A4 9F LDY &9F 1E0D D0 11 BNE &1E20 1E0F A9 E6 LDA #&E6 1E11 AC 57 0D LDY &0D57 1E14 BE 42 0D LDX &0D42,Y 1E17 F0 07 BEQ &1E20 1E19 AC 13 0F LDY &0F13 1E1C C0 80 CPY #&80 1E1E 69 01 ADC #&01 .st6 1E20 20 AB 38 JSR &38AB 1E23 A9 7D LDA #&7D 1E25 20 44 2D JSR &2D44 1E28 A9 13 LDA #&13 1E2A AC 34 03 LDY &0334 1E2D F0 04 BEQ &1E33 1E2F C0 32 CPY #&32 1E31 69 01 ADC #&01 .st5 1E33 20 AB 38 JSR &38AB 1E36 A9 10 LDA #&10 1E38 20 44 2D JSR &2D44 1E3B AD 48 03 LDA &0348 1E3E D0 A5 BNE &1DE5 1E40 AA TAX 1E41 AD 47 03 LDA &0347 1E44 4A LSR A 1E45 4A LSR A .st5L 1E46 E8 INX 1E47 4A LSR A 1E48 D0 FC BNE &1E46 .st3 1E4A 8A TXA 1E4B 18 CLC 1E4C 69 15 ADC #&15 1E4E 20 AB 38 JSR &38AB 1E51 A9 12 LDA #&12 1E53 20 B1 1E JSR &1EB1 1E56 AD 16 03 LDA &0316 1E59 C9 1A CMP #&1A 1E5B 90 05 BCC &1E62 1E5D A9 6B LDA #&6B 1E5F 20 B1 1E JSR &1EB1 1E62 AD 29 03 LDA &0329 1E65 F0 05 BEQ &1E6C 1E67 A9 6F LDA #&6F 1E69 20 B1 1E JSR &1EB1 1E6C AD 28 03 LDA &0328 1E6F F0 05 BEQ &1E76 1E71 A9 6C LDA #&6C 1E73 20 B1 1E JSR &1EB1 1E76 A9 71 LDA #&71 1E78 85 A7 STA &A7 .stqv 1E7A A8 TAY 1E7B BE B9 02 LDX &02B9,Y 1E7E F0 03 BEQ &1E83 1E80 20 B1 1E JSR &1EB1 1E83 E6 A7 INC &A7 1E85 A5 A7 LDA &A7 1E87 C9 75 CMP #&75 1E89 90 EF BCC &1E7A 1E8B A2 00 LDX #&00 .st 1E8D 86 A4 STX &A4 1E8F BC 10 03 LDY &0310,X 1E92 F0 15 BEQ &1EA9 1E94 8A TXA 1E95 18 CLC 1E96 69 60 ADC #&60 1E98 20 44 2D JSR &2D44 1E9B A9 67 LDA #&67 1E9D A6 A4 LDX &A4 1E9F BC 10 03 LDY &0310,X 1EA2 10 02 BPL &1EA6 1EA4 A9 68 LDA #&68 1EA6 20 B1 1E JSR &1EB1 .st1 1EA9 A6 A4 LDX &A4 1EAB E8 INX 1EAC E0 04 CPX #&04 1EAE 90 DD BCC &1E8D 1EB0 60 RTS .plf2 1EB1 20 AB 38 JSR &38AB 1EB4 A2 06 LDX #&06 1EB6 86 2C STX &2C 1EB8 60 RTS .TENS 1EB9 48 76 E8 00 .pr2 1EBD A9 03 LDA #&03 1EBF A0 00 LDY #&00 .TT11 1EC1 85 8F STA &8F 1EC3 A9 00 LDA #&00 1EC5 85 3D STA &3D 1EC7 85 3E STA &3E 1EC9 84 3F STY &3F 1ECB 86 40 STX &40 .BPRNT 1ECD A2 0B LDX #&0B 1ECF 86 D1 STX &D1 1ED1 08 PHP 1ED2 90 04 BCC &1ED8 1ED4 C6 D1 DEC &D1 1ED6 C6 8F DEC &8F .TT30 1ED8 A9 0B LDA #&0B 1EDA 38 SEC 1EDB 85 95 STA &95 1EDD E5 8F SBC &8F 1EDF 85 8F STA &8F 1EE1 E6 8F INC &8F 1EE3 A0 00 LDY #&00 1EE5 84 92 STY &92 1EE7 4C 29 1F JMP &1F29 .TT35 1EEA 06 40 ASL &40 1EEC 26 3F ROL &3F 1EEE 26 3E ROL &3E 1EF0 26 3D ROL &3D 1EF2 26 92 ROL &92 1EF4 A2 03 LDX #&03 .tt35 1EF6 B5 3D LDA &3D,X 1EF8 95 31 STA &31,X 1EFA CA DEX 1EFB 10 F9 BPL &1EF6 1EFD A5 92 LDA &92 1EFF 85 35 STA &35 1F01 06 40 ASL &40 1F03 26 3F ROL &3F 1F05 26 3E ROL &3E 1F07 26 3D ROL &3D 1F09 26 92 ROL &92 1F0B 06 40 ASL &40 1F0D 26 3F ROL &3F 1F0F 26 3E ROL &3E 1F11 26 3D ROL &3D 1F13 26 92 ROL &92 1F15 18 CLC 1F16 A2 03 LDX #&03 .tt36 1F18 B5 3D LDA &3D,X 1F1A 75 31 ADC &31,X 1F1C 95 3D STA &3D,X 1F1E CA DEX 1F1F 10 F7 BPL &1F18 1F21 A5 35 LDA &35 1F23 65 92 ADC &92 1F25 85 92 STA &92 1F27 A0 00 LDY #&00 .TT36 1F29 A2 03 LDX #&03 1F2B 38 SEC .tt37 1F2C B5 3D LDA &3D,X 1F2E FD B9 1E SBC &1EB9,X 1F31 95 31 STA &31,X 1F33 CA DEX 1F34 10 F6 BPL &1F2C 1F36 A5 92 LDA &92 1F38 E9 17 SBC #&17 1F3A 85 35 STA &35 1F3C 90 11 BCC &1F4F 1F3E A2 03 LDX #&03 .tt38 1F40 B5 31 LDA &31,X 1F42 95 3D STA &3D,X 1F44 CA DEX 1F45 10 F9 BPL &1F40 1F47 A5 35 LDA &35 1F49 85 92 STA &92 1F4B C8 INY 1F4C 4C 29 1F JMP &1F29 .TT37 1F4F 98 TYA 1F50 D0 0C BNE &1F5E 1F52 A5 D1 LDA &D1 1F54 F0 08 BEQ &1F5E 1F56 C6 8F DEC &8F 1F58 10 0E BPL &1F68 1F5A A9 20 LDA #&20 1F5C D0 07 BNE &1F65 .TT32 1F5E A0 00 LDY #&00 1F60 84 D1 STY &D1 1F62 18 CLC 1F63 69 30 ADC #&30 .tt34 1F65 20 81 1F JSR &1F81 .TT34 1F68 C6 D1 DEC &D1 1F6A 10 02 BPL &1F6E 1F6C E6 D1 INC &D1 1F6E C6 95 DEC &95 1F70 30 68 BMI &1FDA 1F72 D0 08 BNE &1F7C 1F74 28 PLP 1F75 90 05 BCC &1F7C 1F77 A9 2E LDA #&2E 1F79 20 81 1F JSR &1F81 1F7C 4C EA 1E JMP &1EEA .BELL 1F7F A9 07 LDA #&07 .TT26 1F81 85 D2 STA &D2 1F83 8C 0F 0F STY &0F0F 1F86 8E 0E 0F STX &0F0E 1F89 A4 7E LDY &7E 1F8B C0 FF CPY #&FF 1F8D F0 59 BEQ &1FE8 1F8F C9 07 CMP #&07 1F91 F0 5F BEQ &1FF2 1F93 C9 20 CMP #&20 1F95 B0 0C BCS &1FA3 1F97 C9 0A CMP #&0A 1F99 F0 04 BEQ &1F9F 1F9B A2 01 LDX #&01 1F9D 86 2C STX &2C .RRX1 1F9F E6 2D INC &2D 1FA1 D0 45 BNE &1FE8 .RR1 1FA3 A8 TAY 1FA4 A2 BF LDX #&BF 1FA6 0A ASL A 1FA7 0A ASL A 1FA8 90 02 BCC &1FAC 1FAA A2 C1 LDX #&C1 1FAC 0A ASL A 1FAD 90 01 BCC &1FB0 1FAF E8 INX 1FB0 85 1C STA &1C 1FB2 86 1D STX &1D 1FB4 A5 2C LDA &2C 1FB6 0A ASL A 1FB7 0A ASL A 1FB8 0A ASL A 1FB9 85 07 STA &07 1FBB A5 2D LDA &2D 1FBD C0 7F CPY #&7F 1FBF D0 0C BNE &1FCD 1FC1 C6 2C DEC &2C 1FC3 69 5E ADC #&5E 1FC5 AA TAX 1FC6 A0 F8 LDY #&F8 1FC8 20 31 48 JSR &4831 1FCB F0 1B BEQ &1FE8 .RR2 1FCD E6 2C INC &2C 1FCF C9 18 CMP #&18 1FD1 90 06 BCC &1FD9 1FD3 20 7D 2B JSR &2B7D 1FD6 4C E8 1F JMP &1FE8 .RR3 1FD9 09 60 ORA #&60 .RREN 1FDB 85 08 STA &08 1FDD A0 07 LDY #&07 .RRL1 1FDF B1 1C LDA (&1C),Y 1FE1 51 07 EOR (&07),Y 1FE3 91 07 STA (&07),Y 1FE5 88 DEY 1FE6 10 F7 BPL &1FDF .RR4 1FE8 AC 0F 0F LDY &0F0F 1FEB AE 0E 0F LDX &0F0E 1FEE A5 D2 LDA &D2 1FF0 18 CLC .rT9 1FF1 60 RTS .R5 1FF2 20 CB 49 JSR &49CB 1FF5 4C E8 1F JMP &1FE8 .DIALS 1FF8 A9 D0 LDA #&D0 1FFA 85 07 STA &07 1FFC A9 78 LDA #&78 1FFE 85 08 STA &08 2000 20 BC 20 JSR &20BC 2003 86 3E STX &3E 2005 85 3D STA &3D 2007 A9 0E LDA #&0E 2009 85 06 STA &06 200B A5 8C LDA &8C 200D 20 CF 20 JSR &20CF 2010 A9 00 LDA #&00 2012 85 91 STA &91 2014 85 1B STA &1B 2016 A9 08 LDA #&08 2018 85 92 STA &92 201A A5 87 LDA &87 201C 4A LSR A 201D 4A LSR A 201E 05 88 ORA &88 2020 49 80 EOR #&80 2022 20 5F 28 JSR &285F 2025 20 23 21 JSR &2123 2028 A5 2A LDA &2A 202A A6 2B LDX &2B 202C F0 02 BEQ &2030 202E E9 01 SBC #&01 2030 20 5F 28 JSR &285F 2033 20 23 21 JSR &2123 2036 A5 99 LDA &99 2038 29 03 AND #&03 203A D0 B5 BNE &1FF1 203C A0 00 LDY #&00 203E 20 BC 20 JSR &20BC 2041 86 3D STX &3D 2043 85 3E STA &3E 2045 A2 03 LDX #&03 2047 86 06 STX &06 .DLL23 2049 94 37 STY &37,X 204B CA DEX 204C 10 FB BPL &2049 204E A2 03 LDX #&03 2050 AD 13 0F LDA &0F13 2053 4A LSR A 2054 4A LSR A 2055 85 90 STA &90 .DLL24 2057 38 SEC 2058 E9 10 SBC #&10 205A 90 0D BCC &2069 205C 85 90 STA &90 205E A9 10 LDA #&10 2060 95 37 STA &37,X 2062 A5 90 LDA &90 2064 CA DEX 2065 10 F0 BPL &2057 2067 30 04 BMI &206D .DLL26 2069 A5 90 LDA &90 206B 95 37 STA &37,X .DLL9 206D B9 37 00 LDA &0037,Y 2070 84 1B STY &1B 2072 20 D0 20 JSR &20D0 2075 A4 1B LDY &1B 2077 C8 INY 2078 C0 04 CPY #&04 207A D0 F1 BNE &206D 207C A9 78 LDA #&78 207E 85 08 STA &08 2080 A9 10 LDA #&10 2082 85 07 STA &07 2084 AD 11 0F LDA &0F11 2087 20 CC 20 JSR &20CC 208A AD 12 0F LDA &0F12 208D 20 CC 20 JSR &20CC 2090 AD 0D 03 LDA &030D 2093 20 CE 20 JSR &20CE 2096 20 BC 20 JSR &20BC 2099 86 3E STX &3E 209B 85 3D STA &3D 209D A2 0B LDX #&0B 209F 86 06 STX &06 20A1 AD 4D 0D LDA &0D4D 20A4 20 CC 20 JSR &20CC 20A7 AD 61 0D LDA &0D61 20AA 20 CC 20 JSR &20CC 20AD A9 F0 LDA #&F0 20AF 85 06 STA &06 20B1 85 3E STA &3E 20B3 AD 21 0F LDA &0F21 20B6 20 CC 20 JSR &20CC 20B9 4C 51 3B JMP &3B51 .PZW 20BC A2 F0 LDX #&F0 20BE A5 99 LDA &99 20C0 29 08 AND #&08 20C2 2D 4D 0F AND &0F4D 20C5 F0 02 BEQ &20C9 20C7 8A TXA 20C8 2C 20C9 A9 0F LDA #&0F 20CB 60 RTS .DILX 20CC 4A LSR A 20CD 4A LSR A 20CE 4A LSR A 20CF 4A LSR A .DIL 20D0 85 90 STA &90 20D2 A2 FF LDX #&FF 20D4 86 91 STX &91 20D6 C5 06 CMP &06 20D8 B0 04 BCS &20DE 20DA A5 3E LDA &3E 20DC D0 02 BNE &20E0 .DL30 20DE A5 3D LDA &3D .DL31 20E0 85 A2 STA &A2 20E2 A0 02 LDY #&02 20E4 A2 03 LDX #&03 .DL1 20E6 A5 90 LDA &90 20E8 C9 04 CMP #&04 20EA 90 1A BCC &2106 20EC E9 04 SBC #&04 20EE 85 90 STA &90 20F0 A5 91 LDA &91 .DL5 20F2 25 A2 AND &A2 20F4 91 07 STA (&07),Y 20F6 C8 INY 20F7 91 07 STA (&07),Y 20F9 C8 INY 20FA 91 07 STA (&07),Y 20FC 98 TYA 20FD 18 CLC 20FE 69 06 ADC #&06 2100 A8 TAY 2101 CA DEX 2102 30 1C BMI &2120 2104 10 E0 BPL &20E6 .DL2 2106 49 03 EOR #&03 2108 85 90 STA &90 210A A5 91 LDA &91 .DL3 210C 0A ASL A 210D 29 EF AND #&EF 210F C6 90 DEC &90 2111 10 F9 BPL &210C 2113 48 PHA 2114 A9 00 LDA #&00 2116 85 91 STA &91 2118 A9 63 LDA #&63 211A 85 90 STA &90 211C 68 PLA 211D 4C F2 20 JMP &20F2 .DL6 2120 E6 08 INC &08 .DL9 2122 60 RTS .DIL2 2123 A0 01 LDY #&01 2125 85 90 STA &90 .DLL10 2127 38 SEC 2128 A5 90 LDA &90 212A E9 04 SBC #&04 212C B0 0D BCS &213B 212E A9 FF LDA #&FF 2130 A6 90 LDX &90 2132 85 90 STA &90 2134 BD 72 18 LDA &1872,X 2137 29 F0 AND #&F0 2139 D0 04 BNE &213F .DLL11 213B 85 90 STA &90 213D A9 00 LDA #&00 .DLL12 213F 91 07 STA (&07),Y 2141 C8 INY 2142 91 07 STA (&07),Y 2144 C8 INY 2145 91 07 STA (&07),Y 2147 C8 INY 2148 91 07 STA (&07),Y 214A 98 TYA 214B 18 CLC 214C 69 05 ADC #&05 214E A8 TAY 214F C0 1E CPY #&1E 2151 90 D4 BCC &2127 2153 E6 08 INC &08 2155 60 RTS .TVT1 2156 D4 2157 C4 2158 94 2159 84 215A F5 215B E5 215C B5 215D A5 215E 76 215F 66 2160 36 2161 26 2162 E1 2163 F1 2164 B1 2165 A1 2166 F0 2167 E0 2168 B0 2169 A0 216A D0 216B C0 216C 90 216D 80 216E 77 216F 67 2170 37 2171 27 .LINSCN 2172 A9 1E LDA #&1E 2174 85 9A STA &9A 2176 8D 44 FE STA &FE44 2179 A9 39 LDA #&39 217B 8D 45 FE STA &FE45 217E AD 62 0D LDA &0D62 2181 D0 47 BNE &21CA 2183 A9 08 LDA #&08 2185 8D 20 FE STA &FE20 .VNT3 2188 B9 66 21 LDA &2166,Y 218B 8D 21 FE STA &FE21 218E 88 DEY 218F 10 F7 BPL &2188 2191 AD 60 0D LDA &0D60 2194 F0 03 BEQ &2199 2196 CE 60 0D DEC &0D60 2199 AD FD 7F LDA &7FFD 219C D0 27 BNE &21C5 219E 68 PLA 219F A8 TAY 21A0 AD 41 FE LDA &FE41 21A3 A5 FC LDA &FC 21A5 40 RTI .IRQ1 21A6 98 TYA 21A7 48 PHA 21A8 A0 0B LDY #&0B 21AA A9 02 LDA #&02 21AC 2C 4D FE BIT &FE4D 21AF D0 C1 BNE &2172 21B1 50 12 BVC &21C5 21B3 0A ASL A 21B4 8D 20 FE STA &FE20 21B7 AD 2E 03 LDA &032E 21BA D0 0E BNE &21CA 21BC B9 56 21 LDA &2156,Y 21BF 8D 21 FE STA &FE21 21C2 88 DEY 21C3 10 F7 BPL &21BC .jvec 21C5 68 PLA 21C6 A8 TAY 21C7 6C FE 7F JMP (&7FFE) .VNT1 21CA A0 07 LDY #&07 21CC B9 5E 21 LDA &215E,Y 21CF 8D 21 FE STA &FE21 21D2 88 DEY 21D3 10 F7 BPL &21CC 21D5 30 EE BMI &21C5 .ESCAPE 21D7 AD 5C 0D LDA &0D5C 21DA 48 PHA 21DB 20 B1 43 JSR &43B1 21DE A2 07 LDX #&07 21E0 86 9B STX &9B 21E2 20 66 24 JSR &2466 21E5 A9 08 LDA #&08 21E7 85 6E STA &6E 21E9 A9 C2 LDA #&C2 21EB 85 71 STA &71 21ED 4A LSR A 21EE 85 73 STA &73 .ESL1 21F0 20 A9 13 JSR &13A9 21F3 20 2F 4E JSR &4E2F 21F6 C6 73 DEC &73 21F8 D0 F6 BNE &21F0 21FA 20 20 2C JSR &2C20 21FD 20 9B 43 JSR &439B 2200 68 PLA 2201 F0 03 BEQ &2206 2203 4C 7F 46 JMP &467F 2206 A2 10 LDX #&10 .ESL2 2208 9D 17 03 STA &0317,X 220B CA DEX 220C 10 FA BPL &2208 220E 8D 34 03 STA &0334 2211 8D 2E 03 STA &032E 2214 A9 46 LDA #&46 2216 8D 0D 03 STA &030D 2219 4C 4D 47 JMP &474D ELITE B Assembled at &17F4 Ends at &221C Code size is &A28 Execute at &1128 Reload at &19DC S.ELTB &17F4 &221C &1128 &19DC Saving file '3-assembled-output/ELTB.bin' .TA34 221C A9 00 LDA #&00 221E 20 78 46 JSR &4678 2221 F0 03 BEQ &2226 2223 4C F3 22 JMP &22F3 2226 20 88 22 JSR &2288 2229 20 8C 49 JSR &498C 222C A9 FA LDA #&FA 222E 4C 01 3C JMP &3C01 .TA18 2231 A5 30 LDA &30 2233 D0 43 BNE &2278 2235 A5 73 LDA &73 2237 0A ASL A 2238 30 E2 BMI &221C 223A 4A LSR A 223B AA TAX 223C BD 48 18 LDA &1848,X 223F 85 22 STA &22 2241 BD 49 18 LDA &1849,X 2244 85 23 STA &23 2246 A0 02 LDY #&02 2248 20 03 24 JSR &2403 224B A0 05 LDY #&05 224D 20 03 24 JSR &2403 2250 A0 08 LDY #&08 2252 20 03 24 JSR &2403 2255 A5 D4 LDA &D4 2257 05 D7 ORA &D7 2259 05 DA ORA &DA 225B 29 7F AND #&7F 225D 05 D3 ORA &D3 225F 05 D6 ORA &D6 2261 05 D9 ORA &D9 2263 D0 29 BNE &228E 2265 A5 73 LDA &73 2267 C9 82 CMP #&82 2269 F0 0D BEQ &2278 226B A0 1F LDY #&1F 226D B1 22 LDA (&22),Y 226F 2C 96 22 BIT &2296 2272 D0 04 BNE &2278 2274 09 80 ORA #&80 2276 91 22 STA (&22),Y .TA35 2278 A5 53 LDA &53 227A 05 56 ORA &56 227C 05 59 ORA &59 227E D0 05 BNE &2285 2280 A9 50 LDA #&50 2282 20 01 3C JSR &3C01 .TA87 2285 20 A5 49 JSR &49A5 2288 06 72 ASL &72 228A 38 SEC 228B 66 72 ROR &72 .TA1 228D 60 RTS .TA64 228E 20 57 44 JSR &4457 2291 C9 10 CMP #&10 2293 B0 67 BCS &22FC .M32 2295 A0 20 LDY #&20 2297 B1 22 LDA (&22),Y 2299 4A LSR A 229A 90 60 BCC &22FC 229C 4C 15 3D JMP &3D15 .TACTICS 229F E0 09 CPX #&09 22A1 F0 8E BEQ &2231 22A3 E0 0D CPX #&0D 22A5 D0 06 BNE &22AD 22A7 20 DE 48 JSR &48DE 22AA 4C C2 23 JMP &23C2 22AD E0 08 CPX #&08 22AF D0 15 BNE &22C6 22B1 20 57 44 JSR &4457 22B4 C9 8C CMP #&8C 22B6 90 1D BCC &22D5 22B8 AD 4F 0D LDA &0D4F 22BB C9 04 CMP #&04 22BD B0 16 BCS &22D5 22BF A2 02 LDX #&02 22C1 A9 F1 LDA #&F1 22C3 4C E0 24 JMP &24E0 .TA13 22C6 E0 0C CPX #&0C 22C8 D0 0C BNE &22D6 22CA AD 53 0D LDA &0D53 22CD D0 07 BNE &22D6 22CF 46 73 LSR &73 22D1 06 73 ASL &73 22D3 46 6E LSR &6E 22D5 60 RTS .TA14 22D6 E0 07 CPX #&07 22D8 B0 0F BCS &22E9 22DA E0 02 CPX #&02 22DC F0 0B BEQ &22E9 22DE AD 55 0D LDA &0D55 22E1 F0 06 BEQ &22E9 22E3 A5 73 LDA &73 22E5 29 81 AND #&81 22E7 85 73 STA &73 .TA62 22E9 A0 0E LDY #&0E 22EB A5 76 LDA &76 22ED D1 1E CMP (&1E),Y 22EF B0 02 BCS &22F3 22F1 E6 76 INC &76 .TA21 22F3 A2 08 LDX #&08 .TAL1 22F5 B5 53 LDA &53,X 22F7 95 D2 STA &D2,X 22F9 CA DEX 22FA 10 F9 BPL &22F5 .TA19 22FC 20 ED 48 JSR &48ED 22FF A0 0A LDY #&0A 2301 20 40 28 JSR &2840 2304 85 A4 STA &A4 2306 A5 9B LDA &9B 2308 C9 09 CMP #&09 230A D0 03 BNE &230F 230C 4C AA 23 JMP &23AA 230F 20 57 44 JSR &4457 2312 C9 FA CMP #&FA 2314 90 07 BCC &231D 2316 20 57 44 JSR &4457 2319 09 68 ORA #&68 231B 85 70 STA &70 .TA7 231D A0 0E LDY #&0E 231F B1 1E LDA (&1E),Y 2321 4A LSR A 2322 C5 76 CMP &76 2324 90 41 BCC &2367 2326 4A LSR A 2327 4A LSR A 2328 C5 76 CMP &76 232A 90 14 BCC &2340 232C 20 57 44 JSR &4457 232F C9 E6 CMP #&E6 2331 90 0D BCC &2340 2333 A5 9B LDA &9B 2335 C9 06 CMP #&06 2337 F0 07 BEQ &2340 2339 A9 00 LDA #&00 233B 85 73 STA &73 233D 4C DC 24 JMP &24DC .ta3 2340 A5 72 LDA &72 2342 29 07 AND #&07 2344 F0 21 BEQ &2367 2346 85 D1 STA &D1 2348 20 57 44 JSR &4457 234B 29 1F AND #&1F 234D C5 D1 CMP &D1 234F B0 16 BCS &2367 2351 A5 30 LDA &30 2353 D0 12 BNE &2367 2355 C6 72 DEC &72 2357 A5 9B LDA &9B 2359 C9 06 CMP #&06 235B D0 07 BNE &2364 235D A2 0C LDX #&0C 235F A5 73 LDA &73 2361 4C E0 24 JMP &24E0 .TA16 2364 4C 95 49 JMP &4995 .TA3 2367 A9 00 LDA #&00 2369 20 78 46 JSR &4678 236C 29 E0 AND #&E0 236E D0 23 BNE &2393 2370 A6 A4 LDX &A4 2372 E0 A0 CPX #&A0 2374 90 1D BCC &2393 2376 A5 72 LDA &72 2378 09 40 ORA #&40 237A 85 72 STA &72 237C E0 A3 CPX #&A3 237E 90 13 BCC &2393 .HIT 2380 A0 13 LDY #&13 2382 B1 1E LDA (&1E),Y 2384 4A LSR A 2385 20 01 3C JSR &3C01 2388 C6 6F DEC &6F 238A A5 30 LDA &30 238C D0 74 BNE &2402 238E A9 08 LDA #&08 2390 4C CD 49 JMP &49CD .TA4 2393 A5 5A LDA &5A 2395 C9 03 CMP #&03 2397 B0 08 BCS &23A1 2399 A5 54 LDA &54 239B 05 57 ORA &57 239D 29 FE AND #&FE 239F F0 21 BEQ &23C2 .TA5 23A1 20 57 44 JSR &4457 23A4 09 80 ORA #&80 23A6 C5 73 CMP &73 23A8 B0 18 BCS &23C2 .TA20 23AA A5 31 LDA &31 23AC 49 80 EOR #&80 23AE 85 31 STA &31 23B0 A5 32 LDA &32 23B2 49 80 EOR #&80 23B4 85 32 STA &32 23B6 A5 33 LDA &33 23B8 49 80 EOR #&80 23BA 85 33 STA &33 23BC A5 A4 LDA &A4 23BE 49 80 EOR #&80 23C0 85 A4 STA &A4 .TA15 23C2 A0 10 LDY #&10 23C4 20 40 28 JSR &2840 23C7 49 80 EOR #&80 23C9 29 80 AND #&80 23CB 09 03 ORA #&03 23CD 85 71 STA &71 23CF A5 70 LDA &70 23D1 29 7F AND #&7F 23D3 C9 10 CMP #&10 23D5 B0 0D BCS &23E4 23D7 A0 16 LDY #&16 23D9 20 40 28 JSR &2840 23DC 45 71 EOR &71 23DE 29 80 AND #&80 23E0 49 85 EOR #&85 23E2 85 70 STA &70 .TA6 23E4 A5 A4 LDA &A4 23E6 30 09 BMI &23F1 23E8 C9 16 CMP #&16 23EA 90 05 BCC &23F1 23EC A9 03 LDA #&03 23EE 85 6F STA &6F 23F0 60 RTS .TA9 23F1 29 7F AND #&7F 23F3 C9 12 CMP #&12 23F5 90 0B BCC &2402 23F7 A9 FF LDA #&FF 23F9 A6 9B LDX &9B 23FB E0 09 CPX #&09 23FD D0 01 BNE &2400 23FF 0A ASL A 2400 85 6F STA &6F .TA10 2402 60 RTS .TAS1 2403 B1 22 LDA (&22),Y 2405 49 80 EOR #&80 2407 85 40 STA &40 2409 88 DEY 240A B1 22 LDA (&22),Y 240C 85 3F STA &3F 240E 88 DEY 240F B1 22 LDA (&22),Y 2411 85 3E STA &3E 2413 84 8F STY &8F 2415 A6 8F LDX &8F 2417 20 AA 15 JSR &15AA 241A A4 8F LDY &8F 241C 95 D4 STA &D4,X 241E A5 3F LDA &3F 2420 95 D3 STA &D3,X 2422 A5 3E LDA &3E 2424 95 D2 STA &D2,X 2426 60 RTS .HITCH 2427 18 CLC 2428 A5 5B LDA &5B 242A D0 39 BNE &2465 242C A5 9B LDA &9B 242E 30 35 BMI &2465 2430 A5 72 LDA &72 2432 29 20 AND #&20 2434 05 54 ORA &54 2436 05 57 ORA &57 2438 D0 2B BNE &2465 243A A5 53 LDA &53 243C 20 6F 27 JSR &276F 243F 85 92 STA &92 2441 A5 1B LDA &1B 2443 85 91 STA &91 2445 A5 56 LDA &56 2447 20 6F 27 JSR &276F 244A AA TAX 244B A5 1B LDA &1B 244D 65 91 ADC &91 244F 85 91 STA &91 2451 8A TXA 2452 65 92 ADC &92 2454 B0 7F BCS &24D5 2456 85 92 STA &92 2458 A0 02 LDY #&02 245A B1 1E LDA (&1E),Y 245C C5 92 CMP &92 245E D0 05 BNE &2465 2460 88 DEY 2461 B1 1E LDA (&1E),Y 2463 C5 91 CMP &91 .HI1 2465 60 RTS .FRS1 2466 20 F9 43 JSR &43F9 2469 A9 1C LDA #&1C 246B 85 56 STA &56 246D 4A LSR A 246E 85 59 STA &59 2470 A9 80 LDA #&80 2472 85 58 STA &58 2474 A5 52 LDA &52 2476 0A ASL A 2477 09 80 ORA #&80 2479 85 73 STA &73 .fq1 247B A9 60 LDA #&60 247D 85 61 STA &61 247F 09 80 ORA #&80 2481 85 69 STA &69 2483 A5 8C LDA &8C 2485 2A ROL A 2486 85 6E STA &6E 2488 8A TXA 2489 4C 82 3C JMP &3C82 .FRMIS 248C A2 09 LDX #&09 248E 20 66 24 JSR &2466 2491 90 44 BCC &24D7 2493 A6 52 LDX &52 2495 20 4F 3C JSR &3C4F 2498 BD 40 0D LDA &0D40,X 249B 20 AB 24 JSR &24AB 249E A0 00 LDY #&00 24A0 20 07 3D JSR &3D07 24A3 CE 33 03 DEC &0333 24A6 A9 30 LDA #&30 24A8 4C CD 49 JMP &49CD .ANGRY 24AB C9 08 CMP #&08 24AD F0 1F BEQ &24CE 24AF B0 B4 BCS &2465 24B1 C9 07 CMP #&07 24B3 D0 03 BNE &24B8 24B5 20 CE 24 JSR &24CE 24B8 A0 20 LDY #&20 24BA B1 20 LDA (&20),Y 24BC F0 A7 BEQ &2465 24BE 09 80 ORA #&80 24C0 91 20 STA (&20),Y 24C2 A0 1C LDY #&1C 24C4 A9 02 LDA #&02 24C6 91 20 STA (&20),Y 24C8 0A ASL A 24C9 A0 1E LDY #&1E 24CB 91 20 STA (&20),Y 24CD 60 RTS .AN2 24CE 0E 44 09 ASL &0944 24D1 38 SEC 24D2 6E 44 09 ROR &0944 24D5 18 CLC 24D6 60 RTS .FR1 24D7 A9 C9 LDA #&C9 24D9 4C 29 4B JMP &4B29 .SESCP 24DC A2 0D LDX #&0D 24DE A9 FE LDA #&FE .SFS1 24E0 85 06 STA &06 24E2 A5 1E LDA &1E 24E4 48 PHA 24E5 A5 1F LDA &1F 24E7 48 PHA 24E8 A5 20 LDA &20 24EA 48 PHA 24EB A5 21 LDA &21 24ED 48 PHA 24EE A0 23 LDY #&23 .FRL2 24F0 B9 53 00 LDA &0053,Y 24F3 99 00 01 STA &0100,Y 24F6 B1 20 LDA (&20),Y 24F8 99 53 00 STA &0053,Y 24FB 88 DEY 24FC 10 F2 BPL &24F0 24FE A5 9B LDA &9B 2500 C9 08 CMP #&08 2502 D0 1D BNE &2521 2504 8A TXA 2505 48 PHA 2506 A9 20 LDA #&20 2508 85 6E STA &6E 250A A2 00 LDX #&00 250C A5 5D LDA &5D 250E 20 5A 25 JSR &255A 2511 A2 03 LDX #&03 2513 A5 5F LDA &5F 2515 20 5A 25 JSR &255A 2518 A2 06 LDX #&06 251A A5 61 LDA &61 251C 20 5A 25 JSR &255A 251F 68 PLA 2520 AA TAX .rx 2521 A5 06 LDA &06 2523 85 73 STA &73 2525 46 70 LSR &70 2527 06 70 ASL &70 2529 8A TXA 252A C9 0B CMP #&0B 252C D0 12 BNE &2540 252E 20 57 44 JSR &4457 2531 0A ASL A 2532 85 71 STA &71 2534 8A TXA 2535 29 0F AND #&0F 2537 85 6E STA &6E 2539 A9 FF LDA #&FF 253B 6A ROR A 253C 85 70 STA &70 253E A9 0B LDA #&0B .NOIL 2540 20 82 3C JSR &3C82 2543 68 PLA 2544 85 21 STA &21 2546 68 PLA 2547 85 20 STA &20 2549 A2 23 LDX #&23 .FRL3 254B BD 00 01 LDA &0100,X 254E 95 53 STA &53,X 2550 CA DEX 2551 10 F8 BPL &254B 2553 68 PLA 2554 85 1F STA &1F 2556 68 PLA 2557 85 1E STA &1E 2559 60 RTS .SFS2 255A 0A ASL A 255B 85 91 STA &91 255D A9 00 LDA #&00 255F 6A ROR A 2560 4C 55 15 JMP &1555 .LL164 2563 A9 38 LDA #&38 2565 20 CD 49 JSR &49CD 2568 A9 01 LDA #&01 256A 8D 62 0D STA &0D62 256D A9 04 LDA #&04 256F 20 7D 25 JSR &257D 2572 CE 62 0D DEC &0D62 2575 60 RTS .LAUN 2576 A9 30 LDA #&30 2578 20 CD 49 JSR &49CD 257B A9 08 LDA #&08 .HFS2 257D 85 A6 STA &A6 257F 20 7D 2B JSR &2B7D 2582 20 85 25 JSR &2585 .HFS1 2585 A9 80 LDA #&80 2587 85 D2 STA &D2 2589 A2 60 LDX #&60 258B 86 E0 STX &E0 258D 0A ASL A 258E 85 A7 STA &A7 2590 85 D3 STA &D3 2592 85 E1 STA &E1 .HFL5 2594 20 A0 25 JSR &25A0 2597 E6 A7 INC &A7 2599 A6 A7 LDX &A7 259B E0 08 CPX #&08 259D D0 F5 BNE &2594 259F 60 RTS .HFL1 25A0 A5 A7 LDA &A7 25A2 29 07 AND #&07 25A4 18 CLC 25A5 69 08 ADC #&08 25A7 85 3D STA &3D .HFL2 25A9 A9 01 LDA #&01 25AB 85 77 STA &77 25AD 20 96 40 JSR &4096 25B0 06 3D ASL &3D 25B2 B0 06 BCS &25BA 25B4 A5 3D LDA &3D 25B6 C9 A0 CMP #&A0 25B8 90 EF BCC &25A9 .HF8 25BA 60 RTS .STARS2 25BB A9 00 LDA #&00 25BD E0 02 CPX #&02 25BF 6A ROR A 25C0 85 AA STA &AA 25C2 49 80 EOR #&80 25C4 85 AB STA &AB 25C6 20 6F 26 JSR &266F 25C9 AC 33 0F LDY &0F33 .STL2 25CC B9 E8 0E LDA &0EE8,Y 25CF 85 97 STA &97 25D1 4A LSR A 25D2 4A LSR A 25D3 4A LSR A 25D4 20 C1 28 JSR &28C1 25D7 A5 1B LDA &1B 25D9 45 AB EOR &AB 25DB 85 92 STA &92 25DD B9 5F 03 LDA &035F,Y 25E0 85 1B STA &1B 25E2 B9 4C 03 LDA &034C,Y 25E5 85 31 STA &31 25E7 20 5F 28 JSR &285F 25EA 85 92 STA &92 25EC 86 91 STX &91 25EE B9 C2 0E LDA &0EC2,Y 25F1 85 32 STA &32 25F3 45 8A EOR &8A 25F5 A6 2B LDX &2B 25F7 20 2A 27 JSR &272A 25FA 20 5F 28 JSR &285F 25FD 86 24 STX &24 25FF 85 25 STA &25 2601 BE D5 0E LDX &0ED5,Y 2604 86 91 STX &91 2606 A6 32 LDX &32 2608 86 92 STX &92 260A A6 2B LDX &2B 260C 45 8B EOR &8B 260E 20 2A 27 JSR &272A 2611 20 5F 28 JSR &285F 2614 86 26 STX &26 2616 85 27 STA &27 2618 A6 87 LDX &87 261A 45 88 EOR &88 261C 20 2A 27 JSR &272A 261F 85 90 STA &90 2621 A5 24 LDA &24 2623 85 91 STA &91 2625 A5 25 LDA &25 2627 85 92 STA &92 2629 49 80 EOR #&80 262B 20 5C 28 JSR &285C 262E 85 25 STA &25 2630 8A TXA 2631 99 5F 03 STA &035F,Y 2634 A5 26 LDA &26 2636 85 91 STA &91 2638 A5 27 LDA &27 263A 85 92 STA &92 263C 20 5C 28 JSR &285C 263F 85 92 STA &92 2641 86 91 STX &91 2643 A9 00 LDA #&00 2645 85 1B STA &1B 2647 A5 9E LDA &9E 2649 20 B4 1A JSR &1AB4 264C A5 25 LDA &25 264E 99 4C 03 STA &034C,Y 2651 85 31 STA &31 2653 29 7F AND #&7F 2655 C9 74 CMP #&74 2657 B0 31 BCS &268A 2659 A5 27 LDA &27 265B 99 C2 0E STA &0EC2,Y 265E 85 32 STA &32 2660 29 7F AND #&7F 2662 C9 74 CMP #&74 2664 B0 37 BCS &269D .STC2 2666 20 BD 1A JSR &1ABD 2669 88 DEY 266A F0 03 BEQ &266F 266C 4C CC 25 JMP &25CC .ST2 266F A5 9E LDA &9E 2671 45 AA EOR &AA 2673 85 9E STA &9E 2675 A5 88 LDA &88 2677 45 AA EOR &AA 2679 85 88 STA &88 267B 49 80 EOR #&80 267D 85 89 STA &89 267F A5 8A LDA &8A 2681 45 AA EOR &AA 2683 85 8A STA &8A 2685 49 80 EOR #&80 2687 85 8B STA &8B 2689 60 RTS .KILL2 268A 20 57 44 JSR &4457 268D 85 32 STA &32 268F 99 C2 0E STA &0EC2,Y 2692 A9 73 LDA #&73 2694 05 AA ORA &AA 2696 85 31 STA &31 2698 99 4C 03 STA &034C,Y 269B D0 11 BNE &26AE .ST5 269D 20 57 44 JSR &4457 26A0 85 31 STA &31 26A2 99 4C 03 STA &034C,Y 26A5 A9 6E LDA #&6E 26A7 05 89 ORA &89 26A9 85 32 STA &32 26AB 99 C2 0E STA &0EC2,Y .STF1 26AE 20 57 44 JSR &4457 26B1 09 08 ORA #&08 26B3 85 97 STA &97 26B5 99 E8 0E STA &0EE8,Y 26B8 D0 AC BNE &2666 .SNE 26BA 00 26BB 19 26BC 32 26BD 4A 26BE 62 26BF 79 26C0 8E 26C1 A2 26C2 B5 26C3 C6 26C4 D5 26C5 E2 26C6 ED 26C7 F5 26C8 FB 26C9 FF 26CA FF 26CB FF 26CC FB 26CD F5 26CE ED 26CF E2 26D0 D5 26D1 C6 26D2 B5 26D3 A2 26D4 8E 26D5 79 26D6 62 26D7 4A 26D8 32 26D9 19 .MU5 26DA 85 3D STA &3D 26DC 85 3E STA &3E 26DE 85 3F STA &3F 26E0 85 40 STA &40 26E2 18 CLC 26E3 60 RTS .MULT3 26E4 85 91 STA &91 26E6 29 7F AND #&7F 26E8 85 3F STA &3F 26EA A5 90 LDA &90 26EC 29 7F AND #&7F 26EE F0 EA BEQ &26DA 26F0 38 SEC 26F1 E9 01 SBC #&01 26F3 85 D1 STA &D1 26F5 A5 1C LDA &1C 26F7 46 3F LSR &3F 26F9 6A ROR A 26FA 85 3E STA &3E 26FC A5 1B LDA &1B 26FE 6A ROR A 26FF 85 3D STA &3D 2701 A9 00 LDA #&00 2703 A2 18 LDX #&18 .MUL2 2705 90 02 BCC &2709 2707 65 D1 ADC &D1 2709 6A ROR A 270A 66 3F ROR &3F 270C 66 3E ROR &3E 270E 66 3D ROR &3D 2710 CA DEX 2711 D0 F2 BNE &2705 2713 85 D1 STA &D1 2715 A5 91 LDA &91 2717 45 90 EOR &90 2719 29 80 AND #&80 271B 05 D1 ORA &D1 271D 85 40 STA &40 271F 60 RTS .MLS2 2720 A6 24 LDX &24 2722 86 91 STX &91 2724 A6 25 LDX &25 2726 86 92 STX &92 .MLS1 2728 A6 87 LDX &87 272A 86 1B STX &1B .MULTS 272C AA TAX 272D 29 80 AND #&80 272F 85 D1 STA &D1 2731 8A TXA 2732 29 7F AND #&7F 2734 F0 64 BEQ &279A 2736 AA TAX 2737 CA DEX 2738 86 06 STX &06 273A A9 00 LDA #&00 273C 46 1B LSR &1B 273E 90 02 BCC &2742 2740 65 06 ADC &06 2742 6A ROR A 2743 66 1B ROR &1B 2745 90 02 BCC &2749 2747 65 06 ADC &06 2749 6A ROR A 274A 66 1B ROR &1B 274C 90 02 BCC &2750 274E 65 06 ADC &06 2750 6A ROR A 2751 66 1B ROR &1B 2753 90 02 BCC &2757 2755 65 06 ADC &06 2757 6A ROR A 2758 66 1B ROR &1B 275A 90 02 BCC &275E 275C 65 06 ADC &06 275E 6A ROR A 275F 66 1B ROR &1B 2761 4A LSR A 2762 66 1B ROR &1B 2764 4A LSR A 2765 66 1B ROR &1B 2767 4A LSR A 2768 66 1B ROR &1B 276A 05 D1 ORA &D1 276C 60 RTS .SQUA 276D 29 7F AND #&7F .SQUA2 276F 85 1B STA &1B 2771 AA TAX 2772 D0 12 BNE &2786 .MU1 2774 18 CLC 2775 86 1B STX &1B 2777 8A TXA 2778 60 RTS .MLU1 2779 B9 C2 0E LDA &0EC2,Y 277C 85 32 STA &32 .MLU2 277E 29 7F AND #&7F 2780 85 1B STA &1B .MULTU 2782 A6 90 LDX &90 2784 F0 EE BEQ &2774 .MU11 2786 CA DEX 2787 86 D1 STX &D1 2789 A9 00 LDA #&00 278B A2 08 LDX #&08 278D 46 1B LSR &1B .MUL6 278F 90 02 BCC &2793 2791 65 D1 ADC &D1 2793 6A ROR A 2794 66 1B ROR &1B 2796 CA DEX 2797 D0 F6 BNE &278F 2799 60 RTS .MU6 279A 85 1C STA &1C 279C 85 1B STA &1B 279E 60 RTS .FMLTU2 279F 29 1F AND #&1F 27A1 AA TAX 27A2 BD BA 26 LDA &26BA,X 27A5 85 90 STA &90 27A7 A5 3D LDA &3D .FMLTU 27A9 49 FF EOR #&FF 27AB 38 SEC 27AC 6A ROR A 27AD 85 1B STA &1B 27AF A9 00 LDA #&00 .MUL3 27B1 B0 08 BCS &27BB 27B3 65 90 ADC &90 27B5 6A ROR A 27B6 46 1B LSR &1B 27B8 D0 F7 BNE &27B1 27BA 60 RTS .MU7 27BB 4A LSR A 27BC 46 1B LSR &1B 27BE D0 F1 BNE &27B1 27C0 60 RTS 27C1 A6 90 LDX &90 27C3 F0 AF BEQ &2774 27C5 CA DEX 27C6 86 D1 STX &D1 27C8 A9 00 LDA #&00 27CA A2 08 LDX #&08 27CC 46 1B LSR &1B .MUL6K 27CE 90 02 BCC &27D2 27D0 65 D1 ADC &D1 27D2 6A ROR A 27D3 66 1B ROR &1B 27D5 CA DEX 27D6 D0 F6 BNE &27CE 27D8 60 RTS 27D9 86 90 STX &90 .MLTU2 27DB 49 FF EOR #&FF 27DD 4A LSR A 27DE 85 1C STA &1C 27E0 A9 00 LDA #&00 27E2 A2 10 LDX #&10 27E4 66 1B ROR &1B .MUL7 27E6 B0 0B BCS &27F3 27E8 65 90 ADC &90 27EA 6A ROR A 27EB 66 1C ROR &1C 27ED 66 1B ROR &1B 27EF CA DEX 27F0 D0 F4 BNE &27E6 27F2 60 RTS .MU21 27F3 4A LSR A 27F4 66 1C ROR &1C 27F6 66 1B ROR &1B 27F8 CA DEX 27F9 D0 EB BNE &27E6 27FB 60 RTS .MUT3 27FC A6 87 LDX &87 27FE 86 1B STX &1B .MUT2 2800 A6 25 LDX &25 2802 86 92 STX &92 .MUT1 2804 A6 24 LDX &24 2806 86 91 STX &91 .MULT1 2808 AA TAX 2809 29 7F AND #&7F 280B 4A LSR A 280C 85 1B STA &1B 280E 8A TXA 280F 45 90 EOR &90 2811 29 80 AND #&80 2813 85 D1 STA &D1 2815 A5 90 LDA &90 2817 29 7F AND #&7F 2819 F0 18 BEQ &2833 281B AA TAX 281C CA DEX 281D 86 06 STX &06 281F A9 00 LDA #&00 2821 A2 07 LDX #&07 .MUL4 2823 90 02 BCC &2827 2825 65 06 ADC &06 2827 6A ROR A 2828 66 1B ROR &1B 282A CA DEX 282B D0 F6 BNE &2823 282D 4A LSR A 282E 66 1B ROR &1B 2830 05 D1 ORA &D1 2832 60 RTS .mu10 2833 85 1B STA &1B 2835 60 RTS .MULT12 2836 20 08 28 JSR &2808 2839 85 92 STA &92 283B A5 1B LDA &1B 283D 85 91 STA &91 283F 60 RTS .TAS3 2840 B6 53 LDX &53,Y 2842 86 90 STX &90 2844 A5 31 LDA &31 2846 20 36 28 JSR &2836 2849 B6 55 LDX &55,Y 284B 86 90 STX &90 284D A5 32 LDA &32 284F 20 5C 28 JSR &285C 2852 85 92 STA &92 2854 86 91 STX &91 2856 B6 57 LDX &57,Y 2858 86 90 STX &90 285A A5 33 LDA &33 .MAD 285C 20 08 28 JSR &2808 .ADD 285F 85 06 STA &06 2861 29 80 AND #&80 2863 85 D1 STA &D1 2865 45 92 EOR &92 2867 30 0D BMI &2876 2869 A5 91 LDA &91 286B 18 CLC 286C 65 1B ADC &1B 286E AA TAX 286F A5 92 LDA &92 2871 65 06 ADC &06 2873 05 D1 ORA &D1 2875 60 RTS .MU8 2876 A5 92 LDA &92 2878 29 7F AND #&7F 287A 85 8F STA &8F 287C A5 1B LDA &1B 287E 38 SEC 287F E5 91 SBC &91 2881 AA TAX 2882 A5 06 LDA &06 2884 29 7F AND #&7F 2886 E5 8F SBC &8F 2888 B0 0E BCS &2898 288A 85 8F STA &8F 288C 8A TXA 288D 49 FF EOR #&FF 288F 69 01 ADC #&01 2891 AA TAX 2892 A9 00 LDA #&00 2894 E5 8F SBC &8F 2896 09 80 ORA #&80 .MU9 2898 45 D1 EOR &D1 289A 60 RTS .TIS1 289B 86 90 STX &90 289D 49 80 EOR #&80 289F 20 5C 28 JSR &285C .DVID96 28A2 AA TAX 28A3 29 80 AND #&80 28A5 85 D1 STA &D1 28A7 8A TXA 28A8 29 7F AND #&7F 28AA A2 FE LDX #&FE 28AC 86 06 STX &06 .DVL3 28AE 0A ASL A 28AF C9 60 CMP #&60 28B1 90 02 BCC &28B5 28B3 E9 60 SBC #&60 .DV4 28B5 26 06 ROL &06 28B7 B0 F5 BCS &28AE 28B9 A5 06 LDA &06 28BB 05 D1 ORA &D1 28BD 60 RTS .DV42 28BE B9 E8 0E LDA &0EE8,Y .DV41 28C1 85 90 STA &90 28C3 A5 8C LDA &8C .DVID4 28C5 A2 08 LDX #&08 28C7 0A ASL A 28C8 85 1B STA &1B 28CA A9 00 LDA #&00 .DVL4 28CC 2A ROL A 28CD B0 04 BCS &28D3 28CF C5 90 CMP &90 28D1 90 03 BCC &28D6 .DV8 28D3 E5 90 SBC &90 28D5 38 SEC .DV5 28D6 26 1B ROL &1B 28D8 CA DEX 28D9 D0 F1 BNE &28CC 28DB 4C 96 4D JMP &4D96 .DVID3B2 28DE 85 1D STA &1D 28E0 A5 59 LDA &59 28E2 85 90 STA &90 28E4 A5 5A LDA &5A 28E6 85 91 STA &91 28E8 A5 5B LDA &5B 28EA 85 92 STA &92 .DVID3B 28EC A5 1B LDA &1B 28EE 09 01 ORA #&01 28F0 85 1B STA &1B 28F2 A5 1D LDA &1D 28F4 45 92 EOR &92 28F6 29 80 AND #&80 28F8 85 D1 STA &D1 28FA A0 00 LDY #&00 28FC A5 1D LDA &1D 28FE 29 7F AND #&7F .DVL9 2900 C9 40 CMP #&40 2902 B0 08 BCS &290C 2904 06 1B ASL &1B 2906 26 1C ROL &1C 2908 2A ROL A 2909 C8 INY 290A D0 F4 BNE &2900 .DV14 290C 85 1D STA &1D 290E A5 92 LDA &92 2910 29 7F AND #&7F 2912 30 08 BMI &291C .DVL6 2914 88 DEY 2915 06 90 ASL &90 2917 26 91 ROL &91 2919 2A ROL A 291A 10 F8 BPL &2914 .DV9 291C 85 90 STA &90 291E A9 FE LDA #&FE 2920 85 91 STA &91 2922 A5 1D LDA &1D 2924 20 9A 4D JSR &4D9A 2927 A9 00 LDA #&00 2929 85 3E STA &3E 292B 85 3F STA &3F 292D 85 40 STA &40 292F 98 TYA 2930 10 1E BPL &2950 2932 A5 91 LDA &91 .DVL8 2934 0A ASL A 2935 26 3E ROL &3E 2937 26 3F ROL &3F 2939 26 40 ROL &40 293B C8 INY 293C D0 F6 BNE &2934 293E 85 3D STA &3D 2940 A5 40 LDA &40 2942 05 D1 ORA &D1 2944 85 40 STA &40 2946 60 RTS .DV13 2947 A5 91 LDA &91 2949 85 3D STA &3D 294B A5 D1 LDA &D1 294D 85 40 STA &40 294F 60 RTS .DV12 2950 F0 F5 BEQ &2947 2952 A5 91 LDA &91 .DVL10 2954 4A LSR A 2955 88 DEY 2956 D0 FC BNE &2954 2958 85 3D STA &3D 295A A5 D1 LDA &D1 295C 85 40 STA &40 295E 60 RTS .cntr 295F AD 4A 0F LDA &0F4A 2962 D0 0C BNE &2970 2964 8A TXA 2965 10 03 BPL &296A 2967 CA DEX 2968 30 06 BMI &2970 .BUMP 296A E8 INX 296B D0 03 BNE &2970 .REDU 296D CA DEX 296E F0 FA BEQ &296A .RE1 2970 60 RTS .BUMP2 2971 85 D1 STA &D1 2973 8A TXA 2974 18 CLC 2975 65 D1 ADC &D1 2977 AA TAX 2978 90 02 BCC &297C 297A A2 FF LDX #&FF .RE2 297C 10 10 BPL &298E 297E A5 D1 LDA &D1 2980 60 RTS .REDU2 2981 85 D1 STA &D1 2983 8A TXA 2984 38 SEC 2985 E5 D1 SBC &D1 2987 AA TAX 2988 B0 02 BCS &298C 298A A2 01 LDX #&01 .RE3 298C 10 F0 BPL &297E 298E AD 4B 0F LDA &0F4B 2991 D0 EB BNE &297E 2993 A2 80 LDX #&80 2995 30 E7 BMI &297E .ARCTAN 2997 A5 1B LDA &1B 2999 45 90 EOR &90 299B 85 06 STA &06 299D A5 90 LDA &90 299F F0 25 BEQ &29C6 29A1 0A ASL A 29A2 85 90 STA &90 29A4 A5 1B LDA &1B 29A6 0A ASL A 29A7 C5 90 CMP &90 29A9 B0 09 BCS &29B4 29AB 20 D0 29 JSR &29D0 29AE 38 SEC .AR4 29AF A6 06 LDX &06 29B1 30 16 BMI &29C9 29B3 60 RTS .AR1 29B4 A6 90 LDX &90 29B6 85 90 STA &90 29B8 86 1B STX &1B 29BA 8A TXA 29BB 20 D0 29 JSR &29D0 29BE 85 D1 STA &D1 29C0 A9 40 LDA #&40 29C2 E5 D1 SBC &D1 29C4 B0 E9 BCS &29AF .AR2 29C6 A9 3F LDA #&3F 29C8 60 RTS .AR3 29C9 85 D1 STA &D1 29CB A9 80 LDA #&80 29CD E5 D1 SBC &D1 29CF 60 RTS .ARS1 29D0 20 92 4D JSR &4D92 29D3 A5 91 LDA &91 29D5 4A LSR A 29D6 4A LSR A 29D7 4A LSR A 29D8 AA TAX 29D9 BD DD 29 LDA &29DD,X 29DC 60 RTS .ACT 29DD 00 29DE 01 29DF 03 29E0 04 29E1 05 29E2 06 29E3 08 29E4 09 29E5 0A 29E6 0B 29E7 0C 29E8 0D 29E9 0F 29EA 10 29EB 11 29EC 12 29ED 13 29EE 14 29EF 15 29F0 16 29F1 17 29F2 18 29F3 19 29F4 19 29F5 1A 29F6 1B 29F7 1C 29F8 1D 29F9 1D 29FA 1E 29FB 1F 29FC 1F .WARP 29FD AD 57 0D LDA &0D57 2A00 18 CLC 2A01 6D 5A 0D ADC &0D5A 2A04 6D 58 0D ADC &0D58 2A07 AA TAX 2A08 BD 42 0D LDA &0D42,X 2A0B 0D 55 0D ORA &0D55 2A0E 0D 5C 0D ORA &0D5C 2A11 D0 43 BNE &2A56 2A13 AC 08 09 LDY &0908 2A16 30 07 BMI &2A1F 2A18 A8 TAY 2A19 20 7C 13 JSR &137C 2A1C 4A LSR A 2A1D F0 37 BEQ &2A56 .WA3 2A1F AC 2C 09 LDY &092C 2A22 30 08 BMI &2A2C 2A24 A0 24 LDY #&24 2A26 20 7A 13 JSR &137A 2A29 4A LSR A 2A2A F0 2A BEQ &2A56 .WA2 2A2C A9 81 LDA #&81 2A2E 85 92 STA &92 2A30 85 91 STA &91 2A32 85 1B STA &1B 2A34 AD 08 09 LDA &0908 2A37 20 5F 28 JSR &285F 2A3A 8D 08 09 STA &0908 2A3D AD 2C 09 LDA &092C 2A40 20 5F 28 JSR &285F 2A43 8D 2C 09 STA &092C 2A46 A9 01 LDA #&01 2A48 85 96 STA &96 2A4A 85 99 STA &99 2A4C 4A LSR A 2A4D 8D 63 0D STA &0D63 2A50 AE 5F 0D LDX &0D5F 2A53 4C 44 2B JMP &2B44 .WA1 2A56 A9 28 LDA #&28 2A58 4C CD 49 JMP &49CD .LASLI 2A5B 20 57 44 JSR &4457 2A5E 29 07 AND #&07 2A60 69 5C ADC #&5C 2A62 8D 15 0F STA &0F15 2A65 20 57 44 JSR &4457 2A68 29 07 AND #&07 2A6A 69 7C ADC #&7C 2A6C 8D 14 0F STA &0F14 2A6F AD 61 0D LDA &0D61 2A72 69 08 ADC #&08 2A74 8D 61 0D STA &0D61 2A77 20 46 3B JSR &3B46 .LASLI2 2A7A A5 96 LDA &96 2A7C D0 36 BNE &2AB4 2A7E A9 20 LDA #&20 2A80 A0 E0 LDY #&E0 2A82 20 89 2A JSR &2A89 2A85 A9 30 LDA #&30 2A87 A0 D0 LDY #&D0 .las 2A89 85 33 STA &33 2A8B AD 14 0F LDA &0F14 2A8E 85 31 STA &31 2A90 AD 15 0F LDA &0F15 2A93 85 32 STA &32 2A95 A9 BF LDA #&BF 2A97 85 34 STA &34 2A99 20 77 18 JSR &1877 2A9C AD 14 0F LDA &0F14 2A9F 85 31 STA &31 2AA1 AD 15 0F LDA &0F15 2AA4 85 32 STA &32 2AA6 84 33 STY &33 2AA8 A9 BF LDA #&BF 2AAA 85 34 STA &34 2AAC 4C 77 18 JMP &1877 .PLUT 2AAF AE 5F 0D LDX &0D5F 2AB2 D0 01 BNE &2AB5 2AB4 60 RTS .PU1 2AB5 CA DEX 2AB6 D0 31 BNE &2AE9 2AB8 A5 55 LDA &55 2ABA 49 80 EOR #&80 2ABC 85 55 STA &55 2ABE A5 5B LDA &5B 2AC0 49 80 EOR #&80 2AC2 85 5B STA &5B 2AC4 A5 5D LDA &5D 2AC6 49 80 EOR #&80 2AC8 85 5D STA &5D 2ACA A5 61 LDA &61 2ACC 49 80 EOR #&80 2ACE 85 61 STA &61 2AD0 A5 63 LDA &63 2AD2 49 80 EOR #&80 2AD4 85 63 STA &63 2AD6 A5 67 LDA &67 2AD8 49 80 EOR #&80 2ADA 85 67 STA &67 2ADC A5 69 LDA &69 2ADE 49 80 EOR #&80 2AE0 85 69 STA &69 2AE2 A5 6D LDA &6D 2AE4 49 80 EOR #&80 2AE6 85 6D STA &6D 2AE8 60 RTS .PU2 2AE9 A9 00 LDA #&00 2AEB E0 02 CPX #&02 2AED 6A ROR A 2AEE 85 AB STA &AB 2AF0 49 80 EOR #&80 2AF2 85 AA STA &AA 2AF4 A5 53 LDA &53 2AF6 A6 59 LDX &59 2AF8 85 59 STA &59 2AFA 86 53 STX &53 2AFC A5 54 LDA &54 2AFE A6 5A LDX &5A 2B00 85 5A STA &5A 2B02 86 54 STX &54 2B04 A5 55 LDA &55 2B06 45 AA EOR &AA 2B08 AA TAX 2B09 A5 5B LDA &5B 2B0B 45 AB EOR &AB 2B0D 85 55 STA &55 2B0F 86 5B STX &5B 2B11 A0 09 LDY #&09 2B13 20 1D 2B JSR &2B1D 2B16 A0 0F LDY #&0F 2B18 20 1D 2B JSR &2B1D 2B1B A0 15 LDY #&15 .PUS1 2B1D B9 53 00 LDA &0053,Y 2B20 B6 57 LDX &57,Y 2B22 99 57 00 STA &0057,Y 2B25 96 53 STX &53,Y 2B27 B9 54 00 LDA &0054,Y 2B2A 45 AA EOR &AA 2B2C AA TAX 2B2D B9 58 00 LDA &0058,Y 2B30 45 AB EOR &AB 2B32 99 54 00 STA &0054,Y 2B35 96 58 STX &58,Y .LO2 2B37 60 RTS .LQ 2B38 8E 5F 0D STX &0D5F 2B3B 20 7B 2B JSR &2B7B 2B3E 20 5B 2B JSR &2B5B 2B41 4C CE 3A JMP &3ACE .LOOK1 2B44 A9 00 LDA #&00 2B46 A4 96 LDY &96 2B48 D0 EE BNE &2B38 2B4A EC 5F 0D CPX &0D5F 2B4D F0 E8 BEQ &2B37 2B4F 8E 5F 0D STX &0D5F 2B52 20 7B 2B JSR &2B7B 2B55 20 B2 1B JSR &1BB2 2B58 20 F5 3A JSR &3AF5 .SIGHT 2B5B AC 5F 0D LDY &0D5F 2B5E B9 10 03 LDA &0310,Y 2B61 F0 D4 BEQ &2B37 2B63 A9 80 LDA #&80 2B65 85 7F STA &7F 2B67 A9 48 LDA #&48 2B69 85 80 STA &80 2B6B A9 14 LDA #&14 2B6D 85 81 STA &81 2B6F 20 0B 2F JSR &2F0B 2B72 A9 0A LDA #&0A 2B74 85 81 STA &81 2B76 4C 0B 2F JMP &2F0B 2B79 A9 01 LDA #&01 .TT66 2B7B 85 96 STA &96 .TTX66 2B7D A9 80 LDA #&80 2B7F 85 7E STA &7E 2B81 0A ASL A 2B82 8D 5D 0D STA &0D5D 2B85 8D 64 0D STA &0D64 2B88 8D 65 0D STA &0D65 2B8B A2 60 LDX #&60 .BOL1 2B8D 20 2D 48 JSR &482D 2B90 E8 INX 2B91 E0 78 CPX #&78 2B93 D0 F8 BNE &2B8D 2B95 A6 2F LDX &2F 2B97 F0 03 BEQ &2B9C 2B99 20 E0 33 JSR &33E0 .BOX 2B9C A0 01 LDY #&01 2B9E 84 2D STY &2D 2BA0 A5 96 LDA &96 2BA2 D0 14 BNE &2BB8 2BA4 A0 0B LDY #&0B 2BA6 84 2C STY &2C 2BA8 AD 5F 0D LDA &0D5F 2BAB 09 60 ORA #&60 2BAD 20 B6 38 JSR &38B6 2BB0 20 70 34 JSR &3470 2BB3 A9 AF LDA #&AF 2BB5 20 B6 38 JSR &38B6 .tt66 2BB8 A2 00 LDX #&00 2BBA 86 31 STX &31 2BBC 86 32 STX &32 2BBE 86 7E STX &7E 2BC0 CA DEX 2BC1 86 33 STX &33 2BC3 20 15 1A JSR &1A15 2BC6 A9 02 LDA #&02 2BC8 85 31 STA &31 2BCA 85 33 STA &33 2BCC 20 CF 2B JSR &2BCF .BOS2 2BCF 20 D2 2B JSR &2BD2 .BOS1 2BD2 A9 00 LDA #&00 2BD4 85 32 STA &32 2BD6 A9 BF LDA #&BF 2BD8 85 34 STA &34 2BDA C6 31 DEC &31 2BDC C6 33 DEC &33 2BDE 4C 77 18 JMP &1877 2BE1 A0 02 LDY #&02 2BE3 2C .DEL8 2BE4 A0 08 LDY #&08 .DELAY 2BE6 20 BF 2C JSR &2CBF 2BE9 88 DEY 2BEA D0 FA BNE &2BE6 2BEC 60 RTS .hm 2BED 20 94 31 JSR &3194 2BF0 20 A4 32 JSR &32A4 2BF3 20 94 31 JSR &3194 2BF6 A5 96 LDA &96 2BF8 F0 25 BEQ &2C1F .CLYNS 2BFA A9 14 LDA #&14 2BFC 85 2D STA &2D 2BFE A9 75 LDA #&75 2C00 85 08 STA &08 2C02 A9 07 LDA #&07 2C04 85 07 STA &07 2C06 20 37 2D JSR &2D37 2C09 A9 00 LDA #&00 2C0B 20 18 2C JSR &2C18 2C0E E6 08 INC &08 2C10 20 18 2C JSR &2C18 2C13 E6 08 INC &08 2C15 C8 INY 2C16 84 2C STY &2C .LYN 2C18 A0 E9 LDY #&E9 .EE2 2C1A 91 07 STA (&07),Y 2C1C 88 DEY 2C1D D0 FB BNE &2C1A .SC5 2C1F 60 RTS .SCAN 2C20 A5 72 LDA &72 2C22 29 10 AND #&10 2C24 F0 F9 BEQ &2C1F 2C26 A5 9B LDA &9B 2C28 30 F5 BMI &2C1F 2C2A A2 FF LDX #&FF 2C2C C9 09 CMP #&09 2C2E D0 02 BNE &2C32 2C30 A2 F0 LDX #&F0 2C32 86 A2 STX &A2 2C34 A5 54 LDA &54 2C36 05 57 ORA &57 2C38 05 5A ORA &5A 2C3A 29 C0 AND #&C0 2C3C D0 E1 BNE &2C1F 2C3E A5 54 LDA &54 2C40 18 CLC 2C41 A6 55 LDX &55 2C43 10 04 BPL &2C49 2C45 49 FF EOR #&FF 2C47 69 01 ADC #&01 .SC2 2C49 69 7B ADC #&7B 2C4B 85 31 STA &31 2C4D A5 5A LDA &5A 2C4F 4A LSR A 2C50 4A LSR A 2C51 18 CLC 2C52 A6 5B LDX &5B 2C54 10 03 BPL &2C59 2C56 49 FF EOR #&FF 2C58 38 SEC .SC3 2C59 69 23 ADC #&23 2C5B 49 FF EOR #&FF 2C5D 85 07 STA &07 2C5F A5 57 LDA &57 2C61 4A LSR A 2C62 18 CLC 2C63 A6 58 LDX &58 2C65 30 03 BMI &2C6A 2C67 49 FF EOR #&FF 2C69 38 SEC .SCD6 2C6A 65 07 ADC &07 2C6C 10 0A BPL &2C78 2C6E C9 C2 CMP #&C2 2C70 B0 02 BCS &2C74 2C72 A9 C2 LDA #&C2 2C74 C9 F7 CMP #&F7 2C76 90 02 BCC &2C7A .ld246 2C78 A9 F6 LDA #&F6 2C7A 85 32 STA &32 2C7C 38 SEC 2C7D E5 07 SBC &07 2C7F 08 PHP .SC48 2C80 48 PHA 2C81 20 C4 3B JSR &3BC4 2C84 BD 73 18 LDA &1873,X 2C87 25 A2 AND &A2 2C89 85 31 STA &31 2C8B 68 PLA 2C8C 28 PLP 2C8D AA TAX 2C8E F0 12 BEQ &2CA2 2C90 90 11 BCC &2CA3 .VLL1 2C92 88 DEY 2C93 10 04 BPL &2C99 2C95 A0 07 LDY #&07 2C97 C6 08 DEC &08 .VL1 2C99 A5 31 LDA &31 2C9B 51 07 EOR (&07),Y 2C9D 91 07 STA (&07),Y 2C9F CA DEX 2CA0 D0 F0 BNE &2C92 .RTS 2CA2 60 RTS 2CA3 C8 INY 2CA4 C0 08 CPY #&08 2CA6 D0 04 BNE &2CAC 2CA8 A0 00 LDY #&00 2CAA E6 08 INC &08 .VLL2 2CAC C8 INY 2CAD C0 08 CPY #&08 2CAF D0 04 BNE &2CB5 2CB1 A0 00 LDY #&00 2CB3 E6 08 INC &08 .VL2 2CB5 A5 31 LDA &31 2CB7 51 07 EOR (&07),Y 2CB9 91 07 STA (&07),Y 2CBB E8 INX 2CBC D0 EE BNE &2CAC 2CBE 60 RTS .WSCAN 2CBF A9 00 LDA #&00 2CC1 85 9A STA &9A 2CC3 A5 9A LDA &9A 2CC5 F0 FC BEQ &2CC3 2CC7 60 RTS ELITE C Assembled at &221C Ends at &2CC8 Code size is &AAC Execute at &1128 Reload at &2404 S.ELTC &221C &2CC8 &1128 &2404 Saving file '3-assembled-output/ELTC.bin' .tnpr 2CC8 48 PHA 2CC9 A2 0C LDX #&0C 2CCB EC 1B 0F CPX &0F1B 2CCE 90 0B BCC &2CDB .Tml 2CD0 7D 17 03 ADC &0317,X 2CD3 CA DEX 2CD4 10 FA BPL &2CD0 2CD6 CD 16 03 CMP &0316 2CD9 68 PLA 2CDA 60 RTS .kg 2CDB AC 1B 0F LDY &0F1B 2CDE 79 17 03 ADC &0317,Y 2CE1 C9 C8 CMP #&C8 2CE3 68 PLA 2CE4 60 RTS .TT20 2CE5 20 E8 2C JSR &2CE8 2CE8 20 EB 2C JSR &2CEB .TT54 2CEB A5 78 LDA &78 2CED 18 CLC 2CEE 65 7A ADC &7A 2CF0 AA TAX 2CF1 A5 79 LDA &79 2CF3 65 7B ADC &7B 2CF5 A8 TAY 2CF6 A5 7A LDA &7A 2CF8 85 78 STA &78 2CFA A5 7B LDA &7B 2CFC 85 79 STA &79 2CFE A5 7D LDA &7D 2D00 85 7B STA &7B 2D02 A5 7C LDA &7C 2D04 85 7A STA &7A 2D06 18 CLC 2D07 8A TXA 2D08 65 7A ADC &7A 2D0A 85 7C STA &7C 2D0C 98 TYA 2D0D 65 7B ADC &7B 2D0F 85 7D STA &7D 2D11 60 RTS .TT146 2D12 AD 2F 0F LDA &0F2F 2D15 0D 30 0F ORA &0F30 2D18 D0 03 BNE &2D1D 2D1A E6 2D INC &2D 2D1C 60 RTS .TT63 2D1D A9 BF LDA #&BF 2D1F 20 B1 38 JSR &38B1 2D22 AE 2F 0F LDX &0F2F 2D25 AC 30 0F LDY &0F30 2D28 38 SEC 2D29 20 E8 33 JSR &33E8 2D2C A9 C3 LDA #&C3 .TT60 2D2E 20 B6 38 JSR &38B6 .TTX69 2D31 E6 2D INC &2D .TT69 2D33 A9 80 LDA #&80 2D35 85 7E STA &7E .TT67 2D37 A9 0D LDA #&0D 2D39 4C B6 38 JMP &38B6 .TT70 2D3C A9 AD LDA #&AD 2D3E 20 B6 38 JSR &38B6 2D41 4C 7E 2D JMP &2D7E .spc 2D44 20 B6 38 JSR &38B6 2D47 4C 70 34 JMP &3470 .TT25 2D4A 20 79 2B JSR &2B79 2D4D A9 09 LDA #&09 2D4F 85 2C STA &2C 2D51 A9 A3 LDA #&A3 2D53 20 B6 38 JSR &38B6 2D56 20 FB 19 JSR &19FB 2D59 20 31 2D JSR &2D31 2D5C E6 2D INC &2D 2D5E 20 12 2D JSR &2D12 2D61 A9 C2 LDA #&C2 2D63 20 B1 38 JSR &38B1 2D66 AD 28 0F LDA &0F28 2D69 18 CLC 2D6A 69 01 ADC #&01 2D6C 4A LSR A 2D6D C9 02 CMP #&02 2D6F F0 CB BEQ &2D3C 2D71 AD 28 0F LDA &0F28 2D74 90 03 BCC &2D79 2D76 E9 05 SBC #&05 2D78 18 CLC .TT71 2D79 69 AA ADC #&AA 2D7B 20 B6 38 JSR &38B6 .TT72 2D7E AD 28 0F LDA &0F28 2D81 4A LSR A 2D82 4A LSR A 2D83 18 CLC 2D84 69 A8 ADC #&A8 2D86 20 2E 2D JSR &2D2E 2D89 A9 A2 LDA #&A2 2D8B 20 B1 38 JSR &38B1 2D8E AD 29 0F LDA &0F29 2D91 18 CLC 2D92 69 B1 ADC #&B1 2D94 20 2E 2D JSR &2D2E 2D97 A9 C4 LDA #&C4 2D99 20 B1 38 JSR &38B1 2D9C AE 2A 0F LDX &0F2A 2D9F E8 INX 2DA0 18 CLC 2DA1 20 BD 1E JSR &1EBD 2DA4 20 31 2D JSR &2D31 2DA7 A9 C0 LDA #&C0 2DA9 20 B1 38 JSR &38B1 2DAC 38 SEC 2DAD AE 2B 0F LDX &0F2B 2DB0 20 BD 1E JSR &1EBD 2DB3 A9 C6 LDA #&C6 2DB5 20 2E 2D JSR &2D2E 2DB8 A9 28 LDA #&28 2DBA 20 B6 38 JSR &38B6 2DBD A5 7C LDA &7C 2DBF 30 08 BMI &2DC9 2DC1 A9 BC LDA #&BC 2DC3 20 B6 38 JSR &38B6 2DC6 4C 05 2E JMP &2E05 .TT75 2DC9 A5 7D LDA &7D 2DCB 4A LSR A 2DCC 4A LSR A 2DCD 48 PHA 2DCE 29 07 AND #&07 2DD0 C9 03 CMP #&03 2DD2 B0 05 BCS &2DD9 2DD4 69 E3 ADC #&E3 2DD6 20 44 2D JSR &2D44 .TT205 2DD9 68 PLA 2DDA 4A LSR A 2DDB 4A LSR A 2DDC 4A LSR A 2DDD C9 06 CMP #&06 2DDF B0 05 BCS &2DE6 2DE1 69 E6 ADC #&E6 2DE3 20 44 2D JSR &2D44 .TT206 2DE6 A5 7B LDA &7B 2DE8 45 79 EOR &79 2DEA 29 07 AND #&07 2DEC 85 7F STA &7F 2DEE C9 06 CMP #&06 2DF0 B0 05 BCS &2DF7 2DF2 69 EC ADC #&EC 2DF4 20 44 2D JSR &2D44 .TT207 2DF7 A5 7D LDA &7D 2DF9 29 03 AND #&03 2DFB 18 CLC 2DFC 65 7F ADC &7F 2DFE 29 07 AND #&07 2E00 69 F2 ADC #&F2 2E02 20 B6 38 JSR &38B6 .TT76 2E05 A9 53 LDA #&53 2E07 20 B6 38 JSR &38B6 2E0A A9 29 LDA #&29 2E0C 20 2E 2D JSR &2D2E 2E0F A9 C1 LDA #&C1 2E11 20 B1 38 JSR &38B1 2E14 AE 2D 0F LDX &0F2D 2E17 AC 2E 0F LDY &0F2E 2E1A 20 E7 33 JSR &33E7 2E1D 20 70 34 JSR &3470 2E20 A9 00 LDA #&00 2E22 85 7E STA &7E 2E24 A9 4D LDA #&4D 2E26 20 B6 38 JSR &38B6 2E29 A9 E2 LDA #&E2 2E2B 20 2E 2D JSR &2D2E 2E2E A9 FA LDA #&FA 2E30 20 B1 38 JSR &38B1 2E33 A5 7D LDA &7D 2E35 A6 7B LDX &7B 2E37 29 0F AND #&0F 2E39 18 CLC 2E3A 69 0B ADC #&0B 2E3C A8 TAY 2E3D 20 E8 33 JSR &33E8 2E40 20 70 34 JSR &3470 2E43 A9 6B LDA #&6B 2E45 20 81 1F JSR &1F81 2E48 A9 6D LDA #&6D 2E4A 4C 81 1F JMP &1F81 .TT24 2E4D A5 79 LDA &79 2E4F 29 07 AND #&07 2E51 8D 28 0F STA &0F28 2E54 A5 7A LDA &7A 2E56 4A LSR A 2E57 4A LSR A 2E58 4A LSR A 2E59 29 07 AND #&07 2E5B 8D 29 0F STA &0F29 2E5E 4A LSR A 2E5F D0 08 BNE &2E69 2E61 AD 28 0F LDA &0F28 2E64 09 02 ORA #&02 2E66 8D 28 0F STA &0F28 .TT77 2E69 AD 28 0F LDA &0F28 2E6C 49 07 EOR #&07 2E6E 18 CLC 2E6F 8D 2A 0F STA &0F2A 2E72 A5 7B LDA &7B 2E74 29 03 AND #&03 2E76 6D 2A 0F ADC &0F2A 2E79 8D 2A 0F STA &0F2A 2E7C AD 29 0F LDA &0F29 2E7F 4A LSR A 2E80 6D 2A 0F ADC &0F2A 2E83 8D 2A 0F STA &0F2A 2E86 0A ASL A 2E87 0A ASL A 2E88 6D 28 0F ADC &0F28 2E8B 6D 29 0F ADC &0F29 2E8E 69 01 ADC #&01 2E90 8D 2B 0F STA &0F2B 2E93 AD 28 0F LDA &0F28 2E96 49 07 EOR #&07 2E98 69 03 ADC #&03 2E9A 85 1B STA &1B 2E9C AD 29 0F LDA &0F29 2E9F 69 04 ADC #&04 2EA1 85 90 STA &90 2EA3 20 82 27 JSR &2782 2EA6 AD 2B 0F LDA &0F2B 2EA9 85 90 STA &90 2EAB 20 82 27 JSR &2782 2EAE 06 1B ASL &1B 2EB0 2A ROL A 2EB1 06 1B ASL &1B 2EB3 2A ROL A 2EB4 06 1B ASL &1B 2EB6 2A ROL A 2EB7 8D 2E 0F STA &0F2E 2EBA A5 1B LDA &1B 2EBC 8D 2D 0F STA &0F2D 2EBF 60 RTS .TT22 2EC0 A9 40 LDA #&40 2EC2 20 7B 2B JSR &2B7B 2EC5 A9 07 LDA #&07 2EC7 85 2C STA &2C 2EC9 20 99 32 JSR &3299 2ECC A9 C7 LDA #&C7 2ECE 20 B6 38 JSR &38B6 2ED1 20 FB 19 JSR &19FB 2ED4 A9 98 LDA #&98 2ED6 20 FF 19 JSR &19FF 2ED9 20 76 2F JSR &2F76 2EDC A2 00 LDX #&00 .TT83 2EDE 86 93 STX &93 2EE0 A6 7B LDX &7B 2EE2 A4 7C LDY &7C 2EE4 98 TYA 2EE5 09 50 ORA #&50 2EE7 85 97 STA &97 2EE9 A5 79 LDA &79 2EEB 4A LSR A 2EEC 18 CLC 2EED 69 18 ADC #&18 2EEF 85 32 STA &32 2EF1 20 DF 1A JSR &1ADF 2EF4 20 E5 2C JSR &2CE5 2EF7 A6 93 LDX &93 2EF9 E8 INX 2EFA D0 E2 BNE &2EDE 2EFC AD 31 0F LDA &0F31 2EFF 85 7F STA &7F 2F01 AD 32 0F LDA &0F32 2F04 4A LSR A 2F05 85 80 STA &80 2F07 A9 04 LDA #&04 2F09 85 81 STA &81 .TT15 2F0B A9 18 LDA #&18 2F0D A6 96 LDX &96 2F0F 10 02 BPL &2F13 2F11 A9 00 LDA #&00 2F13 85 84 STA &84 2F15 A5 7F LDA &7F 2F17 38 SEC 2F18 E5 81 SBC &81 2F1A B0 02 BCS &2F1E 2F1C A9 00 LDA #&00 .TT84 2F1E 85 31 STA &31 2F20 A5 7F LDA &7F 2F22 18 CLC 2F23 65 81 ADC &81 2F25 90 02 BCC &2F29 2F27 A9 FF LDA #&FF 2F29 85 33 STA &33 2F2B A5 80 LDA &80 2F2D 18 CLC 2F2E 65 84 ADC &84 2F30 85 32 STA &32 2F32 20 15 1A JSR &1A15 2F35 A5 80 LDA &80 2F37 38 SEC 2F38 E5 81 SBC &81 2F3A B0 02 BCS &2F3E 2F3C A9 00 LDA #&00 .TT86 2F3E 18 CLC 2F3F 65 84 ADC &84 2F41 85 32 STA &32 2F43 A5 80 LDA &80 2F45 18 CLC 2F46 65 81 ADC &81 2F48 65 84 ADC &84 2F4A C9 98 CMP #&98 2F4C 90 06 BCC &2F54 2F4E A6 96 LDX &96 2F50 30 02 BMI &2F54 2F52 A9 97 LDA #&97 .TT87 2F54 85 34 STA &34 2F56 A5 7F LDA &7F 2F58 85 31 STA &31 2F5A 85 33 STA &33 2F5C 4C 77 18 JMP &1877 .TT126 2F5F A9 68 LDA #&68 2F61 85 7F STA &7F 2F63 A9 5A LDA #&5A 2F65 85 80 STA &80 2F67 A9 10 LDA #&10 2F69 85 81 STA &81 2F6B 20 0B 2F JSR &2F0B 2F6E AD 0D 03 LDA &030D 2F71 85 3D STA &3D 2F73 4C 9A 2F JMP &2F9A .TT14 2F76 A5 96 LDA &96 2F78 30 E5 BMI &2F5F 2F7A AD 0D 03 LDA &030D 2F7D 4A LSR A 2F7E 4A LSR A 2F7F 85 3D STA &3D 2F81 AD 01 03 LDA &0301 2F84 85 7F STA &7F 2F86 AD 02 03 LDA &0302 2F89 4A LSR A 2F8A 85 80 STA &80 2F8C A9 07 LDA #&07 2F8E 85 81 STA &81 2F90 20 0B 2F JSR &2F0B 2F93 A5 80 LDA &80 2F95 18 CLC 2F96 69 18 ADC #&18 2F98 85 80 STA &80 .TT128 2F9A A5 7F LDA &7F 2F9C 85 D2 STA &D2 2F9E A5 80 LDA &80 2FA0 85 E0 STA &E0 2FA2 A2 00 LDX #&00 2FA4 86 E1 STX &E1 2FA6 86 D3 STX &D3 2FA8 E8 INX 2FA9 86 77 STX &77 2FAB A2 02 LDX #&02 2FAD 86 A6 STX &A6 2FAF 20 96 40 JSR &4096 2FB2 60 RTS .TT219 2FB3 20 79 2B JSR &2B79 2FB6 20 86 34 JSR &3486 2FB9 A9 80 LDA #&80 2FBB 85 7E STA &7E 2FBD A9 00 LDA #&00 2FBF 8D 1B 0F STA &0F1B .TT220 2FC2 20 F7 33 JSR &33F7 2FC5 AD 19 0F LDA &0F19 2FC8 D0 0F BNE &2FD9 2FCA 4C 3B 30 JMP &303B .TQ4 2FCD A0 B0 LDY #&B0 .Tc 2FCF 20 70 34 JSR &3470 2FD2 98 TYA 2FD3 20 EF 33 JSR &33EF .TTX224 2FD6 20 B7 37 JSR &37B7 .TT224 2FD9 20 FA 2B JSR &2BFA 2FDC A9 CC LDA #&CC 2FDE 20 B6 38 JSR &38B6 2FE1 AD 1B 0F LDA &0F1B 2FE4 18 CLC 2FE5 69 D0 ADC #&D0 2FE7 20 B6 38 JSR &38B6 2FEA A9 2F LDA #&2F 2FEC 20 B6 38 JSR &38B6 2FEF 20 63 34 JSR &3463 2FF2 A9 3F LDA #&3F 2FF4 20 B6 38 JSR &38B6 2FF7 20 37 2D JSR &2D37 2FFA A2 00 LDX #&00 2FFC 86 91 STX &91 2FFE A2 0C LDX #&0C 3000 86 06 STX &06 3002 20 59 30 JSR &3059 3005 B0 C6 BCS &2FCD 3007 85 1B STA &1B 3009 20 C8 2C JSR &2CC8 300C A0 CE LDY #&CE 300E B0 BF BCS &2FCF 3010 AD 18 0F LDA &0F18 3013 85 90 STA &90 3015 20 39 36 JSR &3639 3018 20 F1 35 JSR &35F1 301B A0 C5 LDY #&C5 301D 90 B0 BCC &2FCF 301F AC 1B 0F LDY &0F1B 3022 A5 91 LDA &91 3024 48 PHA 3025 18 CLC 3026 79 17 03 ADC &0317,Y 3029 99 17 03 STA &0317,Y 302C B9 35 03 LDA &0335,Y 302F 38 SEC 3030 E5 91 SBC &91 3032 99 35 03 STA &0335,Y 3035 68 PLA 3036 F0 03 BEQ &303B 3038 20 AF 37 JSR &37AF .TT222 303B AD 1B 0F LDA &0F1B 303E 18 CLC 303F 69 05 ADC #&05 3041 85 2D STA &2D 3043 A9 00 LDA #&00 3045 85 2C STA &2C 3047 EE 1B 0F INC &0F1B 304A AD 1B 0F LDA &0F1B 304D C9 11 CMP #&11 304F B0 03 BCS &3054 3051 4C C2 2F JMP &2FC2 .BAY2 3054 A9 77 LDA #&77 3056 4C 83 45 JMP &4583 .gnum 3059 A2 00 LDX #&00 305B 86 91 STX &91 305D A2 0C LDX #&0C 305F 86 06 STX &06 .TT223 3061 20 02 4B JSR &4B02 3064 85 90 STA &90 3066 38 SEC 3067 E9 30 SBC #&30 3069 90 27 BCC &3092 306B C9 0A CMP #&0A 306D B0 E5 BCS &3054 306F 85 92 STA &92 3071 A5 91 LDA &91 3073 C9 1A CMP #&1A 3075 B0 1B BCS &3092 3077 0A ASL A 3078 85 D1 STA &D1 307A 0A ASL A 307B 0A ASL A 307C 65 D1 ADC &D1 307E 65 92 ADC &92 3080 85 91 STA &91 3082 CD 19 0F CMP &0F19 3085 F0 02 BEQ &3089 3087 B0 09 BCS &3092 .TT226 3089 A5 90 LDA &90 308B 20 81 1F JSR &1F81 308E C6 06 DEC &06 3090 D0 CF BNE &3061 .OUT 3092 A5 91 LDA &91 3094 60 RTS .TT208 3095 A9 04 LDA #&04 3097 20 7B 2B JSR &2B7B 309A A9 04 LDA #&04 309C 85 2D STA &2D 309E 85 2C STA &2C 30A0 A9 CD LDA #&CD 30A2 20 B6 38 JSR &38B6 30A5 A9 CE LDA #&CE 30A7 20 B1 38 JSR &38B1 .TT210 30AA A0 00 LDY #&00 .TT211 30AC 8C 1B 0F STY &0F1B 30AF BE 17 03 LDX &0317,Y 30B2 F0 58 BEQ &310C 30B4 98 TYA 30B5 0A ASL A 30B6 0A ASL A 30B7 A8 TAY 30B8 B9 BD 4B LDA &4BBD,Y 30BB 85 80 STA &80 30BD 8A TXA 30BE 48 PHA 30BF 20 33 2D JSR &2D33 30C2 18 CLC 30C3 AD 1B 0F LDA &0F1B 30C6 69 D0 ADC #&D0 30C8 20 B6 38 JSR &38B6 30CB A9 0E LDA #&0E 30CD 85 2C STA &2C 30CF 68 PLA 30D0 AA TAX 30D1 18 CLC 30D2 20 BD 1E JSR &1EBD 30D5 20 63 34 JSR &3463 30D8 A5 96 LDA &96 30DA C9 04 CMP #&04 30DC D0 2E BNE &310C 30DE A9 CD LDA #&CD 30E0 20 47 31 JSR &3147 30E3 90 27 BCC &310C 30E5 AD 1B 0F LDA &0F1B 30E8 A2 FF LDX #&FF 30EA 86 7E STX &7E 30EC 20 F7 33 JSR &33F7 30EF AC 1B 0F LDY &0F1B 30F2 B9 17 03 LDA &0317,Y 30F5 85 1B STA &1B 30F7 AD 18 0F LDA &0F18 30FA 85 90 STA &90 30FC 20 39 36 JSR &3639 30FF 20 18 36 JSR &3618 3102 A9 00 LDA #&00 3104 AC 1B 0F LDY &0F1B 3107 99 17 03 STA &0317,Y 310A 85 7E STA &7E .TT212 310C AC 1B 0F LDY &0F1B 310F C8 INY 3110 C0 11 CPY #&11 3112 B0 03 BCS &3117 3114 4C AC 30 JMP &30AC 3117 A5 96 LDA &96 3119 C9 04 CMP #&04 311B D0 06 BNE &3123 311D 20 B7 37 JSR &37B7 3120 4C 54 30 JMP &3054 3123 60 RTS .TT213 3124 A9 08 LDA #&08 3126 20 7B 2B JSR &2B7B 3129 A9 0B LDA #&0B 312B 85 2C STA &2C 312D A9 A4 LDA #&A4 312F 20 2E 2D JSR &2D2E 3132 20 F7 19 JSR &19F7 3135 20 82 38 JSR &3882 3138 AD 16 03 LDA &0316 313B C9 1A CMP #&1A 313D 90 05 BCC &3144 313F A9 6B LDA #&6B 3141 20 B6 38 JSR &38B6 3144 4C AA 30 JMP &30AA .TT214 3147 48 PHA 3148 20 70 34 JSR &3470 314B 68 PLA .TT221 314C 20 B6 38 JSR &38B6 314F A9 E1 LDA #&E1 3151 20 B6 38 JSR &38B6 3154 20 02 4B JSR &4B02 3157 09 20 ORA #&20 3159 C9 79 CMP #&79 315B F0 05 BEQ &3162 315D A9 6E LDA #&6E 315F 4C 81 1F JMP &1F81 .TT218 3162 20 81 1F JSR &1F81 3165 38 SEC 3166 60 RTS .TT16 3167 8A TXA 3168 48 PHA 3169 88 DEY 316A 98 TYA 316B 49 FF EOR #&FF 316D 48 PHA 316E 20 BF 2C JSR &2CBF 3171 20 94 31 JSR &3194 3174 68 PLA 3175 85 82 STA &82 3177 AD 32 0F LDA &0F32 317A 20 AC 31 JSR &31AC 317D A5 83 LDA &83 317F 8D 32 0F STA &0F32 3182 85 80 STA &80 3184 68 PLA 3185 85 82 STA &82 3187 AD 31 0F LDA &0F31 318A 20 AC 31 JSR &31AC 318D A5 83 LDA &83 318F 8D 31 0F STA &0F31 3192 85 7F STA &7F .TT103 3194 A5 96 LDA &96 3196 F0 24 BEQ &31BC 3198 30 23 BMI &31BD 319A AD 31 0F LDA &0F31 319D 85 7F STA &7F 319F AD 32 0F LDA &0F32 31A2 4A LSR A 31A3 85 80 STA &80 31A5 A9 04 LDA #&04 31A7 85 81 STA &81 31A9 4C 0B 2F JMP &2F0B .TT123 31AC 85 83 STA &83 31AE 18 CLC 31AF 65 82 ADC &82 31B1 A6 82 LDX &82 31B3 30 03 BMI &31B8 31B5 90 03 BCC &31BA 31B7 60 RTS .TT124 31B8 90 02 BCC &31BC .TT125 31BA 85 83 STA &83 .TT180 31BC 60 RTS .TT105 31BD AD 31 0F LDA &0F31 31C0 38 SEC 31C1 ED 01 03 SBC &0301 31C4 C9 26 CMP #&26 31C6 90 04 BCC &31CC 31C8 C9 E6 CMP #&E6 31CA 90 F0 BCC &31BC .TT179 31CC 0A ASL A 31CD 0A ASL A 31CE 18 CLC 31CF 69 68 ADC #&68 31D1 85 7F STA &7F 31D3 AD 32 0F LDA &0F32 31D6 38 SEC 31D7 ED 02 03 SBC &0302 31DA C9 26 CMP #&26 31DC 90 04 BCC &31E2 31DE C9 DC CMP #&DC 31E0 90 DA BCC &31BC 31E2 0A ASL A 31E3 18 CLC 31E4 69 5A ADC #&5A 31E6 85 80 STA &80 31E8 A9 08 LDA #&08 31EA 85 81 STA &81 31EC 4C 0B 2F JMP &2F0B .TT23 31EF A9 80 LDA #&80 31F1 20 7B 2B JSR &2B7B 31F4 A9 07 LDA #&07 31F6 85 2C STA &2C 31F8 A9 BE LDA #&BE 31FA 20 F4 19 JSR &19F4 31FD 20 76 2F JSR &2F76 3200 20 94 31 JSR &3194 3203 20 99 32 JSR &3299 3206 A9 00 LDA #&00 3208 85 A8 STA &A8 320A A2 18 LDX #&18 .EE3 320C 95 53 STA &53,X 320E CA DEX 320F 10 FB BPL &320C .TT182 3211 A5 7B LDA &7B 3213 38 SEC 3214 ED 01 03 SBC &0301 3217 B0 04 BCS &321D 3219 49 FF EOR #&FF 321B 69 01 ADC #&01 .TT184 321D C9 14 CMP #&14 321F B0 6E BCS &328F 3221 A5 79 LDA &79 3223 38 SEC 3224 ED 02 03 SBC &0302 3227 B0 04 BCS &322D 3229 49 FF EOR #&FF 322B 69 01 ADC #&01 .TT186 322D C9 26 CMP #&26 322F B0 5E BCS &328F 3231 A5 7B LDA &7B 3233 38 SEC 3234 ED 01 03 SBC &0301 3237 0A ASL A 3238 0A ASL A 3239 69 68 ADC #&68 323B 85 37 STA &37 323D 4A LSR A 323E 4A LSR A 323F 4A LSR A 3240 85 2C STA &2C 3242 E6 2C INC &2C 3244 A5 79 LDA &79 3246 38 SEC 3247 ED 02 03 SBC &0302 324A 0A ASL A 324B 69 5A ADC #&5A 324D 85 E0 STA &E0 324F 4A LSR A 3250 4A LSR A 3251 4A LSR A 3252 A8 TAY 3253 B6 53 LDX &53,Y 3255 F0 0B BEQ &3262 3257 C8 INY 3258 B6 53 LDX &53,Y 325A F0 06 BEQ &3262 325C 88 DEY 325D 88 DEY 325E B6 53 LDX &53,Y 3260 D0 10 BNE &3272 .EE4 3262 84 2D STY &2D 3264 C0 03 CPY #&03 3266 90 27 BCC &328F 3268 CA DEX 3269 96 53 STX &53,Y 326B A9 80 LDA #&80 326D 85 7E STA &7E 326F 20 21 38 JSR &3821 .ee1 3272 A9 00 LDA #&00 3274 85 D3 STA &D3 3276 85 E1 STA &E1 3278 85 3E STA &3E 327A A5 37 LDA &37 327C 85 D2 STA &D2 327E A5 7D LDA &7D 3280 29 01 AND #&01 3282 69 02 ADC #&02 3284 85 3D STA &3D 3286 20 27 3B JSR &3B27 3289 20 5A 3F JSR &3F5A 328C 20 27 3B JSR &3B27 .TT187 328F 20 E5 2C JSR &2CE5 3292 E6 A8 INC &A8 3294 F0 0D BEQ &32A3 3296 4C 11 32 JMP &3211 .TT81 3299 A2 05 LDX #&05 329B BD 03 03 LDA &0303,X 329E 95 78 STA &78,X 32A0 CA DEX 32A1 10 F8 BPL &329B 32A3 60 RTS .TT111 32A4 20 99 32 JSR &3299 32A7 A0 7F LDY #&7F 32A9 84 D1 STY &D1 32AB A9 00 LDA #&00 32AD 85 8F STA &8F .TT130 32AF A5 7B LDA &7B 32B1 38 SEC 32B2 ED 31 0F SBC &0F31 32B5 B0 04 BCS &32BB 32B7 49 FF EOR #&FF 32B9 69 01 ADC #&01 .TT132 32BB 4A LSR A 32BC 85 92 STA &92 32BE A5 79 LDA &79 32C0 38 SEC 32C1 ED 32 0F SBC &0F32 32C4 B0 04 BCS &32CA 32C6 49 FF EOR #&FF 32C8 69 01 ADC #&01 .TT134 32CA 4A LSR A 32CB 18 CLC 32CC 65 92 ADC &92 32CE C5 D1 CMP &D1 32D0 B0 0B BCS &32DD 32D2 85 D1 STA &D1 32D4 A2 05 LDX #&05 .TT136 32D6 B5 78 LDA &78,X 32D8 95 7F STA &7F,X 32DA CA DEX 32DB 10 F9 BPL &32D6 .TT135 32DD 20 E5 2C JSR &2CE5 32E0 E6 8F INC &8F 32E2 D0 CB BNE &32AF 32E4 A2 05 LDX #&05 .TT137 32E6 B5 7F LDA &7F,X 32E8 95 78 STA &78,X 32EA CA DEX 32EB 10 F9 BPL &32E6 32ED A5 79 LDA &79 32EF 8D 32 0F STA &0F32 32F2 A5 7B LDA &7B 32F4 8D 31 0F STA &0F31 32F7 38 SEC 32F8 ED 01 03 SBC &0301 32FB B0 04 BCS &3301 32FD 49 FF EOR #&FF 32FF 69 01 ADC #&01 .TT139 3301 20 6F 27 JSR &276F 3304 85 3E STA &3E 3306 A5 1B LDA &1B 3308 85 3D STA &3D 330A AD 32 0F LDA &0F32 330D 38 SEC 330E ED 02 03 SBC &0302 3311 B0 04 BCS &3317 3313 49 FF EOR #&FF 3315 69 01 ADC #&01 .TT141 3317 4A LSR A 3318 20 6F 27 JSR &276F 331B 48 PHA 331C A5 1B LDA &1B 331E 18 CLC 331F 65 3D ADC &3D 3321 85 90 STA &90 3323 68 PLA 3324 65 3E ADC &3E 3326 85 91 STA &91 3328 20 5B 4D JSR &4D5B 332B A5 90 LDA &90 332D 0A ASL A 332E A2 00 LDX #&00 3330 8E 30 0F STX &0F30 3333 2E 30 0F ROL &0F30 3336 0A ASL A 3337 2E 30 0F ROL &0F30 333A 8D 2F 0F STA &0F2F 333D 4C 4D 2E JMP &2E4D .hy6 3340 20 FA 2B JSR &2BFA 3343 A9 0F LDA #&0F 3345 85 2C STA &2C 3347 4C B6 38 JMP &38B6 .hyp 334A A5 9F LDA &9F 334C D0 F2 BNE &3340 334E A5 2F LDA &2F 3350 D0 67 BNE &33B9 3352 20 0F 4A JSR &4A0F 3355 30 3B BMI &3392 3357 20 ED 2B JSR &2BED 335A AD 2F 0F LDA &0F2F 335D 0D 30 0F ORA &0F30 3360 F0 57 BEQ &33B9 3362 A9 07 LDA #&07 3364 85 2C STA &2C 3366 A9 17 LDA #&17 3368 85 2D STA &2D 336A A9 00 LDA #&00 336C 85 7E STA &7E 336E A9 BD LDA #&BD 3370 20 B6 38 JSR &38B6 3373 AD 30 0F LDA &0F30 3376 D0 75 BNE &33ED 3378 AD 0D 03 LDA &030D 337B CD 2F 0F CMP &0F2F 337E 90 6D BCC &33ED 3380 A9 2D LDA #&2D 3382 20 B6 38 JSR &38B6 3385 20 21 38 JSR &3821 .wW 3388 A9 0F LDA #&0F 338A 85 2F STA &2F 338C 85 2E STA &2E 338E AA TAX 338F 4C E0 33 JMP &33E0 .Ghy 3392 AE 2D 03 LDX &032D 3395 F0 48 BEQ &33DF 3397 E8 INX 3398 8E 2D 03 STX &032D 339B 8E 34 03 STX &0334 339E 20 88 33 JSR &3388 33A1 A2 05 LDX #&05 33A3 EE 0F 03 INC &030F 33A6 AD 0F 03 LDA &030F 33A9 29 07 AND #&07 33AB 8D 0F 03 STA &030F .G1 33AE BD 03 03 LDA &0303,X 33B1 0A ASL A 33B2 3E 03 03 ROL &0303,X 33B5 CA DEX 33B6 10 F6 BPL &33AE .zZ 33B8 A9 60 LDA #&60 33BA 8D 31 0F STA &0F31 33BD 8D 32 0F STA &0F32 33C0 20 BA 35 JSR &35BA 33C3 20 A4 32 JSR &32A4 33C6 A2 00 LDX #&00 33C8 8E 2F 0F STX &0F2F 33CB 8E 30 0F STX &0F30 33CE A9 74 LDA #&74 33D0 20 29 4B JSR &4B29 .jmp 33D3 AD 31 0F LDA &0F31 33D6 8D 01 03 STA &0301 33D9 AD 32 0F LDA &0F32 33DC 8D 02 03 STA &0302 .hy5 33DF 60 RTS .ee3 33E0 A0 01 LDY #&01 33E2 84 2D STY &2D 33E4 88 DEY 33E5 84 2C STY &2C .pr6 33E7 18 CLC .pr5 33E8 A9 05 LDA #&05 33EA 4C C1 1E JMP &1EC1 .TT147 33ED A9 CA LDA #&CA .prq 33EF 20 B6 38 JSR &38B6 33F2 A9 3F LDA #&3F 33F4 4C B6 38 JMP &38B6 .TT151 33F7 48 PHA 33F8 85 83 STA &83 33FA 0A ASL A 33FB 0A ASL A 33FC 85 7F STA &7F 33FE A9 01 LDA #&01 3400 85 2C STA &2C 3402 68 PLA 3403 69 D0 ADC #&D0 3405 20 B6 38 JSR &38B6 3408 A9 0E LDA #&0E 340A 85 2C STA &2C 340C A6 7F LDX &7F 340E BD BD 4B LDA &4BBD,X 3411 85 80 STA &80 3413 AD 46 03 LDA &0346 3416 3D BF 4B AND &4BBF,X 3419 18 CLC 341A 7D BC 4B ADC &4BBC,X 341D 8D 18 0F STA &0F18 3420 20 63 34 JSR &3463 3423 20 BC 34 JSR &34BC 3426 A5 80 LDA &80 3428 30 08 BMI &3432 342A AD 18 0F LDA &0F18 342D 65 82 ADC &82 342F 4C 38 34 JMP &3438 .TT155 3432 AD 18 0F LDA &0F18 3435 38 SEC 3436 E5 82 SBC &82 .TT156 3438 8D 18 0F STA &0F18 343B 85 1B STA &1B 343D A9 00 LDA #&00 343F 20 3C 36 JSR &363C 3442 38 SEC 3443 20 E8 33 JSR &33E8 3446 A4 83 LDY &83 3448 A9 05 LDA #&05 344A BE 35 03 LDX &0335,Y 344D 8E 19 0F STX &0F19 3450 18 CLC 3451 F0 06 BEQ &3459 3453 20 BF 1E JSR &1EBF 3456 4C 63 34 JMP &3463 .TT172 3459 A5 2C LDA &2C 345B 69 04 ADC #&04 345D 85 2C STA &2C 345F A9 2D LDA #&2D 3461 D0 0F BNE &3472 .TT152 3463 A5 80 LDA &80 3465 29 60 AND #&60 3467 F0 0C BEQ &3475 3469 C9 20 CMP #&20 346B F0 0F BEQ &347C 346D 20 81 34 JSR &3481 .TT162 3470 A9 20 LDA #&20 3472 4C B6 38 JMP &38B6 .TT160 3475 A9 74 LDA #&74 3477 20 81 1F JSR &1F81 347A 90 F4 BCC &3470 .TT161 347C A9 6B LDA #&6B 347E 20 81 1F JSR &1F81 .TT16a 3481 A9 67 LDA #&67 3483 4C 81 1F JMP &1F81 .TT163 3486 A9 11 LDA #&11 3488 85 2C STA &2C 348A A9 FF LDA #&FF 348C D0 E4 BNE &3472 .TT167 348E A9 10 LDA #&10 3490 20 7B 2B JSR &2B7B 3493 A9 05 LDA #&05 3495 85 2C STA &2C 3497 A9 A7 LDA #&A7 3499 20 F4 19 JSR &19F4 349C A9 03 LDA #&03 349E 85 2D STA &2D 34A0 20 86 34 JSR &3486 34A3 A9 00 LDA #&00 34A5 8D 1B 0F STA &0F1B .TT168 34A8 A2 80 LDX #&80 34AA 86 7E STX &7E 34AC 20 F7 33 JSR &33F7 34AF E6 2D INC &2D 34B1 EE 1B 0F INC &0F1B 34B4 AD 1B 0F LDA &0F1B 34B7 C9 11 CMP #&11 34B9 90 ED BCC &34A8 34BB 60 RTS .var 34BC A5 80 LDA &80 34BE 29 1F AND #&1F 34C0 AC 1A 0F LDY &0F1A 34C3 85 81 STA &81 34C5 18 CLC 34C6 A9 00 LDA #&00 34C8 8D 45 03 STA &0345 .TT153 34CB 88 DEY 34CC 30 05 BMI &34D3 34CE 65 81 ADC &81 34D0 4C CB 34 JMP &34CB .TT154 34D3 85 82 STA &82 34D5 60 RTS .hyp1 34D6 20 A4 32 JSR &32A4 34D9 20 D3 33 JSR &33D3 34DC A2 05 LDX #&05 .TT112 34DE B5 78 LDA &78,X 34E0 9D 22 0F STA &0F22,X 34E3 CA DEX 34E4 10 F8 BPL &34DE 34E6 E8 INX 34E7 8E 63 0D STX &0D63 34EA AD 28 0F LDA &0F28 34ED 8D 1A 0F STA &0F1A 34F0 AD 2A 0F LDA &0F2A 34F3 8D 1D 0F STA &0F1D 34F6 AD 29 0F LDA &0F29 34F9 8D 1C 0F STA &0F1C 34FC 60 RTS .GVL 34FD 20 57 44 JSR &4457 3500 8D 46 03 STA &0346 3503 A2 00 LDX #&00 3505 86 A7 STX &A7 .hy9 3507 BD BD 4B LDA &4BBD,X 350A 85 80 STA &80 350C 20 BC 34 JSR &34BC 350F BD BF 4B LDA &4BBF,X 3512 2D 46 03 AND &0346 3515 18 CLC 3516 7D BE 4B ADC &4BBE,X 3519 A4 80 LDY &80 351B 30 06 BMI &3523 351D 38 SEC 351E E5 82 SBC &82 3520 4C 26 35 JMP &3526 .TT157 3523 18 CLC 3524 65 82 ADC &82 .TT158 3526 10 02 BPL &352A 3528 A9 00 LDA #&00 .TT159 352A A4 A7 LDY &A7 352C 29 3F AND #&3F 352E 99 35 03 STA &0335,Y 3531 C8 INY 3532 98 TYA 3533 85 A7 STA &A7 3535 0A ASL A 3536 0A ASL A 3537 AA TAX 3538 C9 3F CMP #&3F 353A 90 CB BCC &3507 .hyR 353C 60 RTS .GTHG 353D 20 35 44 JSR &4435 3540 A9 FF LDA #&FF 3542 85 73 STA &73 3544 A9 06 LDA #&06 3546 20 82 3C JSR &3C82 3549 A9 0C LDA #&0C 354B 4C 82 3C JMP &3C82 .ptg 354E 4E 0E 03 LSR &030E 3551 38 SEC 3552 2E 0E 03 ROL &030E .MJP 3555 20 79 2B JSR &2B79 3558 20 63 25 JSR &2563 355B 20 B1 43 JSR &43B1 355E 8C 5C 0D STY &0D5C .MJP1 3561 20 3D 35 JSR &353D 3564 A9 03 LDA #&03 3566 CD 53 0D CMP &0D53 3569 B0 F6 BCS &3561 356B 8D 33 0F STA &0F33 356E A2 00 LDX #&00 3570 20 44 2B JSR &2B44 3573 AD 02 03 LDA &0302 3576 49 1F EOR #&1F 3578 8D 02 03 STA &0302 357B 60 RTS .TT18 357C AD 0D 03 LDA &030D 357F 38 SEC 3580 ED 2F 0F SBC &0F2F 3583 8D 0D 03 STA &030D 3586 A5 96 LDA &96 3588 D0 06 BNE &3590 358A 20 7B 2B JSR &2B7B 358D 20 63 25 JSR &2563 .ee5 3590 20 0F 4A JSR &4A0F 3593 2D 4C 0F AND &0F4C 3596 30 B6 BMI &354E 3598 20 57 44 JSR &4457 359B C9 FD CMP #&FD 359D B0 B6 BCS &3555 359F 20 D9 34 JSR &34D9 35A2 20 FD 34 JSR &34FD 35A5 20 B1 43 JSR &43B1 35A8 20 9C 3A JSR &3A9C 35AB A5 96 LDA &96 35AD 29 3F AND #&3F 35AF D0 8B BNE &353C 35B1 20 7D 2B JSR &2B7D 35B4 A5 96 LDA &96 35B6 D0 31 BNE &35E9 35B8 E6 96 INC &96 .TT110 35BA A6 9F LDX &9F 35BC F0 24 BEQ &35E2 35BE 20 76 25 JSR &2576 35C1 20 B1 43 JSR &43B1 35C4 20 A4 32 JSR &32A4 35C7 E6 5B INC &5B 35C9 20 89 3A JSR &3A89 35CC A9 80 LDA #&80 35CE 85 5B STA &5B 35D0 E6 5A INC &5A 35D2 20 5D 3C JSR &3C5D 35D5 A9 0C LDA #&0C 35D7 85 8C STA &8C 35D9 20 5F 46 JSR &465F 35DC 0D 34 03 ORA &0334 35DF 8D 34 03 STA &0334 .NLUNCH 35E2 A2 00 LDX #&00 35E4 86 9F STX &9F 35E6 4C 44 2B JMP &2B44 .TT114 35E9 30 03 BMI &35EE 35EB 4C C0 2E JMP &2EC0 .TT115 35EE 4C EF 31 JMP &31EF .LCASH 35F1 86 06 STX &06 35F3 AD 0C 03 LDA &030C 35F6 38 SEC 35F7 E5 06 SBC &06 35F9 8D 0C 03 STA &030C 35FC 84 06 STY &06 35FE AD 0B 03 LDA &030B 3601 E5 06 SBC &06 3603 8D 0B 03 STA &030B 3606 AD 0A 03 LDA &030A 3609 E9 00 SBC #&00 360B 8D 0A 03 STA &030A 360E AD 09 03 LDA &0309 3611 E9 00 SBC #&00 3613 8D 09 03 STA &0309 3616 B0 20 BCS &3638 .MCASH 3618 8A TXA 3619 18 CLC 361A 6D 0C 03 ADC &030C 361D 8D 0C 03 STA &030C 3620 98 TYA 3621 6D 0B 03 ADC &030B 3624 8D 0B 03 STA &030B 3627 AD 0A 03 LDA &030A 362A 69 00 ADC #&00 362C 8D 0A 03 STA &030A 362F AD 09 03 LDA &0309 3632 69 00 ADC #&00 3634 8D 09 03 STA &0309 3637 18 CLC .TT113 3638 60 RTS .GCASH 3639 20 82 27 JSR &2782 .GC2 363C 06 1B ASL &1B 363E 2A ROL A 363F 06 1B ASL &1B 3641 2A ROL A 3642 A8 TAY 3643 A6 1B LDX &1B 3645 60 RTS .bay 3646 4C 4D 47 JMP &474D .EQSHP 3649 20 F8 1F JSR &1FF8 364C A9 20 LDA #&20 364E 20 7B 2B JSR &2B7B 3651 A9 0C LDA #&0C 3653 85 2C STA &2C 3655 A9 CF LDA #&CF 3657 20 44 2D JSR &2D44 365A A9 B9 LDA #&B9 365C 20 F4 19 JSR &19F4 365F A9 80 LDA #&80 3661 85 7E STA &7E 3663 E6 2D INC &2D 3665 AD 1D 0F LDA &0F1D 3668 18 CLC 3669 69 03 ADC #&03 366B C9 0C CMP #&0C 366D 90 02 BCC &3671 366F A9 0C LDA #&0C 3671 85 90 STA &90 3673 8D 19 0F STA &0F19 3676 E6 90 INC &90 3678 A9 46 LDA #&46 367A 38 SEC 367B ED 0D 03 SBC &030D 367E 0A ASL A 367F 8D CD 1D STA &1DCD 3682 A2 01 LDX #&01 .EQL1 3684 86 98 STX &98 3686 20 37 2D JSR &2D37 3689 A6 98 LDX &98 368B 18 CLC 368C 20 BD 1E JSR &1EBD 368F 20 70 34 JSR &3470 3692 A5 98 LDA &98 3694 18 CLC 3695 69 68 ADC #&68 3697 20 B6 38 JSR &38B6 369A A5 98 LDA &98 369C 20 CF 37 JSR &37CF 369F 38 SEC 36A0 A9 19 LDA #&19 36A2 85 2C STA &2C 36A4 A9 06 LDA #&06 36A6 20 C1 1E JSR &1EC1 36A9 A6 98 LDX &98 36AB E8 INX 36AC E4 90 CPX &90 36AE 90 D4 BCC &3684 36B0 20 FA 2B JSR &2BFA 36B3 A9 7F LDA #&7F 36B5 20 EF 33 JSR &33EF 36B8 20 59 30 JSR &3059 36BB F0 89 BEQ &3646 36BD B0 87 BCS &3646 36BF E9 00 SBC #&00 36C1 A2 02 LDX #&02 36C3 86 2C STX &2C 36C5 E6 2D INC &2D 36C7 48 PHA 36C8 20 BF 37 JSR &37BF 36CB 68 PLA 36CC D0 07 BNE &36D5 36CE 85 99 STA &99 36D0 A2 46 LDX #&46 36D2 8E 0D 03 STX &030D .et0 36D5 C9 01 CMP #&01 36D7 D0 10 BNE &36E9 36D9 AE 33 03 LDX &0333 36DC E8 INX 36DD A0 75 LDY #&75 36DF E0 05 CPX #&05 36E1 B0 68 BCS &374B 36E3 8E 33 03 STX &0333 36E6 20 0E 44 JSR &440E .et1 36E9 A0 6B LDY #&6B 36EB C9 02 CMP #&02 36ED D0 0A BNE &36F9 36EF A2 25 LDX #&25 36F1 EC 16 03 CPX &0316 36F4 F0 55 BEQ &374B 36F6 8E 16 03 STX &0316 .et2 36F9 C9 03 CMP #&03 36FB D0 09 BNE &3706 36FD C8 INY 36FE AE 28 03 LDX &0328 3701 D0 48 BNE &374B 3703 CE 28 03 DEC &0328 .et3 3706 C9 04 CMP #&04 3708 D0 15 BNE &371F 370A 20 DC 37 JSR &37DC 370D A9 04 LDA #&04 370F BC 10 03 LDY &0310,X 3712 F0 04 BEQ &3718 .ed7 3714 A0 BB LDY #&BB 3716 D0 33 BNE &374B .ed4 3718 A9 0F LDA #&0F 371A 9D 10 03 STA &0310,X 371D A9 04 LDA #&04 .et4 371F C9 05 CMP #&05 3721 D0 1D BNE &3740 3723 20 DC 37 JSR &37DC 3726 86 06 STX &06 3728 A9 05 LDA #&05 372A BC 10 03 LDY &0310,X 372D F0 0A BEQ &3739 372F 30 E3 BMI &3714 3731 A9 04 LDA #&04 3733 20 D2 37 JSR &37D2 3736 20 18 36 JSR &3618 .ed5 3739 A9 8F LDA #&8F 373B A6 06 LDX &06 373D 9D 10 03 STA &0310,X .et5 3740 A0 6F LDY #&6F 3742 C9 06 CMP #&06 3744 D0 20 BNE &3766 3746 AE 29 03 LDX &0329 3749 F0 18 BEQ &3763 .pres 374B 84 3D STY &3D 374D 20 D2 37 JSR &37D2 3750 20 18 36 JSR &3618 3753 A5 3D LDA &3D 3755 20 44 2D JSR &2D44 3758 A9 1F LDA #&1F 375A 20 B6 38 JSR &38B6 .err 375D 20 B7 37 JSR &37B7 3760 4C 4D 47 JMP &474D .ed9 3763 CE 29 03 DEC &0329 .et6 3766 C8 INY 3767 C9 07 CMP #&07 3769 D0 08 BNE &3773 376B AE 2E 03 LDX &032E 376E D0 DB BNE &374B 3770 CE 2E 03 DEC &032E .et7 3773 C8 INY 3774 C9 08 CMP #&08 3776 D0 0A BNE &3782 3778 AE 2A 03 LDX &032A 377B D0 CE BNE &374B 377D A2 7F LDX #&7F 377F 8E 2A 03 STX &032A .et8 3782 C8 INY 3783 C9 09 CMP #&09 3785 D0 08 BNE &378F 3787 AE 2B 03 LDX &032B 378A D0 BF BNE &374B 378C EE 2B 03 INC &032B .etA 378F C8 INY 3790 C9 0A CMP #&0A 3792 D0 08 BNE &379C 3794 AE 2C 03 LDX &032C 3797 D0 B2 BNE &374B 3799 CE 2C 03 DEC &032C .etB 379C C8 INY 379D C9 0B CMP #&0B 379F D0 08 BNE &37A9 37A1 AE 2D 03 LDX &032D 37A4 D0 A5 BNE &374B 37A6 CE 2D 03 DEC &032D .et9 37A9 20 AF 37 JSR &37AF 37AC 4C 49 36 JMP &3649 .dn 37AF 20 70 34 JSR &3470 37B2 A9 77 LDA #&77 37B4 20 44 2D JSR &2D44 .dn2 37B7 20 CB 49 JSR &49CB 37BA A0 32 LDY #&32 37BC 4C E6 2B JMP &2BE6 .eq 37BF 20 D2 37 JSR &37D2 37C2 20 F1 35 JSR &35F1 37C5 B0 14 BCS &37DB 37C7 A9 C5 LDA #&C5 37C9 20 EF 33 JSR &33EF 37CC 4C 5D 37 JMP &375D 37CF 38 SEC 37D0 E9 01 SBC #&01 .prx 37D2 0A ASL A 37D3 A8 TAY 37D4 BE CD 1D LDX &1DCD,Y 37D7 B9 CE 1D LDA &1DCE,Y 37DA A8 TAY .c 37DB 60 RTS .qv 37DC A0 10 LDY #&10 37DE 84 2D STY &2D .qv1 37E0 A2 0C LDX #&0C 37E2 86 2C STX &2C 37E4 98 TYA 37E5 18 CLC 37E6 69 20 ADC #&20 37E8 20 44 2D JSR &2D44 37EB A5 2D LDA &2D 37ED 18 CLC 37EE 69 50 ADC #&50 37F0 20 B6 38 JSR &38B6 37F3 E6 2D INC &2D 37F5 A4 2D LDY &2D 37F7 C0 14 CPY #&14 37F9 90 E5 BCC &37E0 .qv3 37FB 20 FA 2B JSR &2BFA .qv2 37FE A9 AF LDA #&AF 3800 20 EF 33 JSR &33EF 3803 20 02 4B JSR &4B02 3806 38 SEC 3807 E9 30 SBC #&30 3809 C9 04 CMP #&04 380B B0 EE BCS &37FB 380D AA TAX 380E 60 RTS ELITE D Assembled at &2CC8 Ends at &380F Code size is &B47 Execute at &1128 Reload at &2EB0 S.ELTD &2CC8 &380F &1128 &2EB0 Saving file '3-assembled-output/ELTD.bin' 380F 8C 3810 E7 3811 8D 3812 E6 3813 C1 3814 C8 3815 C8 3816 8B 3817 E6 3818 D6 3819 C5 381A C6 381B C1 381C CA 381D 95 381E 9D 381F 9C 3820 90 .cpl 3821 A2 05 LDX #&05 .TT53 3823 B5 78 LDA &78,X 3825 95 7F STA &7F,X 3827 CA DEX 3828 10 F9 BPL &3823 382A A0 03 LDY #&03 382C 24 78 BIT &78 382E 70 01 BVS &3831 3830 88 DEY 3831 84 D1 STY &D1 .TT55 3833 A5 7D LDA &7D 3835 29 1F AND #&1F 3837 F0 05 BEQ &383E 3839 09 80 ORA #&80 383B 20 B6 38 JSR &38B6 383E 20 EB 2C JSR &2CEB 3841 C6 D1 DEC &D1 3843 10 EE BPL &3833 3845 A2 05 LDX #&05 .TT56 3847 B5 7F LDA &7F,X 3849 95 78 STA &78,X 384B CA DEX 384C 10 F9 BPL &3847 384E 60 RTS .cmn 384F A0 00 LDY #&00 .QUL4 3851 B9 F4 17 LDA &17F4,Y 3854 C9 0D CMP #&0D 3856 F0 06 BEQ &385E 3858 20 81 1F JSR &1F81 385B C8 INY 385C D0 F3 BNE &3851 385E 60 RTS .ypl 385F AD 5C 0D LDA &0D5C 3862 D0 EA BNE &384E 3864 20 6A 38 JSR &386A 3867 20 21 38 JSR &3821 .TT62 386A A2 05 LDX #&05 .TT78 386C B5 78 LDA &78,X 386E BC 22 0F LDY &0F22,X 3871 9D 22 0F STA &0F22,X 3874 94 78 STY &78,X 3876 CA DEX 3877 10 F3 BPL &386C 3879 60 RTS .tal 387A 18 CLC 387B AE 0F 03 LDX &030F 387E E8 INX 387F 4C BD 1E JMP &1EBD .fwl 3882 A9 69 LDA #&69 3884 20 B1 38 JSR &38B1 3887 AE 0D 03 LDX &030D 388A 38 SEC 388B 20 BD 1E JSR &1EBD 388E A9 C3 LDA #&C3 3890 20 AB 38 JSR &38AB .PCASH 3893 A9 77 LDA #&77 3895 D0 1F BNE &38B6 .csh 3897 A2 03 LDX #&03 .pc1 3899 BD 09 03 LDA &0309,X 389C 95 3D STA &3D,X 389E CA DEX 389F 10 F8 BPL &3899 38A1 A9 09 LDA #&09 38A3 85 8F STA &8F 38A5 38 SEC 38A6 20 CD 1E JSR &1ECD 38A9 A9 E2 LDA #&E2 .plf 38AB 20 B6 38 JSR &38B6 38AE 4C 37 2D JMP &2D37 .TT68 38B1 20 B6 38 JSR &38B6 .TT73 38B4 A9 3A LDA #&3A .TT27 38B6 AA TAX 38B7 F0 DE BEQ &3897 38B9 30 74 BMI &392F 38BB CA DEX 38BC F0 BC BEQ &387A 38BE CA DEX 38BF F0 9E BEQ &385F 38C1 CA DEX 38C2 D0 03 BNE &38C7 38C4 4C 21 38 JMP &3821 38C7 CA DEX 38C8 F0 85 BEQ &384F 38CA CA DEX 38CB F0 B5 BEQ &3882 38CD CA DEX 38CE D0 05 BNE &38D5 38D0 A9 80 LDA #&80 38D2 85 7E STA &7E 38D4 60 RTS 38D5 CA DEX 38D6 CA DEX 38D7 D0 03 BNE &38DC 38D9 86 7E STX &7E 38DB 60 RTS 38DC CA DEX 38DD F0 38 BEQ &3917 38DF C9 60 CMP #&60 38E1 B0 66 BCS &3949 38E3 C9 0E CMP #&0E 38E5 90 04 BCC &38EB 38E7 C9 20 CMP #&20 38E9 90 28 BCC &3913 38EB A6 7E LDX &7E 38ED F0 3D BEQ &392C 38EF 30 11 BMI &3902 38F1 24 7E BIT &7E 38F3 70 30 BVS &3925 .TT42 38F5 C9 41 CMP #&41 38F7 90 06 BCC &38FF 38F9 C9 5B CMP #&5B 38FB B0 02 BCS &38FF 38FD 69 20 ADC #&20 .TT44 38FF 4C 81 1F JMP &1F81 .TT41 3902 24 7E BIT &7E 3904 70 17 BVS &391D 3906 C9 41 CMP #&41 3908 90 22 BCC &392C 390A 48 PHA 390B 8A TXA 390C 09 40 ORA #&40 390E 85 7E STA &7E 3910 68 PLA 3911 D0 EC BNE &38FF .qw 3913 69 72 ADC #&72 3915 D0 32 BNE &3949 .crlf 3917 A9 15 LDA #&15 3919 85 2C STA &2C 391B D0 97 BNE &38B4 .TT45 391D E0 FF CPX #&FF 391F F0 63 BEQ &3984 3921 C9 41 CMP #&41 3923 B0 D0 BCS &38F5 .TT46 3925 48 PHA 3926 8A TXA 3927 29 BF AND #&BF 3929 85 7E STA &7E 392B 68 PLA .TT74 392C 4C 81 1F JMP &1F81 .TT43 392F C9 A0 CMP #&A0 3931 B0 14 BCS &3947 3933 29 7F AND #&7F 3935 0A ASL A 3936 A8 TAY 3937 B9 7C 4B LDA &4B7C,Y 393A 20 B6 38 JSR &38B6 393D B9 7D 4B LDA &4B7D,Y 3940 C9 3F CMP #&3F 3942 F0 40 BEQ &3984 3944 4C B6 38 JMP &38B6 .TT47 3947 E9 A0 SBC #&A0 .ex 3949 AA TAX 394A A9 00 LDA #&00 394C 85 22 STA &22 394E A9 04 LDA #&04 3950 85 23 STA &23 3952 A0 00 LDY #&00 3954 8A TXA 3955 F0 13 BEQ &396A .TT51 3957 B1 22 LDA (&22),Y 3959 F0 07 BEQ &3962 395B C8 INY 395C D0 F9 BNE &3957 395E E6 23 INC &23 3960 D0 F5 BNE &3957 .TT49 3962 C8 INY 3963 D0 02 BNE &3967 3965 E6 23 INC &23 .TT59 3967 CA DEX 3968 D0 ED BNE &3957 .TT50 396A 98 TYA 396B 48 PHA 396C A5 23 LDA &23 396E 48 PHA 396F B1 22 LDA (&22),Y 3971 49 23 EOR #&23 3973 20 B6 38 JSR &38B6 3976 68 PLA 3977 85 23 STA &23 3979 68 PLA 397A A8 TAY 397B C8 INY 397C D0 02 BNE &3980 397E E6 23 INC &23 3980 B1 22 LDA (&22),Y 3982 D0 E6 BNE &396A .TT48 3984 60 RTS .EX2 3985 A5 72 LDA &72 3987 09 A0 ORA #&A0 3989 85 72 STA &72 398B 60 RTS .DOEXP 398C A5 72 LDA &72 398E 29 40 AND #&40 3990 F0 03 BEQ &3995 3992 20 EF 39 JSR &39EF 3995 A5 59 LDA &59 3997 85 D1 STA &D1 3999 A5 5A LDA &5A 399B C9 20 CMP #&20 399D 90 04 BCC &39A3 399F A9 FE LDA #&FE 39A1 D0 08 BNE &39AB 39A3 06 D1 ASL &D1 39A5 2A ROL A 39A6 06 D1 ASL &D1 39A8 2A ROL A 39A9 38 SEC 39AA 2A ROL A .yy 39AB 85 90 STA &90 39AD A0 01 LDY #&01 39AF B1 74 LDA (&74),Y 39B1 69 04 ADC #&04 39B3 B0 D0 BCS &3985 39B5 91 74 STA (&74),Y 39B7 20 C5 28 JSR &28C5 39BA A5 1B LDA &1B 39BC C9 1C CMP #&1C 39BE 90 04 BCC &39C4 39C0 A9 FE LDA #&FE 39C2 D0 09 BNE &39CD 39C4 06 91 ASL &91 39C6 2A ROL A 39C7 06 91 ASL &91 39C9 2A ROL A 39CA 06 91 ASL &91 39CC 2A ROL A .LABEL_1 39CD 88 DEY 39CE 91 74 STA (&74),Y 39D0 A5 72 LDA &72 39D2 29 BF AND #&BF 39D4 85 72 STA &72 39D6 29 08 AND #&08 39D8 F0 AA BEQ &3984 39DA A0 02 LDY #&02 39DC B1 74 LDA (&74),Y 39DE A8 TAY .EXL1 39DF B9 F9 00 LDA &00F9,Y 39E2 91 74 STA (&74),Y 39E4 88 DEY 39E5 C0 06 CPY #&06 39E7 D0 F6 BNE &39DF 39E9 A5 72 LDA &72 39EB 09 40 ORA #&40 39ED 85 72 STA &72 .PTCLS 39EF A0 00 LDY #&00 39F1 B1 74 LDA (&74),Y 39F3 85 90 STA &90 39F5 C8 INY 39F6 B1 74 LDA (&74),Y 39F8 10 02 BPL &39FC 39FA 49 FF EOR #&FF 39FC 4A LSR A 39FD 4A LSR A 39FE 4A LSR A 39FF 09 01 ORA #&01 3A01 85 8F STA &8F 3A03 C8 INY 3A04 B1 74 LDA (&74),Y 3A06 85 A0 STA &A0 3A08 A5 01 LDA &01 3A0A 48 PHA 3A0B A0 06 LDY #&06 .EXL5 3A0D A2 03 LDX #&03 .EXL3 3A0F C8 INY 3A10 B1 74 LDA (&74),Y 3A12 95 D2 STA &D2,X 3A14 CA DEX 3A15 10 F8 BPL &3A0F 3A17 84 A4 STY &A4 3A19 A0 02 LDY #&02 .EXL2 3A1B C8 INY 3A1C B1 74 LDA (&74),Y 3A1E 45 A4 EOR &A4 3A20 99 FD FF STA &FFFD,Y 3A23 C0 06 CPY #&06 3A25 D0 F4 BNE &3A1B 3A27 A4 8F LDY &8F .EXL4 3A29 20 56 44 JSR &4456 3A2C 85 97 STA &97 3A2E A5 D3 LDA &D3 3A30 85 91 STA &91 3A32 A5 D2 LDA &D2 3A34 20 67 3A JSR &3A67 3A37 D0 28 BNE &3A61 3A39 E0 BF CPX #&BF 3A3B B0 24 BCS &3A61 3A3D 86 32 STX &32 3A3F A5 D5 LDA &D5 3A41 85 91 STA &91 3A43 A5 D4 LDA &D4 3A45 20 67 3A JSR &3A67 3A48 D0 05 BNE &3A4F 3A4A A5 32 LDA &32 3A4C 20 DF 1A JSR &1ADF .EX4 3A4F 88 DEY 3A50 10 D7 BPL &3A29 3A52 A4 A4 LDY &A4 3A54 C4 A0 CPY &A0 3A56 90 B5 BCC &3A0D 3A58 68 PLA 3A59 85 01 STA &01 3A5B AD 06 09 LDA &0906 3A5E 85 03 STA &03 3A60 60 RTS .EX11 3A61 20 56 44 JSR &4456 3A64 4C 4F 3A JMP &3A4F .EXS1 3A67 85 92 STA &92 3A69 20 56 44 JSR &4456 3A6C 2A ROL A 3A6D B0 0B BCS &3A7A 3A6F 20 A9 27 JSR &27A9 3A72 65 91 ADC &91 3A74 AA TAX 3A75 A5 92 LDA &92 3A77 69 00 ADC #&00 3A79 60 RTS .EX5 3A7A 20 A9 27 JSR &27A9 3A7D 85 D1 STA &D1 3A7F A5 91 LDA &91 3A81 E5 D1 SBC &D1 3A83 AA TAX 3A84 A5 92 LDA &92 3A86 E9 00 SBC #&00 3A88 60 RTS .SOS1 3A89 20 0E 44 JSR &440E 3A8C A9 7F LDA #&7F 3A8E 85 70 STA &70 3A90 85 71 STA &71 3A92 AD 1D 0F LDA &0F1D 3A95 29 02 AND #&02 3A97 09 80 ORA #&80 3A99 4C 82 3C JMP &3C82 .SOLAR 3A9C 4E 34 03 LSR &0334 3A9F 20 F9 43 JSR &43F9 3AA2 A5 79 LDA &79 3AA4 29 07 AND #&07 3AA6 69 06 ADC #&06 3AA8 4A LSR A 3AA9 85 5B STA &5B 3AAB 6A ROR A 3AAC 85 55 STA &55 3AAE 85 58 STA &58 3AB0 20 89 3A JSR &3A89 3AB3 A5 7B LDA &7B 3AB5 29 07 AND #&07 3AB7 09 81 ORA #&81 3AB9 85 5B STA &5B 3ABB A5 7D LDA &7D 3ABD 29 03 AND #&03 3ABF 85 55 STA &55 3AC1 85 54 STA &54 3AC3 A9 00 LDA #&00 3AC5 85 70 STA &70 3AC7 85 71 STA &71 3AC9 A9 81 LDA #&81 3ACB 20 82 3C JSR &3C82 .NWSTARS 3ACE A5 96 LDA &96 3AD0 D0 23 BNE &3AF5 .nWq 3AD2 AC 33 0F LDY &0F33 .SAL4 3AD5 20 57 44 JSR &4457 3AD8 09 08 ORA #&08 3ADA 99 E8 0E STA &0EE8,Y 3ADD 85 97 STA &97 3ADF 20 57 44 JSR &4457 3AE2 99 4C 03 STA &034C,Y 3AE5 85 31 STA &31 3AE7 20 57 44 JSR &4457 3AEA 99 C2 0E STA &0EC2,Y 3AED 85 32 STA &32 3AEF 20 BD 1A JSR &1ABD 3AF2 88 DEY 3AF3 D0 E0 BNE &3AD5 .WPSHPS 3AF5 A2 00 LDX #&00 .WSL1 3AF7 BD 40 0D LDA &0D40,X 3AFA F0 23 BEQ &3B1F 3AFC 30 1E BMI &3B1C 3AFE 85 9B STA &9B 3B00 20 4F 3C JSR &3C4F 3B03 A0 1F LDY #&1F .WSL2 3B05 B1 20 LDA (&20),Y 3B07 99 53 00 STA &0053,Y 3B0A 88 DEY 3B0B 10 F8 BPL &3B05 3B0D 86 93 STX &93 3B0F 20 20 2C JSR &2C20 3B12 A6 93 LDX &93 3B14 A0 1F LDY #&1F 3B16 B1 20 LDA (&20),Y 3B18 29 A7 AND #&A7 3B1A 91 20 STA (&20),Y .WS1 3B1C E8 INX 3B1D D0 D8 BNE &3AF7 .WS2 3B1F A2 FF LDX #&FF 3B21 8E 26 0E STX &0E26 3B24 8E 74 0E STX &0E74 .FLFLLS 3B27 A0 BF LDY #&BF 3B29 A9 00 LDA #&00 .SAL6 3B2B 99 66 0D STA &0D66,Y 3B2E 88 DEY 3B2F D0 FA BNE &3B2B 3B31 88 DEY 3B32 8C 66 0D STY &0D66 3B35 60 RTS .DET1 3B36 A9 06 LDA #&06 3B38 78 SEI 3B39 8D 00 FE STA &FE00 3B3C 8E 01 FE STX &FE01 3B3F 58 CLI 3B40 60 RTS 3B41 CA DEX 3B42 60 RTS .SHD 3B43 E8 INX 3B44 F0 FB BEQ &3B41 .DENGY 3B46 CE 13 0F DEC &0F13 3B49 08 PHP 3B4A D0 03 BNE &3B4F 3B4C EE 13 0F INC &0F13 3B4F 28 PLP 3B50 60 RTS .COMPAS 3B51 20 B1 3B JSR &3BB1 3B54 AD 55 0D LDA &0D55 3B57 D0 31 BNE &3B8A 3B59 20 DE 48 JSR &48DE 3B5C 4C 8D 3B JMP &3B8D .SPS2 3B5F 0A ASL A 3B60 AA TAX 3B61 A9 00 LDA #&00 3B63 6A ROR A 3B64 A8 TAY 3B65 A9 14 LDA #&14 3B67 85 90 STA &90 3B69 8A TXA 3B6A 20 C5 28 JSR &28C5 3B6D A6 1B LDX &1B 3B6F 98 TYA 3B70 30 03 BMI &3B75 3B72 A0 00 LDY #&00 3B74 60 RTS .LL163 3B75 A0 FF LDY #&FF 3B77 8A TXA 3B78 49 FF EOR #&FF 3B7A AA TAX 3B7B E8 INX 3B7C 60 RTS .SPS4 3B7D A2 08 LDX #&08 .SPL1 3B7F BD 24 09 LDA &0924,X 3B82 95 D2 STA &D2,X 3B84 CA DEX 3B85 10 F8 BPL &3B7F 3B87 4C ED 48 JMP &48ED .SP1 3B8A 20 7D 3B JSR &3B7D .SP2 3B8D A5 31 LDA &31 3B8F 20 5F 3B JSR &3B5F 3B92 8A TXA 3B93 69 C3 ADC #&C3 3B95 8D 16 0F STA &0F16 3B98 A5 32 LDA &32 3B9A 20 5F 3B JSR &3B5F 3B9D 86 D1 STX &D1 3B9F A9 CC LDA #&CC 3BA1 E5 D1 SBC &D1 3BA3 8D 17 0F STA &0F17 3BA6 A9 F0 LDA #&F0 3BA8 A6 33 LDX &33 3BAA 10 02 BPL &3BAE 3BAC A9 FF LDA #&FF 3BAE 8D 48 0F STA &0F48 .DOT 3BB1 AD 17 0F LDA &0F17 3BB4 85 32 STA &32 3BB6 AD 16 0F LDA &0F16 3BB9 85 31 STA &31 3BBB AD 48 0F LDA &0F48 3BBE 85 A2 STA &A2 3BC0 C9 F0 CMP #&F0 3BC2 D0 05 BNE &3BC9 .CPIX4 3BC4 20 C9 3B JSR &3BC9 3BC7 C6 32 DEC &32 .CPIX2 3BC9 A5 32 LDA &32 3BCB A8 TAY 3BCC 4A LSR A 3BCD 4A LSR A 3BCE 4A LSR A 3BCF 09 60 ORA #&60 3BD1 85 08 STA &08 3BD3 A5 31 LDA &31 3BD5 29 F8 AND #&F8 3BD7 85 07 STA &07 3BD9 98 TYA 3BDA 29 07 AND #&07 3BDC A8 TAY 3BDD A5 31 LDA &31 3BDF 29 06 AND #&06 3BE1 4A LSR A 3BE2 AA TAX 3BE3 BD 72 18 LDA &1872,X 3BE6 25 A2 AND &A2 3BE8 51 07 EOR (&07),Y 3BEA 91 07 STA (&07),Y 3BEC BD 73 18 LDA &1873,X 3BEF 10 09 BPL &3BFA 3BF1 A5 07 LDA &07 3BF3 69 08 ADC #&08 3BF5 85 07 STA &07 3BF7 BD 73 18 LDA &1873,X .CP1 3BFA 25 A2 AND &A2 3BFC 51 07 EOR (&07),Y 3BFE 91 07 STA (&07),Y 3C00 60 RTS .OOPS 3C01 85 D1 STA &D1 3C03 A0 08 LDY #&08 3C05 A2 00 LDX #&00 3C07 B1 20 LDA (&20),Y 3C09 30 10 BMI &3C1B 3C0B AD 11 0F LDA &0F11 3C0E E5 D1 SBC &D1 3C10 90 04 BCC &3C16 3C12 8D 11 0F STA &0F11 3C15 60 RTS .OO2 3C16 8E 11 0F STX &0F11 3C19 90 0E BCC &3C29 .OO1 3C1B AD 12 0F LDA &0F12 3C1E E5 D1 SBC &D1 3C20 90 04 BCC &3C26 3C22 8D 12 0F STA &0F12 3C25 60 RTS .OO5 3C26 8E 12 0F STX &0F12 .OO3 3C29 6D 13 0F ADC &0F13 3C2C 8D 13 0F STA &0F13 3C2F F0 02 BEQ &3C33 3C31 B0 03 BCS &3C36 3C33 4C 7F 46 JMP &467F 3C36 20 8C 49 JSR &498C 3C39 4C 4D 4B JMP &4B4D .SPS3 3C3C BD 01 09 LDA &0901,X 3C3F 95 D2 STA &D2,X 3C41 BD 02 09 LDA &0902,X 3C44 A8 TAY 3C45 29 7F AND #&7F 3C47 95 D3 STA &D3,X 3C49 98 TYA 3C4A 29 80 AND #&80 3C4C 95 D4 STA &D4,X 3C4E 60 RTS .GINF 3C4F 8A TXA 3C50 0A ASL A 3C51 A8 TAY 3C52 B9 48 18 LDA &1848,Y 3C55 85 20 STA &20 3C57 B9 49 18 LDA &1849,Y 3C5A 85 21 STA &21 3C5C 60 RTS .NWSPS 3C5D 20 25 3D JSR &3D25 3C60 A2 01 LDX #&01 3C62 86 73 STX &73 3C64 CA DEX 3C65 86 71 STX &71 3C67 8E 41 0D STX &0D41 3C6A CA DEX 3C6B 86 70 STX &70 3C6D A2 0A LDX #&0A 3C6F 20 FE 3C JSR &3CFE 3C72 20 FE 3C JSR &3CFE 3C75 20 FE 3C JSR &3CFE 3C78 A9 66 LDA #&66 3C7A 85 74 STA &74 3C7C A9 0D LDA #&0D 3C7E 85 75 STA &75 3C80 A9 08 LDA #&08 .NWSHP 3C82 85 D1 STA &D1 3C84 A2 00 LDX #&00 .NWL1 3C86 BD 40 0D LDA &0D40,X 3C89 F0 07 BEQ &3C92 3C8B E8 INX 3C8C E0 0C CPX #&0C 3C8E 90 F6 BCC &3C86 .NW3 3C90 18 CLC 3C91 60 RTS .NW1 3C92 20 4F 3C JSR &3C4F 3C95 A5 D1 LDA &D1 3C97 30 50 BMI &3CE9 3C99 0A ASL A 3C9A A8 TAY 3C9B B9 38 56 LDA &5638,Y 3C9E 85 1E STA &1E 3CA0 B9 39 56 LDA &5639,Y 3CA3 85 1F STA &1F 3CA5 C0 10 CPY #&10 3CA7 F0 30 BEQ &3CD9 3CA9 A0 05 LDY #&05 3CAB B1 1E LDA (&1E),Y 3CAD 85 06 STA &06 3CAF AD 1E 0F LDA &0F1E 3CB2 38 SEC 3CB3 E5 06 SBC &06 3CB5 85 74 STA &74 3CB7 AD 1F 0F LDA &0F1F 3CBA E9 00 SBC #&00 3CBC 85 75 STA &75 3CBE A5 74 LDA &74 3CC0 E5 20 SBC &20 3CC2 A8 TAY 3CC3 A5 75 LDA &75 3CC5 E5 21 SBC &21 3CC7 90 C8 BCC &3C91 3CC9 D0 04 BNE &3CCF 3CCB C0 24 CPY #&24 3CCD 90 C2 BCC &3C91 .NW4 3CCF A5 74 LDA &74 3CD1 8D 1E 0F STA &0F1E 3CD4 A5 75 LDA &75 3CD6 8D 1F 0F STA &0F1F .NW6 3CD9 A0 0E LDY #&0E 3CDB B1 1E LDA (&1E),Y 3CDD 85 76 STA &76 3CDF A0 13 LDY #&13 3CE1 B1 1E LDA (&1E),Y 3CE3 29 07 AND #&07 3CE5 85 72 STA &72 3CE7 A5 D1 LDA &D1 .NW2 3CE9 9D 40 0D STA &0D40,X 3CEC AA TAX 3CED 30 03 BMI &3CF2 3CEF FE 4D 0D INC &0D4D,X 3CF2 A0 23 LDY #&23 .NWL3 3CF4 B9 53 00 LDA &0053,Y 3CF7 91 20 STA (&20),Y 3CF9 88 DEY 3CFA 10 F8 BPL &3CF4 3CFC 38 SEC 3CFD 60 RTS .NwS1 3CFE B5 53 LDA &53,X 3D00 49 80 EOR #&80 3D02 95 53 STA &53,X 3D04 E8 INX 3D05 E8 INX 3D06 60 RTS .ABORT 3D07 A2 FF LDX #&FF .ABORT2 3D09 86 52 STX &52 3D0B AE 33 03 LDX &0333 3D0E 20 41 3D JSR &3D41 3D11 8C 5E 0D STY &0D5E 3D14 60 RTS .ECBLB2 3D15 A9 20 LDA #&20 3D17 85 30 STA &30 3D19 0A ASL A 3D1A 20 CD 49 JSR &49CD .ECBLB 3D1D A9 38 LDA #&38 3D1F A2 36 LDX #&36 3D21 A0 3D LDY #&3D 3D23 D0 04 BNE &3D29 .SPBLB 3D25 A9 C0 LDA #&C0 3D27 A2 39 LDX #&39 3D29 A0 3D LDY #&3D .BULB 3D2B 85 07 STA &07 3D2D 86 1C STX &1C 3D2F 84 1D STY &1D 3D31 A9 7D LDA #&7D 3D33 4C DB 1F JMP &1FDB .ECBT 3D36 E0 3D37 E0 3D38 80 .SPBT 3D39 E0 3D3A E0 3D3B 80 3D3C E0 3D3D E0 3D3E 20 3D3F E0 3D40 E0 .MSBAR 3D41 8A TXA 3D42 0A ASL A 3D43 0A ASL A 3D44 0A ASL A 3D45 85 D1 STA &D1 3D47 A9 31 LDA #&31 3D49 E5 D1 SBC &D1 3D4B 85 07 STA &07 3D4D A9 7E LDA #&7E 3D4F 85 08 STA &08 3D51 98 TYA 3D52 A0 05 LDY #&05 .MBL1 3D54 91 07 STA (&07),Y 3D56 88 DEY 3D57 D0 FB BNE &3D54 3D59 60 RTS .PROJ 3D5A A5 53 LDA &53 3D5C 85 1B STA &1B 3D5E A5 54 LDA &54 3D60 85 1C STA &1C 3D62 A5 55 LDA &55 3D64 20 00 42 JSR &4200 3D67 B0 28 BCS &3D91 3D69 A5 3D LDA &3D 3D6B 69 80 ADC #&80 3D6D 85 D2 STA &D2 3D6F 8A TXA 3D70 69 00 ADC #&00 3D72 85 D3 STA &D3 3D74 A5 56 LDA &56 3D76 85 1B STA &1B 3D78 A5 57 LDA &57 3D7A 85 1C STA &1C 3D7C A5 58 LDA &58 3D7E 49 80 EOR #&80 3D80 20 00 42 JSR &4200 3D83 B0 0C BCS &3D91 3D85 A5 3D LDA &3D 3D87 69 60 ADC #&60 3D89 85 E0 STA &E0 3D8B 8A TXA 3D8C 69 00 ADC #&00 3D8E 85 E1 STA &E1 3D90 18 CLC 3D91 60 RTS .PL2 3D92 A5 9B LDA &9B 3D94 4A LSR A 3D95 B0 03 BCS &3D9A 3D97 4C F3 40 JMP &40F3 3D9A 4C 36 41 JMP &4136 .PLANET 3D9D A5 5B LDA &5B 3D9F 30 F1 BMI &3D92 3DA1 C9 30 CMP #&30 3DA3 B0 ED BCS &3D92 3DA5 05 5A ORA &5A 3DA7 F0 E9 BEQ &3D92 3DA9 20 5A 3D JSR &3D5A 3DAC B0 E4 BCS &3D92 3DAE A9 60 LDA #&60 3DB0 85 1C STA &1C 3DB2 A9 00 LDA #&00 3DB4 85 1B STA &1B 3DB6 20 DE 28 JSR &28DE 3DB9 A5 3E LDA &3E 3DBB F0 04 BEQ &3DC1 3DBD A9 F8 LDA #&F8 3DBF 85 3D STA &3D .PL82 3DC1 A5 9B LDA &9B 3DC3 4A LSR A 3DC4 90 03 BCC &3DC9 3DC6 4C 5A 3F JMP &3F5A .PL9 3DC9 20 F3 40 JSR &40F3 3DCC 20 7C 40 JSR &407C 3DCF B0 04 BCS &3DD5 3DD1 A5 3E LDA &3E 3DD3 F0 01 BEQ &3DD6 .PL20 3DD5 60 RTS .PL25 3DD6 A5 9B LDA &9B 3DD8 C9 80 CMP #&80 3DDA D0 3C BNE &3E18 3DDC A5 3D LDA &3D 3DDE C9 06 CMP #&06 3DE0 90 F3 BCC &3DD5 3DE2 A5 61 LDA &61 3DE4 49 80 EOR #&80 3DE6 85 1B STA &1B 3DE8 A5 67 LDA &67 3DEA 20 E1 41 JSR &41E1 3DED A2 09 LDX #&09 3DEF 20 6E 3E JSR &3E6E 3DF2 85 AC STA &AC 3DF4 84 09 STY &09 3DF6 20 6E 3E JSR &3E6E 3DF9 85 AD STA &AD 3DFB 84 0A STY &0A 3DFD A2 0F LDX #&0F 3DFF 20 F1 41 JSR &41F1 3E02 20 8C 3E JSR &3E8C 3E05 A5 61 LDA &61 3E07 49 80 EOR #&80 3E09 85 1B STA &1B 3E0B A5 6D LDA &6D 3E0D 20 E1 41 JSR &41E1 3E10 A2 15 LDX #&15 3E12 20 F1 41 JSR &41F1 3E15 4C 8C 3E JMP &3E8C .PL26 3E18 A5 67 LDA &67 3E1A 30 B9 BMI &3DD5 3E1C A2 0F LDX #&0F 3E1E 20 C0 41 JSR &41C0 3E21 18 CLC 3E22 65 D2 ADC &D2 3E24 85 D2 STA &D2 3E26 98 TYA 3E27 65 D3 ADC &D3 3E29 85 D3 STA &D3 3E2B 20 C0 41 JSR &41C0 3E2E 85 1B STA &1B 3E30 A5 E0 LDA &E0 3E32 38 SEC 3E33 E5 1B SBC &1B 3E35 85 E0 STA &E0 3E37 84 1B STY &1B 3E39 A5 E1 LDA &E1 3E3B E5 1B SBC &1B 3E3D 85 E1 STA &E1 3E3F A2 09 LDX #&09 3E41 20 6E 3E JSR &3E6E 3E44 4A LSR A 3E45 85 AC STA &AC 3E47 84 09 STY &09 3E49 20 6E 3E JSR &3E6E 3E4C 4A LSR A 3E4D 85 AD STA &AD 3E4F 84 0A STY &0A 3E51 A2 15 LDX #&15 3E53 20 6E 3E JSR &3E6E 3E56 4A LSR A 3E57 85 AE STA &AE 3E59 84 0B STY &0B 3E5B 20 6E 3E JSR &3E6E 3E5E 4A LSR A 3E5F 85 AF STA &AF 3E61 84 0C STY &0C 3E63 A9 40 LDA #&40 3E65 85 A0 STA &A0 3E67 A9 00 LDA #&00 3E69 85 A5 STA &A5 3E6B 4C 90 3E JMP &3E90 .PLS1 3E6E B5 53 LDA &53,X 3E70 85 1B STA &1B 3E72 B5 54 LDA &54,X 3E74 29 7F AND #&7F 3E76 85 1C STA &1C 3E78 B5 54 LDA &54,X 3E7A 29 80 AND #&80 3E7C 20 DE 28 JSR &28DE 3E7F A5 3D LDA &3D 3E81 A4 3E LDY &3E 3E83 F0 02 BEQ &3E87 3E85 A9 FE LDA #&FE 3E87 A4 40 LDY &40 3E89 E8 INX 3E8A E8 INX 3E8B 60 RTS .PLS2 3E8C A9 1F LDA #&1F 3E8E 85 A0 STA &A0 .PLS22 3E90 A2 00 LDX #&00 3E92 86 A4 STX &A4 3E94 CA DEX 3E95 86 A3 STX &A3 .PLL4 3E97 A5 A5 LDA &A5 3E99 29 1F AND #&1F 3E9B AA TAX 3E9C BD BA 26 LDA &26BA,X 3E9F 85 90 STA &90 3EA1 A5 AE LDA &AE 3EA3 20 A9 27 JSR &27A9 3EA6 85 91 STA &91 3EA8 A5 AF LDA &AF 3EAA 20 A9 27 JSR &27A9 3EAD 85 3D STA &3D 3EAF A6 A5 LDX &A5 3EB1 E0 21 CPX #&21 3EB3 A9 00 LDA #&00 3EB5 6A ROR A 3EB6 85 0E STA &0E 3EB8 A5 A5 LDA &A5 3EBA 18 CLC 3EBB 69 10 ADC #&10 3EBD 29 1F AND #&1F 3EBF AA TAX 3EC0 BD BA 26 LDA &26BA,X 3EC3 85 90 STA &90 3EC5 A5 AD LDA &AD 3EC7 20 A9 27 JSR &27A9 3ECA 85 3F STA &3F 3ECC A5 AC LDA &AC 3ECE 20 A9 27 JSR &27A9 3ED1 85 1B STA &1B 3ED3 A5 A5 LDA &A5 3ED5 69 0F ADC #&0F 3ED7 29 3F AND #&3F 3ED9 C9 21 CMP #&21 3EDB A9 00 LDA #&00 3EDD 6A ROR A 3EDE 85 0D STA &0D 3EE0 A5 0E LDA &0E 3EE2 45 0B EOR &0B 3EE4 85 92 STA &92 3EE6 A5 0D LDA &0D 3EE8 45 09 EOR &09 3EEA 20 5F 28 JSR &285F 3EED 85 D1 STA &D1 3EEF 10 0F BPL &3F00 3EF1 8A TXA 3EF2 49 FF EOR #&FF 3EF4 18 CLC 3EF5 69 01 ADC #&01 3EF7 AA TAX 3EF8 A5 D1 LDA &D1 3EFA 49 7F EOR #&7F 3EFC 69 00 ADC #&00 3EFE 85 D1 STA &D1 .PL42 3F00 8A TXA 3F01 65 D2 ADC &D2 3F03 85 82 STA &82 3F05 A5 D1 LDA &D1 3F07 65 D3 ADC &D3 3F09 85 83 STA &83 3F0B A5 3D LDA &3D 3F0D 85 91 STA &91 3F0F A5 0E LDA &0E 3F11 45 0C EOR &0C 3F13 85 92 STA &92 3F15 A5 3F LDA &3F 3F17 85 1B STA &1B 3F19 A5 0D LDA &0D 3F1B 45 0A EOR &0A 3F1D 20 5F 28 JSR &285F 3F20 49 80 EOR #&80 3F22 85 D1 STA &D1 3F24 10 0F BPL &3F35 3F26 8A TXA 3F27 49 FF EOR #&FF 3F29 18 CLC 3F2A 69 01 ADC #&01 3F2C AA TAX 3F2D A5 D1 LDA &D1 3F2F 49 7F EOR #&7F 3F31 69 00 ADC #&00 3F33 85 D1 STA &D1 .PL43 3F35 20 18 1B JSR &1B18 3F38 C5 A0 CMP &A0 3F3A F0 02 BEQ &3F3E 3F3C B0 0C BCS &3F4A 3F3E A5 A5 LDA &A5 3F40 18 CLC 3F41 65 A6 ADC &A6 3F43 29 3F AND #&3F 3F45 85 A5 STA &A5 3F47 4C 97 3E JMP &3E97 .PL40 3F4A 60 RTS 3F4B 4C 36 41 JMP &4136 .PLF3 3F4E 8A TXA 3F4F 49 FF EOR #&FF 3F51 18 CLC 3F52 69 01 ADC #&01 3F54 AA TAX .PLF17 3F55 A9 FF LDA #&FF 3F57 4C 9F 3F JMP &3F9F .SUN 3F5A A9 01 LDA #&01 3F5C 8D 66 0D STA &0D66 3F5F 20 86 41 JSR &4186 3F62 B0 E7 BCS &3F4B 3F64 A9 00 LDA #&00 3F66 A6 3D LDX &3D 3F68 E0 60 CPX #&60 3F6A 2A ROL A 3F6B E0 28 CPX #&28 3F6D 2A ROL A 3F6E E0 10 CPX #&10 3F70 2A ROL A .PLF18 3F71 85 A4 STA &A4 3F73 A9 BF LDA #&BF 3F75 A6 1D LDX &1D 3F77 D0 0A BNE &3F83 3F79 C5 1C CMP &1C 3F7B 90 06 BCC &3F83 3F7D A5 1C LDA &1C 3F7F D0 02 BNE &3F83 3F81 A9 01 LDA #&01 .PLF2 3F83 85 A0 STA &A0 3F85 A9 BF LDA #&BF 3F87 38 SEC 3F88 E5 E0 SBC &E0 3F8A AA TAX 3F8B A9 00 LDA #&00 3F8D E5 E1 SBC &E1 3F8F 30 BD BMI &3F4E 3F91 D0 08 BNE &3F9B 3F93 E8 INX 3F94 CA DEX 3F95 F0 BE BEQ &3F55 3F97 E4 3D CPX &3D 3F99 90 04 BCC &3F9F .PLF4 3F9B A6 3D LDX &3D 3F9D A9 00 LDA #&00 .PLF5 3F9F 86 22 STX &22 3FA1 85 23 STA &23 3FA3 A5 3D LDA &3D 3FA5 20 6F 27 JSR &276F 3FA8 85 AD STA &AD 3FAA A5 1B LDA &1B 3FAC 85 AC STA &AC 3FAE A0 BF LDY #&BF 3FB0 A5 28 LDA &28 3FB2 85 26 STA &26 3FB4 A5 29 LDA &29 3FB6 85 27 STA &27 .PLFL2 3FB8 C4 A0 CPY &A0 3FBA F0 0B BEQ &3FC7 3FBC B9 66 0D LDA &0D66,Y 3FBF F0 03 BEQ &3FC4 3FC1 20 0B 1A JSR &1A0B .PLF13 3FC4 88 DEY 3FC5 D0 F1 BNE &3FB8 .PLFL 3FC7 A5 22 LDA &22 3FC9 20 6F 27 JSR &276F 3FCC 85 D1 STA &D1 3FCE A5 AC LDA &AC 3FD0 38 SEC 3FD1 E5 1B SBC &1B 3FD3 85 90 STA &90 3FD5 A5 AD LDA &AD 3FD7 E5 D1 SBC &D1 3FD9 85 91 STA &91 3FDB 84 32 STY &32 3FDD 20 5B 4D JSR &4D5B 3FE0 A4 32 LDY &32 3FE2 20 57 44 JSR &4457 3FE5 25 A4 AND &A4 3FE7 18 CLC 3FE8 65 90 ADC &90 3FEA 90 02 BCC &3FEE 3FEC A9 FF LDA #&FF .PLF44 3FEE BE 66 0D LDX &0D66,Y 3FF1 99 66 0D STA &0D66,Y 3FF4 F0 4A BEQ &4040 3FF6 A5 28 LDA &28 3FF8 85 26 STA &26 3FFA A5 29 LDA &29 3FFC 85 27 STA &27 3FFE 8A TXA 3FFF 20 55 41 JSR &4155 4002 A5 31 LDA &31 4004 85 24 STA &24 4006 A5 33 LDA &33 4008 85 25 STA &25 400A A5 D2 LDA &D2 400C 85 26 STA &26 400E A5 D3 LDA &D3 4010 85 27 STA &27 4012 B9 66 0D LDA &0D66,Y 4015 20 55 41 JSR &4155 4018 B0 0B BCS &4025 401A A5 33 LDA &33 401C A6 24 LDX &24 401E 86 33 STX &33 4020 85 24 STA &24 4022 20 15 1A JSR &1A15 .PLF23 4025 A5 24 LDA &24 4027 85 31 STA &31 4029 A5 25 LDA &25 402B 85 33 STA &33 .PLF16 402D 20 15 1A JSR &1A15 .PLF6 4030 88 DEY 4031 F0 3F BEQ &4072 4033 A5 23 LDA &23 4035 D0 1D BNE &4054 4037 C6 22 DEC &22 4039 D0 8C BNE &3FC7 403B C6 23 DEC &23 .PLFLS 403D 4C C7 3F JMP &3FC7 .PLF11 4040 A6 D2 LDX &D2 4042 86 26 STX &26 4044 A6 D3 LDX &D3 4046 86 27 STX &27 4048 20 55 41 JSR &4155 404B 90 E0 BCC &402D 404D A9 00 LDA #&00 404F 99 66 0D STA &0D66,Y 4052 F0 DC BEQ &4030 .PLF10 4054 A6 22 LDX &22 4056 E8 INX 4057 86 22 STX &22 4059 E4 3D CPX &3D 405B 90 E0 BCC &403D 405D F0 DE BEQ &403D 405F A5 28 LDA &28 4061 85 26 STA &26 4063 A5 29 LDA &29 4065 85 27 STA &27 .PLFL3 4067 B9 66 0D LDA &0D66,Y 406A F0 03 BEQ &406F 406C 20 0B 1A JSR &1A0B .PLF9 406F 88 DEY 4070 D0 F5 BNE &4067 .PLF8 4072 18 CLC 4073 A5 D2 LDA &D2 4075 85 28 STA &28 4077 A5 D3 LDA &D3 4079 85 29 STA &29 .RTS2 407B 60 RTS .CIRCLE 407C 20 86 41 JSR &4186 407F B0 FA BCS &407B 4081 A9 00 LDA #&00 4083 8D 26 0E STA &0E26 4086 A6 3D LDX &3D 4088 A9 08 LDA #&08 408A E0 08 CPX #&08 408C 90 06 BCC &4094 408E 4A LSR A 408F E0 3C CPX #&3C 4091 90 01 BCC &4094 4093 4A LSR A .PL89 4094 85 A6 STA &A6 .CIRCLE2 4096 A2 FF LDX #&FF 4098 86 A3 STX &A3 409A E8 INX 409B 86 A4 STX &A4 .PLL3 409D A5 A4 LDA &A4 409F 20 9F 27 JSR &279F 40A2 A2 00 LDX #&00 40A4 86 D1 STX &D1 40A6 A6 A4 LDX &A4 40A8 E0 21 CPX #&21 40AA 90 0D BCC &40B9 40AC 49 FF EOR #&FF 40AE 69 00 ADC #&00 40B0 AA TAX 40B1 A9 FF LDA #&FF 40B3 69 00 ADC #&00 40B5 85 D1 STA &D1 40B7 8A TXA 40B8 18 CLC .PL37 40B9 65 D2 ADC &D2 40BB 85 82 STA &82 40BD A5 D3 LDA &D3 40BF 65 D1 ADC &D1 40C1 85 83 STA &83 40C3 A5 A4 LDA &A4 40C5 18 CLC 40C6 69 10 ADC #&10 40C8 20 9F 27 JSR &279F 40CB AA TAX 40CC A9 00 LDA #&00 40CE 85 D1 STA &D1 40D0 A5 A4 LDA &A4 40D2 69 0F ADC #&0F 40D4 29 3F AND #&3F 40D6 C9 21 CMP #&21 40D8 90 0D BCC &40E7 40DA 8A TXA 40DB 49 FF EOR #&FF 40DD 69 00 ADC #&00 40DF AA TAX 40E0 A9 FF LDA #&FF 40E2 69 00 ADC #&00 40E4 85 D1 STA &D1 40E6 18 CLC .PL38 40E7 20 18 1B JSR &1B18 40EA C9 41 CMP #&41 40EC B0 03 BCS &40F1 40EE 4C 9D 40 JMP &409D 40F1 18 CLC 40F2 60 RTS .WPLS2 40F3 AC 26 0E LDY &0E26 40F6 D0 34 BNE &412C .WPL1 40F8 C4 77 CPY &77 40FA B0 30 BCS &412C 40FC B9 74 0E LDA &0E74,Y 40FF C9 FF CMP #&FF 4101 F0 1A BEQ &411D 4103 85 34 STA &34 4105 B9 26 0E LDA &0E26,Y 4108 85 33 STA &33 410A 20 77 18 JSR &1877 410D C8 INY 410E A5 A1 LDA &A1 4110 D0 E6 BNE &40F8 4112 A5 33 LDA &33 4114 85 31 STA &31 4116 A5 34 LDA &34 4118 85 32 STA &32 411A 4C F8 40 JMP &40F8 .WP2 411D C8 INY 411E B9 26 0E LDA &0E26,Y 4121 85 31 STA &31 4123 B9 74 0E LDA &0E74,Y 4126 85 32 STA &32 4128 C8 INY 4129 4C F8 40 JMP &40F8 .WP1 412C A9 01 LDA #&01 412E 85 77 STA &77 4130 A9 FF LDA #&FF 4132 8D 26 0E STA &0E26 4135 60 RTS .WPLS 4136 AD 66 0D LDA &0D66 4139 30 FA BMI &4135 413B A5 28 LDA &28 413D 85 26 STA &26 413F A5 29 LDA &29 4141 85 27 STA &27 4143 A0 BF LDY #&BF .WPL2 4145 B9 66 0D LDA &0D66,Y 4148 F0 03 BEQ &414D 414A 20 0B 1A JSR &1A0B 414D 88 DEY 414E D0 F5 BNE &4145 4150 88 DEY 4151 8C 66 0D STY &0D66 4154 60 RTS .EDGES 4155 85 D1 STA &D1 4157 18 CLC 4158 65 26 ADC &26 415A 85 33 STA &33 415C A5 27 LDA &27 415E 69 00 ADC #&00 4160 30 1D BMI &417F 4162 F0 04 BEQ &4168 4164 A9 FE LDA #&FE 4166 85 33 STA &33 4168 A5 26 LDA &26 416A 38 SEC 416B E5 D1 SBC &D1 416D 85 31 STA &31 416F A5 27 LDA &27 4171 E9 00 SBC #&00 4173 D0 02 BNE &4177 4175 18 CLC 4176 60 RTS .ED3 4177 10 06 BPL &417F 4179 A9 02 LDA #&02 417B 85 31 STA &31 417D 18 CLC 417E 60 RTS .ED1 417F A9 00 LDA #&00 4181 99 66 0D STA &0D66,Y 4184 38 SEC 4185 60 RTS .CHKON 4186 A5 D2 LDA &D2 4188 18 CLC 4189 65 3D ADC &3D 418B A5 D3 LDA &D3 418D 69 00 ADC #&00 418F 30 2D BMI &41BE 4191 A5 D2 LDA &D2 4193 38 SEC 4194 E5 3D SBC &3D 4196 A5 D3 LDA &D3 4198 E9 00 SBC #&00 419A 30 02 BMI &419E 419C D0 20 BNE &41BE .PL31 419E A5 E0 LDA &E0 41A0 18 CLC 41A1 65 3D ADC &3D 41A3 85 1C STA &1C 41A5 A5 E1 LDA &E1 41A7 69 00 ADC #&00 41A9 30 13 BMI &41BE 41AB 85 1D STA &1D 41AD A5 E0 LDA &E0 41AF 38 SEC 41B0 E5 3D SBC &3D 41B2 AA TAX 41B3 A5 E1 LDA &E1 41B5 E9 00 SBC #&00 41B7 30 6A BMI &4223 41B9 D0 03 BNE &41BE 41BB E0 BF CPX #&BF 41BD 60 RTS .PL21 41BE 38 SEC 41BF 60 RTS .PLS3 41C0 20 6E 3E JSR &3E6E 41C3 85 1B STA &1B 41C5 A9 DE LDA #&DE 41C7 85 90 STA &90 41C9 86 8F STX &8F 41CB 20 82 27 JSR &2782 41CE A6 8F LDX &8F 41D0 A4 40 LDY &40 41D2 10 0A BPL &41DE 41D4 49 FF EOR #&FF 41D6 18 CLC 41D7 69 01 ADC #&01 41D9 F0 03 BEQ &41DE 41DB A0 FF LDY #&FF 41DD 60 RTS .PL12 41DE A0 00 LDY #&00 41E0 60 RTS .PLS4 41E1 85 90 STA &90 41E3 20 97 29 JSR &2997 41E6 A6 61 LDX &61 41E8 30 02 BMI &41EC 41EA 49 80 EOR #&80 41EC 4A LSR A 41ED 4A LSR A 41EE 85 A5 STA &A5 41F0 60 RTS .PLS5 41F1 20 6E 3E JSR &3E6E 41F4 85 AE STA &AE 41F6 84 0B STY &0B 41F8 20 6E 3E JSR &3E6E 41FB 85 AF STA &AF 41FD 84 0C STY &0C 41FF 60 RTS .PLS6 4200 20 DE 28 JSR &28DE 4203 A5 40 LDA &40 4205 29 7F AND #&7F 4207 05 3F ORA &3F 4209 D0 B3 BNE &41BE 420B A6 3E LDX &3E 420D E0 04 CPX #&04 420F B0 13 BCS &4224 4211 A5 40 LDA &40 4213 10 0F BPL &4224 4215 A5 3D LDA &3D 4217 49 FF EOR #&FF 4219 69 01 ADC #&01 421B 85 3D STA &3D 421D 8A TXA 421E 49 FF EOR #&FF 4220 69 00 ADC #&00 4222 AA TAX .PL44 4223 18 CLC .PL6 4224 60 RTS .TT17 4225 20 7F 4A JSR &4A7F 4228 AD 50 0F LDA &0F50 422B F0 22 BEQ &424F 422D A5 9C LDA &9C 422F 49 FF EOR #&FF 4231 20 38 42 JSR &4238 4234 98 TYA 4235 AA TAX 4236 A5 9D LDA &9D .TJS1 4238 A8 TAY 4239 A9 00 LDA #&00 423B C0 10 CPY #&10 423D E9 00 SBC #&00 423F C0 40 CPY #&40 4241 E9 00 SBC #&00 4243 C0 C0 CPY #&C0 4245 69 00 ADC #&00 4247 C0 E0 CPY #&E0 4249 69 00 ADC #&00 424B A8 TAY 424C A5 41 LDA &41 424E 60 RTS .TJ1 424F A5 41 LDA &41 4251 A2 00 LDX #&00 4253 A0 00 LDY #&00 4255 C9 19 CMP #&19 4257 D0 01 BNE &425A 4259 CA DEX 425A C9 79 CMP #&79 425C D0 01 BNE &425F 425E E8 INX 425F C9 39 CMP #&39 4261 D0 01 BNE &4264 4263 C8 INY 4264 C9 29 CMP #&29 4266 D0 01 BNE &4269 4268 88 DEY 4269 60 RTS .ping 426A A2 01 LDX #&01 .pl1 426C BD 01 03 LDA &0301,X 426F 9D 31 0F STA &0F31,X 4272 CA DEX 4273 10 F7 BPL &426C 4275 60 RTS ELITE E Assembled at &380F Ends at &4276 Code size is &A67 Execute at &1128 Reload at &39F7 S.ELTE &380F &4276 &1128 &39F7 Saving file '3-assembled-output/ELTE.bin' .KS3 4276 A5 1B LDA &1B 4278 8D 1E 0F STA &0F1E 427B A5 1C LDA &1C 427D 8D 1F 0F STA &0F1F 4280 60 RTS .KS1 4281 A6 93 LDX &93 4283 20 DA 42 JSR &42DA 4286 A6 93 LDX &93 4288 4C 76 10 JMP &1076 .KS4 428B 20 F9 43 JSR &43F9 428E 20 27 3B JSR &3B27 4291 8D 41 0D STA &0D41 4294 8D 55 0D STA &0D55 4297 20 25 3D JSR &3D25 429A A9 06 LDA #&06 429C 85 58 STA &58 429E A9 81 LDA #&81 42A0 4C 82 3C JMP &3C82 .KS2 42A3 A2 FF LDX #&FF .KSL4 42A5 E8 INX 42A6 BD 40 0D LDA &0D40,X 42A9 F0 CB BEQ &4276 42AB C9 09 CMP #&09 42AD D0 F6 BNE &42A5 42AF 8A TXA 42B0 0A ASL A 42B1 A8 TAY 42B2 B9 48 18 LDA &1848,Y 42B5 85 07 STA &07 42B7 B9 49 18 LDA &1849,Y 42BA 85 08 STA &08 42BC A0 20 LDY #&20 42BE B1 07 LDA (&07),Y 42C0 10 E3 BPL &42A5 42C2 29 7F AND #&7F 42C4 4A LSR A 42C5 C5 A7 CMP &A7 42C7 90 DC BCC &42A5 42C9 F0 09 BEQ &42D4 42CB E9 01 SBC #&01 42CD 0A ASL A 42CE 09 80 ORA #&80 42D0 91 07 STA (&07),Y 42D2 D0 D1 BNE &42A5 .KS6 42D4 A9 00 LDA #&00 42D6 91 07 STA (&07),Y 42D8 F0 CB BEQ &42A5 .KILLSHP 42DA 86 A7 STX &A7 42DC E4 52 CPX &52 42DE D0 0A BNE &42EA 42E0 A0 EE LDY #&EE 42E2 20 07 3D JSR &3D07 42E5 A9 C8 LDA #&C8 42E7 20 29 4B JSR &4B29 .KS5 42EA A4 A7 LDY &A7 42EC BE 40 0D LDX &0D40,Y 42EF E0 08 CPX #&08 42F1 F0 98 BEQ &428B 42F3 DE 4D 0D DEC &0D4D,X 42F6 A6 A7 LDX &A7 42F8 A0 05 LDY #&05 42FA B1 1E LDA (&1E),Y 42FC A0 21 LDY #&21 42FE 18 CLC 42FF 71 20 ADC (&20),Y 4301 85 1B STA &1B 4303 C8 INY 4304 B1 20 LDA (&20),Y 4306 69 00 ADC #&00 4308 85 1C STA &1C .KSL1 430A E8 INX 430B BD 40 0D LDA &0D40,X 430E 9D 3F 0D STA &0D3F,X 4311 F0 90 BEQ &42A3 4313 0A ASL A 4314 A8 TAY 4315 B9 38 56 LDA &5638,Y 4318 85 07 STA &07 431A B9 39 56 LDA &5639,Y 431D 85 08 STA &08 431F A0 05 LDY #&05 4321 B1 07 LDA (&07),Y 4323 85 D1 STA &D1 4325 A5 1B LDA &1B 4327 38 SEC 4328 E5 D1 SBC &D1 432A 85 1B STA &1B 432C A5 1C LDA &1C 432E E9 00 SBC #&00 4330 85 1C STA &1C 4332 8A TXA 4333 0A ASL A 4334 A8 TAY 4335 B9 48 18 LDA &1848,Y 4338 85 07 STA &07 433A B9 49 18 LDA &1849,Y 433D 85 08 STA &08 433F A0 23 LDY #&23 4341 B1 07 LDA (&07),Y 4343 91 20 STA (&20),Y 4345 88 DEY 4346 B1 07 LDA (&07),Y 4348 85 3E STA &3E 434A A5 1C LDA &1C 434C 91 20 STA (&20),Y 434E 88 DEY 434F B1 07 LDA (&07),Y 4351 85 3D STA &3D 4353 A5 1B LDA &1B 4355 91 20 STA (&20),Y 4357 88 DEY .KSL2 4358 B1 07 LDA (&07),Y 435A 91 20 STA (&20),Y 435C 88 DEY 435D 10 F9 BPL &4358 435F A5 07 LDA &07 4361 85 20 STA &20 4363 A5 08 LDA &08 4365 85 21 STA &21 4367 A4 D1 LDY &D1 .KSL3 4369 88 DEY 436A B1 3D LDA (&3D),Y 436C 91 1B STA (&1B),Y 436E 98 TYA 436F D0 F8 BNE &4369 4371 F0 97 BEQ &430A .SFX 4373 12 4374 01 4375 00 4376 10 4377 12 4378 02 4379 2C 437A 08 437B 11 437C 03 437D F0 437E 18 437F 10 4380 F1 4381 07 4382 1A 4383 03 4384 F1 4385 BC 4386 01 4387 13 4388 F4 4389 0C 438A 08 438B 10 438C F1 438D 06 438E 0C 438F 10 4390 02 4391 60 4392 10 4393 13 4394 04 4395 C2 4396 FF 4397 13 4398 00 4399 00 439A 00 .RESET 439B 20 23 48 JSR &4823 439E A2 06 LDX #&06 .SAL3 43A0 95 2A STA &2A,X 43A2 CA DEX 43A3 10 FB BPL &43A0 43A5 86 9F STX &9F .RES4 43A7 A9 FF LDA #&FF 43A9 A2 02 LDX #&02 .REL5 43AB 9D 11 0F STA &0F11,X 43AE CA DEX 43AF 10 FA BPL &43AB .RES2 43B1 A9 12 LDA #&12 43B3 8D 33 0F STA &0F33 43B6 A2 FF LDX #&FF 43B8 8E 26 0E STX &0E26 43BB 8E 74 0E STX &0E74 43BE 86 52 STX &52 43C0 A9 80 LDA #&80 43C2 85 9D STA &9D 43C4 85 88 STA &88 43C6 85 8A STA &8A 43C8 0A ASL A 43C9 85 89 STA &89 43CB 85 8B STA &8B 43CD 85 99 STA &99 43CF A9 03 LDA #&03 43D1 85 8C STA &8C 43D3 85 9E STA &9E 43D5 85 87 STA &87 43D7 AD 55 0D LDA &0D55 43DA F0 03 BEQ &43DF 43DC 20 25 3D JSR &3D25 43DF A5 30 LDA &30 43E1 F0 03 BEQ &43E6 43E3 20 7E 49 JSR &497E .yu 43E6 20 F5 3A JSR &3AF5 43E9 20 23 48 JSR &4823 43EC A9 3F LDA #&3F 43EE 8D 1E 0F STA &0F1E 43F1 A9 0D LDA #&0D 43F3 8D 1F 0F STA &0F1F 43F6 20 F8 1F JSR &1FF8 .ZINF 43F9 A0 23 LDY #&23 43FB A9 00 LDA #&00 .ZI1 43FD 99 53 00 STA &0053,Y 4400 88 DEY 4401 10 FA BPL &43FD 4403 A9 60 LDA #&60 4405 85 65 STA &65 4407 85 69 STA &69 4409 09 80 ORA #&80 440B 85 61 STA &61 440D 60 RTS .msblob 440E A2 04 LDX #&04 .ss 4410 EC 33 03 CPX &0333 4413 F0 09 BEQ &441E 4415 A0 00 LDY #&00 4417 20 41 3D JSR &3D41 441A CA DEX 441B D0 F3 BNE &4410 441D 60 RTS .SAL8 441E A0 EE LDY #&EE 4420 20 41 3D JSR &3D41 4423 CA DEX 4424 D0 F8 BNE &441E 4426 60 RTS .me2 4427 AD 10 0F LDA &0F10 442A 20 29 4B JSR &4B29 442D A9 00 LDA #&00 442F 8D 64 0D STA &0D64 4432 4C 8A 44 JMP &448A .Ze 4435 20 F9 43 JSR &43F9 4438 20 57 44 JSR &4457 443B 85 06 STA &06 443D 29 80 AND #&80 443F 85 55 STA &55 4441 8A TXA 4442 29 80 AND #&80 4444 85 58 STA &58 4446 A9 20 LDA #&20 4448 85 54 STA &54 444A 85 57 STA &57 444C 85 5A STA &5A 444E 8A TXA 444F C9 F5 CMP #&F5 4451 2A ROL A 4452 09 C0 ORA #&C0 4454 85 73 STA &73 .DORND2 4456 18 CLC .DORND 4457 A5 00 LDA &00 4459 2A ROL A 445A AA TAX 445B 65 02 ADC &02 445D 85 00 STA &00 445F 86 02 STX &02 4461 A5 01 LDA &01 4463 AA TAX 4464 65 03 ADC &03 4466 85 01 STA &01 4468 86 03 STX &03 446A 60 RTS .MTT4 446B 4A LSR A 446C 85 73 STA &73 446E 85 70 STA &70 4470 26 72 ROL &72 4472 29 1F AND #&1F 4474 09 10 ORA #&10 4476 85 6E STA &6E 4478 A9 07 LDA #&07 447A 20 82 3C JSR &3C82 .TT100 447D 20 51 0F JSR &0F51 4480 CE 64 0D DEC &0D64 4483 F0 A2 BEQ &4427 4485 10 03 BPL &448A 4487 EE 64 0D INC &0D64 .me3 448A C6 99 DEC &99 448C F0 03 BEQ &4491 .ytq 448E 4C 60 45 JMP &4560 4491 AD 5C 0D LDA &0D5C 4494 D0 F8 BNE &448E 4496 20 57 44 JSR &4457 4499 C9 23 CMP #&23 449B B0 4D BCS &44EA 449D AD 57 0D LDA &0D57 44A0 C9 03 CMP #&03 44A2 B0 46 BCS &44EA 44A4 20 F9 43 JSR &43F9 44A7 A9 26 LDA #&26 44A9 85 5A STA &5A 44AB 20 57 44 JSR &4457 44AE 85 53 STA &53 44B0 86 56 STX &56 44B2 29 80 AND #&80 44B4 85 55 STA &55 44B6 8A TXA 44B7 29 80 AND #&80 44B9 85 58 STA &58 44BB 26 54 ROL &54 44BD 26 54 ROL &54 44BF 20 57 44 JSR &4457 44C2 70 A7 BVS &446B 44C4 09 6F ORA #&6F 44C6 85 70 STA &70 44C8 AD 55 0D LDA &0D55 44CB D0 1D BNE &44EA 44CD 8A TXA 44CE B0 08 BCS &44D8 44D0 29 1F AND #&1F 44D2 09 10 ORA #&10 44D4 85 6E STA &6E 44D6 90 04 BCC &44DC .MTT2 44D8 09 7F ORA #&7F 44DA 85 71 STA &71 .MTT3 44DC 20 57 44 JSR &4457 44DF C9 05 CMP #&05 44E1 A9 0A LDA #&0A 44E3 B0 02 BCS &44E7 44E5 A9 0B LDA #&0B 44E7 20 82 3C JSR &3C82 .MTT1 44EA AD 55 0D LDA &0D55 44ED D0 71 BNE &4560 44EF 20 5F 46 JSR &465F 44F2 0A ASL A 44F3 AE 4F 0D LDX &0D4F 44F6 F0 03 BEQ &44FB 44F8 0D 34 03 ORA &0334 44FB 85 D1 STA &D1 44FD 20 35 44 JSR &4435 4500 C5 D1 CMP &D1 4502 B0 05 BCS &4509 4504 A9 02 LDA #&02 4506 20 82 3C JSR &3C82 4509 AD 4F 0D LDA &0D4F 450C D0 52 BNE &4560 450E CE 63 0D DEC &0D63 4511 10 4D BPL &4560 4513 EE 63 0D INC &0D63 4516 20 57 44 JSR &4457 4519 AC 1C 0F LDY &0F1C 451C F0 0B BEQ &4529 451E C9 5A CMP #&5A 4520 B0 3E BCS &4560 4522 29 07 AND #&07 4524 CD 1C 0F CMP &0F1C 4527 90 37 BCC &4560 .LABEL_2 4529 20 35 44 JSR &4435 452C C9 C8 CMP #&C8 452E B0 1B BCS &454B 4530 EE 63 0D INC &0D63 4533 29 03 AND #&03 4535 69 03 ADC #&03 4537 A8 TAY 4538 8A TXA 4539 C9 C8 CMP #&C8 453B 2A ROL A 453C 09 C0 ORA #&C0 453E C0 06 CPY #&06 4540 F0 4B BEQ &458D 4542 85 73 STA &73 4544 98 TYA 4545 20 82 3C JSR &3C82 .mj1 4548 4C 60 45 JMP &4560 .mt1 454B 29 03 AND #&03 454D 8D 63 0D STA &0D63 4550 85 98 STA &98 .mt3 4552 20 57 44 JSR &4457 4555 29 03 AND #&03 4557 09 01 ORA #&01 4559 20 82 3C JSR &3C82 455C C6 98 DEC &98 455E 10 F2 BPL &4552 .MLOOP 4560 A9 01 LDA #&01 4562 8D 4E FE STA &FE4E 4565 A2 FF LDX #&FF 4567 9A TXS 4568 AE 61 0D LDX &0D61 456B F0 03 BEQ &4570 456D CE 61 0D DEC &0D61 .EE20 4570 20 F8 1F JSR &1FF8 4573 A5 96 LDA &96 4575 F0 09 BEQ &4580 4577 2D 4C 0F AND &0F4C 457A 4A LSR A 457B B0 03 BCS &4580 457D 20 E1 2B JSR &2BE1 4580 20 25 42 JSR &4225 .FRCE 4583 20 9A 45 JSR &459A 4586 A5 9F LDA &9F 4588 D0 D6 BNE &4560 458A 4C 7D 44 JMP &447D .tha 458D 20 57 44 JSR &4457 4590 C9 C8 CMP #&C8 4592 90 03 BCC &4597 4594 20 3D 35 JSR &353D 4597 4C 60 45 JMP &4560 .TT102 459A C9 76 CMP #&76 459C D0 03 BNE &45A1 459E 4C F8 1D JMP &1DF8 45A1 C9 14 CMP #&14 45A3 D0 03 BNE &45A8 45A5 4C C0 2E JMP &2EC0 45A8 C9 74 CMP #&74 45AA D0 03 BNE &45AF 45AC 4C EF 31 JMP &31EF 45AF C9 75 CMP #&75 45B1 D0 06 BNE &45B9 45B3 20 A4 32 JSR &32A4 45B6 4C 4A 2D JMP &2D4A .TT92 45B9 C9 77 CMP #&77 45BB D0 03 BNE &45C0 45BD 4C 24 31 JMP &3124 45C0 C9 16 CMP #&16 45C2 D0 03 BNE &45C7 45C4 4C 8E 34 JMP &348E 45C7 C9 20 CMP #&20 45C9 D0 03 BNE &45CE 45CB 4C BA 35 JMP &35BA .fvw 45CE 24 9F BIT &9F 45D0 10 1C BPL &45EE 45D2 C9 73 CMP #&73 45D4 D0 03 BNE &45D9 45D6 4C 49 36 JMP &3649 45D9 C9 71 CMP #&71 45DB D0 03 BNE &45E0 45DD 4C B3 2F JMP &2FB3 45E0 C9 47 CMP #&47 45E2 D0 03 BNE &45E7 45E4 4C 3B 48 JMP &483B 45E7 C9 72 CMP #&72 45E9 D0 11 BNE &45FC 45EB 4C 95 30 JMP &3095 .INSP 45EE C9 71 CMP #&71 45F0 90 0A BCC &45FC 45F2 C9 74 CMP #&74 45F4 B0 06 BCS &45FC 45F6 29 03 AND #&03 45F8 AA TAX 45F9 4C 44 2B JMP &2B44 .LABEL_3 45FC C9 54 CMP #&54 45FE D0 03 BNE &4603 4600 4C 4A 33 JMP &334A 4603 C9 32 CMP #&32 4605 F0 3D BEQ &4644 4607 85 06 STA &06 4609 A5 96 LDA &96 460B 29 C0 AND #&C0 460D F0 16 BEQ &4625 460F A5 2F LDA &2F 4611 D0 12 BNE &4625 4613 A5 06 LDA &06 4615 C9 36 CMP #&36 4617 D0 09 BNE &4622 4619 20 94 31 JSR &3194 461C 20 6A 42 JSR &426A 461F 20 94 31 JSR &3194 .ee2 4622 20 67 31 JSR &3167 .TT107 4625 A5 2F LDA &2F 4627 F0 1A BEQ &4643 4629 C6 2E DEC &2E 462B D0 16 BNE &4643 462D A6 2F LDX &2F 462F CA DEX 4630 20 E0 33 JSR &33E0 4633 A9 05 LDA #&05 4635 85 2E STA &2E 4637 A6 2F LDX &2F 4639 20 E0 33 JSR &33E0 463C C6 2F DEC &2F 463E D0 03 BNE &4643 4640 4C 7C 35 JMP &357C .t95 4643 60 RTS .T95 4644 A5 96 LDA &96 4646 29 C0 AND #&C0 4648 F0 F9 BEQ &4643 464A 20 ED 2B JSR &2BED 464D 85 7E STA &7E 464F 20 21 38 JSR &3821 4652 A9 80 LDA #&80 4654 85 7E STA &7E 4656 A9 01 LDA #&01 4658 85 2C STA &2C 465A E6 2D INC &2D 465C 4C 12 2D JMP &2D12 .BAD 465F AD 1A 03 LDA &031A 4662 18 CLC 4663 6D 1D 03 ADC &031D 4666 0A ASL A 4667 6D 21 03 ADC &0321 466A 60 RTS .FAROF 466B A9 E0 LDA #&E0 .FAROF2 466D C5 54 CMP &54 466F 90 06 BCC &4677 4671 C5 57 CMP &57 4673 90 02 BCC &4677 4675 C5 5A CMP &5A .MA34 4677 60 RTS .MAS4 4678 05 54 ORA &54 467A 05 57 ORA &57 467C 05 5A ORA &5A 467E 60 RTS .DEATH 467F 20 8C 49 JSR &498C 4682 20 B1 43 JSR &43B1 4685 06 8C ASL &8C 4687 06 8C ASL &8C 4689 A2 18 LDX #&18 468B 20 36 3B JSR &3B36 468E 20 7B 2B JSR &2B7B 4691 20 9C 2B JSR &2B9C 4694 20 D2 3A JSR &3AD2 4697 A9 0C LDA #&0C 4699 85 2D STA &2D 469B 85 2C STA &2C 469D A9 92 LDA #&92 469F 20 49 39 JSR &3949 .D1 46A2 20 35 44 JSR &4435 46A5 4A LSR A 46A6 4A LSR A 46A7 85 53 STA &53 46A9 A0 00 LDY #&00 46AB 84 96 STY &96 46AD 84 54 STY &54 46AF 84 57 STY &57 46B1 84 5A STY &5A 46B3 84 73 STY &73 46B5 88 DEY 46B6 84 99 STY &99 46B8 8C 60 0D STY &0D60 46BB 49 2A EOR #&2A 46BD 85 56 STA &56 46BF 09 50 ORA #&50 46C1 85 59 STA &59 46C3 8A TXA 46C4 29 8F AND #&8F 46C6 85 70 STA &70 46C8 6A ROR A 46C9 29 87 AND #&87 46CB 85 71 STA &71 46CD 08 PHP 46CE A2 0B LDX #&0B 46D0 20 7B 24 JSR &247B 46D3 28 PLP 46D4 A9 00 LDA #&00 46D6 6A ROR A 46D7 A0 1F LDY #&1F 46D9 91 20 STA (&20),Y 46DB AD 43 0D LDA &0D43 46DE F0 C2 BEQ &46A2 46E0 20 74 4A JSR &4A74 46E3 85 8C STA &8C .D2 46E5 20 51 0F JSR &0F51 46E8 AD 60 0D LDA &0D60 46EB D0 F8 BNE &46E5 46ED A2 1F LDX #&1F 46EF 20 36 3B JSR &3B36 .DEATH2 46F2 20 B1 43 JSR &43B1 .TT170 46F5 A2 FF LDX #&FF 46F7 9A TXS .BR1 46F8 A2 03 LDX #&03 46FA 86 2C STX &2C 46FC 20 D6 48 JSR &48D6 46FF A2 07 LDX #&07 4701 A9 80 LDA #&80 4703 20 56 47 JSR &4756 4706 C9 44 CMP #&44 4708 D0 0C BNE &4716 470A 20 F5 47 JSR &47F5 470D 20 AE 48 JSR &48AE 4710 20 E0 47 JSR &47E0 4713 20 7D 2B JSR &2B7D .QU5 4716 A2 4B LDX #&4B .QUL1 4718 BD FB 17 LDA &17FB,X 471B 9D FF 02 STA &02FF,X 471E CA DEX 471F D0 F7 BNE &4718 4721 86 96 STX &96 4723 20 D2 47 JSR &47D2 4726 CD 47 18 CMP &1847 4729 D0 F8 BNE &4723 472B 49 A9 EOR #&A9 472D AA TAX 472E AD 0E 03 LDA &030E 4731 EC 46 18 CPX &1846 4734 F0 02 BEQ &4738 4736 09 80 ORA #&80 .tZ 4738 09 02 ORA #&02 473A 8D 0E 03 STA &030E 473D 20 0E 44 JSR &440E 4740 A9 93 LDA #&93 4742 A2 03 LDX #&03 4744 20 56 47 JSR &4756 4747 20 6A 42 JSR &426A 474A 20 D6 34 JSR &34D6 .BAY 474D A9 FF LDA #&FF 474F 85 9F STA &9F 4751 A9 76 LDA #&76 4753 4C 83 45 JMP &4583 .TITLE 4756 48 PHA 4757 86 9B STX &9B 4759 20 9B 43 JSR &439B 475C A9 01 LDA #&01 475E 20 7B 2B JSR &2B7B 4761 C6 96 DEC &96 4763 A9 60 LDA #&60 4765 85 61 STA &61 4767 85 5A STA &5A 4769 A2 7F LDX #&7F 476B 86 70 STX &70 476D 86 71 STX &71 476F E8 INX 4770 86 7E STX &7E 4772 A5 9B LDA &9B 4774 20 82 3C JSR &3C82 4777 A0 06 LDY #&06 4779 84 2C STY &2C 477B 20 E6 2B JSR &2BE6 477E A9 1E LDA #&1E 4780 20 AB 38 JSR &38AB 4783 A0 06 LDY #&06 4785 84 2C STY &2C 4787 E6 2D INC &2D 4789 AD 4C 0F LDA &0F4C 478C F0 05 BEQ &4793 478E A9 FE LDA #&FE 4790 20 B6 38 JSR &38B6 .awe 4793 20 FA 2B JSR &2BFA 4796 84 8C STY &8C 4798 8C 50 0F STY &0F50 479B 68 PLA 479C 20 49 39 JSR &3949 479F A9 94 LDA #&94 47A1 A2 07 LDX #&07 47A3 86 2C STX &2C 47A5 20 49 39 JSR &3949 .TLL2 47A8 A5 5A LDA &5A 47AA C9 01 CMP #&01 47AC F0 02 BEQ &47B0 47AE C6 5A DEC &5A .TL1 47B0 20 A9 13 JSR &13A9 47B3 A9 80 LDA #&80 47B5 85 59 STA &59 47B7 0A ASL A 47B8 85 53 STA &53 47BA 85 56 STA &56 47BC 20 2F 4E JSR &4E2F 47BF C6 99 DEC &99 47C1 AD 40 FE LDA &FE40 47C4 29 10 AND #&10 47C6 F0 06 BEQ &47CE 47C8 20 6F 49 JSR &496F 47CB F0 DB BEQ &47A8 47CD 60 RTS .TL2 47CE CE 50 0F DEC &0F50 47D1 60 RTS .CHECK 47D2 A2 49 LDX #&49 47D4 18 CLC 47D5 8A TXA .QUL2 47D6 7D FB 17 ADC &17FB,X 47D9 5D FC 17 EOR &17FC,X 47DC CA DEX 47DD D0 F7 BNE &47D6 47DF 60 RTS .TRNME 47E0 A2 07 LDX #&07 .GTL1 47E2 B5 53 LDA &53,X 47E4 9D F4 17 STA &17F4,X 47E7 CA DEX 47E8 10 F8 BPL &47E2 .TR1 47EA A2 07 LDX #&07 .GTL2 47EC BD F4 17 LDA &17F4,X 47EF 95 53 STA &53,X 47F1 CA DEX 47F2 10 F8 BPL &47EC 47F4 60 RTS .GTNME 47F5 A9 01 LDA #&01 47F7 20 7B 2B JSR &2B7B 47FA A9 7B LDA #&7B 47FC 20 B6 38 JSR &38B6 47FF 20 E4 2B JSR &2BE4 4802 A9 81 LDA #&81 4804 8D 4E FE STA &FE4E 4807 A9 0F LDA #&0F 4809 AA TAX 480A 20 F4 FF JSR &FFF4 480D A2 1E LDX #&1E 480F A0 48 LDY #&48 4811 A9 00 LDA #&00 4813 20 F1 FF JSR &FFF1 4816 B0 D2 BCS &47EA 4818 98 TYA 4819 F0 CF BEQ &47EA 481B 4C 37 2D JMP &2D37 .RLINE 481E 53 00 4820 07 4821 21 4822 7A .ZERO 4823 A2 0D LDX #&0D .ZEL 4825 20 2D 48 JSR &482D 4828 CA DEX 4829 E0 09 CPX #&09 482B D0 F8 BNE &4825 .ZES1 482D A0 00 LDY #&00 482F 84 07 STY &07 .ZES2 4831 A9 00 LDA #&00 4833 86 08 STX &08 .ZEL1 4835 91 07 STA (&07),Y 4837 C8 INY 4838 D0 FB BNE &4835 483A 60 RTS .SVE 483B 20 F5 47 JSR &47F5 483E 20 E0 47 JSR &47E0 4841 20 23 48 JSR &4823 4844 4E 49 03 LSR &0349 4847 A2 4B LDX #&4B .SVL1 4849 BD 00 03 LDA &0300,X 484C 9D 00 0B STA &0B00,X 484F 9D FC 17 STA &17FC,X 4852 CA DEX 4853 10 F4 BPL &4849 4855 20 D2 47 JSR &47D2 4858 8D 47 18 STA &1847 485B 48 PHA 485C 09 80 ORA #&80 485E 85 3D STA &3D 4860 4D 0E 03 EOR &030E 4863 85 3F STA &3F 4865 4D 0B 03 EOR &030B 4868 85 3E STA &3E 486A 49 5A EOR #&5A 486C 4D 48 03 EOR &0348 486F 85 40 STA &40 4871 20 CD 1E JSR &1ECD 4874 20 37 2D JSR &2D37 4877 20 37 2D JSR &2D37 487A 68 PLA 487B 8D 4B 0B STA &0B4B 487E 49 A9 EOR #&A9 4880 8D 46 18 STA &1846 4883 8D 4A 0B STA &0B4A 4886 A0 0B LDY #&0B 4888 8C 0B 0C STY &0C0B 488B C8 INY 488C 8C 0F 0C STY &0C0F 488F A9 81 LDA #&81 4891 8D 4E FE STA &FE4E 4894 EE FD 7F INC &7FFD 4897 A9 00 LDA #&00 4899 20 A4 48 JSR &48A4 489C A2 00 LDX #&00 489E 8E FD 7F STX &7FFD 48A1 4C 4D 47 JMP &474D .QUS1 48A4 A2 53 LDX #&53 48A6 8E 00 0C STX &0C00 48A9 A2 00 LDX #&00 48AB 4C DD FF JMP &FFDD .LOD 48AE A2 02 LDX #&02 48B0 20 D6 48 JSR &48D6 48B3 20 23 48 JSR &4823 48B6 A0 0B LDY #&0B 48B8 8C 03 0C STY &0C03 48BB EE 0B 0C INC &0C0B 48BE C8 INY 48BF A9 FF LDA #&FF 48C1 20 A4 48 JSR &48A4 48C4 AD 00 0B LDA &0B00 48C7 30 16 BMI &48DF 48C9 A2 4B LDX #&4B .LOL1 48CB BD 00 0B LDA &0B00,X 48CE 9D FC 17 STA &17FC,X 48D1 CA DEX 48D2 10 F7 BPL &48CB 48D4 A2 03 LDX #&03 .FX200 48D6 A0 00 LDY #&00 48D8 A9 C8 LDA #&C8 48DA 4C F4 FF JMP &FFF4 48DD 60 RTS .SPS1 48DE A2 00 LDX #&00 48E0 20 3C 3C JSR &3C3C 48E3 A2 03 LDX #&03 48E5 20 3C 3C JSR &3C3C 48E8 A2 06 LDX #&06 48EA 20 3C 3C JSR &3C3C .TAS2 48ED A5 D2 LDA &D2 48EF 05 D5 ORA &D5 48F1 05 D8 ORA &D8 48F3 09 01 ORA #&01 48F5 85 DB STA &DB 48F7 A5 D3 LDA &D3 48F9 05 D6 ORA &D6 48FB 05 D9 ORA &D9 .TAL2 48FD 06 DB ASL &DB 48FF 2A ROL A 4900 B0 0E BCS &4910 4902 06 D2 ASL &D2 4904 26 D3 ROL &D3 4906 06 D5 ASL &D5 4908 26 D6 ROL &D6 490A 06 D8 ASL &D8 490C 26 D9 ROL &D9 490E 90 ED BCC &48FD .TA2 4910 A5 D3 LDA &D3 4912 4A LSR A 4913 05 D4 ORA &D4 4915 85 31 STA &31 4917 A5 D6 LDA &D6 4919 4A LSR A 491A 05 D7 ORA &D7 491C 85 32 STA &32 491E A5 D9 LDA &D9 4920 4A LSR A 4921 05 DA ORA &DA 4923 85 33 STA &33 .NORM 4925 A5 31 LDA &31 4927 20 6D 27 JSR &276D 492A 85 91 STA &91 492C A5 1B LDA &1B 492E 85 90 STA &90 4930 A5 32 LDA &32 4932 20 6D 27 JSR &276D 4935 85 D1 STA &D1 4937 A5 1B LDA &1B 4939 65 90 ADC &90 493B 85 90 STA &90 493D A5 D1 LDA &D1 493F 65 91 ADC &91 4941 85 91 STA &91 4943 A5 33 LDA &33 4945 20 6D 27 JSR &276D 4948 85 D1 STA &D1 494A A5 1B LDA &1B 494C 65 90 ADC &90 494E 85 90 STA &90 4950 A5 D1 LDA &D1 4952 65 91 ADC &91 4954 85 91 STA &91 4956 20 5B 4D JSR &4D5B 4959 A5 31 LDA &31 495B 20 A2 4C JSR &4CA2 495E 85 31 STA &31 4960 A5 32 LDA &32 4962 20 A2 4C JSR &4CA2 4965 85 32 STA &32 4967 A5 33 LDA &33 4969 20 A2 4C JSR &4CA2 496C 85 33 STA &33 .NO1 496E 60 RTS .RDKEY 496F A2 10 LDX #&10 .Rd1 4971 20 11 4A JSR &4A11 4974 30 04 BMI &497A 4976 E8 INX 4977 10 F8 BPL &4971 4979 8A TXA .Rd2 497A 49 80 EOR #&80 497C AA TAX 497D 60 RTS .ECMOF 497E A9 00 LDA #&00 4980 85 30 STA &30 4982 8D 5B 0D STA &0D5B 4985 20 1D 3D JSR &3D1D 4988 A9 48 LDA #&48 498A D0 41 BNE &49CD .EXNO3 498C A9 10 LDA #&10 498E 20 CD 49 JSR &49CD 4991 A9 18 LDA #&18 4993 D0 38 BNE &49CD .SFRMIS 4995 A2 09 LDX #&09 4997 20 DE 24 JSR &24DE 499A 90 D2 BCC &496E 499C A9 78 LDA #&78 499E 20 29 4B JSR &4B29 49A1 A9 30 LDA #&30 49A3 D0 28 BNE &49CD .EXNO2 49A5 EE 47 03 INC &0347 49A8 D0 08 BNE &49B2 49AA EE 48 03 INC &0348 49AD A9 65 LDA #&65 49AF 20 29 4B JSR &4B29 49B2 A2 07 LDX #&07 .EXNO 49B4 86 D1 STX &D1 49B6 A9 18 LDA #&18 49B8 20 DE 49 JSR &49DE 49BB A5 5A LDA &5A 49BD 4A LSR A 49BE 4A LSR A 49BF 25 D1 AND &D1 49C1 09 F1 ORA #&F1 49C3 85 0B STA &0B 49C5 20 D0 49 JSR &49D0 49C8 A9 10 LDA #&10 49CA 2C .BEEP 49CB A9 20 LDA #&20 .NOISE 49CD 20 DE 49 JSR &49DE .NO3 49D0 AE 49 0F LDX &0F49 49D3 D0 99 BNE &496E 49D5 A2 09 LDX #&09 49D7 A0 00 LDY #&00 49D9 A9 07 LDA #&07 49DB 4C F1 FF JMP &FFF1 .NOS1 49DE 4A LSR A 49DF 69 03 ADC #&03 49E1 A8 TAY 49E2 A2 07 LDX #&07 .NOL1 49E4 A9 00 LDA #&00 49E6 95 09 STA &09,X 49E8 CA DEX 49E9 B9 73 43 LDA &4373,Y 49EC 95 09 STA &09,X 49EE 88 DEY 49EF CA DEX 49F0 10 F2 BPL &49E4 .KYTB 49F2 60 RTS 49F3 E8 49F4 E2 49F5 E6 49F6 E7 49F7 C2 49F8 D1 49F9 C1 49FA 60 49FB 70 49FC 23 49FD 35 49FE 65 49FF 22 4A00 45 4A01 52 .DKS1 4A02 BE F2 49 LDX &49F2,Y 4A05 20 11 4A JSR &4A11 4A08 10 1F BPL &4A29 4A0A A2 FF LDX #&FF 4A0C 96 41 STX &41,Y 4A0E 60 RTS .CTRL 4A0F A2 01 LDX #&01 .DKS4 4A11 A9 03 LDA #&03 4A13 78 SEI 4A14 8D 40 FE STA &FE40 4A17 A9 7F LDA #&7F 4A19 8D 43 FE STA &FE43 4A1C 8E 4F FE STX &FE4F 4A1F AE 4F FE LDX &FE4F 4A22 A9 0B LDA #&0B 4A24 8D 40 FE STA &FE40 4A27 58 CLI 4A28 8A TXA 4A29 60 RTS .DKS2 4A2A A9 80 LDA #&80 4A2C 20 F4 FF JSR &FFF4 4A2F 98 TYA 4A30 4D 4F 0F EOR &0F4F 4A33 60 RTS .DKS3 4A34 84 D1 STY &D1 4A36 E4 D1 CPX &D1 4A38 D0 10 BNE &4A4A 4A3A BD 0A 0F LDA &0F0A,X 4A3D 49 FF EOR #&FF 4A3F 9D 0A 0F STA &0F0A,X 4A42 20 7F 1F JSR &1F7F 4A45 20 E6 2B JSR &2BE6 4A48 A4 D1 LDY &D1 .Dk3 4A4A 60 RTS .DKJ1 4A4B A0 01 LDY #&01 4A4D 20 02 4A JSR &4A02 4A50 C8 INY 4A51 20 02 4A JSR &4A02 4A54 AD 40 FE LDA &FE40 4A57 AA TAX 4A58 29 10 AND #&10 4A5A 49 10 EOR #&10 4A5C 85 48 STA &48 4A5E A2 01 LDX #&01 4A60 20 2A 4A JSR &4A2A 4A63 09 01 ORA #&01 4A65 85 9C STA &9C 4A67 A2 02 LDX #&02 4A69 20 2A 4A JSR &4A2A 4A6C 4D 4E 0F EOR &0F4E 4A6F 85 9D STA &9D 4A71 4C B6 4A JMP &4AB6 .U% 4A74 A9 00 LDA #&00 4A76 A0 0F LDY #&0F .DKL3 4A78 99 41 00 STA &0041,Y 4A7B 88 DEY 4A7C D0 FA BNE &4A78 4A7E 60 RTS .DOKEY 4A7F 20 74 4A JSR &4A74 4A82 AD 50 0F LDA &0F50 4A85 D0 C4 BNE &4A4B 4A87 A0 07 LDY #&07 .DKL2 4A89 20 02 4A JSR &4A02 4A8C 88 DEY 4A8D D0 FA BNE &4A89 4A8F A6 9C LDX &9C 4A91 A9 07 LDA #&07 4A93 A4 44 LDY &44 4A95 F0 03 BEQ &4A9A 4A97 20 71 29 JSR &2971 4A9A A4 45 LDY &45 4A9C F0 03 BEQ &4AA1 4A9E 20 81 29 JSR &2981 4AA1 86 9C STX &9C 4AA3 0A ASL A 4AA4 A6 9D LDX &9D 4AA6 A4 46 LDY &46 4AA8 F0 03 BEQ &4AAD 4AAA 20 81 29 JSR &2981 4AAD A4 47 LDY &47 4AAF F0 03 BEQ &4AB4 4AB1 20 71 29 JSR &2971 4AB4 86 9D STX &9D .DK4 4AB6 20 6F 49 JSR &496F 4AB9 86 41 STX &41 4ABB E0 69 CPX #&69 4ABD D0 2B BNE &4AEA .FREEZE 4ABF 20 BF 2C JSR &2CBF 4AC2 20 6F 49 JSR &496F 4AC5 E0 51 CPX #&51 4AC7 D0 05 BNE &4ACE 4AC9 A9 00 LDA #&00 4ACB 8D 49 0F STA &0F49 .DK6 4ACE A0 40 LDY #&40 .DKL4 4AD0 20 34 4A JSR &4A34 4AD3 C8 INY 4AD4 C0 47 CPY #&47 4AD6 D0 F8 BNE &4AD0 .DK55 4AD8 E0 10 CPX #&10 4ADA D0 03 BNE &4ADF 4ADC 8E 49 0F STX &0F49 .DK7 4ADF E0 70 CPX #&70 4AE1 D0 03 BNE &4AE6 4AE3 4C F2 46 JMP &46F2 4AE6 E0 59 CPX #&59 4AE8 D0 D5 BNE &4ABF .DK2 4AEA A5 96 LDA &96 4AEC D0 13 BNE &4B01 4AEE A0 0F LDY #&0F 4AF0 A9 FF LDA #&FF .DKL1 4AF2 BE F2 49 LDX &49F2,Y 4AF5 E4 41 CPX &41 4AF7 D0 03 BNE &4AFC 4AF9 99 41 00 STA &0041,Y .DK1 4AFC 88 DEY 4AFD C0 07 CPY #&07 4AFF D0 F1 BNE &4AF2 .DK5 4B01 60 RTS .TT217 4B02 84 94 STY &94 .t 4B04 20 E1 2B JSR &2BE1 4B07 20 6F 49 JSR &496F 4B0A D0 F8 BNE &4B04 .t2 4B0C 20 6F 49 JSR &496F 4B0F F0 FB BEQ &4B0C 4B11 A8 TAY 4B12 B1 04 LDA (&04),Y 4B14 A4 94 LDY &94 4B16 AA TAX .out 4B17 60 RTS .me1 4B18 8E 64 0D STX &0D64 4B1B 48 PHA 4B1C AD 10 0F LDA &0F10 4B1F 20 40 4B JSR &4B40 4B22 68 PLA 4B23 2C .ou2 4B24 A9 6C LDA #&6C 4B26 2C .ou3 4B27 A9 6F LDA #&6F .MESS 4B29 A2 00 LDX #&00 4B2B 86 7E STX &7E 4B2D A0 09 LDY #&09 4B2F 84 2C STY &2C 4B31 A0 16 LDY #&16 4B33 84 2D STY &2D 4B35 EC 64 0D CPX &0D64 4B38 D0 DE BNE &4B18 4B3A 8C 64 0D STY &0D64 4B3D 8D 10 0F STA &0F10 .mes9 4B40 20 B6 38 JSR &38B6 4B43 4E 65 0D LSR &0D65 4B46 90 CF BCC &4B17 4B48 A9 FD LDA #&FD 4B4A 4C B6 38 JMP &38B6 .OUCH 4B4D 20 57 44 JSR &4457 4B50 30 C5 BMI &4B17 4B52 E0 16 CPX #&16 4B54 B0 C1 BCS &4B17 4B56 BD 17 03 LDA &0317,X 4B59 F0 BC BEQ &4B17 4B5B AD 64 0D LDA &0D64 4B5E D0 B7 BNE &4B17 4B60 A0 03 LDY #&03 4B62 8C 65 0D STY &0D65 4B65 9D 17 03 STA &0317,X 4B68 E0 11 CPX #&11 4B6A B0 05 BCS &4B71 4B6C 8A TXA 4B6D 69 D0 ADC #&D0 4B6F D0 B8 BNE &4B29 .ou1 4B71 F0 B1 BEQ &4B24 4B73 E0 12 CPX #&12 4B75 F0 B0 BEQ &4B27 4B77 8A TXA 4B78 69 5D ADC #&5D 4B7A D0 AD BNE &4B29 .QQ16 4B7C 41 4C 4B7E 4C 45 4B80 58 45 4B82 47 45 4B84 5A 41 4B86 43 45 4B88 42 49 4B8A 53 4F 4B8C 55 53 4B8E 45 53 4B90 41 52 4B92 4D 41 4B94 49 4E 4B96 44 49 4B98 52 45 4B9A 41 3F 4B9C 45 52 4B9E 41 54 4BA0 45 4E 4BA2 42 45 4BA4 52 41 4BA6 4C 41 4BA8 56 45 4BAA 54 49 4BAC 45 44 4BAE 4F 52 4BB0 51 55 4BB2 41 4E 4BB4 54 45 4BB6 49 53 4BB8 52 49 4BBA 4F 4E .QQ23 Macro ITEM: 4BBC 13 4BBD 82 4BBE 06 4BBF 01 End macro ITEM Macro ITEM: 4BC0 14 4BC1 81 4BC2 0A 4BC3 03 End macro ITEM Macro ITEM: 4BC4 41 4BC5 83 4BC6 02 4BC7 07 End macro ITEM Macro ITEM: 4BC8 28 4BC9 85 4BCA E2 4BCB 1F End macro ITEM Macro ITEM: 4BCC 53 4BCD 85 4BCE FB 4BCF 0F End macro ITEM Macro ITEM: 4BD0 C4 4BD1 08 4BD2 36 4BD3 03 End macro ITEM Macro ITEM: 4BD4 EB 4BD5 1D 4BD6 08 4BD7 78 End macro ITEM Macro ITEM: 4BD8 9A 4BD9 0E 4BDA 38 4BDB 03 End macro ITEM Macro ITEM: 4BDC 75 4BDD 06 4BDE 28 4BDF 07 End macro ITEM Macro ITEM: 4BE0 4E 4BE1 01 4BE2 11 4BE3 1F End macro ITEM Macro ITEM: 4BE4 7C 4BE5 0D 4BE6 1D 4BE7 07 End macro ITEM Macro ITEM: 4BE8 B0 4BE9 89 4BEA DC 4BEB 3F End macro ITEM Macro ITEM: 4BEC 20 4BED 81 4BEE 35 4BEF 03 End macro ITEM Macro ITEM: 4BF0 61 4BF1 A1 4BF2 42 4BF3 07 End macro ITEM Macro ITEM: 4BF4 AB 4BF5 A2 4BF6 37 4BF7 1F End macro ITEM Macro ITEM: 4BF8 2D 4BF9 C1 4BFA FA 4BFB 0F End macro ITEM Macro ITEM: 4BFC 35 4BFD 0F 4BFE C0 4BFF 07 End macro ITEM .TI2 4C00 98 TYA 4C01 A0 02 LDY #&02 4C03 20 CF 4C JSR &4CCF 4C06 85 67 STA &67 4C08 4C 48 4C JMP &4C48 .TI1 4C0B AA TAX 4C0C A5 32 LDA &32 4C0E 29 60 AND #&60 4C10 F0 EE BEQ &4C00 4C12 A9 02 LDA #&02 4C14 20 CF 4C JSR &4CCF 4C17 85 65 STA &65 4C19 4C 48 4C JMP &4C48 .TIDY 4C1C A5 5D LDA &5D 4C1E 85 31 STA &31 4C20 A5 5F LDA &5F 4C22 85 32 STA &32 4C24 A5 61 LDA &61 4C26 85 33 STA &33 4C28 20 25 49 JSR &4925 4C2B A5 31 LDA &31 4C2D 85 5D STA &5D 4C2F A5 32 LDA &32 4C31 85 5F STA &5F 4C33 A5 33 LDA &33 4C35 85 61 STA &61 4C37 A0 04 LDY #&04 4C39 A5 31 LDA &31 4C3B 29 60 AND #&60 4C3D F0 CC BEQ &4C0B 4C3F A2 02 LDX #&02 4C41 A9 00 LDA #&00 4C43 20 CF 4C JSR &4CCF 4C46 85 63 STA &63 .TI3 4C48 A5 63 LDA &63 4C4A 85 31 STA &31 4C4C A5 65 LDA &65 4C4E 85 32 STA &32 4C50 A5 67 LDA &67 4C52 85 33 STA &33 4C54 20 25 49 JSR &4925 4C57 A5 31 LDA &31 4C59 85 63 STA &63 4C5B A5 32 LDA &32 4C5D 85 65 STA &65 4C5F A5 33 LDA &33 4C61 85 67 STA &67 4C63 A5 5F LDA &5F 4C65 85 90 STA &90 4C67 A5 67 LDA &67 4C69 20 36 28 JSR &2836 4C6C A6 61 LDX &61 4C6E A5 65 LDA &65 4C70 20 9B 28 JSR &289B 4C73 49 80 EOR #&80 4C75 85 69 STA &69 4C77 A5 63 LDA &63 4C79 20 36 28 JSR &2836 4C7C A6 5D LDX &5D 4C7E A5 67 LDA &67 4C80 20 9B 28 JSR &289B 4C83 49 80 EOR #&80 4C85 85 6B STA &6B 4C87 A5 65 LDA &65 4C89 20 36 28 JSR &2836 4C8C A6 5F LDX &5F 4C8E A5 63 LDA &63 4C90 20 9B 28 JSR &289B 4C93 49 80 EOR #&80 4C95 85 6D STA &6D 4C97 A9 00 LDA #&00 4C99 A2 0E LDX #&0E .TIL1 4C9B 95 5C STA &5C,X 4C9D CA DEX 4C9E CA DEX 4C9F 10 FA BPL &4C9B 4CA1 60 RTS .TIS2 4CA2 A8 TAY 4CA3 29 7F AND #&7F 4CA5 C5 90 CMP &90 4CA7 B0 20 BCS &4CC9 4CA9 A2 FE LDX #&FE 4CAB 86 D1 STX &D1 .TIL2 4CAD 0A ASL A 4CAE C5 90 CMP &90 4CB0 90 02 BCC &4CB4 4CB2 E5 90 SBC &90 4CB4 26 D1 ROL &D1 4CB6 B0 F5 BCS &4CAD 4CB8 A5 D1 LDA &D1 4CBA 4A LSR A 4CBB 4A LSR A 4CBC 85 D1 STA &D1 4CBE 4A LSR A 4CBF 65 D1 ADC &D1 4CC1 85 D1 STA &D1 4CC3 98 TYA 4CC4 29 80 AND #&80 4CC6 05 D1 ORA &D1 4CC8 60 RTS .TI4 4CC9 98 TYA 4CCA 29 80 AND #&80 4CCC 09 60 ORA #&60 4CCE 60 RTS .TIS3 4CCF 85 1D STA &1D 4CD1 B5 5D LDA &5D,X 4CD3 85 90 STA &90 4CD5 B5 63 LDA &63,X 4CD7 20 36 28 JSR &2836 4CDA B6 5D LDX &5D,Y 4CDC 86 90 STX &90 4CDE B9 63 00 LDA &0063,Y 4CE1 20 5C 28 JSR &285C 4CE4 86 1B STX &1B 4CE6 A4 1D LDY &1D 4CE8 B6 5D LDX &5D,Y 4CEA 86 90 STX &90 4CEC 49 80 EOR #&80 .DVIDT 4CEE 85 1C STA &1C 4CF0 45 90 EOR &90 4CF2 29 80 AND #&80 4CF4 85 D1 STA &D1 4CF6 A9 00 LDA #&00 4CF8 A2 10 LDX #&10 4CFA 06 1B ASL &1B 4CFC 26 1C ROL &1C 4CFE 06 90 ASL &90 4D00 46 90 LSR &90 .DVL2 4D02 2A ROL A 4D03 C5 90 CMP &90 4D05 90 02 BCC &4D09 4D07 E5 90 SBC &90 4D09 26 1B ROL &1B 4D0B 26 1C ROL &1C 4D0D CA DEX 4D0E D0 F2 BNE &4D02 4D10 A5 1B LDA &1B 4D12 05 D1 ORA &D1 4D14 60 RTS ELITE F Assembled at &4276 Ends at &4D15 Code size is &A9F Execute at &1128 Reload at &445E S.ELTF &4276 &4D15 &1128 &445E Saving file '3-assembled-output/ELTF.bin' .SHPPT 4D15 20 7D 4E JSR &4E7D 4D18 20 5A 3D JSR &3D5A 4D1B 05 D3 ORA &D3 4D1D D0 21 BNE &4D40 4D1F A5 E0 LDA &E0 4D21 C9 BE CMP #&BE 4D23 B0 1B BCS &4D40 4D25 A0 02 LDY #&02 4D27 20 47 4D JSR &4D47 4D2A A0 06 LDY #&06 4D2C A5 E0 LDA &E0 4D2E 69 01 ADC #&01 4D30 20 47 4D JSR &4D47 4D33 A9 08 LDA #&08 4D35 05 72 ORA &72 4D37 85 72 STA &72 4D39 A9 08 LDA #&08 4D3B 4C E7 53 JMP &53E7 4D3E 68 PLA 4D3F 68 PLA .nono 4D40 A9 F7 LDA #&F7 4D42 25 72 AND &72 4D44 85 72 STA &72 4D46 60 RTS .Shpt 4D47 91 74 STA (&74),Y 4D49 C8 INY 4D4A C8 INY 4D4B 91 74 STA (&74),Y 4D4D A5 D2 LDA &D2 4D4F 88 DEY 4D50 91 74 STA (&74),Y 4D52 69 03 ADC #&03 4D54 B0 E8 BCS &4D3E 4D56 88 DEY 4D57 88 DEY 4D58 91 74 STA (&74),Y 4D5A 60 RTS .LL5 4D5B A4 91 LDY &91 4D5D A5 90 LDA &90 4D5F 85 92 STA &92 4D61 A2 00 LDX #&00 4D63 86 90 STX &90 4D65 A9 08 LDA #&08 4D67 85 D1 STA &D1 .LL6 4D69 E4 90 CPX &90 4D6B 90 0E BCC &4D7B 4D6D D0 04 BNE &4D73 4D6F C0 40 CPY #&40 4D71 90 08 BCC &4D7B .LL8 4D73 98 TYA 4D74 E9 40 SBC #&40 4D76 A8 TAY 4D77 8A TXA 4D78 E5 90 SBC &90 4D7A AA TAX .LL7 4D7B 26 90 ROL &90 4D7D 06 92 ASL &92 4D7F 98 TYA 4D80 2A ROL A 4D81 A8 TAY 4D82 8A TXA 4D83 2A ROL A 4D84 AA TAX 4D85 06 92 ASL &92 4D87 98 TYA 4D88 2A ROL A 4D89 A8 TAY 4D8A 8A TXA 4D8B 2A ROL A 4D8C AA TAX 4D8D C6 D1 DEC &D1 4D8F D0 D8 BNE &4D69 4D91 60 RTS .LL28 4D92 C5 90 CMP &90 4D94 B0 1A BCS &4DB0 4D96 A2 FE LDX #&FE 4D98 86 91 STX &91 .LL31 4D9A 0A ASL A 4D9B B0 0B BCS &4DA8 4D9D C5 90 CMP &90 4D9F 90 02 BCC &4DA3 4DA1 E5 90 SBC &90 4DA3 26 91 ROL &91 4DA5 B0 F3 BCS &4D9A 4DA7 60 RTS .LL29 4DA8 E5 90 SBC &90 4DAA 38 SEC 4DAB 26 91 ROL &91 4DAD B0 EB BCS &4D9A 4DAF 60 RTS .LL2 4DB0 A9 FF LDA #&FF 4DB2 85 91 STA &91 4DB4 60 RTS .LL38 4DB5 45 92 EOR &92 4DB7 30 06 BMI &4DBF 4DB9 A5 90 LDA &90 4DBB 18 CLC 4DBC 65 91 ADC &91 4DBE 60 RTS .LL39 4DBF A5 91 LDA &91 4DC1 38 SEC 4DC2 E5 90 SBC &90 4DC4 90 02 BCC &4DC8 4DC6 18 CLC 4DC7 60 RTS 4DC8 48 PHA 4DC9 A5 92 LDA &92 4DCB 49 80 EOR #&80 4DCD 85 92 STA &92 4DCF 68 PLA 4DD0 49 FF EOR #&FF 4DD2 69 01 ADC #&01 4DD4 60 RTS .LL51 4DD5 A2 00 LDX #&00 4DD7 A0 00 LDY #&00 .ll51 4DD9 A5 31 LDA &31 4DDB 85 90 STA &90 4DDD B5 09 LDA &09,X 4DDF 20 A9 27 JSR &27A9 4DE2 85 D1 STA &D1 4DE4 A5 32 LDA &32 4DE6 55 0A EOR &0A,X 4DE8 85 92 STA &92 4DEA A5 33 LDA &33 4DEC 85 90 STA &90 4DEE B5 0B LDA &0B,X 4DF0 20 A9 27 JSR &27A9 4DF3 85 90 STA &90 4DF5 A5 D1 LDA &D1 4DF7 85 91 STA &91 4DF9 A5 34 LDA &34 4DFB 55 0C EOR &0C,X 4DFD 20 B5 4D JSR &4DB5 4E00 85 D1 STA &D1 4E02 A5 35 LDA &35 4E04 85 90 STA &90 4E06 B5 0D LDA &0D,X 4E08 20 A9 27 JSR &27A9 4E0B 85 90 STA &90 4E0D A5 D1 LDA &D1 4E0F 85 91 STA &91 4E11 A5 36 LDA &36 4E13 55 0E EOR &0E,X 4E15 20 B5 4D JSR &4DB5 4E18 99 37 00 STA &0037,Y 4E1B A5 92 LDA &92 4E1D 99 38 00 STA &0038,Y 4E20 C8 INY 4E21 C8 INY 4E22 8A TXA 4E23 18 CLC 4E24 69 06 ADC #&06 4E26 AA TAX 4E27 C9 11 CMP #&11 4E29 90 AE BCC &4DD9 4E2B 60 RTS .LL25 4E2C 4C 9D 3D JMP &3D9D .LL9 4E2F A5 9B LDA &9B 4E31 30 F9 BMI &4E2C 4E33 A9 1F LDA #&1F 4E35 85 A7 STA &A7 4E37 A9 20 LDA #&20 4E39 24 72 BIT &72 4E3B D0 2D BNE &4E6A 4E3D 10 2B BPL &4E6A 4E3F 05 72 ORA &72 4E41 29 3F AND #&3F 4E43 85 72 STA &72 4E45 A9 00 LDA #&00 4E47 A0 1C LDY #&1C 4E49 91 20 STA (&20),Y 4E4B A0 1E LDY #&1E 4E4D 91 20 STA (&20),Y 4E4F 20 7D 4E JSR &4E7D 4E52 A0 01 LDY #&01 4E54 A9 12 LDA #&12 4E56 91 74 STA (&74),Y 4E58 A0 07 LDY #&07 4E5A B1 1E LDA (&1E),Y 4E5C A0 02 LDY #&02 4E5E 91 74 STA (&74),Y .EE55 4E60 C8 INY 4E61 20 57 44 JSR &4457 4E64 91 74 STA (&74),Y 4E66 C0 06 CPY #&06 4E68 D0 F6 BNE &4E60 .EE28 4E6A A5 5B LDA &5B .EE49 4E6C 10 1D BPL &4E8B .LL14 4E6E A5 72 LDA &72 4E70 29 20 AND #&20 4E72 F0 09 BEQ &4E7D 4E74 A5 72 LDA &72 4E76 29 F7 AND #&F7 4E78 85 72 STA &72 4E7A 4C 8C 39 JMP &398C .EE51 4E7D A9 08 LDA #&08 4E7F 24 72 BIT &72 4E81 F0 07 BEQ &4E8A 4E83 45 72 EOR &72 4E85 85 72 STA &72 4E87 4C EB 53 JMP &53EB 4E8A 60 RTS .LL10 4E8B A5 5A LDA &5A 4E8D C9 C0 CMP #&C0 4E8F B0 DD BCS &4E6E 4E91 A5 53 LDA &53 4E93 C5 59 CMP &59 4E95 A5 54 LDA &54 4E97 E5 5A SBC &5A 4E99 B0 D3 BCS &4E6E 4E9B A5 56 LDA &56 4E9D C5 59 CMP &59 4E9F A5 57 LDA &57 4EA1 E5 5A SBC &5A 4EA3 B0 C9 BCS &4E6E 4EA5 A0 06 LDY #&06 4EA7 B1 1E LDA (&1E),Y 4EA9 AA TAX 4EAA A9 FF LDA #&FF 4EAC 9D 00 01 STA &0100,X 4EAF 9D 01 01 STA &0101,X 4EB2 A5 59 LDA &59 4EB4 85 D1 STA &D1 4EB6 A5 5A LDA &5A 4EB8 4A LSR A 4EB9 66 D1 ROR &D1 4EBB 4A LSR A 4EBC 66 D1 ROR &D1 4EBE 4A LSR A 4EBF 66 D1 ROR &D1 4EC1 4A LSR A 4EC2 D0 0A BNE &4ECE 4EC4 A5 D1 LDA &D1 4EC6 6A ROR A 4EC7 4A LSR A 4EC8 4A LSR A 4EC9 4A LSR A 4ECA 85 A7 STA &A7 4ECC 10 11 BPL &4EDF .LL13 4ECE A0 0D LDY #&0D 4ED0 B1 1E LDA (&1E),Y 4ED2 C5 5A CMP &5A 4ED4 B0 09 BCS &4EDF 4ED6 A9 20 LDA #&20 4ED8 25 72 AND &72 4EDA D0 03 BNE &4EDF 4EDC 4C 15 4D JMP &4D15 .LL17 4EDF A2 05 LDX #&05 .LL15 4EE1 B5 68 LDA &68,X 4EE3 95 09 STA &09,X 4EE5 B5 62 LDA &62,X 4EE7 95 0F STA &0F,X 4EE9 B5 5C LDA &5C,X 4EEB 95 15 STA &15,X 4EED CA DEX 4EEE 10 F1 BPL &4EE1 4EF0 A9 C5 LDA #&C5 4EF2 85 90 STA &90 4EF4 A0 10 LDY #&10 .LL21 4EF6 B9 09 00 LDA &0009,Y 4EF9 0A ASL A 4EFA B9 0A 00 LDA &000A,Y 4EFD 2A ROL A 4EFE 20 92 4D JSR &4D92 4F01 A6 91 LDX &91 4F03 96 09 STX &09,Y 4F05 88 DEY 4F06 88 DEY 4F07 10 ED BPL &4EF6 4F09 A2 08 LDX #&08 .ll91 4F0B B5 53 LDA &53,X 4F0D 95 7E STA &7E,X 4F0F CA DEX 4F10 10 F9 BPL &4F0B 4F12 A9 FF LDA #&FF 4F14 85 E1 STA &E1 4F16 A0 0C LDY #&0C 4F18 A5 72 LDA &72 4F1A 29 20 AND #&20 4F1C F0 12 BEQ &4F30 4F1E B1 1E LDA (&1E),Y 4F20 4A LSR A 4F21 4A LSR A 4F22 AA TAX 4F23 A9 FF LDA #&FF .EE30 4F25 95 D2 STA &D2,X 4F27 CA DEX 4F28 10 FB BPL &4F25 4F2A E8 INX 4F2B 86 A7 STX &A7 .LL41 4F2D 4C A3 50 JMP &50A3 .EE29 4F30 B1 1E LDA (&1E),Y 4F32 F0 F9 BEQ &4F2D 4F34 85 A8 STA &A8 4F36 A0 12 LDY #&12 4F38 B1 1E LDA (&1E),Y 4F3A AA TAX 4F3B A5 85 LDA &85 .LL90 4F3D A8 TAY 4F3E F0 0F BEQ &4F4F 4F40 E8 INX 4F41 46 82 LSR &82 4F43 66 81 ROR &81 4F45 46 7F LSR &7F 4F47 66 7E ROR &7E 4F49 4A LSR A 4F4A 66 84 ROR &84 4F4C A8 TAY 4F4D D0 F1 BNE &4F40 .LL91 4F4F 86 95 STX &95 4F51 A5 86 LDA &86 4F53 85 36 STA &36 4F55 A5 7E LDA &7E 4F57 85 31 STA &31 4F59 A5 80 LDA &80 4F5B 85 32 STA &32 4F5D A5 81 LDA &81 4F5F 85 33 STA &33 4F61 A5 83 LDA &83 4F63 85 34 STA &34 4F65 A5 84 LDA &84 4F67 85 35 STA &35 4F69 20 D5 4D JSR &4DD5 4F6C A5 37 LDA &37 4F6E 85 7E STA &7E 4F70 A5 38 LDA &38 4F72 85 80 STA &80 4F74 A5 39 LDA &39 4F76 85 81 STA &81 4F78 A5 3A LDA &3A 4F7A 85 83 STA &83 4F7C A5 3B LDA &3B 4F7E 85 84 STA &84 4F80 A5 3C LDA &3C 4F82 85 86 STA &86 4F84 A0 04 LDY #&04 4F86 B1 1E LDA (&1E),Y 4F88 18 CLC 4F89 65 1E ADC &1E 4F8B 85 22 STA &22 4F8D A0 11 LDY #&11 4F8F B1 1E LDA (&1E),Y 4F91 65 1F ADC &1F 4F93 85 23 STA &23 4F95 A0 00 LDY #&00 .LL86 4F97 B1 22 LDA (&22),Y 4F99 85 38 STA &38 4F9B 29 1F AND #&1F 4F9D C5 A7 CMP &A7 4F9F B0 0F BCS &4FB0 4FA1 98 TYA 4FA2 4A LSR A 4FA3 4A LSR A 4FA4 AA TAX 4FA5 A9 FF LDA #&FF 4FA7 95 D2 STA &D2,X 4FA9 98 TYA 4FAA 69 04 ADC #&04 4FAC A8 TAY 4FAD 4C 9C 50 JMP &509C .LL87 4FB0 A5 38 LDA &38 4FB2 0A ASL A 4FB3 85 3A STA &3A 4FB5 0A ASL A 4FB6 85 3C STA &3C 4FB8 C8 INY 4FB9 B1 22 LDA (&22),Y 4FBB 85 37 STA &37 4FBD C8 INY 4FBE B1 22 LDA (&22),Y 4FC0 85 39 STA &39 4FC2 C8 INY 4FC3 B1 22 LDA (&22),Y 4FC5 85 3B STA &3B 4FC7 A6 95 LDX &95 4FC9 E0 04 CPX #&04 4FCB 90 23 BCC &4FF0 .LL143 4FCD A5 7E LDA &7E 4FCF 85 31 STA &31 4FD1 A5 80 LDA &80 4FD3 85 32 STA &32 4FD5 A5 81 LDA &81 4FD7 85 33 STA &33 4FD9 A5 83 LDA &83 4FDB 85 34 STA &34 4FDD A5 84 LDA &84 4FDF 85 35 STA &35 4FE1 A5 86 LDA &86 4FE3 85 36 STA &36 4FE5 4C 4E 50 JMP &504E .ovflw 4FE8 46 7E LSR &7E 4FEA 46 84 LSR &84 4FEC 46 81 LSR &81 4FEE A2 01 LDX #&01 .LL92 4FF0 A5 37 LDA &37 4FF2 85 31 STA &31 4FF4 A5 39 LDA &39 4FF6 85 33 STA &33 4FF8 A5 3B LDA &3B .LL93 4FFA CA DEX 4FFB 30 08 BMI &5005 4FFD 46 31 LSR &31 4FFF 46 33 LSR &33 5001 4A LSR A 5002 CA DEX 5003 10 F8 BPL &4FFD .LL94 5005 85 91 STA &91 5007 A5 3C LDA &3C 5009 85 92 STA &92 500B A5 84 LDA &84 500D 85 90 STA &90 500F A5 86 LDA &86 5011 20 B5 4D JSR &4DB5 5014 B0 D2 BCS &4FE8 5016 85 35 STA &35 5018 A5 92 LDA &92 501A 85 36 STA &36 501C A5 31 LDA &31 501E 85 91 STA &91 5020 A5 38 LDA &38 5022 85 92 STA &92 5024 A5 7E LDA &7E 5026 85 90 STA &90 5028 A5 80 LDA &80 502A 20 B5 4D JSR &4DB5 502D B0 B9 BCS &4FE8 502F 85 31 STA &31 5031 A5 92 LDA &92 5033 85 32 STA &32 5035 A5 33 LDA &33 5037 85 91 STA &91 5039 A5 3A LDA &3A 503B 85 92 STA &92 503D A5 81 LDA &81 503F 85 90 STA &90 5041 A5 83 LDA &83 5043 20 B5 4D JSR &4DB5 5046 B0 A0 BCS &4FE8 5048 85 33 STA &33 504A A5 92 LDA &92 504C 85 34 STA &34 .LL89 504E A5 37 LDA &37 5050 85 90 STA &90 5052 A5 31 LDA &31 5054 20 A9 27 JSR &27A9 5057 85 D1 STA &D1 5059 A5 38 LDA &38 505B 45 32 EOR &32 505D 85 92 STA &92 505F A5 39 LDA &39 5061 85 90 STA &90 5063 A5 33 LDA &33 5065 20 A9 27 JSR &27A9 5068 85 90 STA &90 506A A5 D1 LDA &D1 506C 85 91 STA &91 506E A5 3A LDA &3A 5070 45 34 EOR &34 5072 20 B5 4D JSR &4DB5 5075 85 D1 STA &D1 5077 A5 3B LDA &3B 5079 85 90 STA &90 507B A5 35 LDA &35 507D 20 A9 27 JSR &27A9 5080 85 90 STA &90 5082 A5 D1 LDA &D1 5084 85 91 STA &91 5086 A5 36 LDA &36 5088 45 3C EOR &3C 508A 20 B5 4D JSR &4DB5 508D 48 PHA 508E 98 TYA 508F 4A LSR A 5090 4A LSR A 5091 AA TAX 5092 68 PLA 5093 24 92 BIT &92 5095 30 02 BMI &5099 5097 A9 00 LDA #&00 5099 95 D2 STA &D2,X 509B C8 INY .LL88 509C C4 A8 CPY &A8 509E B0 03 BCS &50A3 50A0 4C 97 4F JMP &4F97 .LL42 50A3 A4 0B LDY &0B 50A5 A6 0C LDX &0C 50A7 A5 0F LDA &0F 50A9 85 0B STA &0B 50AB A5 10 LDA &10 50AD 85 0C STA &0C 50AF 84 0F STY &0F 50B1 86 10 STX &10 50B3 A4 0D LDY &0D 50B5 A6 0E LDX &0E 50B7 A5 15 LDA &15 50B9 85 0D STA &0D 50BB A5 16 LDA &16 50BD 85 0E STA &0E 50BF 84 15 STY &15 50C1 86 16 STX &16 50C3 A4 13 LDY &13 50C5 A6 14 LDX &14 50C7 A5 17 LDA &17 50C9 85 13 STA &13 50CB A5 18 LDA &18 50CD 85 14 STA &14 50CF 84 17 STY &17 50D1 86 18 STX &18 50D3 A0 08 LDY #&08 50D5 B1 1E LDA (&1E),Y 50D7 85 A8 STA &A8 50D9 A5 1E LDA &1E 50DB 18 CLC 50DC 69 14 ADC #&14 50DE 85 22 STA &22 50E0 A5 1F LDA &1F 50E2 69 00 ADC #&00 50E4 85 23 STA &23 50E6 A0 00 LDY #&00 50E8 84 A4 STY &A4 .LL48 50EA 84 95 STY &95 50EC B1 22 LDA (&22),Y 50EE 85 31 STA &31 50F0 C8 INY 50F1 B1 22 LDA (&22),Y 50F3 85 33 STA &33 50F5 C8 INY 50F6 B1 22 LDA (&22),Y 50F8 85 35 STA &35 50FA C8 INY 50FB B1 22 LDA (&22),Y 50FD 85 D1 STA &D1 50FF 29 1F AND #&1F 5101 C5 A7 CMP &A7 5103 90 2E BCC &5133 5105 C8 INY 5106 B1 22 LDA (&22),Y 5108 85 1B STA &1B 510A 29 0F AND #&0F 510C AA TAX 510D B5 D2 LDA &D2,X 510F D0 25 BNE &5136 5111 A5 1B LDA &1B 5113 4A LSR A 5114 4A LSR A 5115 4A LSR A 5116 4A LSR A 5117 AA TAX 5118 B5 D2 LDA &D2,X 511A D0 1A BNE &5136 511C C8 INY 511D B1 22 LDA (&22),Y 511F 85 1B STA &1B 5121 29 0F AND #&0F 5123 AA TAX 5124 B5 D2 LDA &D2,X 5126 D0 0E BNE &5136 5128 A5 1B LDA &1B 512A 4A LSR A 512B 4A LSR A 512C 4A LSR A 512D 4A LSR A 512E AA TAX 512F B5 D2 LDA &D2,X 5131 D0 03 BNE &5136 5133 4C AB 52 JMP &52AB .LL49 5136 A5 D1 LDA &D1 5138 85 32 STA &32 513A 0A ASL A 513B 85 34 STA &34 513D 0A ASL A 513E 85 36 STA &36 5140 20 D5 4D JSR &4DD5 5143 A5 55 LDA &55 5145 85 33 STA &33 5147 45 38 EOR &38 5149 30 10 BMI &515B 514B 18 CLC 514C A5 37 LDA &37 514E 65 53 ADC &53 5150 85 31 STA &31 5152 A5 54 LDA &54 5154 69 00 ADC #&00 5156 85 32 STA &32 5158 4C 7E 51 JMP &517E .LL52 515B A5 53 LDA &53 515D 38 SEC 515E E5 37 SBC &37 5160 85 31 STA &31 5162 A5 54 LDA &54 5164 E9 00 SBC #&00 5166 85 32 STA &32 5168 B0 14 BCS &517E 516A 49 FF EOR #&FF 516C 85 32 STA &32 516E A9 01 LDA #&01 5170 E5 31 SBC &31 5172 85 31 STA &31 5174 90 02 BCC &5178 5176 E6 32 INC &32 5178 A5 33 LDA &33 517A 49 80 EOR #&80 517C 85 33 STA &33 .LL53 517E A5 58 LDA &58 5180 85 36 STA &36 5182 45 3A EOR &3A 5184 30 10 BMI &5196 5186 18 CLC 5187 A5 39 LDA &39 5189 65 56 ADC &56 518B 85 34 STA &34 518D A5 57 LDA &57 518F 69 00 ADC #&00 5191 85 35 STA &35 5193 4C BB 51 JMP &51BB .LL54 5196 A5 56 LDA &56 5198 38 SEC 5199 E5 39 SBC &39 519B 85 34 STA &34 519D A5 57 LDA &57 519F E9 00 SBC #&00 51A1 85 35 STA &35 51A3 B0 16 BCS &51BB 51A5 49 FF EOR #&FF 51A7 85 35 STA &35 51A9 A5 34 LDA &34 51AB 49 FF EOR #&FF 51AD 69 01 ADC #&01 51AF 85 34 STA &34 51B1 A5 36 LDA &36 51B3 49 80 EOR #&80 51B5 85 36 STA &36 51B7 90 02 BCC &51BB 51B9 E6 35 INC &35 .LL55 51BB A5 3C LDA &3C 51BD 30 4A BMI &5209 51BF A5 3B LDA &3B 51C1 18 CLC 51C2 65 59 ADC &59 51C4 85 D1 STA &D1 51C6 A5 5A LDA &5A 51C8 69 00 ADC #&00 51CA 85 8F STA &8F 51CC 4C 28 52 JMP &5228 .LL61 51CF A6 90 LDX &90 51D1 F0 1C BEQ &51EF 51D3 A2 00 LDX #&00 .LL63 51D5 4A LSR A 51D6 E8 INX 51D7 C5 90 CMP &90 51D9 B0 FA BCS &51D5 51DB 86 92 STX &92 51DD 20 92 4D JSR &4D92 51E0 A6 92 LDX &92 51E2 A5 91 LDA &91 .LL64 51E4 0A ASL A 51E5 26 8F ROL &8F 51E7 30 06 BMI &51EF 51E9 CA DEX 51EA D0 F8 BNE &51E4 51EC 85 91 STA &91 51EE 60 RTS .LL84 51EF A9 32 LDA #&32 51F1 85 91 STA &91 51F3 85 8F STA &8F 51F5 60 RTS .LL62 51F6 A9 80 LDA #&80 51F8 38 SEC 51F9 E5 91 SBC &91 51FB 9D 00 01 STA &0100,X 51FE E8 INX 51FF A9 00 LDA #&00 5201 E5 8F SBC &8F 5203 9D 00 01 STA &0100,X 5206 4C 68 52 JMP &5268 .LL56 5209 A5 59 LDA &59 520B 38 SEC 520C E5 3B SBC &3B 520E 85 D1 STA &D1 5210 A5 5A LDA &5A 5212 E9 00 SBC #&00 5214 85 8F STA &8F 5216 90 08 BCC &5220 5218 D0 0E BNE &5228 521A A5 D1 LDA &D1 521C C9 04 CMP #&04 521E B0 08 BCS &5228 .LL140 5220 A9 00 LDA #&00 5222 85 8F STA &8F 5224 A9 04 LDA #&04 5226 85 D1 STA &D1 .LL57 5228 A5 8F LDA &8F 522A 05 32 ORA &32 522C 05 35 ORA &35 522E F0 0F BEQ &523F 5230 46 32 LSR &32 5232 66 31 ROR &31 5234 46 35 LSR &35 5236 66 34 ROR &34 5238 46 8F LSR &8F 523A 66 D1 ROR &D1 523C 4C 28 52 JMP &5228 .LL60 523F A5 D1 LDA &D1 5241 85 90 STA &90 5243 A5 31 LDA &31 5245 C5 90 CMP &90 5247 90 06 BCC &524F 5249 20 CF 51 JSR &51CF 524C 4C 52 52 JMP &5252 .LL69 524F 20 92 4D JSR &4D92 .LL65 5252 A6 A4 LDX &A4 5254 A5 33 LDA &33 5256 30 9E BMI &51F6 5258 A5 91 LDA &91 525A 18 CLC 525B 69 80 ADC #&80 525D 9D 00 01 STA &0100,X 5260 E8 INX 5261 A5 8F LDA &8F 5263 69 00 ADC #&00 5265 9D 00 01 STA &0100,X .LL66 5268 8A TXA 5269 48 PHA 526A A9 00 LDA #&00 526C 85 8F STA &8F 526E A5 D1 LDA &D1 5270 85 90 STA &90 5272 A5 34 LDA &34 5274 C5 90 CMP &90 5276 90 19 BCC &5291 5278 20 CF 51 JSR &51CF 527B 4C 94 52 JMP &5294 .LL70 527E A9 60 LDA #&60 5280 18 CLC 5281 65 91 ADC &91 5283 9D 00 01 STA &0100,X 5286 E8 INX 5287 A9 00 LDA #&00 5289 65 8F ADC &8F 528B 9D 00 01 STA &0100,X 528E 4C AB 52 JMP &52AB .LL67 5291 20 92 4D JSR &4D92 .LL68 5294 68 PLA 5295 AA TAX 5296 E8 INX 5297 A5 36 LDA &36 5299 30 E3 BMI &527E 529B A9 60 LDA #&60 529D 38 SEC 529E E5 91 SBC &91 52A0 9D 00 01 STA &0100,X 52A3 E8 INX 52A4 A9 00 LDA #&00 52A6 E5 8F SBC &8F 52A8 9D 00 01 STA &0100,X .LL50 52AB 18 CLC 52AC A5 A4 LDA &A4 52AE 69 04 ADC #&04 52B0 85 A4 STA &A4 52B2 A5 95 LDA &95 52B4 69 06 ADC #&06 52B6 A8 TAY 52B7 B0 07 BCS &52C0 52B9 C5 A8 CMP &A8 52BB B0 03 BCS &52C0 52BD 4C EA 50 JMP &50EA .LL72 52C0 A5 72 LDA &72 52C2 29 20 AND #&20 52C4 F0 09 BEQ &52CF 52C6 A5 72 LDA &72 52C8 09 08 ORA #&08 52CA 85 72 STA &72 52CC 4C 8C 39 JMP &398C .EE31 52CF A9 08 LDA #&08 52D1 24 72 BIT &72 52D3 F0 05 BEQ &52DA 52D5 20 EB 53 JSR &53EB 52D8 A9 08 LDA #&08 .LL74 52DA 05 72 ORA &72 52DC 85 72 STA &72 52DE A0 09 LDY #&09 52E0 B1 1E LDA (&1E),Y 52E2 85 A8 STA &A8 52E4 A0 00 LDY #&00 52E6 84 8F STY &8F 52E8 84 95 STY &95 52EA E6 8F INC &8F 52EC 24 72 BIT &72 52EE 50 54 BVC &5344 52F0 A5 72 LDA &72 52F2 29 BF AND #&BF 52F4 85 72 STA &72 52F6 A0 06 LDY #&06 52F8 B1 1E LDA (&1E),Y 52FA A8 TAY 52FB BE 00 01 LDX &0100,Y 52FE 86 31 STX &31 5300 E8 INX 5301 F0 41 BEQ &5344 5303 BE 01 01 LDX &0101,Y 5306 86 32 STX &32 5308 E8 INX 5309 F0 39 BEQ &5344 530B BE 02 01 LDX &0102,Y 530E 86 33 STX &33 5310 BE 03 01 LDX &0103,Y 5313 86 34 STX &34 5315 A9 00 LDA #&00 5317 85 35 STA &35 5319 85 36 STA &36 531B 85 38 STA &38 531D A5 59 LDA &59 531F 85 37 STA &37 5321 A5 55 LDA &55 5323 10 02 BPL &5327 5325 C6 35 DEC &35 5327 20 13 55 JSR &5513 532A B0 18 BCS &5344 532C A4 8F LDY &8F 532E A5 31 LDA &31 5330 91 74 STA (&74),Y 5332 C8 INY 5333 A5 32 LDA &32 5335 91 74 STA (&74),Y 5337 C8 INY 5338 A5 33 LDA &33 533A 91 74 STA (&74),Y 533C C8 INY 533D A5 34 LDA &34 533F 91 74 STA (&74),Y 5341 C8 INY 5342 84 8F STY &8F .LL170 5344 A0 03 LDY #&03 5346 18 CLC 5347 B1 1E LDA (&1E),Y 5349 65 1E ADC &1E 534B 85 22 STA &22 534D A0 10 LDY #&10 534F B1 1E LDA (&1E),Y 5351 65 1F ADC &1F 5353 85 23 STA &23 5355 A0 05 LDY #&05 5357 B1 1E LDA (&1E),Y 5359 85 06 STA &06 535B A4 95 LDY &95 .LL75 535D B1 22 LDA (&22),Y 535F C5 A7 CMP &A7 5361 90 6B BCC &53CE 5363 C8 INY 5364 B1 22 LDA (&22),Y 5366 C8 INY 5367 85 1B STA &1B 5369 29 0F AND #&0F 536B AA TAX 536C B5 D2 LDA &D2,X 536E D0 0B BNE &537B 5370 A5 1B LDA &1B 5372 4A LSR A 5373 4A LSR A 5374 4A LSR A 5375 4A LSR A 5376 AA TAX 5377 B5 D2 LDA &D2,X 5379 F0 53 BEQ &53CE .LL79 537B B1 22 LDA (&22),Y 537D AA TAX 537E C8 INY 537F B1 22 LDA (&22),Y 5381 85 90 STA &90 5383 BD 01 01 LDA &0101,X 5386 85 32 STA &32 5388 BD 00 01 LDA &0100,X 538B 85 31 STA &31 538D BD 02 01 LDA &0102,X 5390 85 33 STA &33 5392 BD 03 01 LDA &0103,X 5395 85 34 STA &34 5397 A6 90 LDX &90 5399 BD 00 01 LDA &0100,X 539C 85 35 STA &35 539E BD 03 01 LDA &0103,X 53A1 85 38 STA &38 53A3 BD 02 01 LDA &0102,X 53A6 85 37 STA &37 53A8 BD 01 01 LDA &0101,X 53AB 85 36 STA &36 53AD 20 19 55 JSR &5519 53B0 B0 1C BCS &53CE .LL80 53B2 A4 8F LDY &8F 53B4 A5 31 LDA &31 53B6 91 74 STA (&74),Y 53B8 C8 INY 53B9 A5 32 LDA &32 53BB 91 74 STA (&74),Y 53BD C8 INY 53BE A5 33 LDA &33 53C0 91 74 STA (&74),Y 53C2 C8 INY 53C3 A5 34 LDA &34 53C5 91 74 STA (&74),Y 53C7 C8 INY 53C8 84 8F STY &8F 53CA C4 06 CPY &06 53CC B0 17 BCS &53E5 .LL78 53CE E6 95 INC &95 53D0 A4 95 LDY &95 53D2 C4 A8 CPY &A8 53D4 B0 0F BCS &53E5 53D6 A0 00 LDY #&00 53D8 A5 22 LDA &22 53DA 69 04 ADC #&04 53DC 85 22 STA &22 53DE 90 02 BCC &53E2 53E0 E6 23 INC &23 .ll81 53E2 4C 5D 53 JMP &535D .LL81 53E5 A5 8F LDA &8F 53E7 A0 00 LDY #&00 53E9 91 74 STA (&74),Y .LL155 53EB A0 00 LDY #&00 53ED B1 74 LDA (&74),Y 53EF 85 A8 STA &A8 53F1 C9 04 CMP #&04 53F3 90 1C BCC &5411 53F5 C8 INY .LL27 53F6 B1 74 LDA (&74),Y 53F8 85 31 STA &31 53FA C8 INY 53FB B1 74 LDA (&74),Y 53FD 85 32 STA &32 53FF C8 INY 5400 B1 74 LDA (&74),Y 5402 85 33 STA &33 5404 C8 INY 5405 B1 74 LDA (&74),Y 5407 85 34 STA &34 5409 20 77 18 JSR &1877 540C C8 INY 540D C4 A8 CPY &A8 540F 90 E5 BCC &53F6 5411 60 RTS .LL118 5412 A5 32 LDA &32 5414 10 17 BPL &542D 5416 85 92 STA &92 5418 20 8C 54 JSR &548C 541B 8A TXA 541C 18 CLC 541D 65 33 ADC &33 541F 85 33 STA &33 5421 98 TYA 5422 65 34 ADC &34 5424 85 34 STA &34 5426 A9 00 LDA #&00 5428 85 31 STA &31 542A 85 32 STA &32 542C AA TAX .LL119 542D F0 19 BEQ &5448 542F 85 92 STA &92 5431 C6 92 DEC &92 5433 20 8C 54 JSR &548C 5436 8A TXA 5437 18 CLC 5438 65 33 ADC &33 543A 85 33 STA &33 543C 98 TYA 543D 65 34 ADC &34 543F 85 34 STA &34 5441 A2 FF LDX #&FF 5443 86 31 STX &31 5445 E8 INX 5446 86 32 STX &32 .LL134 5448 A5 34 LDA &34 544A 10 1A BPL &5466 544C 85 92 STA &92 544E A5 33 LDA &33 5450 85 91 STA &91 5452 20 BB 54 JSR &54BB 5455 8A TXA 5456 18 CLC 5457 65 31 ADC &31 5459 85 31 STA &31 545B 98 TYA 545C 65 32 ADC &32 545E 85 32 STA &32 5460 A9 00 LDA #&00 5462 85 33 STA &33 5464 85 34 STA &34 .LL135 5466 A5 33 LDA &33 5468 38 SEC 5469 E9 C0 SBC #&C0 546B 85 91 STA &91 546D A5 34 LDA &34 546F E9 00 SBC #&00 5471 85 92 STA &92 5473 90 16 BCC &548B .LL139 5475 20 BB 54 JSR &54BB 5478 8A TXA 5479 18 CLC 547A 65 31 ADC &31 547C 85 31 STA &31 547E 98 TYA 547F 65 32 ADC &32 5481 85 32 STA &32 5483 A9 BF LDA #&BF 5485 85 33 STA &33 5487 A9 00 LDA #&00 5489 85 34 STA &34 .LL136 548B 60 RTS .LL120 548C A5 31 LDA &31 548E 85 91 STA &91 5490 20 F7 54 JSR &54F7 5493 48 PHA 5494 A6 D1 LDX &D1 5496 D0 2B BNE &54C3 .LL122 5498 A9 00 LDA #&00 549A AA TAX 549B A8 TAY 549C 46 92 LSR &92 549E 66 91 ROR &91 54A0 06 90 ASL &90 54A2 90 09 BCC &54AD .LL125 54A4 8A TXA 54A5 18 CLC 54A6 65 91 ADC &91 54A8 AA TAX 54A9 98 TYA 54AA 65 92 ADC &92 54AC A8 TAY .LL126 54AD 46 92 LSR &92 54AF 66 91 ROR &91 54B1 06 90 ASL &90 54B3 B0 EF BCS &54A4 54B5 D0 F6 BNE &54AD 54B7 68 PLA 54B8 10 30 BPL &54EA 54BA 60 RTS .LL123 54BB 20 F7 54 JSR &54F7 54BE 48 PHA 54BF A6 D1 LDX &D1 54C1 D0 D5 BNE &5498 .LL121 54C3 A9 FF LDA #&FF 54C5 A8 TAY 54C6 0A ASL A 54C7 AA TAX .LL130 54C8 06 91 ASL &91 54CA 26 92 ROL &92 54CC A5 92 LDA &92 54CE B0 04 BCS &54D4 54D0 C5 90 CMP &90 54D2 90 0B BCC &54DF .LL131 54D4 E5 90 SBC &90 54D6 85 92 STA &92 54D8 A5 91 LDA &91 54DA E9 00 SBC #&00 54DC 85 91 STA &91 54DE 38 SEC .LL132 54DF 8A TXA 54E0 2A ROL A 54E1 AA TAX 54E2 98 TYA 54E3 2A ROL A 54E4 A8 TAY 54E5 B0 E1 BCS &54C8 54E7 68 PLA 54E8 30 0C BMI &54F6 .LL133 54EA 8A TXA 54EB 49 FF EOR #&FF 54ED 69 01 ADC #&01 54EF AA TAX 54F0 98 TYA 54F1 49 FF EOR #&FF 54F3 69 00 ADC #&00 54F5 A8 TAY .LL128 54F6 60 RTS .LL129 54F7 A6 39 LDX &39 54F9 86 90 STX &90 54FB A5 92 LDA &92 54FD 10 11 BPL &5510 54FF A9 00 LDA #&00 5501 38 SEC 5502 E5 91 SBC &91 5504 85 91 STA &91 5506 A5 92 LDA &92 5508 48 PHA 5509 49 FF EOR #&FF 550B 69 00 ADC #&00 550D 85 92 STA &92 550F 68 PLA .LL127 5510 45 3A EOR &3A 5512 60 RTS .LL145 5513 A9 00 LDA #&00 5515 85 A1 STA &A1 5517 A5 36 LDA &36 .LL147 5519 A2 BF LDX #&BF 551B 05 38 ORA &38 551D D0 06 BNE &5525 551F E4 37 CPX &37 5521 90 02 BCC &5525 5523 A2 00 LDX #&00 .LL107 5525 86 98 STX &98 5527 A5 32 LDA &32 5529 05 34 ORA &34 552B D0 1C BNE &5549 552D A9 BF LDA #&BF 552F C5 33 CMP &33 5531 90 16 BCC &5549 5533 A5 98 LDA &98 5535 D0 10 BNE &5547 .LL146 5537 A5 33 LDA &33 5539 85 32 STA &32 553B A5 35 LDA &35 553D 85 33 STA &33 553F A5 37 LDA &37 5541 85 34 STA &34 5543 18 CLC 5544 60 RTS .LL109 5545 38 SEC 5546 60 RTS .LL108 5547 46 98 LSR &98 .LL83 5549 A5 98 LDA &98 554B 10 2F BPL &557C 554D A5 32 LDA &32 554F 25 36 AND &36 5551 30 F2 BMI &5545 5553 A5 34 LDA &34 5555 25 38 AND &38 5557 30 EC BMI &5545 5559 A6 32 LDX &32 555B CA DEX 555C 8A TXA 555D A6 36 LDX &36 555F CA DEX 5560 86 39 STX &39 5562 05 39 ORA &39 5564 10 DF BPL &5545 5566 A5 33 LDA &33 5568 C9 C0 CMP #&C0 556A A5 34 LDA &34 556C E9 00 SBC #&00 556E 85 39 STA &39 5570 A5 37 LDA &37 5572 C9 C0 CMP #&C0 5574 A5 38 LDA &38 5576 E9 00 SBC #&00 5578 05 39 ORA &39 557A 10 C9 BPL &5545 .LL115 557C 98 TYA 557D 48 PHA 557E A5 35 LDA &35 5580 38 SEC 5581 E5 31 SBC &31 5583 85 39 STA &39 5585 A5 36 LDA &36 5587 E5 32 SBC &32 5589 85 3A STA &3A 558B A5 37 LDA &37 558D 38 SEC 558E E5 33 SBC &33 5590 85 3B STA &3B 5592 A5 38 LDA &38 5594 E5 34 SBC &34 5596 85 3C STA &3C 5598 45 3A EOR &3A 559A 85 92 STA &92 559C A5 3C LDA &3C 559E 10 0D BPL &55AD 55A0 A9 00 LDA #&00 55A2 38 SEC 55A3 E5 3B SBC &3B 55A5 85 3B STA &3B 55A7 A9 00 LDA #&00 55A9 E5 3C SBC &3C 55AB 85 3C STA &3C .LL110 55AD A5 3A LDA &3A 55AF 10 0B BPL &55BC 55B1 38 SEC 55B2 A9 00 LDA #&00 55B4 E5 39 SBC &39 55B6 85 39 STA &39 55B8 A9 00 LDA #&00 55BA E5 3A SBC &3A .LL111 55BC AA TAX 55BD D0 04 BNE &55C3 55BF A6 3C LDX &3C 55C1 F0 0A BEQ &55CD .LL112 55C3 4A LSR A 55C4 66 39 ROR &39 55C6 46 3C LSR &3C 55C8 66 3B ROR &3B 55CA 4C BC 55 JMP &55BC .LL113 55CD 86 D1 STX &D1 55CF A5 39 LDA &39 55D1 C5 3B CMP &3B 55D3 90 0A BCC &55DF 55D5 85 90 STA &90 55D7 A5 3B LDA &3B 55D9 20 92 4D JSR &4D92 55DC 4C EA 55 JMP &55EA .LL114 55DF A5 3B LDA &3B 55E1 85 90 STA &90 55E3 A5 39 LDA &39 55E5 20 92 4D JSR &4D92 55E8 C6 D1 DEC &D1 .LL116 55EA A5 91 LDA &91 55EC 85 39 STA &39 55EE A5 92 LDA &92 55F0 85 3A STA &3A 55F2 A5 98 LDA &98 55F4 F0 02 BEQ &55F8 55F6 10 13 BPL &560B .LL138 55F8 20 12 54 JSR &5412 55FB A5 98 LDA &98 55FD 10 31 BPL &5630 .LL117 55FF A5 32 LDA &32 5601 05 34 ORA &34 5603 D0 30 BNE &5635 5605 A5 33 LDA &33 5607 C9 C0 CMP #&C0 5609 B0 2A BCS &5635 .LLX117 560B A6 31 LDX &31 560D A5 35 LDA &35 560F 85 31 STA &31 5611 86 35 STX &35 5613 A5 36 LDA &36 5615 A6 32 LDX &32 5617 86 36 STX &36 5619 85 32 STA &32 561B A6 33 LDX &33 561D A5 37 LDA &37 561F 85 33 STA &33 5621 86 37 STX &37 5623 A5 38 LDA &38 5625 A6 34 LDX &34 5627 86 38 STX &38 5629 85 34 STA &34 562B 20 12 54 JSR &5412 562E C6 A1 DEC &A1 .LL124 5630 68 PLA 5631 A8 TAY 5632 4C 37 55 JMP &5537 .LL137 5635 68 PLA 5636 A8 TAY 5637 38 SEC 5638 60 RTS ELITE G Assembled at &4D15 Ends at &5639 Code size is &924 Execute at &1128 Reload at &4EFD S.ELTG &4D15 &5639 &1128 &4EFD Saving file '3-assembled-output/ELTG.bin' .checksum0 5639 .XX21 563A 54 56 563C FC 56 563E D6 57 5640 00 7F 5642 04 59 5644 8C 5A 5646 04 59 5648 A8 5B 564A C4 5C 564C C2 5D 564E 98 5E 5650 40 5F 5652 AC 5F .SHIP_SIDEWINDER 5654 00 5655 81 10 5657 50 5658 8C 5659 3D 565A 00 565B 1E 565C 3C 565D 0F 565E 32 00 5660 1C 5661 14 5662 46 5663 25 5664 00 5665 00 5666 02 5667 10 .SHIP_SIDEWINDER_VERTICES Macro VERTEX: 5668 20 5669 00 566A 24 566B 9F 566C 10 566D 54 End macro VERTEX Macro VERTEX: 566E 20 566F 00 5670 24 5671 1F 5672 20 5673 65 End macro VERTEX Macro VERTEX: 5674 40 5675 00 5676 1C 5677 3F 5678 32 5679 66 End macro VERTEX Macro VERTEX: 567A 40 567B 00 567C 1C 567D BF 567E 31 567F 44 End macro VERTEX Macro VERTEX: 5680 00 5681 10 5682 1C 5683 3F 5684 10 5685 32 End macro VERTEX Macro VERTEX: 5686 00 5687 10 5688 1C 5689 7F 568A 43 568B 65 End macro VERTEX Macro VERTEX: 568C 0C 568D 06 568E 1C 568F AF 5690 33 5691 33 End macro VERTEX Macro VERTEX: 5692 0C 5693 06 5694 1C 5695 2F 5696 33 5697 33 End macro VERTEX Macro VERTEX: 5698 0C 5699 06 569A 1C 569B 6C 569C 33 569D 33 End macro VERTEX Macro VERTEX: 569E 0C 569F 06 56A0 1C 56A1 EC 56A2 33 56A3 33 End macro VERTEX .SHIP_SIDEWINDER_EDGES Macro EDGE: 56A4 1F 56A5 50 56A6 00 56A7 04 End macro EDGE Macro EDGE: 56A8 1F 56A9 62 56AA 04 56AB 08 End macro EDGE Macro EDGE: 56AC 1F 56AD 20 56AE 04 56AF 10 End macro EDGE Macro EDGE: 56B0 1F 56B1 10 56B2 00 56B3 10 End macro EDGE Macro EDGE: 56B4 1F 56B5 41 56B6 00 56B7 0C End macro EDGE Macro EDGE: 56B8 1F 56B9 31 56BA 0C 56BB 10 End macro EDGE Macro EDGE: 56BC 1F 56BD 32 56BE 08 56BF 10 End macro EDGE Macro EDGE: 56C0 1F 56C1 43 56C2 0C 56C3 14 End macro EDGE Macro EDGE: 56C4 1F 56C5 63 56C6 08 56C7 14 End macro EDGE Macro EDGE: 56C8 1F 56C9 65 56CA 04 56CB 14 End macro EDGE Macro EDGE: 56CC 1F 56CD 54 56CE 00 56CF 14 End macro EDGE Macro EDGE: 56D0 0F 56D1 33 56D2 18 56D3 1C End macro EDGE Macro EDGE: 56D4 0C 56D5 33 56D6 1C 56D7 20 End macro EDGE Macro EDGE: 56D8 0C 56D9 33 56DA 18 56DB 24 End macro EDGE Macro EDGE: 56DC 0C 56DD 33 56DE 20 56DF 24 End macro EDGE .SHIP_SIDEWINDER_FACES Macro FACE: 56E0 1F 56E1 00 56E2 20 56E3 08 End macro FACE Macro FACE: 56E4 9F 56E5 0C 56E6 2F 56E7 06 End macro FACE Macro FACE: 56E8 1F 56E9 0C 56EA 2F 56EB 06 End macro FACE Macro FACE: 56EC 3F 56ED 00 56EE 00 56EF 70 End macro FACE Macro FACE: 56F0 DF 56F1 0C 56F2 2F 56F3 06 End macro FACE Macro FACE: 56F4 5F 56F5 00 56F6 20 56F7 08 End macro FACE Macro FACE: 56F8 5F 56F9 0C 56FA 2F 56FB 06 End macro FACE .SHIP_VIPER 56FC 00 56FD F9 15 56FF 6E 5700 BE 5701 4D 5702 00 5703 2A 5704 5A 5705 14 5706 00 00 5708 1C 5709 17 570A 78 570B 20 570C 00 570D 00 570E 01 570F 11 .SHIP_VIPER_VERTICES Macro VERTEX: 5710 00 5711 00 5712 48 5713 1F 5714 21 5715 43 End macro VERTEX Macro VERTEX: 5716 00 5717 10 5718 18 5719 1E 571A 10 571B 22 End macro VERTEX Macro VERTEX: 571C 00 571D 10 571E 18 571F 5E 5720 43 5721 55 End macro VERTEX Macro VERTEX: 5722 30 5723 00 5724 18 5725 3F 5726 42 5727 66 End macro VERTEX Macro VERTEX: 5728 30 5729 00 572A 18 572B BF 572C 31 572D 66 End macro VERTEX Macro VERTEX: 572E 18 572F 10 5730 18 5731 7E 5732 54 5733 66 End macro VERTEX Macro VERTEX: 5734 18 5735 10 5736 18 5737 FE 5738 35 5739 66 End macro VERTEX Macro VERTEX: 573A 18 573B 10 573C 18 573D 3F 573E 20 573F 66 End macro VERTEX Macro VERTEX: 5740 18 5741 10 5742 18 5743 BF 5744 10 5745 66 End macro VERTEX Macro VERTEX: 5746 20 5747 00 5748 18 5749 B3 574A 66 574B 66 End macro VERTEX Macro VERTEX: 574C 20 574D 00 574E 18 574F 33 5750 66 5751 66 End macro VERTEX Macro VERTEX: 5752 08 5753 08 5754 18 5755 33 5756 66 5757 66 End macro VERTEX Macro VERTEX: 5758 08 5759 08 575A 18 575B B3 575C 66 575D 66 End macro VERTEX Macro VERTEX: 575E 08 575F 08 5760 18 5761 F2 5762 66 5763 66 End macro VERTEX Macro VERTEX: 5764 08 5765 08 5766 18 5767 72 5768 66 5769 66 End macro VERTEX .SHIP_VIPER_EDGES Macro EDGE: 576A 1F 576B 42 576C 00 576D 0C End macro EDGE Macro EDGE: 576E 1E 576F 21 5770 00 5771 04 End macro EDGE Macro EDGE: 5772 1E 5773 43 5774 00 5775 08 End macro EDGE Macro EDGE: 5776 1F 5777 31 5778 00 5779 10 End macro EDGE Macro EDGE: 577A 1E 577B 20 577C 04 577D 1C End macro EDGE Macro EDGE: 577E 1E 577F 10 5780 04 5781 20 End macro EDGE Macro EDGE: 5782 1E 5783 54 5784 08 5785 14 End macro EDGE Macro EDGE: 5786 1E 5787 53 5788 08 5789 18 End macro EDGE Macro EDGE: 578A 1F 578B 60 578C 1C 578D 20 End macro EDGE Macro EDGE: 578E 1E 578F 65 5790 14 5791 18 End macro EDGE Macro EDGE: 5792 1F 5793 61 5794 10 5795 20 End macro EDGE Macro EDGE: 5796 1E 5797 63 5798 10 5799 18 End macro EDGE Macro EDGE: 579A 1F 579B 62 579C 0C 579D 1C End macro EDGE Macro EDGE: 579E 1E 579F 46 57A0 0C 57A1 14 End macro EDGE Macro EDGE: 57A2 13 57A3 66 57A4 24 57A5 30 End macro EDGE Macro EDGE: 57A6 12 57A7 66 57A8 24 57A9 34 End macro EDGE Macro EDGE: 57AA 13 57AB 66 57AC 28 57AD 2C End macro EDGE Macro EDGE: 57AE 12 57AF 66 57B0 28 57B1 38 End macro EDGE Macro EDGE: 57B2 10 57B3 66 57B4 2C 57B5 38 End macro EDGE Macro EDGE: 57B6 10 57B7 66 57B8 30 57B9 34 End macro EDGE .SHIP_VIPER_FACES Macro FACE: 57BA 1F 57BB 00 57BC 20 57BD 00 End macro FACE Macro FACE: 57BE 9F 57BF 16 57C0 21 57C1 0B End macro FACE Macro FACE: 57C2 1F 57C3 16 57C4 21 57C5 0B End macro FACE Macro FACE: 57C6 DF 57C7 16 57C8 21 57C9 0B End macro FACE Macro FACE: 57CA 5F 57CB 16 57CC 21 57CD 0B End macro FACE Macro FACE: 57CE 5F 57CF 00 57D0 20 57D1 00 End macro FACE Macro FACE: 57D2 3F 57D3 00 57D4 00 57D5 30 End macro FACE .SHIP_MAMBA 57D6 01 57D7 24 13 57D9 AA 57DA 1A 57DB 5D 57DC 00 57DD 22 57DE 96 57DF 1C 57E0 96 00 57E2 14 57E3 19 57E4 5A 57E5 1E 57E6 00 57E7 01 57E8 02 57E9 12 .SHIP_MAMBA_VERTICES Macro VERTEX: 57EA 00 57EB 00 57EC 40 57ED 1F 57EE 10 57EF 32 End macro VERTEX Macro VERTEX: 57F0 40 57F1 08 57F2 20 57F3 FF 57F4 20 57F5 44 End macro VERTEX Macro VERTEX: 57F6 20 57F7 08 57F8 20 57F9 BE 57FA 21 57FB 44 End macro VERTEX Macro VERTEX: 57FC 20 57FD 08 57FE 20 57FF 3E 5800 31 5801 44 End macro VERTEX Macro VERTEX: 5802 40 5803 08 5804 20 5805 7F 5806 30 5807 44 End macro VERTEX Macro VERTEX: 5808 04 5809 04 580A 10 580B 8E 580C 11 580D 11 End macro VERTEX Macro VERTEX: 580E 04 580F 04 5810 10 5811 0E 5812 11 5813 11 End macro VERTEX Macro VERTEX: 5814 08 5815 03 5816 1C 5817 0D 5818 11 5819 11 End macro VERTEX Macro VERTEX: 581A 08 581B 03 581C 1C 581D 8D 581E 11 581F 11 End macro VERTEX Macro VERTEX: 5820 14 5821 04 5822 10 5823 D4 5824 00 5825 00 End macro VERTEX Macro VERTEX: 5826 14 5827 04 5828 10 5829 54 582A 00 582B 00 End macro VERTEX Macro VERTEX: 582C 18 582D 07 582E 14 582F F4 5830 00 5831 00 End macro VERTEX Macro VERTEX: 5832 10 5833 07 5834 14 5835 F0 5836 00 5837 00 End macro VERTEX Macro VERTEX: 5838 10 5839 07 583A 14 583B 70 583C 00 583D 00 End macro VERTEX Macro VERTEX: 583E 18 583F 07 5840 14 5841 74 5842 00 5843 00 End macro VERTEX Macro VERTEX: 5844 08 5845 04 5846 20 5847 AD 5848 44 5849 44 End macro VERTEX Macro VERTEX: 584A 08 584B 04 584C 20 584D 2D 584E 44 584F 44 End macro VERTEX Macro VERTEX: 5850 08 5851 04 5852 20 5853 6E 5854 44 5855 44 End macro VERTEX Macro VERTEX: 5856 08 5857 04 5858 20 5859 EE 585A 44 585B 44 End macro VERTEX Macro VERTEX: 585C 20 585D 04 585E 20 585F A7 5860 44 5861 44 End macro VERTEX Macro VERTEX: 5862 20 5863 04 5864 20 5865 27 5866 44 5867 44 End macro VERTEX Macro VERTEX: 5868 24 5869 04 586A 20 586B 67 586C 44 586D 44 End macro VERTEX Macro VERTEX: 586E 24 586F 04 5870 20 5871 E7 5872 44 5873 44 End macro VERTEX Macro VERTEX: 5874 26 5875 00 5876 20 5877 A5 5878 44 5879 44 End macro VERTEX Macro VERTEX: 587A 26 587B 00 587C 20 587D 25 587E 44 587F 44 End macro VERTEX .SHIP_MAMBA_EDGES Macro EDGE: 5880 1F 5881 20 5882 00 5883 04 End macro EDGE Macro EDGE: 5884 1F 5885 30 5886 00 5887 10 End macro EDGE Macro EDGE: 5888 1F 5889 40 588A 04 588B 10 End macro EDGE Macro EDGE: 588C 1E 588D 42 588E 04 588F 08 End macro EDGE Macro EDGE: 5890 1E 5891 41 5892 08 5893 0C End macro EDGE Macro EDGE: 5894 1E 5895 43 5896 0C 5897 10 End macro EDGE Macro EDGE: 5898 0E 5899 11 589A 14 589B 18 End macro EDGE Macro EDGE: 589C 0C 589D 11 589E 18 589F 1C End macro EDGE Macro EDGE: 58A0 0D 58A1 11 58A2 1C 58A3 20 End macro EDGE Macro EDGE: 58A4 0C 58A5 11 58A6 14 58A7 20 End macro EDGE Macro EDGE: 58A8 14 58A9 00 58AA 24 58AB 2C End macro EDGE Macro EDGE: 58AC 10 58AD 00 58AE 24 58AF 30 End macro EDGE Macro EDGE: 58B0 10 58B1 00 58B2 28 58B3 34 End macro EDGE Macro EDGE: 58B4 14 58B5 00 58B6 28 58B7 38 End macro EDGE Macro EDGE: 58B8 0E 58B9 00 58BA 34 58BB 38 End macro EDGE Macro EDGE: 58BC 0E 58BD 00 58BE 2C 58BF 30 End macro EDGE Macro EDGE: 58C0 0D 58C1 44 58C2 3C 58C3 40 End macro EDGE Macro EDGE: 58C4 0E 58C5 44 58C6 44 58C7 48 End macro EDGE Macro EDGE: 58C8 0C 58C9 44 58CA 3C 58CB 48 End macro EDGE Macro EDGE: 58CC 0C 58CD 44 58CE 40 58CF 44 End macro EDGE Macro EDGE: 58D0 07 58D1 44 58D2 50 58D3 54 End macro EDGE Macro EDGE: 58D4 05 58D5 44 58D6 50 58D7 60 End macro EDGE Macro EDGE: 58D8 05 58D9 44 58DA 54 58DB 60 End macro EDGE Macro EDGE: 58DC 07 58DD 44 58DE 4C 58DF 58 End macro EDGE Macro EDGE: 58E0 05 58E1 44 58E2 4C 58E3 5C End macro EDGE Macro EDGE: 58E4 05 58E5 44 58E6 58 58E7 5C End macro EDGE Macro EDGE: 58E8 1E 58E9 21 58EA 00 58EB 08 End macro EDGE Macro EDGE: 58EC 1E 58ED 31 58EE 00 58EF 0C End macro EDGE .SHIP_MAMBA_FACES Macro FACE: 58F0 5E 58F1 00 58F2 18 58F3 02 End macro FACE Macro FACE: 58F4 1E 58F5 00 58F6 18 58F7 02 End macro FACE Macro FACE: 58F8 9E 58F9 20 58FA 40 58FB 10 End macro FACE Macro FACE: 58FC 1E 58FD 20 58FE 40 58FF 10 End macro FACE Macro FACE: 5900 3E 5901 00 5902 00 5903 7F End macro FACE .SHIP_COBRA_MK_3 5904 03 5905 41 23 5907 BC 5908 54 5909 99 590A 54 590B 2A 590C A8 590D 26 590E 00 00 5910 34 5911 32 5912 96 5913 1C 5914 00 5915 01 5916 01 5917 13 .SHIP_COBRA_MK_3_VERTICES Macro VERTEX: 5918 20 5919 00 591A 4C 591B 1F 591C FF 591D FF End macro VERTEX Macro VERTEX: 591E 20 591F 00 5920 4C 5921 9F 5922 FF 5923 FF End macro VERTEX Macro VERTEX: 5924 00 5925 1A 5926 18 5927 1F 5928 FF 5929 FF End macro VERTEX Macro VERTEX: 592A 78 592B 03 592C 08 592D FF 592E 73 592F AA End macro VERTEX Macro VERTEX: 5930 78 5931 03 5932 08 5933 7F 5934 84 5935 CC End macro VERTEX Macro VERTEX: 5936 58 5937 10 5938 28 5939 BF 593A FF 593B FF End macro VERTEX Macro VERTEX: 593C 58 593D 10 593E 28 593F 3F 5940 FF 5941 FF End macro VERTEX Macro VERTEX: 5942 80 5943 08 5944 28 5945 7F 5946 98 5947 CC End macro VERTEX Macro VERTEX: 5948 80 5949 08 594A 28 594B FF 594C 97 594D AA End macro VERTEX Macro VERTEX: 594E 00 594F 1A 5950 28 5951 3F 5952 65 5953 99 End macro VERTEX Macro VERTEX: 5954 20 5955 18 5956 28 5957 FF 5958 A9 5959 BB End macro VERTEX Macro VERTEX: 595A 20 595B 18 595C 28 595D 7F 595E B9 595F CC End macro VERTEX Macro VERTEX: 5960 24 5961 08 5962 28 5963 B4 5964 99 5965 99 End macro VERTEX Macro VERTEX: 5966 08 5967 0C 5968 28 5969 B4 596A 99 596B 99 End macro VERTEX Macro VERTEX: 596C 08 596D 0C 596E 28 596F 34 5970 99 5971 99 End macro VERTEX Macro VERTEX: 5972 24 5973 08 5974 28 5975 34 5976 99 5977 99 End macro VERTEX Macro VERTEX: 5978 24 5979 0C 597A 28 597B 74 597C 99 597D 99 End macro VERTEX Macro VERTEX: 597E 08 597F 10 5980 28 5981 74 5982 99 5983 99 End macro VERTEX Macro VERTEX: 5984 08 5985 10 5986 28 5987 F4 5988 99 5989 99 End macro VERTEX Macro VERTEX: 598A 24 598B 0C 598C 28 598D F4 598E 99 598F 99 End macro VERTEX Macro VERTEX: 5990 00 5991 00 5992 4C 5993 06 5994 B0 5995 BB End macro VERTEX Macro VERTEX: 5996 00 5997 00 5998 5A 5999 1F 599A B0 599B BB End macro VERTEX Macro VERTEX: 599C 50 599D 06 599E 28 599F E8 59A0 99 59A1 99 End macro VERTEX Macro VERTEX: 59A2 50 59A3 06 59A4 28 59A5 A8 59A6 99 59A7 99 End macro VERTEX Macro VERTEX: 59A8 58 59A9 00 59AA 28 59AB A6 59AC 99 59AD 99 End macro VERTEX Macro VERTEX: 59AE 50 59AF 06 59B0 28 59B1 28 59B2 99 59B3 99 End macro VERTEX Macro VERTEX: 59B4 58 59B5 00 59B6 28 59B7 26 59B8 99 59B9 99 End macro VERTEX Macro VERTEX: 59BA 50 59BB 06 59BC 28 59BD 68 59BE 99 59BF 99 End macro VERTEX .SHIP_COBRA_MK_3_EDGES Macro EDGE: 59C0 1F 59C1 B0 59C2 00 59C3 04 End macro EDGE Macro EDGE: 59C4 1F 59C5 C4 59C6 00 59C7 10 End macro EDGE Macro EDGE: 59C8 1F 59C9 A3 59CA 04 59CB 0C End macro EDGE Macro EDGE: 59CC 1F 59CD A7 59CE 0C 59CF 20 End macro EDGE Macro EDGE: 59D0 1F 59D1 C8 59D2 10 59D3 1C End macro EDGE Macro EDGE: 59D4 1F 59D5 98 59D6 18 59D7 1C End macro EDGE Macro EDGE: 59D8 1F 59D9 96 59DA 18 59DB 24 End macro EDGE Macro EDGE: 59DC 1F 59DD 95 59DE 14 59DF 24 End macro EDGE Macro EDGE: 59E0 1F 59E1 97 59E2 14 59E3 20 End macro EDGE Macro EDGE: 59E4 1F 59E5 51 59E6 08 59E7 14 End macro EDGE Macro EDGE: 59E8 1F 59E9 62 59EA 08 59EB 18 End macro EDGE Macro EDGE: 59EC 1F 59ED 73 59EE 0C 59EF 14 End macro EDGE Macro EDGE: 59F0 1F 59F1 84 59F2 10 59F3 18 End macro EDGE Macro EDGE: 59F4 1F 59F5 10 59F6 04 59F7 08 End macro EDGE Macro EDGE: 59F8 1F 59F9 20 59FA 00 59FB 08 End macro EDGE Macro EDGE: 59FC 1F 59FD A9 59FE 20 59FF 28 End macro EDGE Macro EDGE: 5A00 1F 5A01 B9 5A02 28 5A03 2C End macro EDGE Macro EDGE: 5A04 1F 5A05 C9 5A06 1C 5A07 2C End macro EDGE Macro EDGE: 5A08 1F 5A09 BA 5A0A 04 5A0B 28 End macro EDGE Macro EDGE: 5A0C 1F 5A0D CB 5A0E 00 5A0F 2C End macro EDGE Macro EDGE: 5A10 1D 5A11 31 5A12 04 5A13 14 End macro EDGE Macro EDGE: 5A14 1D 5A15 42 5A16 00 5A17 18 End macro EDGE Macro EDGE: 5A18 06 5A19 B0 5A1A 50 5A1B 54 End macro EDGE Macro EDGE: 5A1C 14 5A1D 99 5A1E 30 5A1F 34 End macro EDGE Macro EDGE: 5A20 14 5A21 99 5A22 48 5A23 4C End macro EDGE Macro EDGE: 5A24 14 5A25 99 5A26 38 5A27 3C End macro EDGE Macro EDGE: 5A28 14 5A29 99 5A2A 40 5A2B 44 End macro EDGE Macro EDGE: 5A2C 13 5A2D 99 5A2E 3C 5A2F 40 End macro EDGE Macro EDGE: 5A30 11 5A31 99 5A32 38 5A33 44 End macro EDGE Macro EDGE: 5A34 13 5A35 99 5A36 34 5A37 48 End macro EDGE Macro EDGE: 5A38 13 5A39 99 5A3A 30 5A3B 4C End macro EDGE Macro EDGE: 5A3C 1E 5A3D 65 5A3E 08 5A3F 24 End macro EDGE Macro EDGE: 5A40 06 5A41 99 5A42 58 5A43 60 End macro EDGE Macro EDGE: 5A44 06 5A45 99 5A46 5C 5A47 60 End macro EDGE Macro EDGE: 5A48 08 5A49 99 5A4A 58 5A4B 5C End macro EDGE Macro EDGE: 5A4C 06 5A4D 99 5A4E 64 5A4F 68 End macro EDGE Macro EDGE: 5A50 06 5A51 99 5A52 68 5A53 6C End macro EDGE Macro EDGE: 5A54 08 5A55 99 5A56 64 5A57 6C End macro EDGE .SHIP_COBRA_MK_3_FACES Macro FACE: 5A58 1F 5A59 00 5A5A 3E 5A5B 1F End macro FACE Macro FACE: 5A5C 9F 5A5D 12 5A5E 37 5A5F 10 End macro FACE Macro FACE: 5A60 1F 5A61 12 5A62 37 5A63 10 End macro FACE Macro FACE: 5A64 9F 5A65 10 5A66 34 5A67 0E End macro FACE Macro FACE: 5A68 1F 5A69 10 5A6A 34 5A6B 0E End macro FACE Macro FACE: 5A6C 9F 5A6D 0E 5A6E 2F 5A6F 00 End macro FACE Macro FACE: 5A70 1F 5A71 0E 5A72 2F 5A73 00 End macro FACE Macro FACE: 5A74 9F 5A75 3D 5A76 66 5A77 00 End macro FACE Macro FACE: 5A78 1F 5A79 3D 5A7A 66 5A7B 00 End macro FACE Macro FACE: 5A7C 3F 5A7D 00 5A7E 00 5A7F 50 End macro FACE Macro FACE: 5A80 DF 5A81 07 5A82 2A 5A83 09 End macro FACE Macro FACE: 5A84 5F 5A85 00 5A86 1E 5A87 06 End macro FACE Macro FACE: 5A88 5F 5A89 07 5A8A 2A 5A8B 09 End macro FACE .SHIP_THARGOID 5A8C 00 5A8D 49 26 5A8F 8C 5A90 F4 5A91 65 5A92 3C 5A93 26 5A94 78 5A95 1A 5A96 F4 01 5A98 28 5A99 37 5A9A F0 5A9B 27 5A9C 00 5A9D 00 5A9E 02 5A9F 16 .SHIP_THARGOID_VERTICES Macro VERTEX: 5AA0 20 5AA1 30 5AA2 30 5AA3 5F 5AA4 40 5AA5 88 End macro VERTEX Macro VERTEX: 5AA6 20 5AA7 44 5AA8 00 5AA9 5F 5AAA 10 5AAB 44 End macro VERTEX Macro VERTEX: 5AAC 20 5AAD 30 5AAE 30 5AAF 7F 5AB0 21 5AB1 44 End macro VERTEX Macro VERTEX: 5AB2 20 5AB3 00 5AB4 44 5AB5 3F 5AB6 32 5AB7 44 End macro VERTEX Macro VERTEX: 5AB8 20 5AB9 30 5ABA 30 5ABB 3F 5ABC 43 5ABD 55 End macro VERTEX Macro VERTEX: 5ABE 20 5ABF 44 5AC0 00 5AC1 1F 5AC2 54 5AC3 66 End macro VERTEX Macro VERTEX: 5AC4 20 5AC5 30 5AC6 30 5AC7 1F 5AC8 64 5AC9 77 End macro VERTEX Macro VERTEX: 5ACA 20 5ACB 00 5ACC 44 5ACD 1F 5ACE 74 5ACF 88 End macro VERTEX Macro VERTEX: 5AD0 18 5AD1 74 5AD2 74 5AD3 DF 5AD4 80 5AD5 99 End macro VERTEX Macro VERTEX: 5AD6 18 5AD7 A4 5AD8 00 5AD9 DF 5ADA 10 5ADB 99 End macro VERTEX Macro VERTEX: 5ADC 18 5ADD 74 5ADE 74 5ADF FF 5AE0 21 5AE1 99 End macro VERTEX Macro VERTEX: 5AE2 18 5AE3 00 5AE4 A4 5AE5 BF 5AE6 32 5AE7 99 End macro VERTEX Macro VERTEX: 5AE8 18 5AE9 74 5AEA 74 5AEB BF 5AEC 53 5AED 99 End macro VERTEX Macro VERTEX: 5AEE 18 5AEF A4 5AF0 00 5AF1 9F 5AF2 65 5AF3 99 End macro VERTEX Macro VERTEX: 5AF4 18 5AF5 74 5AF6 74 5AF7 9F 5AF8 76 5AF9 99 End macro VERTEX Macro VERTEX: 5AFA 18 5AFB 00 5AFC A4 5AFD 9F 5AFE 87 5AFF 99 End macro VERTEX Macro VERTEX: 5B00 18 5B01 40 5B02 50 5B03 9E 5B04 99 5B05 99 End macro VERTEX Macro VERTEX: 5B06 18 5B07 40 5B08 50 5B09 BE 5B0A 99 5B0B 99 End macro VERTEX Macro VERTEX: 5B0C 18 5B0D 40 5B0E 50 5B0F FE 5B10 99 5B11 99 End macro VERTEX Macro VERTEX: 5B12 18 5B13 40 5B14 50 5B15 DE 5B16 99 5B17 99 End macro VERTEX .SHIP_THARGOID_EDGES Macro EDGE: 5B18 1F 5B19 84 5B1A 00 5B1B 1C End macro EDGE Macro EDGE: 5B1C 1F 5B1D 40 5B1E 00 5B1F 04 End macro EDGE Macro EDGE: 5B20 1F 5B21 41 5B22 04 5B23 08 End macro EDGE Macro EDGE: 5B24 1F 5B25 42 5B26 08 5B27 0C End macro EDGE Macro EDGE: 5B28 1F 5B29 43 5B2A 0C 5B2B 10 End macro EDGE Macro EDGE: 5B2C 1F 5B2D 54 5B2E 10 5B2F 14 End macro EDGE Macro EDGE: 5B30 1F 5B31 64 5B32 14 5B33 18 End macro EDGE Macro EDGE: 5B34 1F 5B35 74 5B36 18 5B37 1C End macro EDGE Macro EDGE: 5B38 1F 5B39 80 5B3A 00 5B3B 20 End macro EDGE Macro EDGE: 5B3C 1F 5B3D 10 5B3E 04 5B3F 24 End macro EDGE Macro EDGE: 5B40 1F 5B41 21 5B42 08 5B43 28 End macro EDGE Macro EDGE: 5B44 1F 5B45 32 5B46 0C 5B47 2C End macro EDGE Macro EDGE: 5B48 1F 5B49 53 5B4A 10 5B4B 30 End macro EDGE Macro EDGE: 5B4C 1F 5B4D 65 5B4E 14 5B4F 34 End macro EDGE Macro EDGE: 5B50 1F 5B51 76 5B52 18 5B53 38 End macro EDGE Macro EDGE: 5B54 1F 5B55 87 5B56 1C 5B57 3C End macro EDGE Macro EDGE: 5B58 1F 5B59 98 5B5A 20 5B5B 3C End macro EDGE Macro EDGE: 5B5C 1F 5B5D 90 5B5E 20 5B5F 24 End macro EDGE Macro EDGE: 5B60 1F 5B61 91 5B62 24 5B63 28 End macro EDGE Macro EDGE: 5B64 1F 5B65 92 5B66 28 5B67 2C End macro EDGE Macro EDGE: 5B68 1F 5B69 93 5B6A 2C 5B6B 30 End macro EDGE Macro EDGE: 5B6C 1F 5B6D 95 5B6E 30 5B6F 34 End macro EDGE Macro EDGE: 5B70 1F 5B71 96 5B72 34 5B73 38 End macro EDGE Macro EDGE: 5B74 1F 5B75 97 5B76 38 5B77 3C End macro EDGE Macro EDGE: 5B78 1E 5B79 99 5B7A 40 5B7B 44 End macro EDGE Macro EDGE: 5B7C 1E 5B7D 99 5B7E 48 5B7F 4C End macro EDGE .SHIP_THARGOID_FACES Macro FACE: 5B80 5F 5B81 67 5B82 3C 5B83 19 End macro FACE Macro FACE: 5B84 7F 5B85 67 5B86 3C 5B87 19 End macro FACE Macro FACE: 5B88 7F 5B89 67 5B8A 19 5B8B 3C End macro FACE Macro FACE: 5B8C 3F 5B8D 67 5B8E 19 5B8F 3C End macro FACE Macro FACE: 5B90 1F 5B91 40 5B92 00 5B93 00 End macro FACE Macro FACE: 5B94 3F 5B95 67 5B96 3C 5B97 19 End macro FACE Macro FACE: 5B98 1F 5B99 67 5B9A 3C 5B9B 19 End macro FACE Macro FACE: 5B9C 1F 5B9D 67 5B9E 19 5B9F 3C End macro FACE Macro FACE: 5BA0 5F 5BA1 67 5BA2 19 5BA3 3C End macro FACE Macro FACE: 5BA4 9F 5BA5 30 5BA6 00 5BA7 00 End macro FACE .SHIP_CORIOLIS 5BA8 00 5BA9 00 64 5BAB 74 5BAC E4 5BAD 55 5BAE 00 5BAF 36 5BB0 60 5BB1 1C 5BB2 00 00 5BB4 38 5BB5 78 5BB6 F0 5BB7 00 5BB8 00 5BB9 00 5BBA 00 5BBB 06 .SHIP_CORIOLIS_VERTICES Macro VERTEX: 5BBC A0 5BBD 00 5BBE A0 5BBF 1F 5BC0 10 5BC1 62 End macro VERTEX Macro VERTEX: 5BC2 00 5BC3 A0 5BC4 A0 5BC5 1F 5BC6 20 5BC7 83 End macro VERTEX Macro VERTEX: 5BC8 A0 5BC9 00 5BCA A0 5BCB 9F 5BCC 30 5BCD 74 End macro VERTEX Macro VERTEX: 5BCE 00 5BCF A0 5BD0 A0 5BD1 5F 5BD2 10 5BD3 54 End macro VERTEX Macro VERTEX: 5BD4 A0 5BD5 A0 5BD6 00 5BD7 5F 5BD8 51 5BD9 A6 End macro VERTEX Macro VERTEX: 5BDA A0 5BDB A0 5BDC 00 5BDD 1F 5BDE 62 5BDF B8 End macro VERTEX Macro VERTEX: 5BE0 A0 5BE1 A0 5BE2 00 5BE3 9F 5BE4 73 5BE5 C8 End macro VERTEX Macro VERTEX: 5BE6 A0 5BE7 A0 5BE8 00 5BE9 DF 5BEA 54 5BEB 97 End macro VERTEX Macro VERTEX: 5BEC A0 5BED 00 5BEE A0 5BEF 3F 5BF0 A6 5BF1 DB End macro VERTEX Macro VERTEX: 5BF2 00 5BF3 A0 5BF4 A0 5BF5 3F 5BF6 B8 5BF7 DC End macro VERTEX Macro VERTEX: 5BF8 A0 5BF9 00 5BFA A0 5BFB BF 5BFC 97 5BFD DC End macro VERTEX Macro VERTEX: 5BFE 00 5BFF A0 5C00 A0 5C01 7F 5C02 95 5C03 DA End macro VERTEX Macro VERTEX: 5C04 0A 5C05 1E 5C06 A0 5C07 5E 5C08 00 5C09 00 End macro VERTEX Macro VERTEX: 5C0A 0A 5C0B 1E 5C0C A0 5C0D 1E 5C0E 00 5C0F 00 End macro VERTEX Macro VERTEX: 5C10 0A 5C11 1E 5C12 A0 5C13 9E 5C14 00 5C15 00 End macro VERTEX Macro VERTEX: 5C16 0A 5C17 1E 5C18 A0 5C19 DE 5C1A 00 5C1B 00 End macro VERTEX .SHIP_CORIOLIS_EDGES Macro EDGE: 5C1C 1F 5C1D 10 5C1E 00 5C1F 0C End macro EDGE Macro EDGE: 5C20 1F 5C21 20 5C22 00 5C23 04 End macro EDGE Macro EDGE: 5C24 1F 5C25 30 5C26 04 5C27 08 End macro EDGE Macro EDGE: 5C28 1F 5C29 40 5C2A 08 5C2B 0C End macro EDGE Macro EDGE: 5C2C 1F 5C2D 51 5C2E 0C 5C2F 10 End macro EDGE Macro EDGE: 5C30 1F 5C31 61 5C32 00 5C33 10 End macro EDGE Macro EDGE: 5C34 1F 5C35 62 5C36 00 5C37 14 End macro EDGE Macro EDGE: 5C38 1F 5C39 82 5C3A 14 5C3B 04 End macro EDGE Macro EDGE: 5C3C 1F 5C3D 83 5C3E 04 5C3F 18 End macro EDGE Macro EDGE: 5C40 1F 5C41 73 5C42 08 5C43 18 End macro EDGE Macro EDGE: 5C44 1F 5C45 74 5C46 08 5C47 1C End macro EDGE Macro EDGE: 5C48 1F 5C49 54 5C4A 0C 5C4B 1C End macro EDGE Macro EDGE: 5C4C 1F 5C4D DA 5C4E 20 5C4F 2C End macro EDGE Macro EDGE: 5C50 1F 5C51 DB 5C52 20 5C53 24 End macro EDGE Macro EDGE: 5C54 1F 5C55 DC 5C56 24 5C57 28 End macro EDGE Macro EDGE: 5C58 1F 5C59 D9 5C5A 28 5C5B 2C End macro EDGE Macro EDGE: 5C5C 1F 5C5D A5 5C5E 10 5C5F 2C End macro EDGE Macro EDGE: 5C60 1F 5C61 A6 5C62 10 5C63 20 End macro EDGE Macro EDGE: 5C64 1F 5C65 B6 5C66 14 5C67 20 End macro EDGE Macro EDGE: 5C68 1F 5C69 B8 5C6A 14 5C6B 24 End macro EDGE Macro EDGE: 5C6C 1F 5C6D C8 5C6E 18 5C6F 24 End macro EDGE Macro EDGE: 5C70 1F 5C71 C7 5C72 18 5C73 28 End macro EDGE Macro EDGE: 5C74 1F 5C75 97 5C76 1C 5C77 28 End macro EDGE Macro EDGE: 5C78 1F 5C79 95 5C7A 1C 5C7B 2C End macro EDGE Macro EDGE: 5C7C 1E 5C7D 00 5C7E 30 5C7F 34 End macro EDGE Macro EDGE: 5C80 1E 5C81 00 5C82 34 5C83 38 End macro EDGE Macro EDGE: 5C84 1E 5C85 00 5C86 38 5C87 3C End macro EDGE Macro EDGE: 5C88 1E 5C89 00 5C8A 3C 5C8B 30 End macro EDGE .SHIP_CORIOLIS_FACES Macro FACE: 5C8C 1F 5C8D 00 5C8E 00 5C8F A0 End macro FACE Macro FACE: 5C90 5F 5C91 6B 5C92 6B 5C93 6B End macro FACE Macro FACE: 5C94 1F 5C95 6B 5C96 6B 5C97 6B End macro FACE Macro FACE: 5C98 9F 5C99 6B 5C9A 6B 5C9B 6B End macro FACE Macro FACE: 5C9C DF 5C9D 6B 5C9E 6B 5C9F 6B End macro FACE Macro FACE: 5CA0 5F 5CA1 00 5CA2 A0 5CA3 00 End macro FACE Macro FACE: 5CA4 1F 5CA5 A0 5CA6 00 5CA7 00 End macro FACE Macro FACE: 5CA8 9F 5CA9 A0 5CAA 00 5CAB 00 End macro FACE Macro FACE: 5CAC 1F 5CAD 00 5CAE A0 5CAF 00 End macro FACE Macro FACE: 5CB0 FF 5CB1 6B 5CB2 6B 5CB3 6B End macro FACE Macro FACE: 5CB4 7F 5CB5 6B 5CB6 6B 5CB7 6B End macro FACE Macro FACE: 5CB8 3F 5CB9 6B 5CBA 6B 5CBB 6B End macro FACE Macro FACE: 5CBC BF 5CBD 6B 5CBE 6B 5CBF 6B End macro FACE Macro FACE: 5CC0 3F 5CC1 00 5CC2 00 5CC3 A0 End macro FACE .SHIP_MISSILE 5CC4 00 5CC5 40 06 5CC7 7A 5CC8 DA 5CC9 51 5CCA 00 5CCB 0A 5CCC 66 5CCD 18 5CCE 00 00 5CD0 24 5CD1 0E 5CD2 02 5CD3 2C 5CD4 00 5CD5 00 5CD6 02 5CD7 00 .SHIP_MISSILE_VERTICES Macro VERTEX: 5CD8 00 5CD9 00 5CDA 44 5CDB 1F 5CDC 10 5CDD 32 End macro VERTEX Macro VERTEX: 5CDE 08 5CDF 08 5CE0 24 5CE1 5F 5CE2 21 5CE3 54 End macro VERTEX Macro VERTEX: 5CE4 08 5CE5 08 5CE6 24 5CE7 1F 5CE8 32 5CE9 74 End macro VERTEX Macro VERTEX: 5CEA 08 5CEB 08 5CEC 24 5CED 9F 5CEE 30 5CEF 76 End macro VERTEX Macro VERTEX: 5CF0 08 5CF1 08 5CF2 24 5CF3 DF 5CF4 10 5CF5 65 End macro VERTEX Macro VERTEX: 5CF6 08 5CF7 08 5CF8 2C 5CF9 3F 5CFA 74 5CFB 88 End macro VERTEX Macro VERTEX: 5CFC 08 5CFD 08 5CFE 2C 5CFF 7F 5D00 54 5D01 88 End macro VERTEX Macro VERTEX: 5D02 08 5D03 08 5D04 2C 5D05 FF 5D06 65 5D07 88 End macro VERTEX Macro VERTEX: 5D08 08 5D09 08 5D0A 2C 5D0B BF 5D0C 76 5D0D 88 End macro VERTEX Macro VERTEX: 5D0E 0C 5D0F 0C 5D10 2C 5D11 28 5D12 74 5D13 88 End macro VERTEX Macro VERTEX: 5D14 0C 5D15 0C 5D16 2C 5D17 68 5D18 54 5D19 88 End macro VERTEX Macro VERTEX: 5D1A 0C 5D1B 0C 5D1C 2C 5D1D E8 5D1E 65 5D1F 88 End macro VERTEX Macro VERTEX: 5D20 0C 5D21 0C 5D22 2C 5D23 A8 5D24 76 5D25 88 End macro VERTEX Macro VERTEX: 5D26 08 5D27 08 5D28 0C 5D29 A8 5D2A 76 5D2B 77 End macro VERTEX Macro VERTEX: 5D2C 08 5D2D 08 5D2E 0C 5D2F E8 5D30 65 5D31 66 End macro VERTEX Macro VERTEX: 5D32 08 5D33 08 5D34 0C 5D35 28 5D36 74 5D37 77 End macro VERTEX Macro VERTEX: 5D38 08 5D39 08 5D3A 0C 5D3B 68 5D3C 54 5D3D 55 End macro VERTEX .SHIP_MISSILE_EDGES Macro EDGE: 5D3E 1F 5D3F 21 5D40 00 5D41 04 End macro EDGE Macro EDGE: 5D42 1F 5D43 32 5D44 00 5D45 08 End macro EDGE Macro EDGE: 5D46 1F 5D47 30 5D48 00 5D49 0C End macro EDGE Macro EDGE: 5D4A 1F 5D4B 10 5D4C 00 5D4D 10 End macro EDGE Macro EDGE: 5D4E 1F 5D4F 24 5D50 04 5D51 08 End macro EDGE Macro EDGE: 5D52 1F 5D53 51 5D54 04 5D55 10 End macro EDGE Macro EDGE: 5D56 1F 5D57 60 5D58 0C 5D59 10 End macro EDGE Macro EDGE: 5D5A 1F 5D5B 73 5D5C 08 5D5D 0C End macro EDGE Macro EDGE: 5D5E 1F 5D5F 74 5D60 08 5D61 14 End macro EDGE Macro EDGE: 5D62 1F 5D63 54 5D64 04 5D65 18 End macro EDGE Macro EDGE: 5D66 1F 5D67 65 5D68 10 5D69 1C End macro EDGE Macro EDGE: 5D6A 1F 5D6B 76 5D6C 0C 5D6D 20 End macro EDGE Macro EDGE: 5D6E 1F 5D6F 86 5D70 1C 5D71 20 End macro EDGE Macro EDGE: 5D72 1F 5D73 87 5D74 14 5D75 20 End macro EDGE Macro EDGE: 5D76 1F 5D77 84 5D78 14 5D79 18 End macro EDGE Macro EDGE: 5D7A 1F 5D7B 85 5D7C 18 5D7D 1C End macro EDGE Macro EDGE: 5D7E 08 5D7F 85 5D80 18 5D81 28 End macro EDGE Macro EDGE: 5D82 08 5D83 87 5D84 14 5D85 24 End macro EDGE Macro EDGE: 5D86 08 5D87 87 5D88 20 5D89 30 End macro EDGE Macro EDGE: 5D8A 08 5D8B 85 5D8C 1C 5D8D 2C End macro EDGE Macro EDGE: 5D8E 08 5D8F 74 5D90 24 5D91 3C End macro EDGE Macro EDGE: 5D92 08 5D93 54 5D94 28 5D95 40 End macro EDGE Macro EDGE: 5D96 08 5D97 76 5D98 30 5D99 34 End macro EDGE Macro EDGE: 5D9A 08 5D9B 65 5D9C 2C 5D9D 38 End macro EDGE .SHIP_MISSILE_FACES Macro FACE: 5D9E 9F 5D9F 40 5DA0 00 5DA1 10 End macro FACE Macro FACE: 5DA2 5F 5DA3 00 5DA4 40 5DA5 10 End macro FACE Macro FACE: 5DA6 1F 5DA7 40 5DA8 00 5DA9 10 End macro FACE Macro FACE: 5DAA 1F 5DAB 00 5DAC 40 5DAD 10 End macro FACE Macro FACE: 5DAE 1F 5DAF 20 5DB0 00 5DB1 00 End macro FACE Macro FACE: 5DB2 5F 5DB3 00 5DB4 20 5DB5 00 End macro FACE Macro FACE: 5DB6 9F 5DB7 20 5DB8 00 5DB9 00 End macro FACE Macro FACE: 5DBA 1F 5DBB 00 5DBC 20 5DBD 00 End macro FACE Macro FACE: 5DBE 3F 5DBF 00 5DC0 00 5DC1 B0 End macro FACE .SHIP_ASTEROID 5DC2 00 5DC3 00 19 5DC5 4A 5DC6 9E 5DC7 41 5DC8 00 5DC9 22 5DCA 36 5DCB 15 5DCC 05 00 5DCE 38 5DCF 32 5DD0 3C 5DD1 1E 5DD2 00 5DD3 00 5DD4 01 5DD5 00 .SHIP_ASTEROID_VERTICES Macro VERTEX: 5DD6 00 5DD7 50 5DD8 00 5DD9 1F 5DDA FF 5DDB FF End macro VERTEX Macro VERTEX: 5DDC 50 5DDD 0A 5DDE 00 5DDF DF 5DE0 FF 5DE1 FF End macro VERTEX Macro VERTEX: 5DE2 00 5DE3 50 5DE4 00 5DE5 5F 5DE6 FF 5DE7 FF End macro VERTEX Macro VERTEX: 5DE8 46 5DE9 28 5DEA 00 5DEB 5F 5DEC FF 5DED FF End macro VERTEX Macro VERTEX: 5DEE 3C 5DEF 32 5DF0 00 5DF1 1F 5DF2 65 5DF3 DC End macro VERTEX Macro VERTEX: 5DF4 32 5DF5 00 5DF6 3C 5DF7 1F 5DF8 FF 5DF9 FF End macro VERTEX Macro VERTEX: 5DFA 28 5DFB 00 5DFC 46 5DFD 9F 5DFE 10 5DFF 32 End macro VERTEX Macro VERTEX: 5E00 00 5E01 1E 5E02 4B 5E03 3F 5E04 FF 5E05 FF End macro VERTEX Macro VERTEX: 5E06 00 5E07 32 5E08 3C 5E09 7F 5E0A 98 5E0B BA End macro VERTEX .SHIP_ASTEROID_EDGES Macro EDGE: 5E0C 1F 5E0D 72 5E0E 00 5E0F 04 End macro EDGE Macro EDGE: 5E10 1F 5E11 D6 5E12 00 5E13 10 End macro EDGE Macro EDGE: 5E14 1F 5E15 C5 5E16 0C 5E17 10 End macro EDGE Macro EDGE: 5E18 1F 5E19 B4 5E1A 08 5E1B 0C End macro EDGE Macro EDGE: 5E1C 1F 5E1D A3 5E1E 04 5E1F 08 End macro EDGE Macro EDGE: 5E20 1F 5E21 32 5E22 04 5E23 18 End macro EDGE Macro EDGE: 5E24 1F 5E25 31 5E26 08 5E27 18 End macro EDGE Macro EDGE: 5E28 1F 5E29 41 5E2A 08 5E2B 14 End macro EDGE Macro EDGE: 5E2C 1F 5E2D 10 5E2E 14 5E2F 18 End macro EDGE Macro EDGE: 5E30 1F 5E31 60 5E32 00 5E33 14 End macro EDGE Macro EDGE: 5E34 1F 5E35 54 5E36 0C 5E37 14 End macro EDGE Macro EDGE: 5E38 1F 5E39 20 5E3A 00 5E3B 18 End macro EDGE Macro EDGE: 5E3C 1F 5E3D 65 5E3E 10 5E3F 14 End macro EDGE Macro EDGE: 5E40 1F 5E41 A8 5E42 04 5E43 20 End macro EDGE Macro EDGE: 5E44 1F 5E45 87 5E46 04 5E47 1C End macro EDGE Macro EDGE: 5E48 1F 5E49 D7 5E4A 00 5E4B 1C End macro EDGE Macro EDGE: 5E4C 1F 5E4D DC 5E4E 10 5E4F 1C End macro EDGE Macro EDGE: 5E50 1F 5E51 C9 5E52 0C 5E53 1C End macro EDGE Macro EDGE: 5E54 1F 5E55 B9 5E56 0C 5E57 20 End macro EDGE Macro EDGE: 5E58 1F 5E59 BA 5E5A 08 5E5B 20 End macro EDGE Macro EDGE: 5E5C 1F 5E5D 98 5E5E 1C 5E5F 20 End macro EDGE .SHIP_ASTEROID_FACES Macro FACE: 5E60 1F 5E61 09 5E62 42 5E63 51 End macro FACE Macro FACE: 5E64 5F 5E65 09 5E66 42 5E67 51 End macro FACE Macro FACE: 5E68 9F 5E69 48 5E6A 40 5E6B 1F End macro FACE Macro FACE: 5E6C DF 5E6D 40 5E6E 49 5E6F 2F End macro FACE Macro FACE: 5E70 5F 5E71 2D 5E72 4F 5E73 41 End macro FACE Macro FACE: 5E74 1F 5E75 87 5E76 0F 5E77 23 End macro FACE Macro FACE: 5E78 1F 5E79 26 5E7A 4C 5E7B 46 End macro FACE Macro FACE: 5E7C BF 5E7D 42 5E7E 3B 5E7F 27 End macro FACE Macro FACE: 5E80 FF 5E81 43 5E82 0F 5E83 50 End macro FACE Macro FACE: 5E84 7F 5E85 42 5E86 0E 5E87 4B End macro FACE Macro FACE: 5E88 FF 5E89 46 5E8A 50 5E8B 28 End macro FACE Macro FACE: 5E8C 7F 5E8D 3A 5E8E 66 5E8F 33 End macro FACE Macro FACE: 5E90 3F 5E91 51 5E92 09 5E93 43 End macro FACE Macro FACE: 5E94 3F 5E95 2F 5E96 5E 5E97 3F End macro FACE .SHIP_CANISTER 5E98 00 5E99 90 01 5E9B 50 5E9C 8C 5E9D 31 5E9E 00 5E9F 12 5EA0 3C 5EA1 0F 5EA2 00 00 5EA4 1C 5EA5 0C 5EA6 11 5EA7 0F 5EA8 00 5EA9 00 5EAA 02 5EAB 00 .SHIP_CANISTER_VERTICES Macro VERTEX: 5EAC 18 5EAD 10 5EAE 00 5EAF 1F 5EB0 10 5EB1 55 End macro VERTEX Macro VERTEX: 5EB2 18 5EB3 05 5EB4 0F 5EB5 1F 5EB6 10 5EB7 22 End macro VERTEX Macro VERTEX: 5EB8 18 5EB9 0D 5EBA 09 5EBB 5F 5EBC 20 5EBD 33 End macro VERTEX Macro VERTEX: 5EBE 18 5EBF 0D 5EC0 09 5EC1 7F 5EC2 30 5EC3 44 End macro VERTEX Macro VERTEX: 5EC4 18 5EC5 05 5EC6 0F 5EC7 3F 5EC8 40 5EC9 55 End macro VERTEX Macro VERTEX: 5ECA 18 5ECB 10 5ECC 00 5ECD 9F 5ECE 51 5ECF 66 End macro VERTEX Macro VERTEX: 5ED0 18 5ED1 05 5ED2 0F 5ED3 9F 5ED4 21 5ED5 66 End macro VERTEX Macro VERTEX: 5ED6 18 5ED7 0D 5ED8 09 5ED9 DF 5EDA 32 5EDB 66 End macro VERTEX Macro VERTEX: 5EDC 18 5EDD 0D 5EDE 09 5EDF FF 5EE0 43 5EE1 66 End macro VERTEX Macro VERTEX: 5EE2 18 5EE3 05 5EE4 0F 5EE5 BF 5EE6 54 5EE7 66 End macro VERTEX .SHIP_CANISTER_EDGES Macro EDGE: 5EE8 1F 5EE9 10 5EEA 00 5EEB 04 End macro EDGE Macro EDGE: 5EEC 1F 5EED 20 5EEE 04 5EEF 08 End macro EDGE Macro EDGE: 5EF0 1F 5EF1 30 5EF2 08 5EF3 0C End macro EDGE Macro EDGE: 5EF4 1F 5EF5 40 5EF6 0C 5EF7 10 End macro EDGE Macro EDGE: 5EF8 1F 5EF9 50 5EFA 00 5EFB 10 End macro EDGE Macro EDGE: 5EFC 1F 5EFD 51 5EFE 00 5EFF 14 End macro EDGE Macro EDGE: 5F00 1F 5F01 21 5F02 04 5F03 18 End macro EDGE Macro EDGE: 5F04 1F 5F05 32 5F06 08 5F07 1C End macro EDGE Macro EDGE: 5F08 1F 5F09 43 5F0A 0C 5F0B 20 End macro EDGE Macro EDGE: 5F0C 1F 5F0D 54 5F0E 10 5F0F 24 End macro EDGE Macro EDGE: 5F10 1F 5F11 61 5F12 14 5F13 18 End macro EDGE Macro EDGE: 5F14 1F 5F15 62 5F16 18 5F17 1C End macro EDGE Macro EDGE: 5F18 1F 5F19 63 5F1A 1C 5F1B 20 End macro EDGE Macro EDGE: 5F1C 1F 5F1D 64 5F1E 20 5F1F 24 End macro EDGE Macro EDGE: 5F20 1F 5F21 65 5F22 24 5F23 14 End macro EDGE .SHIP_CANISTER_FACES Macro FACE: 5F24 1F 5F25 60 5F26 00 5F27 00 End macro FACE Macro FACE: 5F28 1F 5F29 00 5F2A 29 5F2B 1E End macro FACE Macro FACE: 5F2C 5F 5F2D 00 5F2E 12 5F2F 30 End macro FACE Macro FACE: 5F30 5F 5F31 00 5F32 33 5F33 00 End macro FACE Macro FACE: 5F34 7F 5F35 00 5F36 12 5F37 30 End macro FACE Macro FACE: 5F38 3F 5F39 00 5F3A 29 5F3B 1E End macro FACE Macro FACE: 5F3C 9F 5F3D 60 5F3E 00 5F3F 00 End macro FACE .SHIP_THARGON 5F40 00 5F41 40 06 5F43 A8 5F44 50 5F45 41 5F46 00 5F47 12 5F48 3C 5F49 0F 5F4A 32 00 5F4C 1C 5F4D 14 5F4E 14 5F4F 1E 5F50 FF 5F51 00 5F52 02 5F53 10 .SHIP_THARGON_VERTICES Macro VERTEX: 5F54 09 5F55 00 5F56 28 5F57 9F 5F58 01 5F59 55 End macro VERTEX Macro VERTEX: 5F5A 09 5F5B 26 5F5C 0C 5F5D DF 5F5E 01 5F5F 22 End macro VERTEX Macro VERTEX: 5F60 09 5F61 18 5F62 20 5F63 FF 5F64 02 5F65 33 End macro VERTEX Macro VERTEX: 5F66 09 5F67 18 5F68 20 5F69 BF 5F6A 03 5F6B 44 End macro VERTEX Macro VERTEX: 5F6C 09 5F6D 26 5F6E 0C 5F6F 9F 5F70 04 5F71 55 End macro VERTEX Macro VERTEX: 5F72 09 5F73 00 5F74 08 5F75 3F 5F76 15 5F77 66 End macro VERTEX Macro VERTEX: 5F78 09 5F79 0A 5F7A 0F 5F7B 7F 5F7C 12 5F7D 66 End macro VERTEX Macro VERTEX: 5F7E 09 5F7F 06 5F80 1A 5F81 7F 5F82 23 5F83 66 End macro VERTEX Macro VERTEX: 5F84 09 5F85 06 5F86 1A 5F87 3F 5F88 34 5F89 66 End macro VERTEX Macro VERTEX: 5F8A 09 5F8B 0A 5F8C 0F 5F8D 3F 5F8E 45 5F8F 66 End macro VERTEX .SHIP_THARGON_FACES Macro FACE: 5F90 9F 5F91 24 5F92 00 5F93 00 End macro FACE Macro FACE: 5F94 5F 5F95 14 5F96 05 5F97 07 End macro FACE Macro FACE: 5F98 7F 5F99 2E 5F9A 2A 5F9B 0E End macro FACE Macro FACE: 5F9C 3F 5F9D 24 5F9E 00 5F9F 68 End macro FACE Macro FACE: 5FA0 3F 5FA1 2E 5FA2 2A 5FA3 0E End macro FACE Macro FACE: 5FA4 1F 5FA5 14 5FA6 05 5FA7 07 End macro FACE Macro FACE: 5FA8 1F 5FA9 24 5FAA 00 5FAB 00 End macro FACE .SHIP_ESCAPE_POD 5FAC 00 5FAD 00 01 5FAF 2C 5FB0 44 5FB1 19 5FB2 00 5FB3 16 5FB4 18 5FB5 06 5FB6 00 00 5FB8 10 5FB9 08 5FBA 11 5FBB 08 5FBC 00 5FBD 00 5FBE 03 5FBF 00 .SHIP_ESCAPE_POD_VERTICES Macro VERTEX: 5FC0 07 5FC1 00 5FC2 24 5FC3 9F 5FC4 12 5FC5 33 End macro VERTEX Macro VERTEX: 5FC6 07 5FC7 0E 5FC8 0C 5FC9 FF 5FCA 02 5FCB 33 End macro VERTEX Macro VERTEX: 5FCC 07 5FCD 0E 5FCE 0C 5FCF BF 5FD0 01 5FD1 33 End macro VERTEX Macro VERTEX: 5FD2 15 5FD3 00 5FD4 00 5FD5 1F 5FD6 01 5FD7 22 End macro VERTEX .SHIP_ESCAPE_POD_EDGES Macro EDGE: 5FD8 1F 5FD9 23 5FDA 00 5FDB 04 End macro EDGE Macro EDGE: 5FDC 1F 5FDD 03 5FDE 04 5FDF 08 End macro EDGE Macro EDGE: 5FE0 1F 5FE1 01 5FE2 08 5FE3 0C End macro EDGE Macro EDGE: 5FE4 1F 5FE5 12 5FE6 0C 5FE7 00 End macro EDGE Macro EDGE: 5FE8 1F 5FE9 13 5FEA 00 5FEB 08 End macro EDGE Macro EDGE: 5FEC 1F 5FED 02 5FEE 0C 5FEF 04 End macro EDGE .SHIP_ESCAPE_POD_FACES Macro FACE: 5FF0 3F 5FF1 1A 5FF2 00 5FF3 3D End macro FACE Macro FACE: 5FF4 1F 5FF5 13 5FF6 33 5FF7 0F End macro FACE Macro FACE: 5FF8 5F 5FF9 13 5FFA 33 5FFB 0F End macro FACE Macro FACE: 5FFC 9F 5FFD 38 5FFE 00 5FFF 00 End macro FACE SHIPS Assembled at &563A Ends at &6000 Code size is &9C6 Execute at &1128 Reload at &5822 S.SHIPS &563A &6000 &1128 &5822 Saving file '3-assembled-output/SHIPS.bin' .SHIP_PYTHON 7F00 03 7F01 40 38 7F03 56 7F04 BE 7F05 55 7F06 00 7F07 2E 7F08 42 7F09 1A 7F0A C8 00 7F0C 34 7F0D 28 7F0E FA 7F0F 14 7F10 00 7F11 00 7F12 00 7F13 1B .SHIP_PYTHON_VERTICES Macro VERTEX: 7F14 00 7F15 00 7F16 E0 7F17 1F 7F18 10 7F19 32 End macro VERTEX Macro VERTEX: 7F1A 00 7F1B 30 7F1C 30 7F1D 1E 7F1E 10 7F1F 54 End macro VERTEX Macro VERTEX: 7F20 60 7F21 00 7F22 10 7F23 3F 7F24 FF 7F25 FF End macro VERTEX Macro VERTEX: 7F26 60 7F27 00 7F28 10 7F29 BF 7F2A FF 7F2B FF End macro VERTEX Macro VERTEX: 7F2C 00 7F2D 30 7F2E 20 7F2F 3E 7F30 54 7F31 98 End macro VERTEX Macro VERTEX: 7F32 00 7F33 18 7F34 70 7F35 3F 7F36 89 7F37 CC End macro VERTEX Macro VERTEX: 7F38 30 7F39 00 7F3A 70 7F3B BF 7F3C B8 7F3D CC End macro VERTEX Macro VERTEX: 7F3E 30 7F3F 00 7F40 70 7F41 3F 7F42 A9 7F43 CC End macro VERTEX Macro VERTEX: 7F44 00 7F45 30 7F46 30 7F47 5E 7F48 32 7F49 76 End macro VERTEX Macro VERTEX: 7F4A 00 7F4B 30 7F4C 20 7F4D 7E 7F4E 76 7F4F BA End macro VERTEX Macro VERTEX: 7F50 00 7F51 18 7F52 70 7F53 7E 7F54 BA 7F55 CC End macro VERTEX .SHIP_PYTHON_EDGES Macro EDGE: 7F56 1E 7F57 32 7F58 00 7F59 20 End macro EDGE Macro EDGE: 7F5A 1F 7F5B 20 7F5C 00 7F5D 0C End macro EDGE Macro EDGE: 7F5E 1F 7F5F 31 7F60 00 7F61 08 End macro EDGE Macro EDGE: 7F62 1E 7F63 10 7F64 00 7F65 04 End macro EDGE Macro EDGE: 7F66 1D 7F67 59 7F68 08 7F69 10 End macro EDGE Macro EDGE: 7F6A 1D 7F6B 51 7F6C 04 7F6D 08 End macro EDGE Macro EDGE: 7F6E 1D 7F6F 37 7F70 08 7F71 20 End macro EDGE Macro EDGE: 7F72 1D 7F73 40 7F74 04 7F75 0C End macro EDGE Macro EDGE: 7F76 1D 7F77 62 7F78 0C 7F79 20 End macro EDGE Macro EDGE: 7F7A 1D 7F7B A7 7F7C 08 7F7D 24 End macro EDGE Macro EDGE: 7F7E 1D 7F7F 84 7F80 0C 7F81 10 End macro EDGE Macro EDGE: 7F82 1D 7F83 B6 7F84 0C 7F85 24 End macro EDGE Macro EDGE: 7F86 05 7F87 88 7F88 0C 7F89 14 End macro EDGE Macro EDGE: 7F8A 05 7F8B BB 7F8C 0C 7F8D 28 End macro EDGE Macro EDGE: 7F8E 05 7F8F 99 7F90 08 7F91 14 End macro EDGE Macro EDGE: 7F92 05 7F93 AA 7F94 08 7F95 28 End macro EDGE Macro EDGE: 7F96 1F 7F97 A9 7F98 08 7F99 1C End macro EDGE Macro EDGE: 7F9A 1F 7F9B B8 7F9C 0C 7F9D 18 End macro EDGE Macro EDGE: 7F9E 1F 7F9F C8 7FA0 14 7FA1 18 End macro EDGE Macro EDGE: 7FA2 1F 7FA3 C9 7FA4 14 7FA5 1C End macro EDGE Macro EDGE: 7FA6 1D 7FA7 AC 7FA8 1C 7FA9 28 End macro EDGE Macro EDGE: 7FAA 1D 7FAB CB 7FAC 18 7FAD 28 End macro EDGE Macro EDGE: 7FAE 1D 7FAF 98 7FB0 10 7FB1 14 End macro EDGE Macro EDGE: 7FB2 1D 7FB3 BA 7FB4 24 7FB5 28 End macro EDGE Macro EDGE: 7FB6 1D 7FB7 54 7FB8 04 7FB9 10 End macro EDGE Macro EDGE: 7FBA 1D 7FBB 76 7FBC 20 7FBD 24 End macro EDGE .SHIP_PYTHON_FACES Macro FACE: 7FBE 9E 7FBF 1B 7FC0 28 7FC1 0B End macro FACE Macro FACE: 7FC2 1E 7FC3 1B 7FC4 28 7FC5 0B End macro FACE Macro FACE: 7FC6 DE 7FC7 1B 7FC8 28 7FC9 0B End macro FACE Macro FACE: 7FCA 5E 7FCB 1B 7FCC 28 7FCD 0B End macro FACE Macro FACE: 7FCE 9E 7FCF 13 7FD0 26 7FD1 00 End macro FACE Macro FACE: 7FD2 1E 7FD3 13 7FD4 26 7FD5 00 End macro FACE Macro FACE: 7FD6 DE 7FD7 13 7FD8 26 7FD9 00 End macro FACE Macro FACE: 7FDA 5E 7FDB 13 7FDC 26 7FDD 00 End macro FACE Macro FACE: 7FDE BE 7FDF 19 7FE0 25 7FE1 0B End macro FACE Macro FACE: 7FE2 3E 7FE3 19 7FE4 25 7FE5 0B End macro FACE Macro FACE: 7FE6 7E 7FE7 19 7FE8 25 7FE9 0B End macro FACE Macro FACE: 7FEA FE 7FEB 19 7FEC 25 7FED 0B End macro FACE Macro FACE: 7FEE 3E 7FEF 00 7FF0 00 7FF1 70 End macro FACE 7FF2 .SVN 7FFD .VEC 7FFE PYTHON Assembled at &7F00 Ends at &8000 Code size is &100 Execute at &1128 Reload at &1B00 S.PYTHON &17F4 &8000 &1128 &1B00 Saving file '3-assembled-output/PYTHON.bin' ELITE game code &FFFFE000 bytes free Ends at &8000 .ZP 0070 .LBL 1100 6C 1101 A2 60 LDX #&60 1103 A9 0B LDA #&0B 1105 85 71 STA &71 1107 A0 00 LDY #&00 1109 84 70 STY &70 110B 98 TYA 110C C8 INY .CHK3 110D 18 CLC 110E 71 70 ADC (&70),Y 1110 C8 INY 1111 D0 FA BNE &110D 1113 E6 71 INC &71 .CHK4 1115 18 CLC 1116 71 70 ADC (&70),Y 1118 C8 INY 1119 10 FA BPL &1115 111B CD 00 0B CMP &0B00 111E F0 E2 BEQ &1102 1120 A9 7F LDA #&7F 1122 8D 4E FE STA &FE4E 1125 6C FC FF JMP (&FFFC) .elitea elitea = &1128 1128 F5 46 81 ... INCBIN "3-assembled-output/ELTA.bin" .eliteb eliteb = &19DC 19DC 4A 41 4D ... INCBIN "3-assembled-output/ELTB.bin" .elitec elitec = &2404 2404 A9 00 20 ... INCBIN "3-assembled-output/ELTC.bin" .elited elited = &2EB0 2EB0 48 A2 0C ... INCBIN "3-assembled-output/ELTD.bin" .elitee elitee = &39F7 39F7 8C E7 8D ... INCBIN "3-assembled-output/ELTE.bin" .elitef elitef = &445E 445E A5 1B 8D ... INCBIN "3-assembled-output/ELTF.bin" .eliteg eliteg = &4EFD 4EFD 20 7D 4E ... INCBIN "3-assembled-output/ELTG.bin" .checksum0 checksum0 = &5821 5821 20 .ships ships = &5822 5822 54 56 FC ... INCBIN "3-assembled-output/SHIPS.bin" .end P% = &61E8 S.ELTcode 1100 &61E8 &1128 &1128 Saving file '3-assembled-output/ELTcode.unprot.bin' Saving file '3-assembled-output/ELThead.bin' .TRTB% 0004 .ZP 0070 .P 0072 .Q 0073 .YY 0074 .T 0075 .SC 0076 .SCH 0077 .BLPTR 0078 .V219 007A 007C .K3 0080 .BLCNT 0081 .BLN 0083 .EXCN 0085 WORDS9 = &1100 1100 4C 32 24 ... INCBIN "3-assembled-output/WORDS9.bin" P.DIALS = &1500 1500 F0 80 87 ... INCBIN "1-source-files/images/P.DIALS.bin" PYTHON = &1C00 1C00 03 40 38 ... INCBIN "3-assembled-output/PYTHON.bin" P.ELITE = &1D00 1D00 00 00 00 ... INCBIN "1-source-files/images/P.ELITE.bin" P.A-SOFT = &1E00 1E00 00 00 00 ... INCBIN "1-source-files/images/P.A-SOFT.bin" P.(C)ASFT = &1F00 1F00 00 00 00 ... INCBIN "1-source-files/images/P.(C)ASFT.bin" .run 2000 4C C9 20 JMP &20C9 .B% 2003 16 2004 04 2005 1C 2006 02 2007 11 2008 0F 2009 10 200A 17 200B 00 200C 06 200D 1F 200E 00 200F 00 2010 00 2011 00 2012 00 2013 00 2014 17 2015 00 2016 0C 2017 0C 2018 00 2019 00 201A 00 201B 00 201C 00 201D 00 201E 17 201F 00 2020 0D 2021 00 2022 00 2023 00 2024 00 2025 00 2026 00 2027 00 2028 17 2029 00 202A 01 202B 20 202C 00 202D 00 202E 00 202F 00 2030 00 2031 00 2032 17 2033 00 2034 02 2035 2D 2036 00 2037 00 2038 00 2039 00 203A 00 203B 00 203C 17 203D 00 203E 0A 203F 20 2040 00 2041 00 2042 00 2043 00 2044 00 2045 00 .E% 2046 01 2047 01 2048 00 2049 6F 204A F8 204B 04 204C 01 204D 08 204E 08 204F FE 2050 00 2051 FF 2052 70 2053 2C 2054 02 2055 01 2056 0E 2057 EE 2058 FF 2059 2C 205A 20 205B 32 205C 06 205D 01 205E 00 205F FE 2060 78 2061 7E 2062 03 2063 01 2064 01 2065 FF 2066 FD 2067 11 2068 20 2069 80 206A 01 206B 00 206C 00 206D FF 206E 01 206F 01 2070 04 2071 01 2072 04 2073 F8 2074 2C 2075 04 2076 06 2077 08 2078 16 2079 00 207A 00 207B 81 207C 7E 207D 00 .swine 207E A9 7F LDA #&7F 2080 8D 4E FE STA &FE4E 2083 6C FC FF JMP (&FFFC) .OSB 2086 A0 00 LDY #&00 2088 4C F4 FF JMP &FFF4 208B 52 2E 45 ... 2096 0D 2097 42 79 20 ... 20A9 0D 20AA B0 .oscliv 20AB F7 FF .David9 20AD 68 22 20AF D8 CLD .David23 20B0 DF 01 .doPROT1 20B2 A0 DB LDY #&DB 20B4 84 04 STY &04 20B6 A0 EF LDY #&EF 20B8 84 05 STY &05 20BA A0 02 LDY #&02 20BC 84 7B STY &7B 20BE 9D 7D 20 STA &207D,X 20C1 A0 18 LDY #&18 20C3 94 7B STY &7B,X 20C5 60 RTS .MHCA 20C6 CA .David7 20C7 90 48 BCC &2111 .ENTRY 20C9 78 SEI 20CA D8 CLD 20CB A9 7F LDA #&7F 20CD 8D 4E FE STA &FE4E 20D0 8D 6E FE STA &FE6E 20D3 AD FC FF LDA &FFFC 20D6 8D 00 02 STA &0200 20D9 8D 02 02 STA &0202 20DC 8D 06 02 STA &0206 20DF 8D 20 02 STA &0220 20E2 AD FD FF LDA &FFFD 20E5 8D 01 02 STA &0201 20E8 8D 03 02 STA &0203 20EB 8D 07 02 STA &0207 20EE 8D 21 02 STA &0221 20F1 A2 2D LDX #&2D .purge 20F3 BD 02 02 LDA &0202,X 20F6 09 C0 ORA #&C0 20F8 9D 02 02 STA &0202,X 20FB CA DEX 20FC CA DEX 20FD 10 F4 BPL &20F3 20FF A9 60 LDA #&60 2101 8D 32 02 STA &0232 2104 A9 02 LDA #&02 2106 8D 25 02 STA &0225 2109 A9 32 LDA #&32 210B 8D 24 02 STA &0224 210E A9 20 LDA #&20 2110 2C .Ian1 2111 D0 66 BNE &2179 2113 8D 4B 22 STA &224B 2116 4A LSR A 2117 A2 03 LDX #&03 2119 86 79 STX &79 211B 86 84 STX &84 211D 86 86 STX &86 211F CA DEX 2120 20 F4 FF JSR &FFF4 2123 2C .FRED1 2124 D0 A1 BNE &20C7 2126 A2 FF LDX #&FF 2128 A9 48 LDA #&48 212A 20 B2 20 JSR &20B2 212D A9 90 LDA #&90 212F 20 86 20 JSR &2086 2132 A9 F7 LDA #&F7 2134 A2 00 LDX #&00 2136 20 86 20 JSR &2086 2139 A9 BE LDA #&BE 213B A2 08 LDX #&08 213D 20 86 20 JSR &2086 2140 2C .David8 2141 D0 E1 BNE &2124 2143 A9 8F LDA #&8F 2145 A2 0C LDX #&0C 2147 A0 FF LDY #&FF 2149 20 F4 FF JSR &FFF4 214C A9 0D LDA #&0D .abrk 214E A2 00 LDX #&00 2150 20 86 20 JSR &2086 2153 A9 E1 LDA #&E1 2155 A2 80 LDX #&80 2157 20 86 20 JSR &2086 215A A9 AC LDA #&AC 215C A2 00 LDX #&00 215E A0 FF LDY #&FF 2160 20 F4 FF JSR &FFF4 2163 86 04 STX &04 2165 84 05 STY &05 2167 A9 C8 LDA #&C8 2169 A2 03 LDX #&03 216B 20 86 20 JSR &2086 216E A9 0D LDA #&0D 2170 A2 02 LDX #&02 2172 20 86 20 JSR &2086 .OS01 2175 A2 FF LDX #&FF 2177 9A TXS 2178 E8 INX .David3 2179 BD 13 24 LDA &2413,X .PROT1 217C C8 INY 217D E8 INX 217E E0 21 CPX #&21 2180 D0 BF BNE &2141 2182 A9 03 LDA #&03 2184 85 70 STA &70 2186 A9 C8 LDA #&C8 2188 8D 7C 21 STA &217C 218B A9 20 LDA #&20 218D 85 71 STA &71 218F A0 00 LDY #&00 .LOOP 2191 B1 70 LDA (&70),Y 2193 20 EE FF JSR &FFEE 2196 C8 INY 2197 C0 43 CPY #&43 2199 D0 F6 BNE &2191 219B A9 01 LDA #&01 219D AA TAX 219E A8 TAY 219F 91 7A STA (&7A),Y 21A1 A9 04 LDA #&04 21A3 20 86 20 JSR &2086 21A6 A9 09 LDA #&09 21A8 A2 00 LDX #&00 21AA 20 86 20 JSR &2086 21AD A9 6C LDA #&6C 21AF 4D 61 22 EOR &2261 21B2 8D 61 22 STA &2261 Macro FNE: 21B5 A2 46 LDX #&46 21B7 A0 20 LDY #&20 21B9 A9 08 LDA #&08 21BB 20 F1 FF JSR &FFF1 End macro FNE Macro FNE: 21BE A2 54 LDX #&54 21C0 A0 20 LDY #&20 21C2 A9 08 LDA #&08 21C4 20 F1 FF JSR &FFF1 End macro FNE Macro FNE: 21C7 A2 62 LDX #&62 21C9 A0 20 LDY #&20 21CB A9 08 LDA #&08 21CD 20 F1 FF JSR &FFF1 End macro FNE Macro FNE: 21D0 A2 70 LDX #&70 21D2 A0 20 LDY #&20 21D4 A9 08 LDA #&08 21D6 20 F1 FF JSR &FFF1 End macro FNE 21D9 A2 04 LDX #&04 21DB 86 73 STX &73 21DD A9 11 LDA #&11 21DF 85 71 STA &71 21E1 A0 00 LDY #&00 21E3 A9 F1 LDA #&F1 21E5 81 76 STA (&76,X) 21E7 84 70 STY &70 21E9 84 72 STY &72 21EB 20 61 22 JSR &2261 21EE A2 01 LDX #&01 21F0 A9 1D LDA #&1D 21F2 85 71 STA &71 21F4 A9 63 LDA #&63 21F6 85 73 STA &73 21F8 A0 00 LDY #&00 21FA 20 61 22 JSR &2261 21FD A2 01 LDX #&01 21FF A9 1E LDA #&1E 2201 85 71 STA &71 2203 A9 61 LDA #&61 2205 85 73 STA &73 2207 A0 00 LDY #&00 2209 20 61 22 JSR &2261 220C A2 01 LDX #&01 220E A9 1F LDA #&1F 2210 85 71 STA &71 2212 A9 76 LDA #&76 2214 85 73 STA &73 2216 A0 00 LDY #&00 2218 20 61 22 JSR &2261 221B 20 A6 22 JSR &22A6 221E A2 08 LDX #&08 2220 A9 15 LDA #&15 2222 85 71 STA &71 2224 A9 78 LDA #&78 2226 85 73 STA &73 2228 A0 00 LDY #&00 222A 84 70 STY &70 222C 84 81 STY &81 222E 84 72 STY &72 2230 20 61 22 JSR &2261 2233 A2 02 LDX #&02 2235 A9 24 LDA #&24 2237 85 71 STA &71 2239 A9 34 LDA #&34 223B 85 70 STA &70 223D A9 0B LDA #&0B 223F 85 73 STA &73 2241 A0 00 LDY #&00 2243 84 72 STY &72 2245 20 61 22 JSR &2261 2248 8C 77 21 STY &2177 .David2 224B AC 224C D4 FF .LBLa 224E BD 40 0F LDA &0F40,X 2251 49 A5 EOR #&A5 2253 9D 40 0F STA &0F40,X 2256 CA DEX 2257 D0 F5 BNE &224E 2259 6C 0F 10 JMP (&100F) .swine2 225C 4C 7E 20 JMP &207E 225F FF 4C .crunchit 2261 00 BRK 2262 B0 20 .RAND 2264 49 53 78 6C .David5 2268 C8 INY 2269 C0 80 CPY #&80 226B D0 DE BNE &224B 226D 78 SEI 226E A9 C2 LDA #&C2 2270 8D 4E FE STA &FE4E 2273 A9 7F LDA #&7F 2275 8D 6E FE STA &FE6E 2278 AD 04 02 LDA &0204 227B 8D FE 7F STA &7FFE 227E AD 05 02 LDA &0205 2281 10 D9 BPL &225C 2283 8D FF 7F STA &7FFF 2286 A9 0C LDA #&0C 2288 8D 05 02 STA &0205 228B A9 4A LDA #&4A 228D 8D 04 02 STA &0204 2290 A9 38 LDA #&38 2292 8D 45 FE STA &FE45 2295 58 CLI 2296 A9 81 LDA #&81 2298 8D 4E FE STA &FE4E 229B A0 14 LDY #&14 229D 20 F4 FF JSR &FFF4 22A0 A9 01 LDA #&01 22A2 8D 4E FE STA &FE4E 22A5 60 RTS .PLL1 22A6 AD 44 FE LDA &FE44 22A9 8D 65 22 STA &2265 22AC 20 75 23 JSR &2375 22AF 20 90 23 JSR &2390 22B2 85 71 STA &71 22B4 A5 72 LDA &72 22B6 85 70 STA &70 22B8 20 75 23 JSR &2375 22BB 85 74 STA &74 22BD 20 90 23 JSR &2390 22C0 AA TAX 22C1 A5 72 LDA &72 22C3 65 70 ADC &70 22C5 85 70 STA &70 22C7 8A TXA 22C8 65 71 ADC &71 22CA B0 1F BCS &22EB 22CC 85 71 STA &71 22CE A9 01 LDA #&01 22D0 E5 70 SBC &70 22D2 85 70 STA &70 22D4 A9 40 LDA #&40 22D6 E5 71 SBC &71 22D8 85 71 STA &71 22DA 90 0F BCC &22EB 22DC 20 DC 23 JSR &23DC 22DF A5 70 LDA &70 22E1 4A LSR A 22E2 AA TAX 22E3 A5 74 LDA &74 22E5 C9 80 CMP #&80 22E7 6A ROR A 22E8 20 AD 23 JSR &23AD .PLC1 22EB CE D6 23 DEC &23D6 22EE D0 B6 BNE &22A6 22F0 CE D7 23 DEC &23D7 22F3 D0 B1 BNE &22A6 22F5 A2 C2 LDX #&C2 22F7 86 85 STX &85 .PLL2 22F9 20 75 23 JSR &2375 22FC AA TAX 22FD 20 90 23 JSR &2390 2300 85 71 STA &71 2302 20 75 23 JSR &2375 2305 85 74 STA &74 2307 20 90 23 JSR &2390 230A 65 71 ADC &71 230C C9 11 CMP #&11 230E 90 05 BCC &2315 2310 A5 74 LDA &74 2312 20 AD 23 JSR &23AD .PLC2 2315 CE D8 23 DEC &23D8 2318 D0 DF BNE &22F9 231A CE D9 23 DEC &23D9 231D D0 DA BNE &22F9 231F AE C6 20 LDX &20C6 2322 86 78 STX &78 2324 A2 C6 LDX #&C6 2326 86 83 STX &83 .PLL3 2328 20 75 23 JSR &2375 232B 85 70 STA &70 232D 20 90 23 JSR &2390 2330 85 71 STA &71 2332 20 75 23 JSR &2375 2335 85 74 STA &74 2337 20 90 23 JSR &2390 233A 85 75 STA &75 233C 65 71 ADC &71 233E 85 71 STA &71 2340 A5 70 LDA &70 2342 C9 80 CMP #&80 2344 6A ROR A 2345 C9 80 CMP #&80 2347 6A ROR A 2348 65 74 ADC &74 234A AA TAX 234B 20 90 23 JSR &2390 234E A8 TAY 234F 65 71 ADC &71 2351 B0 18 BCS &236B 2353 C9 50 CMP #&50 2355 B0 14 BCS &236B 2357 C9 20 CMP #&20 2359 90 10 BCC &236B 235B 98 TYA 235C 65 75 ADC &75 235E C9 10 CMP #&10 2360 B0 04 BCS &2366 2362 A5 70 LDA &70 2364 10 05 BPL &236B .PL1 2366 A5 74 LDA &74 2368 20 AD 23 JSR &23AD .PLC3 236B CE DA 23 DEC &23DA 236E D0 B8 BNE &2328 2370 CE DB 23 DEC &23DB 2373 D0 B3 BNE &2328 .DORND 2375 AD 65 22 LDA &2265 2378 AA TAX 2379 6D 67 22 ADC &2267 237C 8D 65 22 STA &2265 237F 8E 67 22 STX &2267 2382 AD 64 22 LDA &2264 2385 AA TAX 2386 6D 66 22 ADC &2266 2389 8D 64 22 STA &2264 238C 8E 66 22 STX &2266 238F 60 RTS .SQUA2 2390 10 05 BPL &2397 2392 49 FF EOR #&FF 2394 18 CLC 2395 69 01 ADC #&01 .SQUA 2397 85 73 STA &73 2399 85 72 STA &72 239B A9 00 LDA #&00 239D A0 08 LDY #&08 239F 46 72 LSR &72 .SQL1 23A1 90 03 BCC &23A6 23A3 18 CLC 23A4 65 73 ADC &73 .SQ1 23A6 6A ROR A 23A7 66 72 ROR &72 23A9 88 DEY 23AA D0 F5 BNE &23A1 23AC 60 RTS .PIX 23AD A8 TAY 23AE 49 80 EOR #&80 23B0 4A LSR A 23B1 4A LSR A 23B2 4A LSR A 23B3 09 60 ORA #&60 23B5 85 71 STA &71 23B7 8A TXA 23B8 49 80 EOR #&80 23BA 29 F8 AND #&F8 23BC 85 70 STA &70 23BE 98 TYA 23BF 29 07 AND #&07 23C1 A8 TAY 23C2 8A TXA 23C3 29 07 AND #&07 23C5 AA TAX 23C6 BD CE 23 LDA &23CE,X 23C9 11 70 ORA (&70),Y 23CB 91 70 STA (&70),Y 23CD 60 RTS .TWOS 23CE 80 23CF 40 23D0 20 23D1 10 23D2 08 23D3 04 23D4 02 23D5 01 .CNT 23D6 00 05 .CNT2 23D8 DD 01 .CNT3 23DA 00 05 .ROOT 23DC A4 71 LDY &71 23DE A5 70 LDA &70 23E0 85 73 STA &73 23E2 A2 00 LDX #&00 23E4 86 70 STX &70 23E6 A9 08 LDA #&08 23E8 85 72 STA &72 .LL6 23EA E4 70 CPX &70 23EC 90 0E BCC &23FC 23EE D0 04 BNE &23F4 23F0 C0 40 CPY #&40 23F2 90 08 BCC &23FC .LL8 23F4 98 TYA 23F5 E9 40 SBC #&40 23F7 A8 TAY 23F8 8A TXA 23F9 E5 70 SBC &70 23FB AA TAX .LL7 23FC 26 70 ROL &70 23FE 06 73 ASL &73 2400 98 TYA 2401 2A ROL A 2402 A8 TAY 2403 8A TXA 2404 2A ROL A 2405 AA TAX 2406 06 73 ASL &73 2408 98 TYA 2409 2A ROL A 240A A8 TAY 240B 8A TXA 240C 2A ROL A 240D AA TAX 240E C6 72 DEC &72 2410 D0 D8 BNE &23EA 2412 60 RTS .BEGIN% 2413 20 2414 AD 2415 6C 2416 0B 2417 AD 2418 99 2419 0B 241A AD 241B 59 241C 48 PHA 241D 0C 241E 7C 241F B9 2420 68 PLA 2421 68 PLA .DOMOVE 2422 60 RTS 2423 EF D0 2425 CA DEX 2426 71 2427 E6 73 INC &73 2429 E6 242A F6 D0 242C 88 DEY 242D 72 242E 91 242F 20 2430 86 2431 59 2432 70 2433 B1 .UU% .CHECKbyt 0B00 00 BRK .MAINSUM 0B01 CB 0B02 00 .FOOLV 0B03 A4 0B .CHECKV 0B05 01 11 .block1 0B07 F5 0B08 E5 0B09 B5 0B0A A5 0B0B 76 0B0C 66 0B0D 36 0B0E 26 0B0F D4 0B10 C4 0B11 94 0B12 84 .block2 0B13 D0 0B14 C0 0B15 B0 0B16 A0 0B17 F0 0B18 E0 0B19 90 0B1A 80 0B1B 77 0B1C 67 0B1D 37 0B1E 27 .TT26 0B1F 85 80 STA &80 0B21 98 TYA 0B22 48 PHA 0B23 8A TXA 0B24 48 PHA .rr 0B25 A5 80 LDA &80 0B27 C9 07 CMP #&07 0B29 F0 7A BEQ &0BA5 0B2B C9 20 CMP #&20 0B2D B0 0E BCS &0B3D 0B2F C9 0D CMP #&0D 0B31 F0 03 BEQ &0B36 0B33 EE FD 0C INC &0CFD .RRX1 0B36 A2 07 LDX #&07 0B38 8E FC 0C STX &0CFC 0B3B D0 61 BNE &0B9E .RR1 0B3D A2 BF LDX #&BF 0B3F 0A ASL A 0B40 0A ASL A 0B41 90 02 BCC &0B45 0B43 A2 C1 LDX #&C1 0B45 0A ASL A 0B46 90 01 BCC &0B49 0B48 E8 INX 0B49 85 72 STA &72 0B4B 86 73 STX &73 0B4D AD FC 0C LDA &0CFC 0B50 C9 14 CMP #&14 0B52 90 08 BCC &0B5C 0B54 A9 07 LDA #&07 0B56 8D FC 0C STA &0CFC 0B59 EE FD 0C INC &0CFD .NOLF 0B5C 0A ASL A 0B5D 0A ASL A 0B5E 0A ASL A 0B5F 85 70 STA &70 0B61 EE FC 0C INC &0CFC 0B64 AD FD 0C LDA &0CFD 0B67 C9 13 CMP #&13 0B69 90 26 BCC &0B91 0B6B A9 07 LDA #&07 0B6D 8D FC 0C STA &0CFC 0B70 A9 65 LDA #&65 0B72 85 77 STA &77 0B74 A0 38 LDY #&38 0B76 A2 0E LDX #&0E 0B78 84 76 STY &76 0B7A A9 00 LDA #&00 0B7C A8 TAY .David1 0B7D 91 76 STA (&76),Y 0B7F C8 INY 0B80 C0 70 CPY #&70 0B82 90 F9 BCC &0B7D 0B84 A8 TAY 0B85 E6 77 INC &77 0B87 CA DEX 0B88 10 F3 BPL &0B7D 0B8A A9 05 LDA #&05 0B8C 8D FD 0C STA &0CFD 0B8F D0 94 BNE &0B25 .RR3 0B91 09 60 ORA #&60 0B93 85 71 STA &71 0B95 A0 07 LDY #&07 .RRL1 0B97 B1 72 LDA (&72),Y 0B99 91 70 STA (&70),Y 0B9B 88 DEY 0B9C 10 F9 BPL &0B97 .RR4 0B9E 68 PLA 0B9F AA TAX 0BA0 68 PLA 0BA1 A8 TAY 0BA2 A5 80 LDA &80 .FOOL 0BA4 60 RTS .R5 0BA5 A9 07 LDA #&07 0BA7 20 AD 0B JSR &0BAD 0BAA 4C 9E 0B JMP &0B9E .TUT .osprint 0BAD 6C 34 02 JMP (&0234) 0BB0 6C .command 0BB1 6C AB 20 JMP (&20AB) .MESS1 0BB4 4C 2E 45 ... 0BC2 0D .ENTRY2 0BC3 AD 0E 02 LDA &020E 0BC6 8D 34 02 STA &0234 0BC9 A9 1F LDA #&1F 0BCB 8D 0E 02 STA &020E 0BCE A2 B4 LDX #&B4 0BD0 AD 0F 02 LDA &020F 0BD3 8D 35 02 STA &0235 0BD6 A9 0B LDA #&0B 0BD8 A0 0B LDY #&0B 0BDA 8D 0F 02 STA &020F 0BDD 20 31 0C JSR &0C31 0BE0 20 B1 0B JSR &0BB1 0BE3 20 B4 01 JSR &01B4 0BE6 20 31 0C JSR &0C31 0BE9 A9 8C LDA #&8C 0BEB A2 0C LDX #&0C 0BED 20 F4 FF JSR &FFF4 0BF0 A9 00 LDA #&00 0BF2 8D FD 7F STA &7FFD 0BF5 A2 50 LDX #&50 0BF7 A9 28 LDA #&28 0BF9 85 70 STA &70 0BFB A9 11 LDA #&11 0BFD 85 71 STA &71 0BFF A9 40 LDA #&40 0C01 85 72 STA &72 0C03 A9 0F LDA #&0F 0C05 85 73 STA &73 0C07 A0 00 LDY #&00 .ML1 0C09 98 TYA 0C0A 51 70 EOR (&70),Y 0C0C 91 72 STA (&72),Y 0C0E C8 INY 0C0F D0 F8 BNE &0C09 0C11 E6 71 INC &71 0C13 E6 73 INC &73 0C15 CA DEX 0C16 10 F1 BPL &0C09 0C18 AD 46 0F LDA &0F46 0C1B 8D 02 02 STA &0202 0C1E AD 47 0F LDA &0F47 0C21 8D 03 02 STA &0203 0C24 AD 42 0F LDA &0F42 0C27 8D 0E 02 STA &020E 0C2A AD 43 0F LDA &0F43 0C2D 8D 0F 02 STA &020F 0C30 60 RTS .AFOOL 0C31 6C 03 0B JMP (&0B03) .M2 0C34 02 .VIA2 0C35 A9 04 LDA #&04 0C37 8D 20 FE STA &FE20 0C3A A0 0B LDY #&0B .inlp1 0C3C B9 07 0B LDA &0B07,Y 0C3F 8D 21 FE STA &FE21 0C42 88 DEY 0C43 10 F7 BPL &0C3C 0C45 68 PLA 0C46 A8 TAY 0C47 6C FE 7F JMP (&7FFE) .IRQ1 0C4A 98 TYA 0C4B 48 PHA 0C4C AD 4D FE LDA &FE4D 0C4F 2C 34 0C BIT &0C34 0C52 D0 09 BNE &0C5D 0C54 29 40 AND #&40 0C56 D0 DD BNE &0C35 0C58 68 PLA 0C59 A8 TAY 0C5A 6C FE 7F JMP (&7FFE) .LINSCN 0C5D A9 32 LDA #&32 0C5F 8D 44 FE STA &FE44 0C62 A9 38 LDA #&38 0C64 8D 45 FE STA &FE45 0C67 A9 08 LDA #&08 0C69 8D 20 FE STA &FE20 0C6C A0 0B LDY #&0B .inlp2 0C6E B9 13 0B LDA &0B13,Y 0C71 8D 21 FE STA &FE21 0C74 88 DEY 0C75 10 F7 BPL &0C6E 0C77 68 PLA 0C78 A8 TAY 0C79 6C FE 7F JMP (&7FFE) .BLOCK 0C7C C2 0B 0C7E 62 01 0C80 AD 44 FE LDA &FE44 0C83 85 01 STA &01 0C85 78 SEI 0C86 A9 39 LDA #&39 0C88 8D 4E FE STA &FE4E 0C8B AD 44 0F LDA &0F44 0C8E 8D 04 02 STA &0204 0C91 AD 45 0F LDA &0F45 0C94 8D 05 02 STA &0205 0C97 A9 38 LDA #&38 0C99 8D 45 FE STA &FE45 0C9C 58 CLI 0C9D A0 00 LDY #&00 0C9F A9 C8 LDA #&C8 0CA1 A2 03 LDX #&03 0CA3 20 F4 FF JSR &FFF4 .BLAST 0CA6 A9 0F LDA #&0F 0CA8 85 71 STA &71 0CAA A9 40 LDA #&40 0CAC 85 70 STA &70 0CAE A2 45 LDX #&45 0CB0 A0 00 LDY #&00 0CB2 98 TYA .CHK 0CB3 18 CLC 0CB4 71 70 ADC (&70),Y 0CB6 C8 INY 0CB7 D0 FA BNE &0CB3 0CB9 E6 71 INC &71 0CBB CA DEX 0CBC 10 F5 BPL &0CB3 0CBE CD 39 56 CMP &5639 0CC1 F0 0B BEQ &0CCE .nononono 0CC3 8D 41 0F STA &0F41 0CC6 A9 7F LDA #&7F 0CC8 8D 4E FE STA &FE4E 0CCB 6C FC FF JMP (&FFFC) .itsOK 0CCE 6C 40 0F JMP (&0F40) .CHECKER 0CD1 A0 00 LDY #&00 0CD3 A2 04 LDX #&04 0CD5 86 71 STX &71 0CD7 84 70 STY &70 0CD9 98 TYA .CHKq 0CDA 18 CLC 0CDB 71 70 ADC (&70),Y 0CDD C8 INY 0CDE D0 FA BNE &0CDA 0CE0 E6 71 INC &71 0CE2 CA DEX 0CE3 D0 F5 BNE &0CDA 0CE5 CD 02 0B CMP &0B02 0CE8 D0 D9 BNE &0CC3 0CEA 98 TYA .CHKb 0CEB 18 CLC 0CEC 79 00 11 ADC &1100,Y 0CEF C8 INY 0CF0 C0 28 CPY #&28 0CF2 D0 F7 BNE &0CEB 0CF4 CD 01 0B CMP &0B01 0CF7 D0 CA BNE &0CC3 0CF9 6C 05 0B JMP (&0B05) .ENDBLOCK .XC 0CFC 07 .YC 0CFD 06 Addresses for the scramble routines in elite-checksum.py BLOCK_offset = &14B0 ENDBLOCK_offset = &1530 MAINSUM_offset = &1335 TUT_offset = &13E1 CHECKbyt_offset = &1334 CODE_offset = &F86 UU% = &2434 Q% = &1934 OSB = &2086 Memory usage: &B00 - &CFE Stack: 161 S. ELITE &1100 &2632 &2000 &1100 Saving file '3-assembled-output/ELITE.unprot.bin' .readme 0000 0A 0001 0D 0002 2D 2D 2D ... 0029 0A 002A 0D 002B 41 63 6F ... 003A 0A 003B 0D 003C 0A 003D 0D 003E 56 65 72 ... 0059 0A 005A 0D 005B 56 61 72 ... 007D 0A 007E 0D 007F 50 72 6F ... 0097 0A 0098 0D 0099 0A 009A 0D 009B 53 65 65 ... 00BB 0A 00BC 0D 00BD 2D 2D 2D ... 00E4 0A 00E5 0D Saving file '3-assembled-output/README.txt' ================================================ FILE: 4-reference-binaries/README.md ================================================ # Reference binaries for the BBC Micro cassette version of Elite This folder contains the binaries from the original sources for the BBC Micro cassette version of Elite on Ian Bell's personal website, as well as reference binaries for the other releases. * [source-disc](source-disc) contains the binaries from the source disc on Ian Bell's personal website * [sth](sth) contains the binaries from the Stairway to Hell version * [sth-for-tape](sth-for-tape) contains the binaries from the Stairway to Hell version when built for tape (i.e. with disc=no) * [text-sources](text-sources) contains the binaries from the text version of the source code on Ian Bell's personal website --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: 5-compiled-game-discs/README.md ================================================ # Compiled game discs for the BBC Micro cassette version of Elite This folder contains the SSD disc images for the BBC Micro cassette version of Elite, as produced by the build process. There is one SSD file for each supported release. These SSD images can be loaded into an emulator like JSBeeb or BeebEm, or into a real BBC Micro using a device like a Gotek. It also contains UEF tape images that will work with emulators and the TZXDuino (though you may need to unzip them before they will work with the latter). --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: Makefile ================================================ BEEBASM?=beebasm PYTHON?=python PHP?=php # A make command with no arguments will build the source disc variant with # encrypted binaries, checksums enabled, the standard commander and crc32 # verification of the game binaries # # Optional arguments for the make command are: # # variant= Build the specified variant: # # source-disc (default) # text-sources # sth # # disc=no Build a version to load from cassette rather than disc # # protect=no Disable block-level tape protection code (disc=no only) # # commander=max Start with a maxed-out commander # # encrypt=no Disable encryption and checksum routines # # verify=no Disable crc32 verification of the game binaries # # So, for example: # # make variant=text-sources commander=max encrypt=no verify=no # # will build an unencrypted text sources variant with a maxed-out commander # and no crc32 verification # # The following variables are written into elite-build-options.asm depending on # the above arguments, so they can be passed to BeebAsm: # # _VERSION # 1 = BBC Micro cassette # # _VARIANT # 1 = Source disc # 2 = Text sources # 3 = Stairway to Hell (default) # # _MAX_COMMANDER # TRUE = Maxed-out commander # FALSE = Standard commander # # _REMOVE_CHECKSUMS # TRUE = Disable checksum routines # FALSE = Enable checksum routines # # _MATCH_ORIGINAL_BINARIES # TRUE = Match binaries to released version (i.e. fill workspaces with noise) # FALSE = Zero-fill workspaces # # _DISC # TRUE = Build for loading from disc # FALSE = Build for loading from cassette # # _PROT # TRUE = Apply block-level tape protection # FALSE = Do not apply block-level tape protection # # The encrypt and verify arguments are passed to the elite-checksum.py and # crc32.py scripts, rather than BeebAsm ifeq ($(commander), max) max-commander=TRUE else max-commander=FALSE endif ifeq ($(encrypt), no) unencrypt=-u remove-checksums=TRUE else unencrypt= remove-checksums=FALSE endif ifeq ($(match), no) match-original-binaries=FALSE else match-original-binaries=TRUE endif ifeq ($(protect), no) protect-tape= prot=FALSE else protect-tape=-p prot=TRUE endif ifeq ($(disc), no) tape-or-disc=-t build-for-disc=FALSE else tape-or-disc= build-for-disc=TRUE protect-tape= prot=FALSE endif ifeq ($(variant), text-sources) variant-number=2 folder=text-sources suffix=-from-text-sources else ifeq ($(variant), source-disc) variant-number=1 folder=source-disc suffix=-from-source-disc else variant-number=3 suffix=-sth ifeq ($(disc), no) folder=sth-for-tape else folder=sth endif endif .PHONY:all all: echo _VERSION=1 > 1-source-files/main-sources/elite-build-options.asm echo _VARIANT=$(variant-number) >> 1-source-files/main-sources/elite-build-options.asm echo _REMOVE_CHECKSUMS=$(remove-checksums) >> 1-source-files/main-sources/elite-build-options.asm echo _MAX_COMMANDER=$(max-commander) >> 1-source-files/main-sources/elite-build-options.asm echo _DISC=$(build-for-disc) >> 1-source-files/main-sources/elite-build-options.asm echo _PROT=$(prot) >> 1-source-files/main-sources/elite-build-options.asm $(BEEBASM) -i 1-source-files/main-sources/elite-source.asm -v > 3-assembled-output/compile.txt $(BEEBASM) -i 1-source-files/main-sources/elite-bcfs.asm -v >> 3-assembled-output/compile.txt $(BEEBASM) -i 1-source-files/main-sources/elite-loader.asm -v >> 3-assembled-output/compile.txt $(BEEBASM) -i 1-source-files/main-sources/elite-readme.asm -v >> 3-assembled-output/compile.txt $(PYTHON) 2-build-files/elite-checksum.py $(unencrypt) $(tape-or-disc) $(protect-tape) -rel$(variant-number) $(BEEBASM) -i 1-source-files/main-sources/elite-disc.asm -do 5-compiled-game-discs/elite-cassette$(suffix).ssd -opt 3 -title "E L I T E" ifneq ($(verify), no) @$(PYTHON) 2-build-files/crc32.py 4-reference-binaries/$(folder) 3-assembled-output endif .PHONY:b2 b2: curl -G "http://localhost:48075/reset/b2" curl -H "Content-Type:application/binary" --upload-file "5-compiled-game-discs/elite-cassette$(suffix).ssd" "http://localhost:48075/run/b2?name=elite-cassette$(suffix).ssd" .PHONY:uef uef: all $(PHP) 2-build-files/mktibet-0.3.php +t temp.tbt +n ELITE +d FFFF0E00 +x FFFF8023 1-source-files/basic-programs/$$.ELITE-cassette.bin +n ELITEdata +d FFFF0E00 +x FFFF1D00 3-assembled-output/ELITE.bin +n ELITEcode +d 00000E00 +x 00000132 3-assembled-output/ELTcode.bin +n README +d FFFFFFFF +x FFFFFFFF 3-assembled-output/README.txt php 2-build-files/tibetuef-0.8.php +nz temp.tbt 5-compiled-game-discs/elite-cassette$(suffix).uef rm temp.tbt ================================================ FILE: README.md ================================================ # Fully documented source code for the cassette version of Elite on the BBC Micro
Links to my other software archaeology repositories
**Elite sources:** [BBC Micro (cassette)](https://github.com/markmoxon/elite-source-code-bbc-micro-cassette) | [BBC Micro (disc)](https://github.com/markmoxon/elite-source-code-bbc-micro-disc) | [Elite Demonstration Disc](https://github.com/markmoxon/elite-demo-source-code-bbc-micro) | [Acorn Electron](https://github.com/markmoxon/elite-source-code-acorn-electron) | [6502 Second Processor](https://github.com/markmoxon/elite-source-code-6502-second-processor) | [Commodore 64](https://github.com/markmoxon/elite-source-code-commodore-64) | [Apple II](https://github.com/markmoxon/elite-source-code-apple-ii) | [BBC Master](https://github.com/markmoxon/elite-source-code-bbc-master) | [NES](https://github.com/markmoxon/elite-source-code-nes) **Elite hacks:** [Elite-A](https://github.com/markmoxon/elite-a-source-code-bbc-micro) | [Teletext Elite](https://github.com/markmoxon/teletext-elite) | [Elite Universe Editor](https://github.com/markmoxon/elite-universe-editor) | [Flicker-free Commodore 64 Elite](https://github.com/markmoxon/c64-elite-flicker-free) | [Elite over Econet](https://github.com/markmoxon/elite-over-econet) | [!EliteNet](https://github.com/markmoxon/elite-over-econet-acorn-archimedes) **Elite Compendium:** [BBC Master](https://github.com/markmoxon/elite-compendium-bbc-master) | [BBC Micro](https://github.com/markmoxon/elite-compendium-bbc-micro) | [BBC Micro B+](https://github.com/markmoxon/elite-compendium-bbc-micro-b-plus) | [Acorn Electron](https://github.com/markmoxon/elite-compendium-acorn-electron) **Other sources:** [Aviator (BBC Micro)](https://github.com/markmoxon/aviator-source-code-bbc-micro) | [Revs (BBC Micro)](https://github.com/markmoxon/revs-source-code-bbc-micro) | [The Sentinel (BBC Micro)](https://github.com/markmoxon/the-sentinel-source-code-bbc-micro) | [Lander (Acorn Archimedes)](https://github.com/markmoxon/lander-source-code-acorn-archimedes) See [my profile](https://github.com/markmoxon) for more repositories to explore.
![Screenshot of Elite on the BBC Micro](https://elite.bbcelite.com/images/github/Elite-BBCMicro.png) This repository contains the original source code for the cassette version of Ian Bell and David Braben's classic game Elite on the BBC Micro, with every single line documented and (for the most part) explained. It is literally the original source code, just heavily commented. It is a companion to the [elite.bbcelite.com website](https://elite.bbcelite.com). See the [introduction](#introduction) for more information, or jump straight into the [documented source code](1-source-files/main-sources). ## Contents * [Introduction](#introduction) * [Acknowledgements](#acknowledgements) * [A note on licences, copyright etc.](#user-content-a-note-on-licences-copyright-etc) * [Browsing the source in an IDE](#browsing-the-source-in-an-ide) * [Folder structure](#folder-structure) * [Flicker-free Elite](#flicker-free-elite) * [Elite Compendium](#elite-compendium) * [Building BBC Micro cassette Elite from the source](#building-bbc-micro-cassette-elite-from-the-source) * [Requirements](#requirements) * [Windows](#windows) * [Mac and Linux](#mac-and-linux) * [Build options](#build-options) * [Updating the checksum scripts if you change the code](#updating-the-checksum-scripts-if-you-change-the-code) * [Verifying the output](#verifying-the-output) * [Log files](#log-files) * [Auto-deploying to the b2 emulator](#auto-deploying-to-the-b2-emulator) * [Building a UEF tape image](#building-a-uef-tape-image) * [Building different variants of the cassette version of Elite](#building-different-variants-of-the-cassette-version-of-elite) * [Building the Stairway to Hell variant](#building-the-stairway-to-hell-variant) * [Building the source disc variant](#building-the-source-disc-variant) * [Building the text sources variant](#building-the-text-sources-variant) * [Differences between the variants](#differences-between-the-variants) * [Notes on the original source files](#notes-on-the-original-source-files) * [Fixing a bug in the source disc](#fixing-a-bug-in-the-source-disc) ## Introduction This repository contains the original source code for the cassette version of Elite on the BBC Micro, with every single line documented and (for the most part) explained. You can build the fully functioning game from this source. [Three variants](#building-different-variants-of-the-cassette-version-of-elite) are currently supported: the tape version from the Stairway to Hell archive, the version produced by the original source discs from Ian Bell's personal website, and the version built from the text sources from the same site. This repository is a companion to the [elite.bbcelite.com website](https://elite.bbcelite.com), which contains all the code from this repository, but laid out in a much more human-friendly fashion. The links at the top of this page will take you to repositories for the other versions of Elite that are covered by this project. * If you want to browse the source and read about how Elite works under the hood, you will probably find [the website](https://elite.bbcelite.com) a better place to start than this repository. * If you would rather explore the source code in your favourite IDE, then the [annotated source](1-source-files/main-sources) is what you're looking for. It contains the exact same content as the website, so you won't be missing out (the website is generated from the source files, so they are guaranteed to be identical). You might also like to read the section on [browsing the source in an IDE](#browsing-the-source-in-an-ide) for some tips. * If you want to build BBC Micro cassette Elite from the source on a modern computer, to produce a working game disc that can be loaded into a BBC Micro or an emulator, then you want the section on [building BBC Micro cassette Elite from the source](#building-bbc-micro-cassette-elite-from-the-source). My hope is that this repository and the [accompanying website](https://elite.bbcelite.com) will be useful for those who want to learn more about Elite and what makes it tick. It is provided on an educational and non-profit basis, with the aim of helping people appreciate one of the most iconic games of the 8-bit era. ## Acknowledgements BBC Micro Elite was written by Ian Bell and David Braben and is copyright © Acornsoft 1984. The code on this site is identical to the source discs released on [Ian Bell's personal website](http://www.elitehomepage.org/) (it's just been reformatted to be more readable). The commentary is copyright © Mark Moxon. Any misunderstandings or mistakes in the documentation are entirely my fault. Huge thanks are due to the original authors for not only creating such an important piece of my childhood, but also for releasing the source code for us to play with; to Paul Brink for his annotated disassembly; and to Kieran Connell for his [BeebAsm version](https://github.com/kieranhj/elite-beebasm), which I forked as the original basis for this project. You can find more information about this project in the [accompanying website's project page](https://elite.bbcelite.com/about_site/about_this_project.html). Thank you to Diminished for the UEF scripts, which are part of the [Quadbike 2](https://stardot.org.uk/forums/viewtopic.php?t=26669) tape transcriber. The following archives from Ian Bell's personal website form the basis for this project: * [BBC Micro cassette Elite sources as a disc image](http://www.elitehomepage.org/archive/a/a4080602.zip) * [BBC Micro cassette Elite sources as text files](http://www.elitehomepage.org/archive/a/a4080610.zip) ### A note on licences, copyright etc. This repository is _not_ provided with a licence, and there is intentionally no `LICENSE` file provided. According to [GitHub's licensing documentation](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/licensing-a-repository), this means that "the default copyright laws apply, meaning that you retain all rights to your source code and no one may reproduce, distribute, or create derivative works from your work". The reason for this is that my commentary is intertwined with the original source code for Elite, and the original source code is copyright. The whole site is therefore covered by default copyright law, to ensure that this copyright is respected. Under GitHub's rules, you have the right to read and fork this repository... but that's it. No other use is permitted, I'm afraid. My hope is that the educational and non-profit intentions of this repository will enable it to stay hosted and available, but the original copyright holders do have the right to ask for it to be taken down, in which case I will comply without hesitation. I do hope, though, that along with the various other disassemblies and commentaries of this source, it will remain viable. ## Browsing the source in an IDE If you want to browse the source in an IDE, you might find the following useful. * The most interesting files are in the [main-sources](1-source-files/main-sources) folder: * The main game's source code is in the [elite-source.asm](1-source-files/main-sources/elite-source.asm) file - this is the motherlode and probably contains all the stuff you're interested in. * The game's loader is in the [elite-loader.asm](1-source-files/main-sources/elite-loader.asm) file - this is mainly concerned with setup and copy protection. * It's probably worth skimming through the [notes on terminology and notations](https://elite.bbcelite.com/terminology/) on the accompanying website, as this explains a number of terms used in the commentary, without which it might be a bit tricky to follow at times (in particular, you should understand the terminology I use for multi-byte numbers). * The accompanying website contains [a number of "deep dive" articles](https://elite.bbcelite.com/deep_dives/), each of which goes into an aspect of the game in detail. Routines that are explained further in these articles are tagged with the label `Deep dive:` and the relevant article name. * There are loads of routines and variables in Elite - literally hundreds. You can find them in the source files by searching for the following: `Type: Subroutine`, `Type: Variable`, `Type: Workspace` and `Type: Macro`. * If you know the name of a routine, you can find it by searching for `Name: `, as in `Name: SCAN` (for the 3D scanner routine) or `Name: LL9` (for the ship-drawing routine). * The entry point for the [main game code](1-source-files/main-sources/elite-source.asm) is routine `TT170`, which you can find by searching for `Name: TT170`. If you want to follow the program flow all the way from the title screen around the main game loop, then you can find a number of [deep dives on program flow](https://elite.bbcelite.com/deep_dives/) on the accompanying website. * The source code is designed to be read at an 80-column width and with a monospaced font, just like in the good old days. I hope you enjoy exploring the inner workings of BBC Elite as much as I have. ## Folder structure There are five main folders in this repository, which reflect the order of the build process. * [1-source-files](1-source-files) contains all the different source files, such as the main assembler source files, image binaries, fonts, boot files and so on. * [2-build-files](2-build-files) contains build-related scripts, such as the checksum, encryption and crc32 verification scripts. * [3-assembled-output](3-assembled-output) contains the output from the assembly process, when the source files are assembled and the results processed by the build files. * [4-reference-binaries](4-reference-binaries) contains the correct binaries for each variant, so we can verify that our assembled output matches the reference. * [5-compiled-game-discs](5-compiled-game-discs) contains the final output of the build process: an SSD disc image that contains the compiled game and which can be run on real hardware or in an emulator. ## Flicker-free Elite This repository also includes a flicker-free version, which incorporates the backported flicker-free ship-drawing routines from the BBC Master. The flicker-free code is in a separate branch called `flicker-free`, and apart from the code differences for reducing flicker, this branch is identical to the main branch and the same build process applies. The annotated source files in the `flicker-free` branch contain both the original Acornsoft code and all of the modifications for flicker-free Elite, so you can look through the source to see exactly what's changed. Any code that I've removed from the original version is commented out in the source files, so when they are assembled they produce the flicker-free binaries, while still containing details of all the modifications. You can find all the diffs by searching the sources for `Mod:`. For more information on flicker-free Elite, see the [hacks section of the accompanying website](https://elite.bbcelite.com/hacks/flicker-free_elite.html). ## Elite Compendium This repository also includes a version of BBC Micro cassette Elite for the Elite Compendium, which incorporates all the available hacks in one game. The Compendium version is in a separate branch called `elite-compendium`, which is included in the [Elite Compendium (BBC Micro)](https://github.com/markmoxon/elite-compendium-bbc-micro) repository as a submodule. The annotated source files in the `elite-compendium` branch contain both the original Acornsoft code and all of the modifications for the Elite Compendium, so you can look through the source to see exactly what's changed. Any code that I've removed from the original version is commented out in the source files, so when they are assembled they produce the Compendium binaries, while still containing details of all the modifications. You can find all the diffs by searching the sources for `Mod:`. For more information on the Elite Compendium, see the [hacks section of the accompanying website](https://elite.bbcelite.com/hacks/elite_compendium.html). ## Building BBC Micro cassette Elite from the source Builds are supported for both Windows and Mac/Linux systems. In all cases the build process is defined in the `Makefile` provided. ### Requirements You will need the following to build BBC Micro cassette Elite from the source: * BeebAsm, which can be downloaded from the [BeebAsm repository](https://github.com/stardot/beebasm). Mac and Linux users will have to build their own executable with `make code`, while Windows users can just download the `beebasm.exe` file. * Python. The build process has only been tested on 3.x, but 2.7 might work. * Mac and Linux users may need to install `make` if it isn't already present (for Windows users, `make.exe` is included in this repository). For details of how the build process works, see the [build documentation on bbcelite.com](https://elite.bbcelite.com/about_site/building_elite.html). Let's look at how to build BBC Micro cassette Elite from the source. ### Windows For Windows users, there is a batch file called `make.bat` which you can use to build the game. Before this will work, you should edit the batch file and change the values of the `BEEBASM` and `PYTHON` variables to point to the locations of your `beebasm.exe` and `python.exe` executables. You also need to change directory to the repository folder (i.e. the same folder as `make.bat`). All being well, entering the following into a command window: ``` make.bat ``` will produce a file called `elite-cassette-sth.ssd` in the `5-compiled-game-discs` folder that contains the source disc variant, which you can then load into an emulator, or into a real BBC Micro using a device like a Gotek. ### Mac and Linux The build process uses a standard GNU `Makefile`, so you just need to install `make` if your system doesn't already have it. If BeebAsm or Python are not on your path, then you can either fix this, or you can edit the `Makefile` and change the `BEEBASM` and `PYTHON` variables in the first two lines to point to their locations. You also need to change directory to the repository folder (i.e. the same folder as `Makefile`). All being well, entering the following into a terminal window: ``` make ``` will produce a file called `elite-cassette-sth.ssd` in the `5-compiled-game-discs` folder that contains the source disc variant, which you can then load into an emulator, or into a real BBC Micro using a device like a Gotek. ### Build options By default the build process will create a typical Elite game disc with a standard commander and verified binaries. There are various arguments you can pass to the build to change how it works. They are: * `variant=` - Build the specified variant: * `variant=sth` (default) * `variant=source-disc` * `variant=text-sources` * `disc=no` - Build a version to load from cassette rather than disc (the default is to build a version that loads from disc) * `protect=no` - When building for cassette with `disc=no`, the loader contains block-level tape protection code, which you can disable with this argument (the protection only works if you save the ELITEcode file to tape with corrupted block data, so if you want to create a UEF without re-implementing the Acornsoft protection system, you should use this argument) * `commander=max` - Start with a maxed-out commander (specifically, this is the test commander file from the original source, which is almost but not quite maxed-out) * `encrypt=no` - Disable encryption and checksum routines * `verify=no` - Disable crc32 verification of the game binaries So, for example: `make variant=text-sources commander=max encrypt=no match=no verify=no` will build an unencrypted text sources variant with a maxed-out commander, no workspace noise and no crc32 verification. The unencrypted version should be more useful for anyone who wants to make modifications to the game code. As this argument produces unencrypted files, the binaries produced will be quite different to the binaries on the original source disc, which are encrypted. See below for more on the verification process. ### Updating the checksum scripts if you change the code If you change the source code in any way, you may break the game; if so, it will typically hang at the loading screen, though in some versions it may hang when launching from the space station. To fix this, you may need to update some of the hard-coded addresses in the checksum script so that they match the new addresses in your changed version of the code. See the comments in the [elite-checksum.py](2-build-files/elite-checksum.py) script for details. ### Verifying the output The default build process prints out checksums of all the generated files, along with the checksums of the files from the original sources. You can disable verification by passing `verify=no` to the build. The Python script `crc32.py` in the `2-build-files` folder does the actual verification, and shows the checksums and file sizes of both sets of files, alongside each other, and with a Match column that flags any discrepancies. If you are building an unencrypted set of files then there will be lots of differences, while the encrypted files should mostly match (see the Differences section below for more on this). The binaries in the `4-reference-binaries` folder were taken straight from the [cassette sources disc image](http://www.elitehomepage.org/archive/a/a4080602.zip), while those in the `3-assembled-output` folder are produced by the build process. For example, if you don't make any changes to the code and build the project with `make`, then this is the output of the verification process: ``` Results for variant: sth [--originals--] [---output----] Checksum Size Checksum Size Match Filename ----------------------------------------------------------- a88ca82b 5426 a88ca82b 5426 Yes ELITE.bin f40816ec 5426 f40816ec 5426 Yes ELITE.unprot.bin b17f9589 2228 b17f9589 2228 Yes ELTA.bin 82de44f7 2600 82de44f7 2600 Yes ELTB.bin f005a7bf 2732 f005a7bf 2732 Yes ELTC.bin ac3476d9 2887 ac3476d9 2887 Yes ELTD.bin 3084f112 2663 3084f112 2663 Yes ELTE.bin e46bac22 2719 e46bac22 2719 Yes ELTF.bin b4ac917d 2340 b4ac917d 2340 Yes ELTG.bin b1bf493e 20712 b1bf493e 20712 Yes ELTcode.bin 33de34f5 20712 33de34f5 20712 Yes ELTcode.unprot.bin 00d5bb7a 40 00d5bb7a 40 Yes ELThead.bin 99529ca8 256 99529ca8 256 Yes PYTHON.bin 49ee043c 2502 49ee043c 2502 Yes SHIPS.bin c4547e5e 1023 c4547e5e 1023 Yes WORDS9.bin ``` All the compiled binaries match the originals, so we know we are producing the same final game as the Stairway to Hell variant. ### Log files During compilation, details of every step are output in a file called `compile.txt` in the `3-assembled-output` folder. If you have problems, it might come in handy, and it's a great reference if you need to know the addresses of labels and variables for debugging (or just snooping around). ### Auto-deploying to the b2 emulator For users of the excellent [b2 emulator](https://github.com/tom-seddon/b2), you can include the build parameter `b2` to automatically load and boot the assembled disc image in b2. The b2 emulator must be running for this to work. For example, to build, verify and load the game into b2, you can do this on Windows: ``` make.bat all b2 ``` or this on Mac/Linux: ``` make all b2 ``` If you omit the `all` target then b2 will start up with the results of the last successful build. Note that you should manually choose the correct platform in b2 (I intentionally haven't automated this part to make it easier to test across multiple platforms). ### Building a UEF tape image Despite this being the cassette version of BBC Micro Elite, this repository only builds disc images by default, as that's how BeebAsm works. If you want the authentic experience of loading Elite from cassette, then you can build a UEF with the following command on Windows: ``` make.bat uef disc=no protect=no ``` or this on Mac/Linux: ``` make uef disc=no protect=no ``` You should now be able to load Elite from your UEF on a BBC Micro, by entering `CHAIN "ELITE"`. These UEF tape images will work with emulators and the TZXDuino (though you may need to unzip them before they will work with the latter). For this to work, you will need PHP installed, and you should edit the `Makefile` (and `make.bat` on Windows) to point to PHP (specifically, you'll need to point the `PHP` variable to point to the locations of your `php` or `php.exe` binary). Note that in order for your UEF to work, you need to include the `disc=no` and `protect=no` arguments to the build (as above). This ensures that the binaries are built to load at the correct address for tape systems, and it also disables the block-level tape protection system, as this only works with specially created tape images, like the ones that Acornsoft originally released. ## Building different variants of the cassette version of Elite This repository contains the source code for three different variants of the cassette version of Elite: * The variant from the Stairway to Hell archive * The variant produced by the original source discs from Ian Bell's personal website * The variant built from the text sources from the same site By default the build process builds the Stairway to Hell variant, but you can build a specified variant using the `variant=` build parameter. ### Building the Stairway to Hell variant You can add `variant=source-disc` to produce the `elite-cassette-from-source-disc.ssd` file containing the source disc variant, though that's the default value so it isn't necessary. In other words, you can build it like this: ``` make.bat variant=sth ``` or this on a Mac or Linux: ``` make variant=sth ``` This will produce a file called `elite-cassette-sth.ssd` in the `5-compiled-game-discs` folder that contains the Stairway to Hell variant. The verification checksums for this version are as follows: ``` Results for variant: sth [--originals--] [---output----] Checksum Size Checksum Size Match Filename ----------------------------------------------------------- a88ca82b 5426 a88ca82b 5426 Yes ELITE.bin f40816ec 5426 f40816ec 5426 Yes ELITE.unprot.bin b17f9589 2228 b17f9589 2228 Yes ELTA.bin 82de44f7 2600 82de44f7 2600 Yes ELTB.bin f005a7bf 2732 f005a7bf 2732 Yes ELTC.bin ac3476d9 2887 ac3476d9 2887 Yes ELTD.bin 3084f112 2663 3084f112 2663 Yes ELTE.bin e46bac22 2719 e46bac22 2719 Yes ELTF.bin b4ac917d 2340 b4ac917d 2340 Yes ELTG.bin b1bf493e 20712 b1bf493e 20712 Yes ELTcode.bin 33de34f5 20712 33de34f5 20712 Yes ELTcode.unprot.bin 00d5bb7a 40 00d5bb7a 40 Yes ELThead.bin 99529ca8 256 99529ca8 256 Yes PYTHON.bin 49ee043c 2502 49ee043c 2502 Yes SHIPS.bin c4547e5e 1023 c4547e5e 1023 Yes WORDS9.bin ``` Note that if you add the `disc=no` build parameter, then the build will produce binaries that are designed to be loaded from cassette rather than disc. The verification step will compare the results to the exact binaries from the UEF from the Stairway to Hell archive. These binaries have block-level tape protection enabled by default, so they will not match. You can override the block-level protection with `protect=no`. ### Building the source disc variant You can build the source disc variant by appending `variant=source-disc` to the `make` command, like this on Windows: ``` make.bat variant=source-disc ``` or this on a Mac or Linux: ``` make variant=source-disc ``` This will produce a file called `elite-cassette-from-source-disc.ssd` in the `5-compiled-game-discs` folder that contains the source disc variant. The verification checksums for this version are as follows: ``` Results for variant: source-disc [--originals--] [---output----] Checksum Size Checksum Size Match Filename ----------------------------------------------------------- a88ca82b 5426 a88ca82b 5426 Yes ELITE.bin f40816ec 5426 f40816ec 5426 Yes ELITE.unprot.bin 0f1ad255 2228 0f1ad255 2228 Yes ELTA.bin e725760a 2600 e725760a 2600 Yes ELTB.bin 97e338e8 2735 97e338e8 2735 Yes ELTC.bin 322b174c 2882 322b174c 2882 Yes ELTD.bin 29f7b8cb 2663 29f7b8cb 2663 Yes ELTE.bin 8a4cecc2 2721 8a4cecc2 2721 Yes ELTF.bin 7a6a5d1a 2340 7a6a5d1a 2340 Yes ELTG.bin 01a00dce 20712 01a00dce 20712 Yes ELTcode.bin 1e4466ec 20712 1e4466ec 20712 Yes ELTcode.unprot.bin 00d5bb7a 40 00d5bb7a 40 Yes ELThead.bin 99529ca8 256 99529ca8 256 Yes PYTHON.bin 49ee043c 2502 49ee043c 2502 Yes SHIPS.bin c4547e5e 1023 c4547e5e 1023 Yes WORDS9.bin ``` ### Building the text sources variant You can build the text sources variant by appending `variant=text-sources` to the `make` command, like this on Windows: ``` make.bat variant=text-sources ``` or this on a Mac or Linux: ``` make variant=text-sources ``` This will produce a file called `elite-cassette-from-text-sources.ssd` in the `5-compiled-game-discs` folder that contains the Ian Bell disc variant. The verification checksums for this version are as follows: ``` Results for variant: text-sources [--originals--] [---output----] Checksum Size Checksum Size Match Filename ----------------------------------------------------------- 093c73aa 5426 093c73aa 5426 Yes ELITE.bin 24da3246 5426 24da3246 5426 Yes ELITE.unprot.bin 6c109c76 2228 6c109c76 2228 Yes ELTA.bin cd8bee0c 2600 cd8bee0c 2600 Yes ELTB.bin 20c22628 2732 20c22628 2732 Yes ELTC.bin 23c13c71 2885 23c13c71 2885 Yes ELTD.bin ce0d9ec7 2663 ce0d9ec7 2663 Yes ELTE.bin 5aed3c61 2719 5aed3c61 2719 Yes ELTF.bin 13f3eace 2340 13f3eace 2340 Yes ELTG.bin 8b79fe39 20710 8b79fe39 20710 Yes ELTcode.bin 7c24aab0 20712 7c24aab0 20712 Yes ELTcode.unprot.bin 00d5bb7a 40 00d5bb7a 40 Yes ELThead.bin 99529ca8 256 99529ca8 256 Yes PYTHON.bin 8f4b6f2b 2502 8f4b6f2b 2502 Yes SHIPS.bin c4547e5e 1023 c4547e5e 1023 Yes WORDS9.bin ``` ### Differences between the variants You can see the differences between the variants by searching the source code for `_STH_CASSETTE` (for features in the Stairway to Hell variant), `_SOURCE_DISC` (for features in the source disc variant) or `_TEXT_SOURCES` (for features in the text sources variant). There are only minor differences: * The text sources contain an extra call in the galactic hyperspace routine that sets the current system to the nearest system to the crosshairs, in an attempt to fix a bug in the original source disc variant (though it doesn't quite fix it properly). * The Stairway to Hell variant contains the extra call in the galactic hyperspace routine, but in a different place, and it also zeroes the distance to the current system in QQ8. This fixes the galactic hyperspace bug properly, and this full bug fix is present in all other versions of the game. * In order to fit in this extra call, the text sources and Stairway to Hell variants also contain modifications to create space for the call. * There is a small change in the TTX66 routine to reset LAS2 to 0 instead of LASCT to stop laser pulsing, as this is slightly more efficient. See the [accompanying website](https://elite.bbcelite.com/cassette/releases.html) for a comprehensive list of differences between the variants. ## Notes on the original source files ### Fixing a bug in the source disc It also turns out there are two versions of the `ELITEB` BASIC source program on the [cassette sources disc image](http://www.elitehomepage.org/archive/a/a4080602.zip), one called `$.ELITEB` and another called `O.ELITEB`. These two versions of `ELITEB` differ by just one byte in the default commander data. This byte controls whether or not the commander has a rear pulse laser. In `O.ELITEB` this byte is generated by: ``` EQUB (POW + 128) AND Q% ``` while in `$.ELITEB`, this byte is generated by: ``` EQUB POW ``` The BASIC variable `Q%` is a Boolean flag that, if `TRUE`, will create a default commander with lots of cash and equipment, which is useful for testing. You can see this in action if you build an unencrypted binary with `make build`, as the unencrypted build sets `Q%` to `TRUE` for this build target. The BASIC variable `POW` has a value of 15, which is the power of a pulse laser. `POW + 128`, meanwhile, is the power of a beam laser. Given the above, we can see that `O.ELITEB` correctly produces a default commander with no a rear laser if `Q%` is `FALSE`, but adds a rear beam laser if `Q%` is `TRUE`. This matches the default commander from the released game, and produces the `ELTcode` executable on the same disc. The version of `ELITEB` in the [cassette sources as text files](http://www.elitehomepage.org/archive/a/a4080610.zip) matches this version, `O.ELITEB`. In contrast, `$.ELITEB` will always produce a default commander with a rear pulse laser, irrespective of the setting of `Q%`, so it doesn't match the released version. The `ELTB` binary file in the `4-reference-binaries` folder of this repository matches the version generated by the source disc, so we can easily tell whether any changes we've made to the code deviate from this version. However, the `ELTB` binary file on the sources disc matches the version produced by `$.ELITEB`, rather than the version produced by `O.ELITEB` - in other words, `ELTB` on the source disc is not the version generated by the source code on the same disc. The implication is that the `ELTB` binary file on the [cassette sources disc image](http://www.elitehomepage.org/archive/a/a4080602.zip) was produced by `$.ELITEB`, while the `ELTcode` file (the released game) used `O.ELITEB`. Perhaps the released game was compiled, and then someone backed up the `ELITEB` source to `O.ELITEB`, edited the `$.ELITEB` to have a rear pulse laser, and then generated a new `ELTB` binary file. Who knows? Unfortunately, files on DFS discs don't have timestamps, so it's hard to tell. --- Right on, Commanders! _Mark Moxon_ ================================================ FILE: make.bat ================================================ @echo off SETLOCAL SET BEEBASM=C:\Users\user\bin\beebasm.exe SET PYTHON=C:\Users\user\AppData\Local\Microsoft\WindowsApps\python.exe 2-build-files\make %*