Skip to navigation


Elite J source

[Apple II version]

ELITE J FILE Produces the binary file ELTJ.bin that gets loaded by elite-bcfs.asm.
CODE_J% = P% LOAD_J% = LOAD% + P% - CODE%
Name: comnam [Show more] Type: Variable Category: Save and load Summary: Storage for the commander filename, padded out with spaces to a fixed size of 30 characters, for the rfile and wfile routines
Context: See this variable on its own page References: This variable is used as follows: * COPYNAME uses comnam * rentry uses comnam * wfile uses comnam
.comnam EQUS "COMMANDER "
Name: rfile [Show more] Type: Subroutine Category: Save and load Summary: Read a commander file from a DOS disk into the buffer
Context: See this subroutine on its own page References: This subroutine is called as follows: * LOD calls rfile * wfile calls via rfile3

For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list.
Returns: C flag The result of the read: * Clear = file found and loaded into the comfil buffer * Set = file not found, in which case A = 5, which we can pass to the diskerror routine to print a "File not found" error buffer Contains the commander file
Other entry points: rfile3 Contains an RTS
.rfile TSX ; Store the stack pointer in stkptr so we can restore it STX stkptr ; if there's a disk error JSR findf ; Search the disk catalog for a file with the filename ; in comnam LDA #5 ; If no file is found with this name then findf will BCS rfile3 ; set the C flag, so jump to rfile3 to return from the ; subroutine with the C flag set and A = 5, to indicate ; that the file cannot be found JSR gettsl ; Get the track/sector list of the file and populate the ; track and sector variables with the track and sector ; of the file's contents, to pass to the call to rsect JSR rsect ; Read the first sector of the file's data into the ; buffer (this contains the whole commander file, as it ; fits into one sector) LDY #0 ; We now copy the loaded file into the comfil buffer, ; so set a byte counter in Y .rfile2 LDA buffer+4,Y ; Copy the Y-th byte from the disk buffer at buffer+4 STA comfil,Y ; to the Y-th byte of the comfil buffer INY ; Increment the byte counter CPY #comsiz ; Loop back until we have copied the whole file (which BNE rfile2 ; contains comsiz bytes) CLC ; Clear the C flag to indicate that the file was found ; and loaded .rfile3 RTS ; Return from the subroutine
Name: wfile [Show more] Type: Subroutine Category: Save and load Summary: Write a commander file from the buffer to a DOS disk
Context: See this subroutine on its own page References: This subroutine is called as follows: * SVE calls wfile

For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list.
Arguments: buffer Contains the commander file
Returns: C flag The result of the write: * Clear = file written * Set = file not written, with the error number in A, which we can pass to the diskerror routine to print the error message: * A = 2 = Disk full * A = 3 = Catalog full
.wfile JSR MUTILATE ; Encrypt the commander file in the buffer at comfil TSX ; Store the stack pointer in stkptr so we can restore it STX stkptr ; if there's a disk error JSR findf ; Search the disk catalog for a file with the filename ; in comnam BCC oldfil ; If a file is found with this name then findf will ; return with the C flag clear, so jump to oldfil if ; this is the case so we overwrite the existing file .newfil ; If we get here then this file does not already exist ; on the disk, so we need to save a new one JSR isfull ; Check the disk to ensure there are least two free ; sectors, returning one sector for the commander file's ; track/sector list and another sector for the commander ; file's contents LDA #2 ; If there are not enough free sectors on the disk then BCS rfile3 ; isfull will set the C flag, so jump to rfile3 to ; return from the subroutine with the C flag set and ; A = 2, to indicate that the disk is full JSR finde ; Search the disk catalog for an empty file entry that ; we can use for the new file, loading the catalog ; sector into the buffer and setting Y to the offset of ; the start of the empty file entry (if there is one) LDA #3 ; If there is no empty file entry in the disk catalog BCS rfile3 ; then finde will set the C flag, so jump to rfile3 to ; return from the subroutine with the C flag set and ; A = 3, to indicate that the catalog is full ; We have two free sectors and there is room in the disk ; catalog for a new file, so we can now write the file ; ; We do this in three stages: ; ; * Add the new file to the disk catalog ; ; * Write the track/sector list for the new file ; ; * Write the file contents (which all fits into one ; sector) ; ; We start by adding the new file to the disk catalog, ; which involves populating the empty entry in the VTOC ; and adding a file entry for this file to the catalog ; sector ; ; The call to finde loaded the VTOC into the disk buffer ; at buffer, and the empty file entry is at offset Y, so ; that's what we need to populate LDA tsltrk ; Copy the track field from the track/sector list into STA buffer,Y ; the file entry at byte #0 LDA tslsct ; Copy the sector field from the track/sector list into STA buffer+1,Y ; the file entry at byte #1 LDA #4 ; Set the file type to 4, for a BINARY file, at byte #2 STA buffer+2,Y ; in the file entry LDA #2 ; Set the sector count to 2, stored as a 16-bit value STA buffer+$21,Y ; in bytes ($22 $21) of the file entry LDA #0 STA buffer+$22,Y TAX ; We now copy the filename from comnam to byte #3 in ; the file entry for this file, so set X = 0 to use as a ; byte counter .newfl2 LDA comnam,X ; Copy the X-th character from the filename into the ORA #$80 ; file entry, starting at byte #3 (which is where the STA buffer+3,Y ; filename is stored in the entry) INY ; Increment the offset index in Y to point to the next ; byte in the file entry INX ; Increment the byte counter in X to point to the next ; character in the filename CPX #30 ; Loop back to copy the next character until we have BNE newfl2 ; copied all 30 characters in the filename JSR wsect ; Write the updated catalog sector to the disk JSR isfull ; Check the disk to ensure there are least two free ; sectors, returning one sector for the commander file's ; track/sector list and another sector for the commander ; file's contents ; ; We do this so the VTOC gets loaded and updated once ; again (as we corrupted it above when updating the ; catalog sector), and because isfull doesn't write the ; updated VTOC to disk, we do that now JSR wsect ; Write the updated VTOC sector to the disk .newfl3 ; Next we create the track/sector list for the new file LDA #0 ; First we zero the buffer so we can use it to build the ; track/sector list, so set A = 0 to use as a reset ; value TAY ; Set Y = 0 to use as a byte counter .newfl4 STA buffer,Y ; Zero the Y-th byte in the buffer INY ; Increment the byte counter BNE newfl4 ; Loop back until we have zeroed all 256 bytes LDA filtrk ; Set byte #12 of the track/sector list to the track STA buffer+12 ; number for the file contents, which the call to isfull ; put into filtrk LDA filsct ; Set byte #13 of the track/sector list to the sector STA buffer+13 ; number for the file contents, which the call to isfull ; put into filsct LDA tsltrk ; Set the track variable to the track number of the STA track ; track/sector list, which the call to isfull put into ; tsltrk, so we can pass this to the wsect routine LDA tslsct ; Set the sector variable to the sector number of the STA sector ; track/sector list, which the call to isfull put into ; tslsct, so we can pass this to the wsect routine JSR wsect ; Write the contents of the buffer to the specified ; track and sector, to write the track/sector list for ; the commander file to disk ; And finally we write the file contents LDA filtrk ; Set the track variable to the track number of the STA track ; file contents, which the call to isfull put into ; filtrk, so we can pass this to the wsect routine LDA filsct ; Set the sector variable to the sector number of the STA sector ; file contents, which the call to isfull put into ; filsct, so we can pass this to the wsect routine BPL oldfl2 ; Jump to oldfl2 to write the file contents to the disk ; using the track and sector we just specified (this BPL ; if effectively a JMP as the sector number in A is ; always less than 128) .oldfil ; If we get here then this file already exists on the ; disk, so we need to overwrite it with the new file JSR gettsl ; Get the track/sector list of the file and populate the ; track and sector variables with the track and sector ; of the file's contents, to pass to the call to wsect .oldfl2 LDY #0 ; We first copy the commander file we want to save from ; the comfil buffer to the disk buffer, so set a byte ; counter in Y .oldfl3 LDA comfil,Y ; Copy the Y-th byte from the commander file at comfil STA buffer+4,Y ; to the Y-th byte of the disk buffer at buffer+4 INY ; Increment the byte counter CPY #comsiz ; Loop back until we have copied the whole file (which BNE oldfl3 ; contains comsiz bytes) JMP wsect ; Write the first sector of the commander file, which ; will write the whole file as it fits into one sector, ; and return from the subroutine using a tail call
Name: findf [Show more] Type: Subroutine Category: Save and load Summary: Search the disk catalog for an existing file
Context: See this subroutine on its own page References: This subroutine is called as follows: * rfile calls findf * wfile calls findf

Returns: C flag The result of the search: * Clear = file found * Set = file not found
.findf CLC ; Clear the C flag to pass to rentry to indicate that we ; should search the disk catalog for an existing file BCC rentry ; Jump to rentry to find the file (this BCC is ; effectively a JMP as we just cleared the C flag
Name: finde [Show more] Type: Subroutine Category: Save and load Summary: Search the disk catalog for an empty file entry
Context: See this subroutine on its own page References: This subroutine is called as follows: * wfile calls finde

Returns: C flag The result of the search: * Clear = empty entry found * Set = no empty entry found (i.e. catalog is full)
.finde SEC ; Set the C flag to pass to rentry to indicate that we ; should search the disk catalog for an empty file entry ; Fall through into rentry to perform the search
Name: rentry [Show more] Type: Subroutine Category: Save and load Summary: Search the disk catalog for an existing file or an empty file entry
Context: See this subroutine on its own page References: This subroutine is called as follows: * findf calls rentry

For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list.
Arguments: C flag The type of search: * Clear = search the catalog for an existing file * Set = search the catalog for an empty file entry
Returns: C flag The result of the search: * Clear = file/entry found * Set = file/entry not found Y The offset to the file entry in the catalog sector
.rentry ROR atemp0 ; Store the C flag in bit 7 of atemp0, so we can check ; it later JSR rvtoc ; Read the VTOC sector into the buffer ; We now work through the catalog sectors to look for ; the existing file entry (if bit 7 of atemp0 is clear) ; or an empty file empty (if bit 7 of atemp0 is set) .rentr2 LDA buffer+1 ; Set track to the track number of the next catalog STA track ; sector from byte #1 of the VTOC LDA buffer+2 ; Set sector to the sector number of the next catalog STA sector ; sector from byte #2 of the VTOC JSR rsect ; Read the catalog sector into the buffer LDY #$B ; Set Y to use as an index to the first file entry in ; the catalog sector (as the file entries start at ; offset $B in the catalog, with each entry taking up ; 35 bytes) .rentr3 LDA buffer,Y ; Set A to the first byte from the file entry, which ; will either be the track number of the file, or 0 to ; indicate an empty file entry, or $FF to indicate a ; deleted file BIT atemp0 ; If bit 7 of atemp0 is clear then we are searching the BPL rentr4 ; catalog for an existing file entry, so jump to rentr4 ; to do this ; If we get here then we are searching for an empty file ; entry TAX ; If A = 0 then we have just found an empty file entry, BEQ rentr6 ; so jump to rentr6 to return from the subroutine with a ; successful result CMP #$FF ; If A = $FF then we have just found a deleted file BEQ rentr6 ; entry, so jump to rentr6 to return from the subroutine ; with a successful result BNE rentr8 ; This file entry doesn't match our requirements, so ; jump to rentr8 to try the next file entry in this ; catalog sector .rentr4 ; If we get here then we are searching for an existing ; file entry TAX ; If A = 0 then we have just found an empty file entry, BEQ rentr9 ; which means we have not found a match for our file, so ; jump to rentr9 to return from the subroutine with the ; C flag set to indicate that we can't find the file CMP #$FF ; If A = $FF then we have just found a deleted file BEQ rentr8 ; entry, which is not a match for our file, so jump to ; rentr8 to try the next file entry in this catalog ; sector TYA ; Store the file entry index in Y on the stack, so we PHA ; can retrieve it after the following loop ; We now check the file entry to see if it matches the ; filename in comnam LDX #0 ; Set X = 0 to use as a character index for the filename ; in the file entry .rentr5 LDA buffer+3,Y ; Set A to the Y-th character from the filename in the AND #%01111111 ; file entry we are checking (the filename in a file ; entry starts at byte #3) CMP comnam,X ; If the character does not match the X-th character of BNE rentr7 ; comnam then the names don't match, to jump to rentr7 ; to try the next file entry in this catalog sector INY ; Increment the character index for the file entry INX ; Increment the character index for the filename we are ; searching for CPX #30 ; Loop back until we have checked all 30 characters BNE rentr5 ; If we get here then all 30 characters of the filename ; in the file entry match the filename in comnam, so we ; have found the file entry we are looking for PLA ; Set Y to the file entry index that we stored on the TAY ; stack above, so it once again points to the entry we ; are checking .rentr6 CLC ; Clear the C flag to indicate that we have found the ; file entry we are looking for RTS ; Return from the subroutine .rentr7 PLA ; Set Y to the file entry index that we stored on the TAY ; stack above, so it once again points to the entry we ; are checking .rentr8 TYA ; Set Y = Y + 35 CLC ; ADC #35 ; Each file entry in the catalog consists of 35 bytes, TAY ; so this increments Y to point to the next entry BNE rentr3 ; Loop back until we have reached the last file entry LDA buffer+1 ; Set track to the track number of the next catalog ; sector from byte #1 of the VTOC BNE rentr2 ; If the next catalog sector is non-zero then loop back ; to load and search this sector ; Otherwise we have searched every catalog sector and we ; haven't found what we're looking for, so fall through ; into rentr9 to return from the subroutine with the C ; flag set to indicate that the catalog is full .rentr9 SEC ; Clear the C flag to indicate that we have not found ; the file entry we are looking for RTS ; Return from the subroutine
Name: getsct [Show more] Type: Subroutine Category: Save and load Summary: Analyse the VTOC sector to allocate one free sector
Context: See this subroutine on its own page References: This subroutine is called as follows: * isfull calls getsct

For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list.
Arguments: buffer The VTOC sector for this disk
Returns: C flag The result of the check: * Clear = free sector found * Set = no free sectors found (i.e. the disk is full) X The track number containing the free sector Y The free sector number
.getsct LDA #0 ; Set ztemp0 = 0 to denote that we are starting this STA ztemp0 ; search in the outer half of the disk from track 16 ; down to track 0 BEQ getsc4 ; Jump into the loop below at getsc4 with A = 0, so we ; start the search at the last track number that we ; checked, which is in fretrk .getsc3 LDA dirtrk ; Set A to the direction we are moving in our search for ; a free sector (-1 or +1) .getsc4 CLC ; Add the direction in A to the last allocated track so ADC fretrk ; we move in the direction in A ; ; Or, if we just started searching with A = 0, we check ; the last allocated track, as it might not have been ; used last time and might still be free ; ; In either case, A now contains the next track to check ; for a free sector BEQ getsc5 ; If we have reached track 0, jump to getsc5 CMP tracks ; If A is less than the number of tracks on the disc BCC getsc7 ; then we haven't reached the highest numbered track ; yet, so jump to getsc7 to check this track for a free ; sector LDA #$FF ; Otherwise we have reached the highest numbered track, ; so set A = -1 so we start searching from track 16 down ; to track 0 BNE getsc6 ; Jump to getsc6 to set the direction to -1 and start ; searching from track 16 down to track 0 (this BNE is ; effectively a JMP as A is always non-zero) .getsc5 LDA ztemp0 ; If ztemp0 is non-zero then we have already searched BNE getscB ; the disk from track 18 up to track 34, and we jumped ; here when we finished searching track 16 down to track ; 0, so we have searched the whole disk and haven't ; found a free sector, so jump to getscB to return from ; the subroutine with a disk full error LDA #1 ; Otherwise we have not already searched from track 18 ; up to track 34, so set A = +1 so we start searching ; from track 18 up to track 34 STA ztemp0 ; Set ztemp0 = 1 to record that we are now searching the ; half of the disk track 18 up to track 34 .getsc6 STA dirtrk ; Set the search direction to A, so it's now -1 or +1 CLC ; Set A = A + 17, so A is now the track next to the VTOC ADC #17 ; track in the direction we want to search (the VTOC is ; always in track 17) ; ; So this is the track to start searching from, heading ; in the new direction in dirtrk .getsc7 STA fretrk ; Store the number of the track we are checking for a ; free sector in fretrk ; We now search the bitmap of free sectors for the track ; in A, which is part of the VTOC and is therefore in ; buffer ; ; The bitmaps for each track are stored at byte $38 (for ; track 0) onwards, with four bitmap bytes per track, ; though only the first two bytes contain bitmap data ; ; The bitmap variable points to byte #56 ($38) of the ; buffer where we loaded the VTOC, so it points to the ; first bitmap for track 0 ASL A ; Set Y = A * 4 ASL A ; TAY ; So we can use Y as an index into the bitmap of free ; sectors in the buffer, so the bitmap for track Y is ; at bitmap + Y LDX #16 ; Set X = 16 to denote that we are searching the first ; byte of the bitmap LDA bitmap,Y ; Set A to the first byte of the bitmap for the track ; we are checking BNE getsc8 ; If A is non-zero then there is a non-zero bit in the ; bitmap, which indicates a free sector, so jump to ; getsc8 to convert this into a sector number INY ; Increment Y to point to the next byte in the bitmap ; of free sectors LDX #8 ; Set X = 8 to denote that we are searching the second ; byte of the bitmap LDA bitmap,Y ; Set A to the second byte of the bitmap for the track ; we are checking BEQ getsc3 ; If A is zero then every sector is occupied in the ; bitmap, so loop back getsc3 to move on to the next ; track, as there are no free sectors in this one .getsc8 ; If we get here then we have found a free sector in ; the bitmap for this track, so we need to convert this ; into a sector number ; ; We do this by looping through the bitmap byte in A ; until we find a set bit to indicate a free sector STX ztemp0 ; Store X in ztemp0, so it is 16 if we found a free ; sector in the first bitmap byte, or 8 if we found a ; free sector in the second bitmap byte ; ; So ztemp0 is the sector number that corresponds to ; bit 7 in the relevant byte, as the first byte covers ; sectors 8 to 15 (bit 0 to 7), and the second byte ; covers sectors 0 to 7 (bit 0 to 7) LDX #0 ; Set a counter in X to keep track of the position of ; the bit we are currently checking .getsc9 INX ; Increment the bit position in X DEC ztemp0 ; Decrement the sector number in ztemp0 ROL A ; Set the C flag to the next bit from the bitmap byte BCC getsc9 ; Loop back to getsc9 until we shift a 1 out of the ; bitmap byte, which indicates a free sector ; We now change this 1 to a 0 and shift all the other ; bits in the bitmap back to their original positions CLC ; Clear the C flag so the first rotation in the ; following loop will replace the 1 we just found with a ; 0, to indicate that it is no longer free .getscA ROR A ; Rotate the bits back into A again DEX ; Decrement the position counter in X BNE getscA ; Loop back until we have rotated all the bits back into ; the bitmap, with the 1 changed to a 0 STA bitmap,Y ; update VTOC LDX fretrk ; Set X to the track number where we found the free ; sector, which we stored in fretrk, so we can return it ; from the subroutine LDY ztemp0 ; Set X to the number of the free sector in ztemp0, so ; we can return it from the subroutine CLC ; Clear the C flag to indicate that we have successfully ; found a free sector RTS ; Return from the subroutine .getscB SEC ; Clear the C flag to indicate that we have not found ; a free sector and the disk is full RTS ; Return from the subroutine
Name: isfull [Show more] Type: Subroutine Category: Save and load Summary: Check the disk to ensure there are least two free sectors, one for the file's track/sector list and one for the file's contents
Context: See this subroutine on its own page References: This subroutine is called as follows: * wfile calls isfull

For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list.
Returns: C flag The result of the check: * Clear = two free sectors found * Set = no free sectors found (i.e. the disk is full) tsltrk The track for the file's track/sector list tslsct The sector for the file's track/sector list filtrk The track for the file's contents filsct The sector for the file's contents
.isfull JSR rvtoc ; Read the VTOC sector into the buffer JSR getsct ; Allocate a free sector in the VTOL, that we can use ; for the track/sector list, and return the track number ; in X and the sector number in Y BCS isful2 ; If we the call to getsct couldn't find a free sector, ; then it will have set the C flag, so jump to isful2 to ; return this from the subroutine to indicate that the ; catalog is full STX tsltrk ; Store the track number containing the free sector in ; tsltrk STY tslsct ; Store the free sector number in tslsct JSR getsct ; Allocate a free sector in the VTOL, that we can use ; for the file contents, and return the track number ; in X and the sector number in Y ; ; If there is not enough space, this will set the C ; flag, which we will return from the subroutine to ; indicate that the catalog is full STX filtrk ; Store the track number containing the free sector in ; filtrk STY filsct ; Store the free sector number in filsct .isful2 RTS ; Return from the subroutine
Name: gettsl [Show more] Type: Subroutine Category: Save and load Summary: Read a file's track/sector list
Context: See this subroutine on its own page References: This subroutine is called as follows: * rfile calls gettsl * wfile calls gettsl

For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list.
Arguments: buffer The catalog sector for this file Y The offset within the catalog sector for the relevant file entry
Returns: buffer The track/sector list for the file track The track number of the file's data sector The sector number of the file's data
.gettsl LDA buffer,Y ; Set track to the track containing the track/sector STA track ; list LDA buffer+1,Y ; Set sector to the sector containing the track/sector STA sector ; list JSR rsect ; Read the track/sector list into the buffer LDY #$C ; Set Y to offset $C, so it points to the track and ; sector of first data sector in the track/sector list ; we just loaded LDA buffer,Y ; Set track to the track containing the file data STA track LDA buffer+1,Y ; Set sector to the sector containing the file data STA sector RTS ; Return from the subroutine
Name: rvtoc [Show more] Type: Subroutine Category: Save and load Summary: Read the VTOC sector into the buffer
Context: See this subroutine on its own page References: This subroutine is called as follows: * isfull calls rvtoc * rentry calls rvtoc

For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list.
Returns: buffer Contains the VTOC sector
.rvtoc LDA #17 ; Set the track number to 17, which is where the VTOC is STA track ; stored on the disk LDA #0 ; Set the sector number to 0, which is where the VTOC is STA sector ; stored on the disk ; Fall through into rsect to read sector 0 in track 17, ; so we read the VTOC sector from the disk into the ; buffer
Name: rsect [Show more] Type: Subroutine Category: Save and load Summary: Read a specific sector from disk into the buffer
Context: See this subroutine on its own page References: This subroutine is called as follows: * gettsl calls rsect * rentry calls rsect * rfile calls rsect

Arguments: track The track number sector The sector number
Returns: buffer Contains the sector
.rsect CLC ; Clear the C flag to denote that this is a read ; operation (this value will be read throughout the ; RWTS code that follows) BCC wsect2 ; Jump to wsect2 to read the specified sector
Name: wsect [Show more] Type: Subroutine Category: Save and load Summary: Write a specific sector from the buffer to disk
Context: See this subroutine on its own page References: This subroutine is called as follows: * wfile calls wsect * rsect calls via wsect2

For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list.
Arguments: track The track number sector The sector number buffer Contains the data to write
Other entry points: wsect2 Read or write a sector, depending on the value of the C flag (clear = read, set = write)
.wsect SEC ; Set the C flag to denote that this is a write ; operation (this value will be read throughout the ; RWTS code that follows) .wsect2 PHP ; Store the read/write status on the stack (specifically ; the C flag) LDA #$60 ; Set the slot number containing the disk controller STA slot16 ; to 6 (storing it as the number multiplied by 16 so we ; can use this as an offset to add to the soft switch ; addresses for the disk controller, to ensure we access ; the addresses for slot 6) LDA #2 ; Set the maximum number of arm recalibrations to 2 STA recals LDA #4 ; Set the maximum number of seeks to 4 STA seeks LDA #$D8 ; Set the high byte of the motor on time to $D8 STA mtimeh LDX slot16 ; Set X to the disk controller card slot number * 16 ; Fall through into rwts to read or write the specified ; sector
Name: rwts [Show more] Type: Subroutine Category: Save and load Summary: Read or write a specific sector
Context: See this subroutine on its own page References: No direct references to this subroutine in this source file

This routine is almost identical to the RWTS routine in Apple DOS 3.3. It omits the code from the start of the routine that checks the command block and slot number, as Elite doesn't use either of those features. The original DOS 3.3 source code for this routine in is shown in the comments. For detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. For details of the VTOC layout, catalog sector layout and file entry layout, see chapter 4, "Diskette organisation". Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
LDA Q7L,X ; SAMESLOT LDA Q7L,X ; MAKE SURE IN READ MODE LDA Q6L,X ; LDA Q6L,X LDY #8 ; LDY #8 ; WE MAY HAFTA CHECK SEVERAL ; TIMES TO BE SURE .rwts2 ; CHKIFON EQU * LDA Q6L,X ; LDA Q6L,X ; GET THE DATA PHA ; PHA ; DELAY FOR DISK DATA TO ; CHANGE PLA ; PLA PHA ; PHA PLA ; PLA ; STX SLOT CMP $100 ; This instruction replaces the STX SLOT instruction in ; the original code ; ; It has no effect as any changes to the flags will be ; overridden by the next instruction, but the important ; thing is that both STX SLOT and CMP $100 take four CPU ; cycles, so this is effectively a way of commenting out ; the original instruction without affecting the timings ; that are so crucial to the workings of the RWTS code CMP Q6L,X ; CMP Q6L,X ; CHECK RUNNING HERE BNE rwts3 ; BNE ITISON ; =>IT'S ON... DEY ; DEY ; MAYBE WE DIDN'T CATCH IT BNE rwts2 ; BNE CHKIFON ; SO WE'LL TRY AGAIN ; A chunk of the original DOS is omitted here, from ; ITISON to the start of OK, where we pick up the story ; once again .rwts3 PHP ; Save the result of the above checks on the stack, so ; we have the Z flag clear (BNE) if the disk is ; spinning, or the Z flag set (BEQ) if the disk is not ; spinning LDA mtron,X ; Read the disk controller I/O soft switch at MOTORON ; for slot X to turn the disk motor on ; The following code omits the drive select code, as ; Elite only supports drive 1 ; OK ROR A ; BY GOING INTO THE CARRY ; BCC SD1 ; SELECT DRIVE 2 ! LDA drv1en,X ; LDA DRV1EN,X ; ASSUME DRIVE 1 TO HIT ; BCS DRVSEL ; IF WRONG, ENABLE DRIVE 2 ; INSTEAD ; ; SD1 LDA DRV2EN,X ; ; DRVSEL EQU * ; ROR DRIVNO ; SAVE SELECTED DRIVE ; * ; * DRIVE SELECTED. IF MOTORING-UP, ; * WAIT BEFORE SEEKING... ; * PLP ; PLP ; WAS THE MOTOR PHP ; PHP ; PREVIOUSLY OFF? BNE rwts5 ; BNE NOWAIT ; =>NO, FORGET WAITING. LDY #7 ; LDY #7 ; YES, DELAY 150 MS .rwts4 JSR armwat ; SEEKW JSR MSWAIT DEY ; DEY BNE rwts4 ; BNE SEEKW LDX slot16 ; LDX SLOT ; RESTORE SLOT NUMBER .rwts5 ; NOWAIT EQU * ; * ; * SEEK TO DESIRED TRACK... ; * ; LDY #4 ; SET TO IOBTRK ; LDA (IOBPL),Y ; GET DESIRED TRACK LDA track ; We fetch the track number from the track variable ; rather than the IOBPL block, as the Elite code just ; stores values in variables instead JSR seek ; JSR MYSEEK ; SEEK! ; * ; * SEE IFMOTOR WAS ALREADY SPINNING. ; * PLP ; PLP ; WAS MOTOR ON? BNE trytrk ; BNE TRYTRK ; IF SO, DON'T DELAY, GET IT ; TODAY! ; * ; * WAIT FOR MOTOR SPEED TO COME UP. ; * LDY mtimeh ; LDY MONTIME+1 ; IF MOTORTIME IS POSITIVE, BPL trytrk ; BPL MOTORUP ; THEN SEEK WASTED ENUFF TIME ; FOR US .rwts6 LDY #18 ; MOTOF LDY #$12 ; DELAY 100 USEC PER COUNT .rwts7 DEY ; CONWAIT DEY BNE rwts7 ; BNE CONWAIT INC mtimel ; INC MONTIME BNE rwts6 ; BNE MOTOF INC mtimeh ; INC MONTIME+1 BNE rwts6 ; BNE MOTOF ; COUNT UP TO $0000
Name: trytrk [Show more] Type: Subroutine Category: Save and load Summary: Try finding a specific track on the disk
Context: See this subroutine on its own page References: This subroutine is called as follows: * rwts calls trytrk * rttrk calls via trytr4 * rdrght calls via trytr5 * rdrght calls via trytr6

This routine is almost identical to the TRYTRK routine in Apple DOS 3.3. It omits the code from the start of the routine that checks for the format command, as this is not required. The original DOS 3.3 source code for this routine in is shown in the comments. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
Other entry points: trytr4 Entry point for track errors, so we can try reading it again (must have the status flags on the stack with the C flag set) trytr5 Re-entry point for the loop from the rdrght subroutine, for when we need to re-calibrate trytr6 Re-entry point for the loop from the rdrght subroutine, for when we need to re-seek
.trytrk ; TRYTRK EQU * ; LDY #$0C ; LDA (IOBPL),Y ; GET COMMAND CODE # ; BEQ GALLDONE ; IF NULL COMMAND, GO HOME TO ; BED. ; CMP #$04 ; FORMAT THE DISK? ; BEQ FORMDSK ; ALLRIGHT,ALLRIGHT, I WILL... ; ROR A ; SET CARRY=1 FOR READ, 0 FOR ; WRITE ; PHP ; AND SAVE THAT ; BCS TRYTRK2 ; MUST PRENIBBLIZE FOR WRITE. PLP ; Instead of the above checks, which we don't need to do PHP ; as we don't want to format the disk, we can simply BCC trytr2 ; fetch the read/write status into the C flag from the ; stack, and if the C flag is clear then we are reading ; a sector, so skip the following instruction as we ; only need to call prenib if we are writing JSR prenib ; JSR PRENIB16 .trytr2 LDY #48 ; TRYTRK2 LDY #$30 ; ONLY 48 RETRIES OF ANY KIND. STY ztemp2 ; STY RETRYCNT .trytr3 LDX slot16 ; TRYADR LDX SLOT ; GET SLOT NUM INTO X-REG JSR rdaddr ; JSR RDADR16 ; READ NEXT ADDRESS FIELD BCC rdrght ; BCC RDRIGHT ; IF READ IT RIGHT, HURRAH! .trytr4 DEC ztemp2 ; TRYADR2 DEC RETRYCNT ; ANOTHER MISTAEK!! BPL trytr3 ; BPL TRYADR ; WELL, LET IT GO THIS TIME., ; * ; * RRRRRECALIBRATE !!!! ; * .trytr5 ; RECAL EQU * ; LDA CURTRK ; PHA ; SAVE TRACK WE REALLY WANT ; LDA #$60 ; RECALIBRATE ALL OVER AGAIN! ; JSR SETTRK ; PRETEND TO BE ON TRACK 96 DEC recals ; DEC RECALCNT ; ONCE TOO MANY?? BEQ drverr ; BEQ DRVERR ; TRIED TO RECALIBRATE TOO ; MANY TIMES, ERROR! LDA #4 ; LDA #MAXSEEKS ; RESET THE STA seeks ; STA SEEKCNT ; SEEK COUNTER LDA #$60 ; The instructions LDA #$60 and JSR SETTRK above have STA curtrk ; been replaced by these two, which do the same thing ; but without the more generalised code of the original LDA #0 ; LDA #$00 JSR seek ; JSR MYSEEK ; MOVE TO TRACK 00 ; PLA ; The first two instructions at RECAL (LDA CURTRK and ; PHA) and the PLA instruction above have been replaced ; by the LDA track instruction below, which do the same ; thing .trytr6 LDA track ; Fetch the track number into A JSR seek ; RESEEK JSR MYSEEK ; GO TO CORRECT TRACK THIS ; TIME! JMP trytr2 ; JMP TRYTRK2 ; LOOP BACK, TRY AGAIN ON THIS ; TRACK
Name: rdrght [Show more] Type: Subroutine Category: Save and load Summary: Check that this is the correct track
Context: See this subroutine on its own page References: This subroutine is called as follows: * trytrk calls rdrght

This routine is almost identical to the RDRIGHT routine in Apple DOS 3.3. It omits the code that saves the destination track, as this is not required. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.rdrght LDY idfld+2 ; RDRIGHT LDY TRACK ; ON THE RIGHT TRACK? CPY track ; CPY CURTRK BEQ rttrk ; BEQ RTTRK ; IF SO, GOOD ; * NO, DRIVE WAS ON A DIFFERENT TRACK. TRY ; * RESEEKING/RECALIBRATING FROM THIS TRACK ; LDA CURTRK ; PRESERVE DESTINATION TRACK ; PHA ; TYA ; JSR SETTRK ; PLA DEC seeks ; DEC SEEKCNT ; SHOULD WE RESEEK? BNE trytr6 ; BNE RESEEK ; =>YES, RESEEK BEQ trytr5 ; BEQ RECAL ; =>NO, RECALIBRATE!
Name: prterr [Show more] Type: Subroutine Category: Save and load Summary: Return from the RWTS code with a "Disk write protected" error
Context: See this subroutine on its own page References: This subroutine is called as follows: * rttrk calls via drver2K

Returns: A The error number for the Disk write protected error (1) C flag The C flag is set
Other entry points: drver2K Restore the stack pointer and return from the RWTS code with the error number in A and the C flag set to indicate an error
.prterr LDA #1 ; Set A = 1 to return as the error number for the "Disk ; write protected" error BPL drver2 ; Jump to drver2 to restore the stack pointer and ; return from the RWTS code with an error number of 1 ; and the C flag set to indicate an error (this BPL is ; effectively a JMP as A is always positive) .drverrK ; This label is a duplicate of a label in the drverr ; routine ; ; In the original source this label is drverr, but ; because BeebAsm doesn't allow us to redefine labels, ; I have renamed it to drverrK LDA #4 ; This code is never called and seems to be left over ; from a copy of the label and instruction from the ; drverr routine .drver2K ; This label is a duplicate of a label in the drverr ; routine ; ; In the original source this label is drver2, but ; because BeebAsm doesn't allow us to redefine labels, ; I have renamed it to drver2K LDX stkptr ; Restore the value of the stack pointer from when we TXS ; first ran the RWTS code, to remove any return ; addresses or values from the disk access routines ; and make sure the RTS below returns from the RWTS ; code LDX slot16 ; Set X to the disk controller card slot number * 16 LDY mtroff,X ; Read the disk controller I/O soft switch at MOTOROFF ; for slot X to turn the disk motor off SEC ; Set the C flag to denote that an error has occurred RTS ; Return from the subroutine
Name: rttrk [Show more] Type: Subroutine Category: Save and load Summary: Read or write a sector on the current track
Context: See this subroutine on its own page References: This subroutine is called as follows: * rdrght calls rttrk
.rttrk LDY sector ; Use the scttab lookup table to set A to the physical LDA scttab,Y ; sector number of logical sector Y CMP idfld+1 ; If the physical sector number doesn't match the sector BNE trytr4 ; ID, jump to trytr4 to try reading the track again PLP ; Fetch the read/write status into the C flag from the ; stack BCS rttrk2 ; If the C flag is set then we are writing a sector, so ; jump to rttrk2 to write the sector to the disk JSR read ; Otherwise we are reading a sector, so call the read ; routine to read the current sector into the buffer at ; buffr2, which will load the entire commander file as ; it fits into one sector ; ; Note that this loads the file straight from disk, so ; it is in the 6-bit nibble format PHP ; Store the status flags on the stack, so if we take the ; following branch, the stack will be in the correct ; state, with the read/write status on top BCS trytr4 ; If there was an error then the read routine will have ; set the C flag, so if this is the case, jump to trytr4 ; to try reading the track again PLP ; Otherwise there was no error, so pull the status flags ; back off the stack as we don't need them there any ; more JSR pstnib ; Call pstnib to convert the sector data that we just ; read into 8-bit bytes, processing the 6-bit nibbles in ; buffr2 into 8-bit bytes in buffer JMP rttrk3 ; Jump to rttrk3 to return from the RWTS code with no ; error reported .rttrk2 JSR write ; Call the write routine to write a sector's worth of ; data from buffr2 to the specified track and sector, ; which will save the entire commander file as it fits ; into one sector ; ; Note that the data in buffr2 is in the 6-bit nibble ; format, as we pre-nibblized it in the trytrk routine BCC rttrk3 ; If there was no write error then the write routine ; will have cleared the C flag, so jump to rttrk3 to ; return from the RWTS code with no error reported LDA #1 ; Set A = 1 to return as the error number for the "Disk ; write protected" error BPL drver2K ; Jump to drver2K to restore the stack pointer and ; return from the RWTS code with an error number of 1 ; and the C flag set to indicate an error (this BPL is ; effectively a JMP as A is always positive)
Name: drverr [Show more] Type: Subroutine Category: Save and load Summary: Return from the RWTS code with a "Disk I/O error"
Context: See this subroutine on its own page References: This subroutine is called as follows: * trytrk calls drverr * prterr calls via drver2

Returns: A The error number for the Disk I/O error (4) C flag The C flag is set
Other entry points: drver2 Restore the stack pointer and return from the RWTS code with the error number in A and the C flag set to indicate an error
.drverr LDA #4 ; Set A = 4 to return as the error number for the "Disk ; I/O error" .drver2 LDX stkptr ; Restore the value of the stack pointer from when we TXS ; first ran the RWTS code, to remove any return ; addresses or values from the disk access routines ; and make sure the RTS below returns from the RWTS ; code SEC ; Set the C flag to denote that an error has occurred BCS rttrk4 ; Jump to rttrk4 to return from the RWTS code with the ; error number in A and the error status in the C flag
Name: rttrk3 [Show more] Type: Subroutine Category: Save and load Summary: Successfully return from the RWTS code with no error reported
Context: See this subroutine on its own page References: This subroutine is called as follows: * rttrk calls rttrk3 * drverr calls via rttrk4

Returns: A The error number for no error (0) C flag The C flag is clear
Other entry points: rttrk4 Turn off the disk motor and return from the RWTS code with the error number in A and the error status in the C flag
.rttrk3 LDA #0 ; Set A = 0 to indicate there is no error CLC ; Clear the C flag to indicate there is no disk error .rttrk4 LDX slot16 ; Set X to the disk controller card slot number * 16 LDY mtroff,X ; Read the disk controller I/O soft switch at MOTOROFF ; for slot X to turn the disk motor off RTS ; Return from the subroutine
Name: read [Show more] Type: Subroutine Category: Save and load Summary: Read a sector's worth of data into the buffr2 buffer
Context: See this subroutine on its own page References: This subroutine is called as follows: * rttrk calls read

This routine is identical to the READ16 routine in Apple DOS 3.3. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.read LDY #32 ; READ16 LDY #$20 ; 'MUST FIND' COUNT. .read2 DEY ; RSYNC DEY IF ; CAN'T FIND MARKS BEQ readE ; BEQ RDERR ; THEN EXIT WITH CARRY SET. .read3 LDA Q6L,X ; READ1 LDA Q6L,X ; READ NIBL. BPL read3 ; BPL READ1 ; *** NO PAGE CROSS! *** .read4 EOR #$D5 ; RSYNC1 EOR #$D5 ; DATA MARK 1? BNE read2 ; BNE RSYNC ; LOOP IF NOT. NOP ; NOP DELAY ; BETWEEN NIBLS. .read5 LDA Q6L,X ; READ2 LDA Q6L,X BPL read5 ; BPL READ2 ; *** NO PAGE CROSS! *** CMP #$AA ; CMP #$AA ; DATA MARK 2? BNE read4 ; BNE RSYNC1 ; (IF NOT, IS IT DM1?) LDY #$56 ; LDY #$56 ; INIT NBUF2 INDEX. ; * (ADDED NIBL DELAY) .read6 LDA Q6L,X ; READ3 LDA Q6L,X BPL read6 ; BPL READ3 ; *** NO PAGE CROSS! *** CMP #$AD ; CMP #$AD ; DATA MARK 3? BNE read4 ; BNE RSYNC1 ; (IF NOT, IS IT DM1?) ; * (CARRY SET IF DM3!) LDA #0 ; LDA #$00 ; INIT CHECKSUM. .read7 DEY ; RDATA1 DEY STY ztemp0 ; STY IDX .read8 LDY Q6L,X ; READ4 LDY Q6L,X BPL read8 ; BPL READ4 ; *** NO PAGE CROSS! *** EOR rtable-$96,Y ; EOR DNIBL,Y ; XOR 6-BIT NIBL. LDY ztemp0 ; LDY IDX STA buffr2+256,Y ; STA NBUF2,Y ; STORE IN NBUF2 PAGE. BNE read7 ; BNE RDATA1 ; TAKEN IF Y-REG NONZERO. .read9 STY ztemp0 ; RDATA2 STY IDX .readA LDY Q6L,X ; READ5 LDY Q6L,X BPL readA ; BPL READ5 ; *** NO PAGE CROSS! *** EOR rtable-$96,Y ; EOR DNIBL,Y ; XOR 6-BIT NIBL. LDY ztemp0 ; LDY IDX STA buffr2,Y ; STA NBUF1,Y ; STORE IN NBUF1 PAGE. INY ; INY BNE read9 ; BNE RDATA2 .readB LDY Q6L,X ; READ6 LDY Q6L,X ; READ 7-BIT CSUM NIBL. BPL readB ; BPL READ6 ; *** NO PAGE CROSS! *** CMP rtable-$96,Y ; CMP DNIBL,Y ; IF LAST NBUF1 NIBL NOT BNE readE ; BNE RDERR ; EQUAL CHKSUM NIBL THEN ERR. .readC LDA Q6L,X ; READ7 LDA Q6L,X BPL readC ; BPL READ7 ; *** NO PAGE CROSS! *** CMP #$DE ; CMP #$DE ; FIRST BIT SLIP MARK? BNE readE ; BNE RDERR ; (ERR IF NOT) NOP ; NOP DELAY ; BETWEEN NIBLS. .readD LDA Q6L,X ; READ8 LDA Q6L,X BPL readD ; BPL READ8 ; *** NO PAGE CROSS! *** CMP #$AA ; CMP #$AA ; SECOND BIT SLIP MARK? BEQ readF ; BEQ RDEXIT ; (DONE IF IT IS) .readE SEC ; RDERR SEC INDICATE ; 'ERROR EXIT'. RTS ; RTS RETURN ; FROM READ16 OR RDADR16. .readF CLC ; RDEXIT CLC CLEAR ; CARRY ON RTS ; RTS NORMAL ; READ EXITS.
Name: write [Show more] Type: Subroutine Category: Save and load Summary: Write a sector's worth of data from the buffr2 buffer to the current track and sector
Context: See this subroutine on its own page References: This subroutine is called as follows: * rttrk calls write

This routine is almost identical to the WRITE16 routine in Apple DOS 3.3. There is one instruction missing here that is in the original DOS. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.write SEC ; WRITE16 SEC ANTICIPATE ; WPROT ERR. STX ztemp1 ; STX SLOTZ ; FOR ZERO PAGE ACCESS. ; The following instruction from DOS 3.3 is omitted: ; ; STX SLOTABS ; FOR NON-ZERO PAGE. ; ; This would populate SLOTABS (slot16 in Elite) with X, ; which contains the slot number * 16 ; ; The value of slot16 is set to $60 in the wsect routine ; and is never changed again, so this omission is ; presumably to prevent the slot number from changing LDA Q6H,X ; LDA Q6H,X LDA Q7L,X ; LDA Q7L,X ; SENSE WPROT FLAG. BMI write6 ; BMI WEXIT ; IF HIGH, THEN ERR. LDA buffr2+256 ; LDA NBUF2 STA ztemp0 ; STA WTEMP ; FOR ZERO-PAGE ACCESS. LDA #$FF ; LDA #$FF ; SYNC DATA. STA Q7H,X ; STA Q7H,X ; (5) WRITE 1ST NIBL. ORA Q6L,X ; ORA Q6L,X ; (4) PHA ; PHA (3) PLA ; PLA (4) ; CRITICAL TIMING! NOP ; NOP (2) LDY #4 ; LDY #4 ; (2) FOR 5 NIBLS. .write2 PHA ; WSYNC PHA (3) ; EXACT TIMING. PLA ; PLA (4) ; EXACT TIMING. JSR wbyte2 ; JSR WNIBL7 ; (13,9,6) WRITE SYNC. DEY ; DEY (2) BNE write2 ; BNE WSYNC ; (2*) MUST NOT CROSS PAGE! LDA #$D5 ; LDA #$D5 ; (2) 1ST DATA MARK. JSR wbyte ; JSR WNIBL9 ; (15,9,6) LDA #$AA ; LDA #$AA ; (2) 2ND DATA MARK. JSR wbyte ; JSR WNIBL9 ; (15,9,6) LDA #$AD ; LDA #$AD ; (2) 3RD DATA MARK. JSR wbyte ; JSR WNIBL9 ; (15,9,6) TYA ; TYA (2) ; CLEAR CHKSUM. LDY #$56 ; LDY #$56 ; (2) NBUF2 INDEX. BNE write4 ; BNE WDATA1 ; (3) ALWAYS. NO PAGE ; CROSS!! .write3 LDA buffr2+256,Y ; WDATA0 LDA NBUF2,Y ; (4) PRIOR 6-BIT NIBL. .write4 EOR buffr2+255,Y ; WDATA1 EOR NBUF2-1,Y ; (5) XOR WITH CURRENT. ; * (NBUF2 MUST BE ON PAGE BOUNDARY FOR TIMING!!) TAX ; TAX (2) ; INDEX TO 7-BIT NIBL. LDA wtable,X ; LDA NIBL,X ; (4) MUST NOT CROSS PAGE! LDX ztemp1 ; LDX SLOTZ ; (3) CRITICAL TIMING! STA Q6H,X ; STA Q6H,X ; (5) WRITE NIBL. LDA Q6L,X ; LDA Q6L,X ; (4) DEY ; DEY (2) ; NEXT NIBL. BNE write3 ; BNE WDATA0 ; (2*) MUST NOT CROSS PAGE! LDA ztemp0 ; LDA WTEMP ; (3) PRIOR NIBL FROM BUF6. NOP ; NOP (2) ; CRITICAL TIMING. .write5 EOR buffr2,Y ; WDATA2 EOR NBUF1,Y ; (4) XOR NBUF1 NIBL. TAX ; TAX (2) ; INDEX TO 7-BIT NIBL. LDA wtable,X ; LDA NIBL,X ; (4) LDX slot16 ; LDX SLOTABS ; (4) TIMING CRITICAL. STA Q6H,X ; STA Q6H,X ; (5) WRITE NIBL. LDA Q6L,X ; LDA Q6L,X ; (4) LDA buffr2,Y ; LDA NBUF1,Y ; (4) PRIOR 6-BIT NIBL. INY ; INY (2) ; NEXT NBUF1 NIBL. BNE write5 ; BNE WDATA2 ; (2*) MUST NOT CROSS PAGE! TAX ; TAX (2) ; LAST NIBL AS CHKSUM. LDA wtable,X ; LDA NIBL,X ; (4) INDEX TO 7-BIT NIBL. LDX ztemp1 ; LDX SLOTZ ; (3) JSR wbyte3 ; JSR WNIBL ; (6,9,6) WRITE CHKSUM. LDA #$DE ; LDA #$DE ; (2) DM4, BIT SLIP MARK. JSR wbyte ; JSR WNIBL9 ; (15,9,6) WRITE IT. LDA #$AA ; LDA #$AA ; (2) DM5, BIT SLIP MARK. JSR wbyte ; JSR WNIBL9 ; (15,9,6) WRITE IT. LDA #$EB ; LDA #$EB ; (2) DM6, BIT SLIP MARK. JSR wbyte ; JSR WNIBL9 ; (15,9,6) WRITE IT. LDA #$FF ; LDA #$FF ; (2) TURN-OFF BYTE. JSR wbyte ; JSR WNIBL9 ; (15,9,9) WRITE IT. LDA Q7L,X ; LDA Q7L,X ; OUT OF WRITE MODE. .write6 LDA Q6L,X ; WEXIT LDA Q6L,X ; TO READ MODE. RTS ; RTS RETURN ; FROM WRITE.
Name: rdaddr [Show more] Type: Subroutine Category: Save and load Summary: Read a track address field
Context: See this subroutine on its own page References: This subroutine is called as follows: * trytrk calls rdaddr

This routine is identical to the RDADR16 routine in Apple DOS 3.3. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.rdaddr LDY #$FC ; RDADR16 LDY #$FC STY ztemp0 ; STY COUNT ; 'MUST FIND' COUNT. .rdadr2 INY ; RDASYN INY BNE rdadr3 ; BNE RDA1 ; LOW ORDER OF COUNT. INC ztemp0 ; INC COUNT ; (2K NIBLS TO FIND BEQ rdadrD ; BEQ RDERR ; ADR MARK, ELSE ERR) .rdadr3 LDA Q6L,X ; RDA1 LDA Q6L,X ; READ NIBL. BPL rdadr3 ; BPL RDA1 ; *** NO PAGE CROSS! *** .rdadr4 CMP #$D5 ; RDASN1 CMP #$D5 ; ADR MARK 1? BNE rdadr2 ; BNE RDASYN ; (LOOP IF NOT) NOP ; NOP ADDED ; NIBL DELAY. .rdadr5 LDA Q6L,X ; RDA2 LDA Q6L,X BPL rdadr5 ; BPL RDA2 ; *** NO PAGE CROSS! *** CMP #$AA ; CMP #$AA ; ADR MARK 2? BNE rdadr4 ; BNE RDASN1 ; (IF NOT, IS IT AM1?) LDY #3 ; LDY #$3 ; INDEX FOR 4-BYTE READ. ; * (ADDED NIBL DELAY) .rdadr6 LDA Q6L,X ; RDA3 LDA Q6L,X BPL rdadr6 ; BPL RDA3 ; *** NO PAGE CROSS! *** CMP #$96 ; CMP #$96 ; ADR MARK 3? BNE rdadr4 ; BNE RDASN1 ; (IF NOT, IS IT AM1?) ; * (LEAVES CARRY SET!) LDA #0 ; LDA #$0 ; INIT CHECKSUM. .rdadr7 STA ztemp1 ; RDAFLD STA CSUM .rdadr8 LDA Q6L,X ; RDA4 LDA Q6L,X ; READ 'ODD BIT' NIBL. BPL rdadr8 ; BPL RDA4 ; *** NO PAGE CROSS! *** ROL A ; ROL A ; ALIGN ODD BITS, '1' INTO ; LSB. STA ztemp0 ; STA LAST ; (SAVE THEM) .rdadr9 LDA Q6L,X ; RDA5 LDA Q6L,X ; READ 'EVEN BIT' NIBL. BPL rdadr9 ; BPL RDA5 ; *** NO PAGE CROSS! *** AND ztemp0 ; AND LAST ; MERGE ODD AND EVEN BITS. STA idfld,Y ; STA CSSTV,Y ; STORE DATA BYTE. EOR ztemp1 ; EOR CSUM ; XOR CHECKSUM. DEY ; DEY BPL rdadr7 ; BPL RDAFLD ; LOOP ON 4 DATA BYTES. TAY ; TAY IF ; FINAL CHECKSUM BNE rdadrD ; BNE RDERR ; NONZERO, THEN ERROR. .rdadrA LDA Q6L,X ; RDA6 LDA Q6L,X ; FIRST BIT-SLIP NIBL. BPL rdadrA ; BPL RDA6 ; *** NO PAGE CROSS! *** CMP #$DE ; CMP #$DE BNE rdadrD ; BNE RDERR ; ERROR IF NONMATCH. NOP ; NOP DELAY ; BETWEEN NIBLS. .rdadrB LDA Q6L,X ; RDA7 LDA Q6L,X ; SECOND BIT-SLIP NIBL. BPL rdadrB ; BPL RDA7 ; *** NO PAGE CROSS! *** CMP #$AA ; CMP #$AA BNE rdadrD ; BNE RDERR ; ERROR IF NONMATCH. .rdadrC CLC ; RDEXIT CLC CLEAR ; CARRY ON RTS ; RTS NORMAL ; READ EXITS. .rdadrD SEC ; RDERR SEC INDICATE ; 'ERROR EXIT'. RTS ; RTS RETURN ; FROM READ16 OR RDADR16.
Name: seek [Show more] Type: Subroutine Category: Save and load Summary: Fast seek routine
Context: See this subroutine on its own page References: This subroutine is called as follows: * rwts calls seek * trytrk calls seek

This routine is almost identical to the SEEK routine in Apple DOS 3.3. There is one extra instruction and one moved instruction when compared to the original DOS. These extra instructions double the track number in A. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
Arguments: A The track number
.seek STX ztemp0 ; SEEK STX SLOTTEMP ; SAVE X-REG ; STA TRKN ; SAVE TARGET TRACK ASL A ; This is an extra instruction that doubles the track ; number in A CMP curtrk ; CMP CURTRK ; ON DESIRED TRACK? BEQ step3 ; BEQ SEEKRTS ; YES, RETURN STA ztemp1 ; This is the second instruction from above, which has ; been moved here (STA TRKN) ; ; This saves the now-doubled track number in ztemp1 LDA #0 ; LDA #$0 STA ztemp2 ; STA TRKCNT ; HALFTRACK COUNT. .seek2 LDA curtrk ; SEEK2 LDA CURTRK ; SAVE CURTRK FOR STA ztemp3 ; STA PRIOR ; DELAYED TURNOFF. SEC ; SEC SBC ztemp1 ; SBC TRKN ; DELTA-TRACKS. BEQ seek7 ; BEQ SEEKEND ; BR IF CURTRK=DESTINATION BCS seek3 ; BCS OUT ; (MOVE OUT, NOT IN) EOR #$FF ; EOR #$FF ; CALC TRKS TO GO. INC curtrk ; INC CURTRK ; INCR CURRENT TRACK (IN). BCC seek4 ; BCC MINTST ; (ALWAYS TAKEN) .seek3 ADC #$FE ; OUT ADC #$FE ; CALC TRKS TO GO. DEC curtrk ; DEC CURTRK ; DECR CURRENT TRACK (OUT). .seek4 CMP ztemp2 ; MINTST CMP TRKCNT BCC seek5 ; BCC MAXTST ; AND 'TRKS MOVED'. LDA ztemp2 ; LDA TRKCNT .seek5 CMP #12 ; MAXTST CMP #$C BCS seek6 ; BCS STEP2 ; IF TRKCNT>$B LEAVE Y ALONE ; (Y=$B). TAY ; STEP TAY ; ELSE SET ACCELERATION INDEX ; IN Y .seek6 ; STEP2 EQU * SEC ; SEC ; CARRY SET=PHASE ON JSR step ; JSR SETPHASE ; PHASE ON LDA armtab,Y ; LDA ONTABLE,Y ; FOR 'ONTIME'. JSR armwat ; JSR MSWAIT ; (100 USEC INTERVALS) ; * LDA ztemp3 ; LDA PRIOR CLC ; CLC ; CARRY CLEAR=PHASE OFF JSR step2 ; JSR CLRPHASE ; PHASE OFF LDA armtb2,Y ; LDA OFFTABLE,Y ; THEN WAIT 'OFFTIME'. JSR armwat ; JSR MSWAIT ; (100 USEC INTERVALS) INC ztemp2 ; INC TRKCNT ; 'TRACKS MOVED' COUNT. BNE seek2 ; BNE SEEK2 ; (ALWAYS TAKEN) ; * .seek7 ; SEEKEND EQU * ; END OF SEEKING JSR armwat ; JSR MSWAIT ; A=0: WAIT 25 MS SETTLE CLC ; CLC ; AND TURN OFF PHASE ; * ; * TURN HEAD STEPPER PHASE ON/OFF ; * .step ; SETPHASE EQU * LDA curtrk ; LDA CURTRK ; GET CURRENT PHASE .step2 ; CLRPHASE EQU * AND #3 ; AND #3 ; MASK FOR 1 OF 4 PHASES ROL A ; ROL A ; DOUBLE FOR PHASE INDEX ORA ztemp0 ; ORA SLOTTEMP TAX ; TAX LDA phsoff,X ; LDA PHASEOFF,X ; FLIP THE PHASE LDX ztemp0 ; LDX SLOTTEMP ; RESTORE X-REG .step3 RTS ; SEEKRTS RTS ; AND RETURN
Name: armwat [Show more] Type: Subroutine Category: Save and load Summary: Implement the arm move delay
Context: See this subroutine on its own page References: This subroutine is called as follows: * rwts calls armwat * seek calls armwat

This routine is identical to the MSWAIT routine in Apple DOS 3.3. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.armwat LDX #17 ; MSWAIT LDX #$11 .armwt2 DEX ; MSW1 DEX DELAY ; 86 USEC. BNE armwt2 ; BNE MSW1 INC mtimel ; INC MONTIMEL BNE armwt3 ; BNE MSW2 ; DOUBLE-BYTE INC mtimeh ; INC MONTIMEH ; INCREMENT. .armwt3 SEC ; MSW2 SEC SBC #1 ; SBC #$1 ; DONE 'N' INTERVALS? BNE armwat ; BNE MSWAIT ; (A-REG COUNTS) RTS ; RTS
Name: armtab [Show more] Type: Variable Category: Save and load Summary: Phase-on time table in 100-usec intervals
Context: See this variable on its own page References: This variable is used as follows: * seek uses armtab

This table is identical to the ONTABLE table in Apple DOS 3.3. The original DOS 3.3 source code for this table in is shown in the comments. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.armtab EQUB 1 ; ONTABLE DFB 1,$30,$28 EQUB $30 ; DFB $24,$20,$1E EQUB $28 ; DFB $1D,$1C,$1C EQUB $24 ; DFB $1C,$1C,$1C EQUB $20 EQUB $1E EQUB $1D EQUB $1C EQUB $1C EQUB $1C EQUB $1C EQUB $1C
Name: armtb2 [Show more] Type: Variable Category: Save and load Summary: Phase-off time table in 100-usec intervals
Context: See this variable on its own page References: This variable is used as follows: * seek uses armtb2

This table is identical to the OFFTABLE table in Apple DOS 3.3. The original DOS 3.3 source code for this table in is shown in the comments. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.armtb2 EQUB $70 ; OFFTABLE DFB $70,$2C,$26 EQUB $2C ; DFB $22,$1F,$1E EQUB $26 ; DFB $1D,$1C,$1C EQUB $22 ; DFB $1C,$1C,$1C EQUB $1F EQUB $1E EQUB $1D EQUB $1C EQUB $1C EQUB $1C EQUB $1C EQUB $1C
Name: prenib [Show more] Type: Subroutine Category: Save and load Summary: Convert 256 8-bit bytes in buffer into 342 6-bit nibbles in buffr2
Context: See this subroutine on its own page References: This subroutine is called as follows: * trytrk calls prenib

This routine is identical to the PRENIB16 routine in Apple DOS 3.3. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.prenib LDX #0 ; PRENIB16 LDX #$0 ; START NBUF2 INDEX. CHANGED ; BY WOZ LDY #2 ; LDY #2 ; START USER BUF INDEX. ; CHANGED BY WOZ. .prenb2 DEY ; PRENIB1 DEY NEXT ; USER BYTE. LDA buffer,Y ; LDA (BUF),Y LSR A ; LSR A ; SHIFT TWO BITS OF ROL buffr2+256,X ; ROL NBUF2,X ; CURRENT USER BYTE LSR A ; LSR A ; INTO CURRENT NBUF2 ROL buffr2+256,X ; ROL NBUF2,X ; BYTE. STA buffr2,Y ; STA NBUF1,Y ; (6 BITS LEFT). INX ; INX ; FROM 0 TO $55. CPX #$56 ; CPX #$56 BCC prenb2 ; BCC PRENIB1 ; BR IF NO WRAPAROUND. LDX #0 ; LDX #0 ; RESET NBUF2 INDEX. TYA ; TYA ; USER BUF INDEX. BNE prenb2 ; BNE PRENIB1 ; (DONE IF ZERO) LDX #$55 ; LDX #$55 ; NBUF2 IDX $55 TO 0. .prenb3 LDA buffr2+256,X ; PRENIB2 LDA NBUF2,X AND #$3F ; AND #$3F ; STRIP EACH BYTE STA buffr2+256,X ; STA NBUF2,X ; OF NBUF2 TO 6 BITS. DEX ; DEX BPL prenb3 ; BPL PRENIB2 ; LOOP UNTIL X NEG. RTS ; RTS ; RETURN.
Name: pstnib [Show more] Type: Subroutine Category: Save and load Summary: Convert 342 6-bit nibbles in buffr2 into 256 8-bit bytes in buffer
Context: See this subroutine on its own page References: This subroutine is called as follows: * rttrk calls pstnib

This routine is almost identical to the POSTNB16 routine in Apple DOS 3.3. The CPY T0 instruction from the original source is omitted as we only need to check whether the byte counter in Y has reached zero. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.pstnib LDY #0 ; POSTNB16 LDY #0 ; USER DATA BUF IDX. .pstnb2 LDX #$56 ; POST1 LDX #$56 ; INIT NBUF2 INDEX. .pstnb3 DEX ; POST2 DEX NBUF ; IDX $55 TO $0. BMI pstnb2 ; BMI POST1 ; WRAPAROUND IF NEG. LDA buffr2,Y ; LDA NBUF1,Y LSR buffr2+256,X ; LSR NBUF2,X ; SHIFT 2 BITS FROM ROL A ; ROL A ; CURRENT NBUF2 NIBL LSR buffr2+256,X ; LSR NBUF2,X ; INTO CURRENT NBUF1 ROL A ; ROL A ; NIBL. STA buffer,Y ; STA (BUF),Y ; BYTE OF USER DATA. INY ; INY NEXT ; USER BYTE. ; CPY T0 ; DONE IF EQUAL T0. BNE pstnb3 ; BNE POST2 RTS ; RTS RETURN.
Name: wbyte [Show more] Type: Subroutine Category: Save and load Summary: Write one byte to disk
Context: See this subroutine on its own page References: This subroutine is called as follows: * write calls wbyte * write calls via wbyte2 * write calls via wbyte3

This routine is identical to the WNIBL9 routine in Apple DOS 3.3. For a detailed look at how DOS works, see the book "Beneath Apple DOS" by Don Worth and Pieter Lechner. In particular, see chapter 4 for the layout of the VTOC, catalog sector, file entry and file/track list. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
Other entry points: wbyte2 Wait for seven cycles before writing instead of nine (this is WNIBL7 in the original source) wbyte3 Write straight away without waiting (this is WNIBL in the original source)
.wbyte CLC ; WNIBL9 CLC (2) ; 9 CYCLES, THEN WRITE. .wbyte2 PHA ; WNIBL7 PHA (3) ; 7 CYCLES, THEN WRITE. PLA ; PLA (4) .wbyte3 STA Q6H,X ; WNIBL STA Q6H,X ; (5) NIBL WRITE SUB. ORA Q6L,X ; ORA Q6L,X ; (4) CLOBBERS ACC, NOT ; CARRY. RTS ; RTS
Name: scttab [Show more] Type: Variable Category: Save and load Summary: Lookup table to translate logical (requested) sector number to physical sector number
Context: See this variable on its own page References: This variable is used as follows: * rttrk uses scttab

This table is identical to the INTRLEAV table in Apple DOS 3.3. The original DOS 3.3 source code for this table in is shown in the comments. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.scttab ; INTRLEAV EQU * EQUD $090B0D00 ; DFB $00,$0D,$0B,$09 EQUD $01030507 ; DFB $07,$05,$03,$01 EQUD $080A0C0E ; DFB $0E,$0C,$0A,$08 EQUD $0F020406 ; DFB $06,$04,$02,$0F
Name: rtable [Show more] Type: Variable Category: Save and load Summary: 64 disk nibbles of "6-and-2" Read Translate Table
Context: See this variable on its own page References: This variable is used as follows: * read uses rtable

This table is identical to the table at address $3A96 in Apple DOS 3.3. The table doesn't have a label in the original source. The original DOS 3.3 source code for this table in is shown in the comments. Elite uses different label names to the original DOS 3.3 source, but the code is the same. This code forms part of the RWTS ("read/write track sector") layer from Apple DOS, which was written by Randy Wigginton and Steve Wozniak. It implements the low-level functions to read and write Apple disks, and is included in Elite so the game can use the memory that's normally allocated to DOS for its own use.
.rtable EQUD $99980100 ; DFB $00,$01,$98 EQUD $049C0302 ; DFB $99,$02,$03 EQUD $A1A00605 ; DFB $9C,$04,$05 EQUD $A5A4A3A2 ; DFB $06,$A0,$A1 EQUD $A9A80807 ; DFB $A2,$A3,$A4 EQUD $0B0A09AA ; DFB $A5,$07,$08 EQUD $B1B00D0C ; DFB $A8,$A9,$AA EQUD $11100F0E ; DFB $09,$0A,$0B EQUD $14B81312 ; DFB $0C,$0D,$B0 EQUD $18171615 ; DFB $B1,$0E,$0F EQUD $C1C01A19 ; DFB $10,$11,$12 EQUD $C5C4C3C2 ; DFB $13,$B8,$14 EQUD $C9C8C7C6 ; DFB $15,$16,$17 EQUD $1CCC1BCA ; DFB $18,$19,$1A EQUD $D1D01E1D ; DFB $C0,$C1,$C2 EQUD $D5D41FD2 ; DFB $C3,$C4,$C5 EQUD $22D82120 ; DFB $C6,$C7,$C8 EQUD $26252423 ; DFB $C9,$CA,$1B EQUD $E1E02827 ; DFB $CC,$1C,$1D EQUD $29E4E3E2 ; DFB $1E,$D0,$D1 EQUD $2CE82B2A ; DFB $D2,$1F,$D4 EQUD $302F2E2D ; DFB $D5,$20,$21 EQUD $F1F03231 ; DFB $D8,$22,$23 EQUD $36353433 ; DFB $24,$25,$26 EQUD $39F83837 ; DFB $27,$28,$E0 EQUD $3D3C3B3A ; DFB $E1,$E2,$E3 EQUW $3F3E ; DFB $E4,$29,$2A ; DFB $2B,$E8,$2C ; DFB $2D,$2E,$2F ; DFB $30,$31,$32 ; DFB $F0,$F1,$33 ; DFB $34,$35,$36 ; DFB $37,$38,$F8 ; DFB $39,$3A,$3B ; DFB $3C,$3D,$3E ; DFB $3F
Name: MUTILATE [Show more] Type: Subroutine Category: Save and load Summary: Encrypt the commander file in the buffer at comfil
Context: See this subroutine on its own page References: This subroutine is called as follows: * wfile calls MUTILATE * UNMUTILATE calls via MUTIL3

At this point, the commander file is set up in memory like this (as defined in the configuration variables comsiz, comfil and comfil2): .comfil 20 bytes .TAP% 77 bytes containing the full commander file from byte #0 to byte #76 9 bytes .comfil2 4 bytes The entire structure above contains comsiz (110) bytes. This routine encrypts the commander file by first calculating a set of four random number seeds, using a set of bitwise operations that start with the third checksum byte at CHK3. These seed values get stored in the four bytes at comfil and are saved with the file, so they can be used by the UNMUTILATE routine to reverse the encryption. The encryption process simply takes the repeatable sequence of random numbers that are generated from these four seeds, and EOR's the bytes in the commander file with the numbers in the sequence. Because this is a simple EOR with a number sequence that can be reproduced from the four seeds, the decryption process just repeats the encryption process, generating the same sequence of random numbers from the seeds in the commander file, and EOR'ing them with the bytes in the encrypted file to produce the decrypted bytes (which works because a EOR b EOR b = a).
Other entry points: MUTIL3 Decrypt the commander file
.MUTILATE LDA CHK3 ; Set A to the third checksum byte at CHK3 for this ; commander file ; We now use this value to change the four random number ; seeds in RAND to RAND+3 into four different values ; that we can use to encrypt the file EOR RAND ; EOR it into the first random number seed in RAND STA RAND STA comfil2 ; Store the seed value in comfil2, so it gets saved as ; part of the commander file EOR #$A5 ; EOR and OR the result into the second random number ORA #17 ; seed in RAND+1 EOR RAND+1 STA RAND+1 STA comfil2+1 ; Store the seed value in comfil2+1, so it gets saved as ; part of the commander file EOR RAND+2 ; EOR the result into the third random number seed in EOR #$F8 ; RAND+2 STA RAND+2 STA comfil2+2 ; Store the seed value in comfil2+2, so it gets saved as ; part of the commander file EOR RAND+3 ; EOR the result into the fourth random number seed in EOR #$12 ; RAND+3 STA RAND+3 STA comfil2+3 ; Store the seed value in comfil2+3, so it gets saved as ; part of the commander file ; We now have four random seeds that are partially based ; on the third checksum and partially based on the ; previous value of the four random seeds, so we now use ; these seeds to encrypt the file ; ; The encryption process uses a simple EOR with the next ; random number from the repeatable sequence produced by ; the four seeds we stored at comfil2, so repeating the ; encryption process with the same four seeds will ; decrypt the file .MUTIL3 LDY #comsiz-5 ; Set Y to a byte counter so we can work our way ; backwards through the whole commander file structure, ; omitting the four bytes at comfil2 at the end .MUTIL1 JSR DORND2 ; Set A and X to random numbers, making sure the C flag ; doesn't affect the outcome EOR comfil,Y ; EOR the Y-th byte in the commander file with the next STA comfil,Y ; random number in the sequence generated by the four ; seeds stored at comfil2 DEY ; Decrement the byte counter BPL MUTIL1 ; Loop back until we have processed the whole commander ; file structure RTS ; Return from the subroutine
Name: UNMUTILATE [Show more] Type: Subroutine Category: Save and load Summary: Decrypt the commander file in the buffer at comfil
Context: See this subroutine on its own page References: This subroutine is called as follows: * LOD calls UNMUTILATE
.UNMUTILATE LDY #3 ; To decrypt the commander file, we need to set the four ; random number seeds at RAND to RAND+3 to the four ; bytes at comfil2 in the encrypted commander file, so ; set a byte counter in Y to copy four bytes .MUTIL2 LDA comfil2,Y ; Copy the Y-th seed from the commander file to the Y-th STA RAND,Y ; random number seed at RAND DEY ; Decrement the byte counter BPL MUTIL2 ; Loop back until we have copied all four bytes BMI MUTIL3 ; Jump to MUTIL3 to apply the decryption process to the ; commander file, which is simply a repeat of the ; encryption process with the same seeds (this BMI is ; effectively a JMP as we just passed through a BPL)
Save ELTJ.bin
PRINT "ELITE J" PRINT "Assembled at ", ~CODE_J% PRINT "Ends at ", ~P% PRINT "Code size is ", ~(P% - CODE_J%) PRINT "Execute at ", ~LOAD% PRINT "Reload at ", ~LOAD_J% PRINT "S.ELTJ ", ~CODE_J%, " ", ~P%, " ", ~LOAD%, " ", ~LOAD_J% SAVE "3-assembled-output/ELTJ.bin", CODE_J%, P%, LOAD%