| Save routine

80F2: Save Contact Sam Cruise to tape

| This is the program used to save the standard speed code block for Contact Sam Cruise.
The standard speed code block consists of two sections of data. The first section contains the 16572 bytes of data for addresses 4000-80BB. The second section contains 32892 bytes of data starting at address 80D0, moving forward in steps of 247 bytes (rolling back to page 0x7F every time the 64K boundary is reached), and ending at 817D. Note that the second section does not contain data for addresses 8274-FFE2 (step 247); these addresses are filled in by the routine at 8116 after the fast code block has loaded. Also note that although the byte for address 817D is saved to tape, it is not loaded by the load routine; instead, it is also filled in by the routine at 8116.
80F2 | LD SP,$5CFE |
80F5 | LD HL,$81C8 | 81C8 is where the game starts after loading
80F8 | LD ($5D1B),HL | Store this address where it will be popped off the stack by the load routine
80FB | EXX | Prepare BC' for saving the second section of data
80FC | LD BC,$00F7
80FF | EXX
8100 | LD IX,$4000 | 4000 to 80BB will be saved first
8104 | LD DE,$40BB
8107 | LD A,$FF | A flag byte of 0xFF (the first byte saved) indicates a data block
8109 | LD HL,$0C98 | This constant will give a leader tone of about 2 seconds
810C | EX AF,AF' |
810D | INC DE | Adjust the length and start address to allow for the flag byte
810E | DEC IX
8110 | DI | Disable interrupts
8111 | LD A,$02 | MIC on, border red
8113 | LD B,A |
First create the 2-second leader tone.
8114 | DJNZ $8114 |
8116 | OUT ($FE),A |
8118 | XOR $0F |
811A | LD B,$A4 |
811C | DEC L |
811D | JR NZ,$8114 |
811F | DEC B |
8120 | DEC H |
8121 | JP P,$8114 |
Then create the sync pulse.
8124 | LD B,$2F |
8126 | DJNZ $8126 |
8128 | OUT ($FE),A |
812A | LD A,$0D |
812C | LD B,$37 |
812E | DJNZ $812E |
8130 | OUT ($FE),A |
It's time to save the first byte, which will be the flag byte (0xFF).
8132 | LD BC,$3B0E | B=0x3B (timing constant), C=0x0E (MIC off, border yellow)
8135 | EX AF,AF' | A=0xFF
8136 | LD L,A | L=0xFF
8137 | JP $8143 | Jump forward to save the flag byte
This is the main byte-saving loop.
813A | LD A,D | In the analagous ROM routine, the second instruction here is 'OR E', to check whether it's time to save the last byte (the parity byte)
813B | LD A,D
813C | JR Z,$814A | This jump (to save the parity byte) is never made
813E | LD L,(IX+$00) | Fetch the next byte to be saved
8141 | LD A,H | A=current parity byte
8142 | XOR L | Update this for the next byte to be saved
8143 | LD H,A | H=new parity byte
8144 | LD A,$01 | A=0x01 (MIC on, border blue)
8146 | SCF | Set the carry flag (which will act as the marker bit)
8147 | JP $8161 | Jump forward to save the byte
This section of code, if it were used, would save the parity byte.
814A | LD L,H | Pick up the parity byte in L
814B | JR $8141 | Save it
This is the bit-saving loop for the first section of data (4000-80BB).
814D | LD A,C | A=0x0E (MIC off, border yellow) for the second pass
814E | BIT 7,B | Set the zero flag to indicate that this is the second pass through the loop
8150 | DJNZ $8150 |
8152 | JR NC,$8158 | Jump if we are saving a '0'
8154 | LD B,$42 |
8156 | DJNZ $8156 |
8158 | OUT ($FE),A |
815A | LD B,$3E | Set the timing constant for the second pass
815C | JR NZ,$814D | Jump back for the second pass if we've just done the first
815E | DEC B |
815F | XOR A | Clear the carry flag
8160 | INC A | A=0x01 (MIC on, border blue)
8161 | RL L | Move the bit to be saved into the carry flag, and the marker bit leftwards
8163 | JP NZ,$8150 | Jump unless we've saved all 8 bits of the byte
A byte from the first section (4000-80BB) has just been saved. Are there any more left?
8166 | DEC DE | Decrease the length counter
8167 | INC IX | Move to the next byte to be saved
8169 | LD B,$31 | Set the timing constant for the first bit of the next byte
816B | LD A,$7F | Return if the BREAK key is being pressed
816D | IN A,($FE)
816F | RRA
8170 | RET NC
8171 | LD A,D | Have we saved 4000 to 80BB yet?
8172 | INC A
8173 | JP NZ,$813A | Jump back if not
Now a further 32892 bytes are saved: starting at 80D0, moving forward in steps of 247 bytes, rolling back to page 0x7F whenever the 64K boundary is hit, and ending at 817D.
8176 | RET NZ | This return does not happen
8177 | LD DE,$807C | We need to save a further 32892 bytes
817A | LD A,$31 | Change the instruction at 8086 (in the load routine) to LD SP,$5D1B
817C | LD ($8086),A
817F | LD B,$2E |
8181 | LD A,D | Have we saved every byte of the second section yet?
8182 | OR E
8183 | JR Z,$8191 | Jump if so
8185 | LD L,(IX+$14) | Otherwise pick up the next byte to save
8188 | LD A,H | A=current parity byte
8189 | XOR L | Update this for the next byte to be saved
818A | LD H,A | H=new parity byte
818B | LD A,$01 | A=0x01 (MIC on, border blue)
818D | SCF | Set the carry flag (which will act as the marker bit)
818E | JP $81A8 | Jump forward to save the byte
This is where we come when all 49464 bytes have been saved.
8191 | LD L,$00 |
8193 | RET |
This is the bit-saving loop for the second section of data.
8194 | LD A,C | A=0x0E (MIC off, border yellow) for the second pass
8195 | BIT 7,B | Set the zero flag to indicate that this is the second pass through the loop
8197 | DJNZ $8197 |
8199 | JR NC,$819F | Jump if we are saving a '0'
819B | LD B,$42 |
819D | DJNZ $819D |
819F | OUT ($FE),A |
81A1 | LD B,$3E | Set the timing constant for the second pass
81A3 | JR NZ,$8194 | Jump back for the second pass if we've just done the first
81A5 | DEC B |
81A6 | XOR A | Clear the carry flag
81A7 | INC A | A=0x01 (MIC on, border blue)
81A8 | RL L | Move the bit to be saved into the carry flag, and the marker bit leftwards
81AA | JP NZ,$8197 | Jump unless we've saved all 8 bits of the byte
A byte from the second section has just been saved. Are there any more left?
81AD | DEC DE | Decrease the length counter
81AE | EXX | Move forward 247 bytes to the next byte to be saved
81AF | ADD IX,BC
81B1 | EXX
81B2 | LD B,$2F | Set the timing constant for the first bit of the next byte
81B4 | JR NC,$81B8 | Jump unless IX was incremented beyond the 64K boundary
81B6 | LD IXh,$7F | Reset the high byte of the IX register
81B9 | LD A,$7F | These instructions check the BREAK key but do not act on the result
81BB | IN A,($FE)
81BD | RRA
81BE | NOP |
81BF | NOP |
81C0 | NOP |
81C1 | JP $8181 | Save the next byte