![]() |
Routines |
| Prev: 053F | Up: Map | Next: 05E3 |
|
This subroutine is called to load the header information and later load or verify an actual block of data from a tape.
|
||||||||||||||||||
| LD_BYTES | 0556 | INC D | This resets the zero flag. (D cannot hold +FF.) | |||||||||||||||
| 0557 | EX AF,AF' | The A register holds +00 for a header and +FF for a block of data. The carry flag is reset for verifying and set for loading. | ||||||||||||||||
| 0558 | DEC D | Restore D to its original value. | ||||||||||||||||
| 0559 | DI | The maskable interrupt is now disabled. | ||||||||||||||||
| 055A | LD A,$0F | The border is made white. | ||||||||||||||||
| 055C | OUT ($FE),A | |||||||||||||||||
| 055E | LD HL,$053F | Preload the machine stack with the address SA_LD_RET. | ||||||||||||||||
| 0561 | PUSH HL | |||||||||||||||||
| 0562 | IN A,($FE) | Make an initial read of port '254'. | ||||||||||||||||
| 0564 | RRA | Rotate the byte obtained but keep only the EAR bit. | ||||||||||||||||
| 0565 | AND $20 | |||||||||||||||||
| 0567 | OR $02 | Signal red border. | ||||||||||||||||
| 0569 | LD C,A | Store the value in the C register (+22 for 'off' and +02 for 'on' - the present EAR state). | ||||||||||||||||
| 056A | CP A | Set the zero flag. | ||||||||||||||||
|
The first stage of reading a tape involves showing that a pulsing signal actually exists (i.e. 'on/off' or 'off/on' edges).
|
||||||||||||||||||
| LD_BREAK | 056B | RET NZ | Return if the BREAK key is being pressed. | |||||||||||||||
| LD_START | 056C | CALL LD_EDGE_1 | Return with the carry flag reset if there is no 'edge' within approx. 14,000 T states. But if an 'edge' is found the border will go cyan. | |||||||||||||||
| 056F | JR NC,LD_BREAK | |||||||||||||||||
|
The next stage involves waiting a while and then showing that the signal is still pulsing.
|
||||||||||||||||||
| 0571 | LD HL,$0415 | The length of this waiting period will be almost one second in duration. | ||||||||||||||||
| LD_WAIT | 0574 | DJNZ LD_WAIT | ||||||||||||||||
| 0576 | DEC HL | |||||||||||||||||
| 0577 | LD A,H | |||||||||||||||||
| 0578 | OR L | |||||||||||||||||
| 0579 | JR NZ,LD_WAIT | |||||||||||||||||
| 057B | CALL LD_EDGE_2 | Continue only if two edges are found within the allowed time period. | ||||||||||||||||
| 057E | JR NC,LD_BREAK | |||||||||||||||||
|
Now accept only a 'leader signal'.
|
||||||||||||||||||
| LD_LEADER | 0580 | LD B,$9C | The timing constant. | |||||||||||||||
| 0582 | CALL LD_EDGE_2 | Continue only if two edges are found within the allowed time period. | ||||||||||||||||
| 0585 | JR NC,LD_BREAK | |||||||||||||||||
| 0587 | LD A,$C6 | However the edges must have been found within about 3,000 T states of each other. | ||||||||||||||||
| 0589 | CP B | |||||||||||||||||
| 058A | JR NC,LD_START | |||||||||||||||||
| 058C | INC H | Count the pair of edges in the H register until '256' pairs have been found. | ||||||||||||||||
| 058D | JR NZ,LD_LEADER | |||||||||||||||||
|
After the leader come the 'off' and 'on' parts of the sync pulse.
|
||||||||||||||||||
| LD_SYNC | 058F | LD B,$C9 | The timing constant. | |||||||||||||||
| 0591 | CALL LD_EDGE_1 | Every edge is considered until two edges are found close together - these will be the start and finishing edges of the 'off' sync pulse. | ||||||||||||||||
| 0594 | JR NC,LD_BREAK | |||||||||||||||||
| 0596 | LD A,B | |||||||||||||||||
| 0597 | CP $D4 | |||||||||||||||||
| 0599 | JR NC,LD_SYNC | |||||||||||||||||
| 059B | CALL LD_EDGE_1 | The finishing edge of the 'on' pulse must exist. (Return carry flag reset.) | ||||||||||||||||
| 059E | RET NC | |||||||||||||||||
|
The bytes of the header or the program/data block can now be loaded or verified. But the first byte is the type flag.
|
||||||||||||||||||
| 059F | LD A,C | The border colours from now on will be blue and yellow. | ||||||||||||||||
| 05A0 | XOR $03 | |||||||||||||||||
| 05A2 | LD C,A | |||||||||||||||||
| 05A3 | LD H,$00 | Initialise the 'parity matching' byte to zero. | ||||||||||||||||
| 05A5 | LD B,$B0 | Set the timing constant for the flag byte. | ||||||||||||||||
| 05A7 | JR LD_MARKER | Jump forward into the byte loading loop. | ||||||||||||||||
|
The byte loading loop is used to fetch the bytes one at a time. The flag byte is first. This is followed by the data bytes and the last byte is the 'parity' byte.
|
||||||||||||||||||
| LD_LOOP | 05A9 | EX AF,AF' | Fetch the flags. | |||||||||||||||
| 05AA | JR NZ,LD_FLAG | Jump forward only when handling the first byte. | ||||||||||||||||
| 05AC | JR NC,LD_VERIFY | Jump forward if verifying a tape. | ||||||||||||||||
| 05AE | LD (IX+$00),L | Make the actual load when required. | ||||||||||||||||
| 05B1 | JR LD_NEXT | Jump forward to load the next byte. | ||||||||||||||||
| LD_FLAG | 05B3 | RL C | Keep the carry flag in a safe place temporarily. | |||||||||||||||
| 05B5 | XOR L | Return now if the type flag does not match the first byte on the tape. (Carry flag reset.) | ||||||||||||||||
| 05B6 | RET NZ | |||||||||||||||||
| 05B7 | LD A,C | Restore the carry flag now. | ||||||||||||||||
| 05B8 | RRA | |||||||||||||||||
| 05B9 | LD C,A | |||||||||||||||||
| 05BA | INC DE | Increase the counter to compensate for its 'decrease' after the jump. | ||||||||||||||||
| 05BB | JR LD_DEC | |||||||||||||||||
|
If a data block is being verified then the freshly loaded byte is tested against the original byte.
|
||||||||||||||||||
| LD_VERIFY | 05BD | LD A,(IX+$00) | Fetch the original byte. | |||||||||||||||
| 05C0 | XOR L | Match it against the new byte. | ||||||||||||||||
| 05C1 | RET NZ | Return if 'no match'. (Carry flag reset.) | ||||||||||||||||
|
A new byte can now be collected from the tape.
|
||||||||||||||||||
| LD_NEXT | 05C2 | INC IX | Increase the 'destination'. | |||||||||||||||
| LD_DEC | 05C4 | DEC DE | Decrease the 'counter'. | |||||||||||||||
| 05C5 | EX AF,AF' | Save the flags. | ||||||||||||||||
| 05C6 | LD B,$B2 | Set the timing constant. | ||||||||||||||||
| LD_MARKER | 05C8 | LD L,$01 | Clear the 'object' register apart from a 'marker' bit. | |||||||||||||||
|
The following loop is used to build up a byte in the L register.
|
||||||||||||||||||
| LD_8_BITS | 05CA | CALL LD_EDGE_2 | Find the length of the 'off' and 'on' pulses of the next bit. | |||||||||||||||
| 05CD | RET NC | Return if the time period is exceeded. (Carry flag reset.) | ||||||||||||||||
| 05CE | LD A,$CB | Compare the length against approx. 2,400 T states, resetting the carry flag for a '0' and setting it for a '1'. | ||||||||||||||||
| 05D0 | CP B | |||||||||||||||||
| 05D1 | RL L | Include the new bit in the L register. | ||||||||||||||||
| 05D3 | LD B,$B0 | Set the timing constant for the next bit. | ||||||||||||||||
| 05D5 | JP NC,LD_8_BITS | Jump back whilst there are still bits to be fetched. | ||||||||||||||||
|
The 'parity matching' byte has to be updated with each new byte.
|
||||||||||||||||||
| 05D8 | LD A,H | Fetch the 'parity matching' byte and include the new byte. | ||||||||||||||||
| 05D9 | XOR L | |||||||||||||||||
| 05DA | LD H,A | Save it once again. | ||||||||||||||||
|
Passes round the loop are made until the 'counter' reaches zero. At that point the 'parity matching' byte should be holding zero.
|
||||||||||||||||||
| 05DB | LD A,D | Make a further pass if the DE register pair does not hold zero. | ||||||||||||||||
| 05DC | OR E | |||||||||||||||||
| 05DD | JR NZ,LD_LOOP | |||||||||||||||||
| 05DF | LD A,H | Fetch the 'parity matching' byte. | ||||||||||||||||
| 05E0 | CP $01 | Return with the carry flag set if the value is zero. (Carry flag reset if in error.) | ||||||||||||||||
| 05E2 | RET | |||||||||||||||||
| Prev: 053F | Up: Map | Next: 05E3 |