.SVE LDA #1 ; Print extended token 1, the disk access menu, which JSR DETOK ; presents these options: ; ; 1. Load New Commander ; 2. Save Commander {commander name} ; 3. Change to {other media} ; 4. Default JAMESON ; 5. Exit JSR t ; Scan the keyboard until a key is pressed, returning ; the ASCII code in A and X CMP #'1' ; Option 1 was chosen, so jump to loading to load a new BEQ loading ; commander CMP #'2' ; Option 2 was chosen, so jump to SV1 to save the BEQ SV1 ; current commander CMP #'3' ; Option 3 was chosen, so jump to feb10 to change to the BEQ feb10 ; other media CMP #'4' ; If option 4 wasn't chosen, jump to feb13 to exit the BNE feb13 ; menu LDA #224 ; Option 4 was chosen, so print extended token 224 JSR DETOK ; ("ARE YOU SURE?") JSR YESNO ; Call YESNO to wait until either "Y" or "N" is pressed BCC feb13 ; If "N" was pressed, jump to feb13 JSR JAMESON ; Otherwise "Y" was pressed, so call JAMESON to set the ; last saved commander to the default "JAMESON" ; commander JMP DFAULT ; Jump to DFAULT to reset the current commander data ; block to the last saved commander, returning from the ; subroutine using a tail call .feb13 CLC ; Option 5 was chosen, so clear the C flag to indicate ; that nothing was loaded RTS ; Return from the subroutine .feb10 LDA DISK ; Toggle the value of DISK between 0 and $FF to swap the EOR #$FF ; current media between tape and disk STA DISK JMP SVE ; Jump to SVE to display the disk access menu and return ; from the subroutine using a tail call .loading JSR GTNMEW ; If we get here then option 1 (load) was chosen, so ; call GTNMEW to fetch the name of the commander file ; to load (including drive number and directory) into ; INWK JSR LOD ; Call LOD to load the commander file JSR TRNME ; Transfer the commander filename from INWK to NA% SEC ; Set the C flag to indicate we loaded a new commander .jan2186 RTS ; Return from the subroutine .SV1 JSR GTNMEW ; If we get here then option 2 (save) was chosen, so ; call GTNMEW to fetch the name of the commander file ; to save (including drive number and directory) into ; INWK JSR TRNME ; Transfer the commander filename from INWK to NA% LSR SVC ; Halve the save count value in SVC LDA #4 ; Print extended token 4 ("COMPETITION NUMBER:") JSR DETOK 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 .SVL1 LDA TP,X ; Copy the X-th byte of TP to the X-th byte of NA%+8 ;STA $0B00,X ; STA NA%+8,X ; The STA is commented out in the original source DEX ; Decrement the loop counter BPL SVL1 ; Loop back until we have copied all the bytes in the ; commander data block JSR CHECK2 ; Call CHECK2 to calculate the third checksum for the ; last saved commander and return it in A STA CHK3 ; Store the checksum in CHK3, which is at the end of the ; last saved commander 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 CLC ; Clear the C flag so the call to BPRNT does not include ; a decimal point 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% ; This instruction is commented out in the original ; source EOR #$A9 ; Store the checksum EOR $A9 in CHK2, the penultimate STA CHK2 ; byte of the last saved commander block ;STA $AFF+NT% ; This instruction is commented out in the original ; source ;LDA #0 ; These instructions are commented out in the original ;JSR QUS1 ; source JSR KERNALSETUP ; Set up memory so we can use the Kernal functions, ; which includes swapping the contents of zero page with ; the page at $CE00 (so the Kernal functions get a zero ; page that works for them, and any changes they make do ; not corrupt the game's zero page variables) ; ; This also enables interrupts that are generated by ; timer A underflow LDA #LO(NA%+8) ; Set $FD(1 0) = NA%+8 STA $FD ; LDA #HI(NA%+8) ; This sets the address at zero page location $FD and STA $FE ; $FD+1 to NA%+8, which is the address of the commander ; data that we want to save LDA #$FD ; Call the Kernal's SAVE function to save the commander LDX #LO(CHK+1) ; file as follows: LDY #HI(CHK+1) ; JSR KERNALSVE ; * A = address in zero page of the start address of ; the memory block to save, so this makes SAVE ; save the data from NA%+8 onwards ; ; * (Y X) = address of the end of the block of memory ; to save + 1, so this makes SAVE save the ; data from NA%+8 to CHK (inclusive) PHP ; If something goes wrong with the save then the C flag ; will be set, so save this on the stack so we can check ; it below SEI ; Disable interrupts while we configure the CIA and ; VIC-II BIT CIA+$D ; Reading from register $D of CIA1 will acknowledge any ; interrupts and clear them, so this line acknowledges ; any pending interrupts that might be waiting to be ; processed (using a BIT reads the location without ; changing any CPU registers - it only affects the ; flags, which we can simply ignore) LDA #%00000001 ; Set CIA1 register $0D to enable and disable interrupts STA CIA+$D ; as follows: ; ; * Bit 0 set = configure interrupts generated by ; timer A underflow ; ; * Bits 1-4 clear = do not change configuration of ; other interrupts ; ; * Bit 7 clear = disable interrupts whose ; corresponding bits are set ; ; So this disables interrupts that are generated by ; timer A underflow, while leaving other interrupts as ; they are LDX #0 ; Set the raster count to 0 to initialise the raster STX RASTCT ; effects in the COMIRQ handler (such as the split ; screen) INX ; Set bit 0 of VIC register $1A and clear bits 1-3 to STX VIC+$1A ; configure the following interrupts: ; ; * Bit 0 = enable raster interrupt ; ; * Bit 1 = disable sprite-background collision ; interrupt ; ; * Bit 2 = disable sprite-sprite collision interrupt ; ; * Bit 3 = disable light pen interrupt LDA VIC+$11 ; Clear bit 7 of VIC register $11, to clear the top bit AND #%01111111 ; of the raster line that generates the interrupt (as STA VIC+$11 ; the line number is a 9-bit value, with bits 0-7 in VIC ; register $12) LDA #40 ; Set VIC register $11 to 40, so along with bit 7 of VIC STA VIC+$12 ; register $10, this sets the raster interrupt to be ; generated when the raster reaches line 40 LDA #%100 ; Call SETL1 to set the 6510 input/output port to the JSR SETL1 ; following: ; ; * LORAM = 0 ; * HIRAM = 0 ; * CHAREN = 1 ; ; This sets the entire 64K memory map to RAM ; ; See the memory map at the top of page 265 in the ; Programmer's Reference Guide CLI ; Enable interrupts again JSR SWAPPZERO ; The call to KERNALSETUP above swapped the contents of ; zero page with the page at $CE00, to ensure the Kernal ; routines ran with their copy of zero page rather than ; the game's zero page ; ; We are done using the Kernal functions, so now we swap ; them back so the Kernal's zero page is moved to $CE00 ; again, ready for next time, and the game's zero page ; variables are once again set up, ready for the game ; code to use PLP ; Retrieve the processor flags that we stashed after the ; call to KERNALSVE above CLI ; Enable interrupts to make sure the PHP doesn't disable ; interrupts (which it could feasibly do by restoring a ; set I flag) BCS saveerror ; If KERNALSVE returns with the C flag set then this ; indicates that a save error occurred, so jump to ; tapeerror via saveerror to print either "TAPE ERROR" ; or "DISK ERROR" JSR DFAULT ; Call DFAULT to reset the current commander data block ; to the last saved commander JSR t ; Scan the keyboard until a key is pressed, returning ; the ASCII code in A and X .SVEX CLC ; Clear the C flag to indicate we didn't just load a new ; commander file RTS ; Return from the subroutine .saveerror JMP tapeerror ; Jump to tapeerror to print either "TAPE ERROR" or ; "DISK ERROR" (this JMP enables us to use a branch ; instruction to jump to tapeerror)Name: SVE [Show more] Type: Subroutine Category: Save and load Summary: Display the disk access menu and process saving of commander files Deep dive: Commander save files The competition codeContext: See this subroutine in context in the source code References: This subroutine is called as follows: * BR1 (Part 1 of 2) calls SVE * LOD calls SVE * tapeerror calls SVE * TT102 calls SVE
[X]
Subroutine BPRNT (category: Text)
Print a 32-bit number, left-padded to a specific number of digits, with an optional decimal point
[X]
Subroutine CHECK (category: Save and load)
Calculate the checksum for the last saved commander data block
[X]
Subroutine CHECK2 (category: Save and load)
Calculate the third checksum for the last saved commander data block (Commodore 64 and Apple II versions only)
[X]
Variable CHK (category: Save and load)
First checksum byte for the saved commander data file
[X]
Variable CHK2 (category: Save and load)
Second checksum byte for the saved commander data file
[X]
Variable CHK3 (category: Save and load)
Third checksum byte for the saved commander data file
[X]
Configuration variable CIA = $DC00
Registers for the CIA1 I/O interface chip, which are memory-mapped to the 16 bytes from $DC00 to $DC0F (see page 428 of the Programmer's Reference Guide)
[X]
Subroutine DETOK (category: Text)
Print an extended recursive token from the TKN1 token table
[X]
Subroutine DFAULT (category: Start and end)
Reset the current commander data block to the last saved commander
[X]
Variable DISK in workspace Option variables
Current media configuration setting
[X]
Subroutine GTNMEW (category: Save and load)
Fetch the name of a commander file to save or load
[X]
Subroutine JAMESON (category: Save and load)
Restore the default JAMESON commander
[X]
Subroutine KERNALSETUP (category: Save and load)
Set up memory and interrupts so we can use the Kernal functions and configure the file system device number and filename
[X]
Configuration variable KERNALSVE = $FFD8
The Kernal function to save a file to a device
[X]
Subroutine LOD (category: Save and load)
Load a commander file
[X]
Variable NA% (category: Save and load)
The data block for the last saved commander
[X]
Variable RASTCT (category: Drawing the screen)
The current raster count, which flips between 0 and 1 on each call to the COMIRQ1 interrupt handler (0 = space view, 1 = dashboard)
[X]
Subroutine SETL1 (category: Utility routines)
Set the 6510 input/output port register to control the memory map
[X]
Label SV1 is local to this routine
[X]
Subroutine SVE (category: Save and load)
Display the disk access menu and process saving of commander files
[X]
Label SVL1 is local to this routine
[X]
Subroutine SWAPPZERO (category: Utility routines)
A routine that swaps zero page with the page at $CE00, so that zero page changes made by Kernal functions can be reversed
[X]
Subroutine TRNME (category: Save and load)
Copy the last saved commander's name from INWK to NA%
[X]
Subroutine TT67 (category: Text)
Print a newline
[X]
Configuration variable VIC = $D000
Registers for the VIC-II video controller chip, which are memory-mapped to the 46 bytes from $D000 to $D02E (see page 454 of the Programmer's Reference Guide)
[X]
Subroutine YESNO (category: Keyboard)
Wait until either "Y" or "N" is pressed
[X]
Label feb10 is local to this routine
[X]
Label feb13 is local to this routine
[X]
Label loading is local to this routine
[X]
Label saveerror is local to this routine
[X]
Subroutine tapeerror (category: Save and load)
Print either "TAPE ERROR" or "DISK ERROR"