TRS-80 DOS - TRSDOS v2.3 for the Model I - BACKUP/CMD Disassembled

Page Customization

Introduction/Summary

TRSDOS v2.3 BACKUP/CMD Disassembly - The Diskette Copy Utility (Model I)

BACKUP/CMD copies a TRSDOS 2.3 diskette track by track, on two drives or on one drive with diskette changes. It asks for (or takes from the command line) the source and destination drives and the backup date, checks both drives, formats the destination when it cannot be read, refuses a readable destination whose pack ID differs from the source's, copies every track that holds data, reads each sector back, and writes the source's allocation table with the new date to the destination. It then shows BACKUP COMPLETE and halts the computer: the copy routines are moved over SYS0/SYS at 4200H, so there is no TRSDOS left to return to.

The file is 3,840 bytes: a name record (BACKUP), a 169-byte copyright comment record, 14 load records and a transfer record (5200H), then 616 bytes of E5H. The load records hold 2,985 bytes: 5200H-5AA3H, 5AAEH-5AAFH and 5F9BH-629DH. At 52CAH the program copies 559BH-609AH to 4200H-4CFFH; the code and messages at 559BH-5AAFH run there, at their file address minus 139BH. On this page those rows show the address they run at, with the file address under it; every other row shows its file address. Every loaded byte is on one row, checked against S:\1\BACKUP.CMD and its listing.

Memory Map

Address RangeUse
5200H-52C9H
202 bytes
Start: refuse while program chaining, the title, the source and destination drives, the backup date (SYS0/SYS still present).
52CAH-539BH
210 bytes
Move the copy code to 4200H; check the source and its boot sector and allocation table; check the destination; compare the pack IDs or start the format.
539CH-54ECH
337 bytes
Format: check the index pulses, build and write each track.
54EDH-559AH
174 bytes
Format: verify; check the source's data against the destination's flaws; size the buffer on one drive.
559BH-5AAFH
1,301 bytes
The copy code, its messages and variables, run at 4200H-4714H (see below).
5AB0H-5F9AH
1,259 bytes
Not in the file; its copy at 4715H-4BFFH holds the work tables.
5F9BH-629DH
771 bytes
The messages of the start and the format, and the sector order table (6293H).
6300H-6F20H
3,105 bytes
Outside the file: the image of one track built by the format.

After 52CAH:

Address RangeUse
4200H-434EH
335 bytes
The copy: mark the destination, load passes, write and read back.
434FH-43B2H
100 bytes
Finish (allocation table with the date, boot sector) and the halt routine 43A3H.
43B3H-4436H
132 bytes
Write a sector, lock a track out, two decimal digits, store bytes into the track image, RESTORE, select the source.
4437H-458AH
340 bytes
Make sure the right diskette is in, ask for a diskette, select a drive, read a sector, display a message.
458BH-4714H
394 bytes
The copy's messages and variables.
4800H-4822H
35 bytes
The controller's status after reading sector 9 of each track: the data mark the track is written with.
4900H-49FFH
256 bytes
The source's allocation table: 4900H-4922H allocation, 4960H-4982H lockout table, 49CEH-49D7H pack ID, 49D8H-49DFH date.
4A00H-4AFFH
256 bytes
The destination's allocation table, or the format's lockout table at 4A00H-4A22H; 4A60H-4A82H the destination's lockout table.
4B00H-4BFFH
256 bytes
The sector buffer (boot sectors, allocation tables, the format's verify).
4D00H up
2,560 bytes a track
The tracks loaded: one on two drives, as many as fit below the top of memory on one drive.

How BACKUP Works

BACKUP refuses to run when bit 5 of the system flags at 430FH is set, with SINGLE DRIVE BACKUP INVALID DURING PROGRAM CHAINING!, before it knows the drives. The drives may be given as BACKUP :s :d (anything between the two drive numbers is skipped); otherwise, or when 4030H holds C7H (the value the ROM itself puts there, not TRSDOS's error exit), they are asked for. The date comes from SYS0/SYS (4470H) when its month byte is not 0, else it is asked for: eight characters with slashes in the third and sixth places.

The two drive numbers become select bits (01H, 02H, 04H, 08H) stored in the copy code. When they are the same, BACKUP works on one drive and asks for INSERT SOURCE DISK or INSERT DESTINATION DISK each time it needs the other diskette; the prompt blinks until ENTER is pressed. On one drive every diskette inserted is checked: the source by its boot sector's first byte (00H) and its pack ID, the destination by the 76H that BACKUP writes as the first byte of its boot sector at the start of the copy.

Both drives are restored to track 0; NOT READY or a head not on track 0 stops BACKUP with a message. The source's boot sector gives the directory track (byte 2), whose sector 0, the allocation table, is read to 4900H. When the destination's boot sector cannot be read, the destination is formatted. When it can, its allocation table must have the same bytes CEH-D7H as the source's (the master password hash and the diskette name, which BACKUP calls the pack ID); a different diskette is refused, so BACKUP only writes over blank diskettes or earlier backups of the same diskette.

Formatting the Destination

BACKUP first times the index pulses of the destination: a pulse that does not end means no diskette, a pulse that does not come means the door is open, and pulses too close together mean a hard-sectored diskette. Each of the 35 tracks is then built at 6300H (ten sectors of 256 E5H bytes, in the order 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, with the FAH data mark on the directory track and FBH elsewhere) and written with WRITE TRACK. The number of bytes the controller took is checked: fewer than 0BEDH gives MOTOR SPEED TOO SLOW, 0C69H or more MOTOR SPEED TOO FAST. Every sector is then read; a track with a sector not found or with a CRC error is locked out (FFH in the table at 4A00H). Finally every granule the source uses must lie on a destination track that is not locked out.

The Copy

The copy marks the destination's boot sector with 76H, then works in passes. A load pass reads, from track 0 up, every track whose allocation byte shows a granule in use (and not locked out on the source) into memory from 4D00H, showing LOADING TRACK tt, SECTOR ss; it stops after one track on two drives, or when the tracks that fit (4713H) are loaded on one drive. The write pass writes those tracks to the destination at the same track and sector, showing COPYING, with the data mark the source's sector 9 had, and reads each sector back (VERIFYING). Tracks without data are neither read nor written. At the end the source's allocation table, with the backup date at bytes D8H-DFH, is written to the destination's directory track, the boot sector gets its real first byte back, and BACKUP COMPLETE is shown.

Errors end BACKUP the same way as success: the message, HIT 'ENTER' TO CONTINUE, and HALT after ENTER. The read and write routines try each sector twice; the read accepts the FAH data mark of directory sectors.

Notes from the Code

  • The refusal at 520CH tests only bit 5 of 430FH, but its message speaks of a single drive backup: the drives have not been read yet.
  • The format's byte count is low when the diskette turns fast (a shorter revolution takes fewer bytes) and high when it turns slowly, but the code shows MOTOR SPEED TOO SLOW for a low count (54DFH) and MOTOR SPEED TOO FAST for a high one (54E9H).
  • 54A3H calls 54A7H a second time when it returns the NZ FLAG, but 54A7H returns only with the Z FLAG of the BIT at 54CEH (it halts on every error), so each track is written once.
  • The destination's allocation table is the source's with the new date (434FH-4368H): the lockout table the format made, with the tracks it locked out, is not written to it, and 4A00H, which 42C4H fills during the copy, is never used.
  • Every sector of a track is written with the data mark of the source's sector 9 (4284H, 42F5H-42FEH).
  • The read back after each write checks only that the sector can be read; the data read is not compared with the data written.
  • 5507H loads the track into Register A and 5508H replaces it with the sector at once.
  • RESTORE (441AH) and the waits for BUSY have no time limit.

Variables

Variables and Changed Operands

Address RangePurpose
5256H
1 byte
The second byte of SET n,A at 5255H, n = the source drive (5251H).
5290H
1 byte
The second byte of SET n,A at 528FH, n = the destination drive (528BH).
5435H
1 byte
The track being formatted (53F8H, 548AH), read at 53FBH, 540BH, 5434H and 5486H.
545FH
1 byte
The data mark of the track being formatted, FAH or FBH (541AH), read at 545EH.
5AA5H-5AACH
8 bytes
Not in the file: the backup date as typed or from 4470H, moved to 470AH by 52CAH.
42ADH
1 byte
The controller's track register at the start of a load pass (423AH), put back at 42ACH-42AEH.
42B2H
1 byte
The first track of the current pass (423EH), read at 42B1H.
4390H
1 byte
The first byte of the source's boot sector (42D4H), written back at 438FH-4391H.
43D4H
1 byte
The write command of 43B3H (stored there), sent at 43D3H.
442BH
1 byte
The source drive's select bit (5257H through 52CAH), read at 442AH and 52D9H.
449DH
1 byte
The destination drive's select bit (5291H through 52CAH), read at 449CH and 52DCH-52DFH.
44E8H
1 byte
The drive selected and the diskette in place: select bit plus 80H for the source or 40H for the destination; 00H when not known (52D6H, 44EBH, 4497H, 44E2H). Read at 44E7H, 4437H, 44B4H and 452BH.
44EFH
1 byte
00H for a backup on one drive, not 00H for two drives (52E0H); read at 44EEH, 4441H, 44BEH, 428FH and 5573H.
4709H
1 byte
Not in the file: the directory track (530EH).
470AH-4711H
8 bytes
Not in the file: the backup date, copied into the allocation table at 434FH.
4713H
1 byte
The tracks that fit in memory on one drive (5595H), read at 4295H.
4714H
1 byte
The tracks loaded and not yet written (422FH, 428EH, 433EH), read at 4298H, 42A2H and 4345H.
459CH, 45A7H, 45BBH, 45C6H, 45DAH, 45E5H, 6176H
2 bytes each
The track and sector digits of the progress lines, stored through 4402H.

Addresses Outside BACKUP/CMD

Address RangeUse
4030H
1 byte
Tested for C7H (5205H, 5223H, 525AH, 5294H); BACKUP jumps to 4030H after the chaining refusal.
430FH
1 byte
The system flags: bit 5 makes BACKUP refuse to run.
4046H
1 byte
SYS0/SYS's month; 00H means no date is set.
4467H, 4470H
SYS0/SYS
Display a message, the date as MM/DD/YY: used only before 52CAH.
37E1H
1 byte
The drive select latch (452EH).
37ECH-37EFH
4 bytes
The controller: command and status, track, sector, data registers.
3840H
1 byte
Keyboard row 6; bit 0 is ENTER.
0033H, 0040H, 0060H
ROM
Display a character, read a line, wait Register Pair BC delay units.

Disassembly

5200H - BACKUP Starts: Title and Source Drive

SYS1/SYS loads BACKUP/CMD at 5200H and jumps here with Register Pair HL = the command line after the name. BACKUP takes the source and destination drive numbers from the command line (each after a colon) or asks for them, and takes the backup date from SYS0/SYS's date or asks for it. When the byte at 4030H is C7H (RST 00H, the value the ROM's own start-up puts there) instead of TRSDOS's exit after an error, the command line and the date are not used and everything is asked for. Until 52CAH the program uses SYS0/SYS's message routines; after that it overwrites 4200H-4CFFH and works alone.

5200
DI F3
Disable interrupts: SYS0/SYS's clock and disk interrupt routines must not run, and 52CAH will overwrite them.
5201
LD SP,41FCH 31 FC 41
Load the Stack Pointer with 41FCH, the top of TRSDOS's stack area below 4200H.
5204
PUSH HL E5
Save Register Pair HL (the command line after BACKUP) onto the stack.
5205
LD A,(4030H) 3A 30 40
Fetch the first byte of the exit after an error from 4030H into Register A: 3EH (LD A,A3H) or CDH (CALL 400FH under DEBUG) with TRSDOS's SYS0/SYS, C7H (RST 00H) as the ROM leaves it.
5208
CP C7H FE C7
Compare Register A against C7H, the RST 00H the ROM puts at 4030H.
520A
If the Z FLAG is set (C7H), JUMP to 521CH: the system flags are not looked at.
520C
LD A,(430FH) 3A 0F 43
Fetch the system flags from 430FH into Register A.
520F
BIT 5,A CB 6F
Test bit 5 of Register A (the system flags), the bit the refusal message calls program chaining.
5211
If the Z FLAG is set (bit 5 clear), JUMP to 521CH to start.
5213
LD HL,5F9BH 21 9B 5F
Point Register Pair HL to 5F9BH, the message SINGLE DRIVE BACKUP INVALID DURING PROGRAM CHAINING!; it is shown whatever the drives, which are not known yet.
5216
GOSUB to SYS0/SYS's 4467H to display the text at Register Pair HL (5F9BH) up to and including its 0DH.
5219
JUMP to 4030H, the exit after an error, back to TRSDOS.

521CH - Title, then the Source Drive

Shows the title, then reads the source drive number: from the command line when it starts with a colon, else by asking SOURCE DRIVE NUMBER ?. A digit 0-3 is turned into a SET n,A instruction whose result is the drive's select bit, stored in the relocated code at 442BH.

521C
LD HL,5FD0H 21 D0 5F
Point Register Pair HL to 5FD0H, the title: clear the screen, TRSDOS DISK BACKUP UTILITY VER 2.3. 520AH and 5211H jump here.
521F
GOSUB to SYS0/SYS's 4467H to display the title at Register Pair HL (5FD0H).
5222
POP HL E1
Restore Register Pair HL (the command line after BACKUP) from the stack.
5223
LD A,(4030H) 3A 30 40
Fetch the first byte of the exit after an error from 4030H into Register A again.
5226
CP C7H FE C7
Compare Register A against C7H, the RST 00H the ROM puts at 4030H.
5228
If the Z FLAG is set (no TRSDOS command line to read), JUMP to 5232H to ask for the source drive.
522A
LD A,(HL) 7E
Fetch the first character of the command line from (HL) (Register Pair HL = the command line pointer) into Register A.
522B
CP 3AH FE 3A
Compare Register A against 3AH, the colon before a drive number.
522D
If the NZ FLAG is set (no colon), JUMP to 5232H to ask for the source drive.
522F
INC HL 23
INCrement Register Pair HL (the command line pointer) by 1, to the drive digit.
5230
JUMP to 5240H to check the drive digit taken from the command line.
5232
LD HL,5FF8H 21 F8 5F
Ask for the Source Drive
Point Register Pair HL to 5FF8H, the prompt SOURCE DRIVE NUMBER ?. 5228H, 522DH, 5243H and 5248H jump here.
5235
GOSUB to SYS0/SYS's 4467H to display the prompt at Register Pair HL; it ends with 03H, so the cursor stays after it.
5238
LD HL,4B00H 21 00 4B
Point Register Pair HL to 4B00H, the buffer for the answer, inside SYS0/SYS's resident area; the routines BACKUP still calls before 52CAH (4467H, 4470H) are elsewhere.
523B
LD B,01H 06 01
Load Register B with 01H: one character may be typed.
523D
GOSUB to ROM routine at 0040H to read a line of at most Register B characters into the buffer at Register Pair HL; it returns Register Pair HL = 4B00H.
5240
LD A,(HL) 7E
Check the Source Drive
Fetch the drive character from (HL) (Register Pair HL = the command line or 4B00H) into Register A. 5230H jumps here.
5241
SUB 30H D6 30
SUBtract 30H from Register A, turning the digit into a drive number; the CARRY FLAG is set for a character below the digit 0.
5243
If the CARRY FLAG is set (not a digit), JUMP to 5232H to ask again.
5246
CP 04H FE 04
Compare Register A (the drive number) against 04H: the NO CARRY FLAG is set for 4 or more.
5248
If the NO CARRY FLAG is set (not 0-3), JUMP to 5232H to ask again.
524B
INC HL 23
INCrement Register Pair HL by 1, past the digit.
524C
RLCA 07
Rotate Register A (the drive number 0-3) left: times 2.
524D
RLCA 07
Rotate Register A (the source drive number) left again: times 4.
524E
RLCA 07
Rotate Register A left again: the drive number times 8, in bits 3-4.
524F
OR C7H F6 C7
OR Register A with C7H: the second byte of SET n,A (CBH C7H plus 8 times n), with n the drive number.
5251
LD (5256H),A 32 56 52
Store Register A into 5256H, the second byte of the SET instruction at 5255H.
5254
XOR A AF
Set Register A to ZERO with XOR A, the value the SET at 5255H works on.
5255
SET 0,A CB C7
SET bit n of Register A, with n the source drive written into 5256H by 5251H (SET 0,A in the file): Register A = the drive's select bit, 01H, 02H, 04H or 08H.
5257
LD (57C6H),A 32 C6 57
Store Register A (the source drive's select bit) into 57C6H, which 52CAH moves to 442BH, the operand of LD A,nn at 442AH.
525A
LD A,(4030H) 3A 30 40
The Destination Drive
Fetch the first byte of the exit after an error from 4030H into Register A again.
525D
CP C7H FE C7
Compare Register A against C7H, the RST 00H the ROM puts at 4030H.
525F
If the Z FLAG is set (no TRSDOS command line to read), JUMP to 526DH to ask for the destination drive.
5261
LD A,(HL) 7E
Find the Second Colon
Fetch the next character from (HL) (Register Pair HL = the command line pointer) into Register A. 5269H loops back here.
5262
INC HL 23
INCrement Register Pair HL (the command line pointer) by 1.
5263
CP 0DH FE 0D
Compare Register A against 0DH, the ENTER that ends the line.
5265
If the Z FLAG is set (no second drive given), JUMP to 526DH to ask for it.
5267
CP 3AH FE 3A
Compare Register A against 3AH, the colon before the destination drive; anything else (spaces, TO) is passed over.
5269
If the NZ FLAG is set (not a colon), LOOP BACK to 5261H.
526B
JUMP to 527BH to check the digit after the colon.
526D
LD HL,600FH 21 0F 60
Ask for the Destination Drive
Point Register Pair HL to 600FH, the prompt DESTINATION DRIVE NUMBER ?. 525FH, 5265H, 527EH and 5283H jump here.
5270
GOSUB to SYS0/SYS's 4467H to display the prompt at Register Pair HL; it ends with 03H.
5273
LD HL,4B00H 21 00 4B
Point Register Pair HL to 4B00H, the buffer for the answer.
5276
LD B,01H 06 01
Load Register B with 01H: one character may be typed.
5278
GOSUB to ROM routine at 0040H to read a line of at most Register B characters into the buffer at Register Pair HL.
527B
LD A,(HL) 7E
Check the Destination Drive
Fetch the drive character from (HL) (Register Pair HL = the command line or 4B00H) into Register A. 526BH jumps here.
527C
SUB 30H D6 30
SUBtract 30H from Register A, turning the digit into a drive number.
527E
If the CARRY FLAG is set (not a digit), JUMP to 526DH to ask again.
5281
CP 04H FE 04
Compare Register A (the drive number) against 04H: the NO CARRY FLAG is set for 4 or more.
5283
If the NO CARRY FLAG is set (not 0-3), JUMP to 526DH to ask again.
5286
RLCA 07
Rotate Register A (the drive number 0-3) left: times 2.
5287
RLCA 07
Rotate Register A (the destination drive number) left again: times 4.
5288
RLCA 07
Rotate Register A left again: the drive number times 8.
5289
OR C7H F6 C7
OR Register A with C7H: the second byte of SET n,A for the destination drive.
528B
LD (5290H),A 32 90 52
Store Register A into 5290H, the second byte of the SET instruction at 528FH.
528E
XOR A AF
Set Register A to ZERO with XOR A, the value the SET at 528FH works on.
528F
SET 0,A CB C7
SET bit n of Register A, with n the destination drive written into 5290H by 528BH (SET 0,A in the file): Register A = the drive's select bit.
5291
LD (5838H),A 32 38 58
Store Register A (the destination drive's select bit) into 5838H, which 52CAH moves to 449DH, the operand of LD A,nn at 449CH.

5294H - The Backup Date

Takes SYS0/SYS's date (MM/DD/YY through 4470H) when TRSDOS is present and its month byte at 4046H is not 0; otherwise asks BACKUP DATE (MM/DD/YY) ? and accepts any eight characters with slashes in the third and sixth places. The date goes to 5AA5H-5AACH, which 52CAH moves to 470AH-4711H; it becomes the date of the backup's allocation table (434FH).

5294
LD A,(4030H) 3A 30 40
Fetch the first byte of the exit after an error from 4030H into Register A again.
5297
CP C7H FE C7
Compare Register A against C7H, the RST 00H the ROM puts at 4030H.
5299
If the Z FLAG is set (no TRSDOS date to use), JUMP to 52A9H to ask for the date.
529B
LD A,(4046H) 3A 46 40
Fetch the month from 4046H, SYS0/SYS's date, into Register A.
529E
OR A B7
OR Register A with itself: the Z FLAG is set when the month is 0, no date set.
529F
If the Z FLAG is set, JUMP to 52A9H to ask for the date.
52A1
LD HL,5AA5H 21 A5 5A
Point Register Pair HL to 5AA5H, the eight-byte date buffer (not in the file).
52A4
GOSUB to SYS0/SYS's 4470H to write the date as MM/DD/YY at Register Pair HL (5AA5H).
52A7
JUMP to 52CAH to move the copy code into place.
52A9
LD HL,602BH 21 2B 60
Ask for the Date
Point Register Pair HL to 602BH, the prompt BACKUP DATE (MM/DD/YY) ?. 5299H, 529FH, 52BAH, 52C1H and 52C8H jump here.
52AC
GOSUB to SYS0/SYS's 4467H to display the prompt at Register Pair HL; it ends with 03H.
52AF
LD HL,5AA5H 21 A5 5A
Point Register Pair HL to 5AA5H, the date buffer.
52B2
LD B,08H 06 08
Load Register B with 08H: up to eight characters may be typed.
52B4
GOSUB to ROM routine at 0040H to read a line of at most Register B characters into the buffer at Register Pair HL (5AA5H); Register B returns the number typed.
52B7
LD A,B 78
Copy the number of characters typed from Register B into Register A.
52B8
CP 08H FE 08
Compare Register A against 08H: the date must have all eight characters.
52BA
If the NZ FLAG is set (fewer typed), JUMP to 52A9H to ask again.
52BC
LD A,(5AA7H) 3A A7 5A
Fetch the third character of the date from 5AA7H into Register A.
52BF
CP 2FH FE 2F
Compare Register A against 2FH, the slash after MM.
52C1
If the NZ FLAG is set, JUMP to 52A9H to ask again.
52C3
LD A,(5AAAH) 3A AA 5A
Fetch the sixth character of the date from 5AAAH into Register A.
52C6
CP 2FH FE 2F
Compare Register A against 2FH, the slash after DD; the digits themselves are not checked.
52C8
If the NZ FLAG is set, JUMP to 52A9H to ask again.

52CAH - Move the Copy Code to 4200H and Check the Diskettes

Copies 0B00H bytes from 559BH to 4200H-4CFFH: the copy routines (559BH-5AAFH, which run at 4200H-4714H) and, after them, memory BACKUP uses as work tables. From here SYS0/SYS is gone and BACKUP drives the controller itself. Then the source drive is restored to track 0 and checked, its boot sector gives the directory track, its allocation table goes to 4900H; the destination drive is checked; when its boot sector can be read, its allocation table must carry the same pack ID (bytes CEH-D7H: the master password hash and the diskette name) as the source, else the backup is refused; when it cannot be read, the destination is formatted (5386H).

52CA
LD HL,559BH 21 9B 55
Point Register Pair HL to 559BH, the start of the code that runs at 4200H. 52A7H jumps here.
52CD
LD DE,4200H 11 00 42
Point Register Pair DE to 4200H, where it runs, over SYS0/SYS's resident code.
52D0
LD BC,B00H 01 00 0B
Load Register Pair BC with 0B00H, 2,816 bytes: 559BH-609AH go to 4200H-4CFFH.
52D3
LDIR ED B0
Move the code: LDIR copies Register Pair BC bytes from (HL) (Register Pair HL = 559BH) to (DE) (Register Pair DE = 4200H). From here on the addresses 4200H-4CFFH are BACKUP's.
52D5
XOR A AF
Set Register A to ZERO with XOR A: no drive has been selected yet.
52D6
LD (44E8H),A 32 E8 44
Store Register A (00H) into 44E8H, the operand of CP nn at 44E7H: the drive (and diskette) last selected.
52D9
LD A,(442BH) 3A 2B 44
Fetch the source drive's select bit from 442BH (stored at 5257H, moved by the LDIR) into Register A.
52DC
LD HL,449DH 21 9D 44
Point Register Pair HL to 449DH, the destination drive's select bit (stored at 5291H).
52DF
SUB (HL) 96
SUBtract the destination's select bit at (HL) (Register Pair HL = 449DH) from Register A: 00H when both are the same drive.
52E0
LD (44EFH),A 32 EF 44
Store Register A into 44EFH, the operand of LD A,nn at 44EEH: 00H for a backup on one drive (with diskette changes), not 00H for two drives.
52E3
GOSUB to 442AH to select the source drive, first asking INSERT SOURCE DISK on a one-drive backup.
52E6
GOSUB to 441AH to send RESTORE to the controller and wait until it is done: the head goes to track 0.
52E9
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A: after RESTORE bit 7 is NOT READY and bit 2 TRACK 0.
52EC
LD HL,6045H 21 45 60
Point Register Pair HL to 6045H, the message SOURCE DRIVE NOT READY!.
52EF
BIT 7,A CB 7F
Test bit 7 of Register A (the status), NOT READY.
52F1
If the NZ FLAG is set (the source drive is not ready), JUMP to 43A3H to show the message at Register Pair HL, wait for ENTER and halt.
52F4
LD HL,605DH 21 5D 60
Point Register Pair HL to 605DH, the message SOURCE DRIVE NOT IN SYSTEM!.
52F7
BIT 2,A CB 57
Test bit 2 of Register A (the status), TRACK 0: a drive that is there has its head on track 0 after RESTORE.
52F9
If the Z FLAG is set (not at track 0, no such drive), JUMP to 43A3H to show the message at Register Pair HL and halt.
52FC
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: Register D = track 0, Register E = sector 0, the boot sector.
52FF
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
5302
GOSUB to 453CH to read track Register D, sector Register E of the selected drive into (BC); the NZ FLAG after two failed tries.
5305
LD HL,45E8H 21 E8 45
Point Register Pair HL to 45E8H, the message SOURCE DISK READ ERROR!; LD does not change the flags.
5308
If the NZ FLAG is set (the read failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
530B
LD A,(4B02H) 3A 02 4B
Fetch byte 2 of the source's boot sector from 4B02H into Register A: the directory track.
530E
LD (4709H),A 32 09 47
Store Register A (the directory track) into 4709H, BACKUP's variable for it (not in the file).
5311
LD A,(4709H) 3A 09 47
Fetch the directory track from 4709H into Register A again.
5314
LD D,A 57
Copy the directory track from Register A into Register D.
5315
LD E,00H 1E 00
Load Register E with 00H, sector 0 of the directory track, the granule allocation table.
5317
LD BC,4900H 01 00 49
Point Register Pair BC to 4900H, the buffer for the source's allocation table.
531A
GOSUB to 453CH to read track Register D, sector Register E into (BC) (Register Pair BC = 4900H).
531D
LD HL,45E8H 21 E8 45
Point Register Pair HL to 45E8H, the message SOURCE DISK READ ERROR!.
5320
If the NZ FLAG is set (the read failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
5323
GOSUB to 449CH to select the destination drive (asking INSERT DESTINATION DISK on one drive); it halts with DESTINATION DISK IS WRITE PROTECTED! when the status says so.
5326
GOSUB to 441AH to send RESTORE to the controller and wait: the destination's head goes to track 0.
5329
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A.
532C
LD HL,6079H 21 79 60
Point Register Pair HL to 6079H, the message DESTINATION DRIVE NOT READY!.
532F
BIT 7,A CB 7F
Test bit 7 of Register A (the status), NOT READY.
5331
If the NZ FLAG is set (not ready), JUMP to 43A3H to show the message at Register Pair HL and halt.
5334
LD HL,6096H 21 96 60
Point Register Pair HL to 6096H, the message DESTINATION DRIVE NOT IN SYSTEM!.
5337
BIT 2,A CB 57
Test bit 2 of Register A (the status), TRACK 0.
5339
If the Z FLAG is set (not at track 0, no such drive), JUMP to 43A3H to show the message at Register Pair HL and halt.
533C
LD HL,463EH 21 3E 46
Point Register Pair HL to 463EH, the message DESTINATION DISK IS WRITE PROTECTED!.
533F
BIT 6,A CB 77
Test bit 6 of Register A (the status), WRITE PROTECT.
5341
If the NZ FLAG is set (protected), JUMP to 43A3H to show the message at Register Pair HL and halt.
5344
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
5347
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: track 0, sector 0, the destination's boot sector.
534A
GOSUB to 453CH to read track Register D, sector Register E of the destination into (BC) (Register Pair BC = 4B00H).
534D
If the NZ FLAG is set (it cannot be read, an unformatted diskette), JUMP to 5386H to format the destination.
5350
LD A,(4709H) 3A 09 47
Fetch the source's directory track from 4709H into Register A; the destination's table is looked for on the same track.
5353
LD D,A 57
Copy the directory track from Register A into Register D.
5354
LD E,00H 1E 00
Load Register E with 00H, sector 0, the allocation table.
5356
LD BC,4A00H 01 00 4A
Point Register Pair BC to 4A00H, the buffer for the destination's allocation table.
5359
GOSUB to 453CH to read track Register D, sector Register E of the destination into (BC) (Register Pair BC = 4A00H).
535C
LD HL,4601H 21 01 46
Point Register Pair HL to 4601H, the message DESTINATION DISK READ ERROR!.
535F
If the NZ FLAG is set (the read failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
5362
LD HL,49CEH 21 CE 49
Point Register Pair HL to 49CEH, bytes CEH-D7H of the source's table: the master password hash and the diskette name, the pack ID.
5365
LD DE,4ACEH 11 CE 4A
Point Register Pair DE to 4ACEH, the same ten bytes of the destination's table.
5368
LD B,0AH 06 0A
Load Register B with 0AH, the ten bytes to compare.
536A
LD A,(DE) 1A
Compare the Pack IDs
Fetch the destination's byte from (DE) (Register Pair DE = the destination pointer) into Register A. 5370H loops back here.
536B
CP (HL) BE
Compare Register A against the source's byte at (HL) (Register Pair HL = the source pointer).
536C
If the NZ FLAG is set (different), JUMP to 5380H to refuse the backup.
536E
INC DE 13
INCrement Register Pair DE (the destination pointer) by 1.
536F
INC HL 23
INCrement Register Pair HL (the source pointer) by 1.
5370
Compare Loop End
DECrement Register B and LOOP BACK to 536AH until the ten bytes match.
5372
LD HL,4A60H 21 60 4A
Point Register Pair HL to 4A60H, bytes 60H-82H of the destination's table, its track lockout table.
5375
LD DE,4A00H 11 00 4A
Point Register Pair DE to 4A00H, the start of the same buffer.
5378
LD BC,0023H 01 23 00
Load Register Pair BC with 0023H, one byte for each of the 35 tracks.
537B
LDIR ED B0
Copy the lockout table: LDIR moves 23H bytes from (HL) (Register Pair HL = 4A60H) to (DE) (Register Pair DE = 4A00H), counting Register Pair BC down, to the place the format builds its own table.
537D
JUMP to 5553H: a destination with the same pack ID is not formatted again.
5380
LD HL,612DH 21 2D 61
Different Pack IDs
Point Register Pair HL to 612DH, the message BACKUP REJECTED, DISKETTES CONTAIN DIFFERENT PACK IDS!. 536CH jumps here.
5383
JUMP to 43A3H to show the message at Register Pair HL, wait for ENTER and halt.

5386H - Format the Destination: the Lockout Table

Reached when the destination's boot sector cannot be read. Fills 4A00H-4A22H, one byte per track, with FCH (both granules usable) and 4A23H-4ACAH with FFH; the format's verify (54EDH) puts FFH for each track that fails. Then checks the drive's index pulses (539CH), formats the 35 tracks (53F7H) and verifies them (54EDH).

5386
LD HL,4A00H 21 00 4A
Point Register Pair HL to 4A00H, the lockout table being built. 534DH jumps here.
5389
XOR A AF
Set Register A to ZERO with XOR A, the track count.
538A
LD (HL),FCH 36 FC
Track Loop
Store FCH at (HL) (Register Pair HL = the table pointer): bits 0 and 1 clear, both granules of the track usable. 5390H loops back here.
538C
INC HL 23
INCrement Register Pair HL (the table pointer) by 1.
538D
INC A 3C
INCrement Register A (the track count) by 1, to the next track.
538E
CP 23H FE 23
Compare Register A against 23H, the 35 tracks.
5390
Track Loop End
If the NZ FLAG is set, LOOP BACK to 538AH for the next track.
5392
CP CBH FE CB
Fill Loop
Compare Register A (the byte count) against CBH. 539AH loops back here.
5394
If the Z FLAG is set (4ACBH reached), JUMP to 539CH.
5396
LD (HL),FFH 36 FF
Store FFH at (HL) (Register Pair HL = the buffer pointer).
5398
INC HL 23
INCrement Register Pair HL (the buffer pointer) by 1.
5399
INC A 3C
INCrement Register A (the byte count) by 1, to the next byte of the buffer.
539A
Fill Loop End
LOOP BACK to 5392H for the next byte.

539CH - Format: Check the Index Pulses

The failed read left the controller with FORCE INTERRUPT (4578H), so bit 1 of its status is the index pulse. BACKUP waits for the pulse to end (NO DISKETTE IN DESTINATION DRIVE! when it does not), waits for the next one to start (DOOR NOT CLOSED ON DESTINATION DRIVE! when none comes), then counts the loop turns of one whole pulse and gap in Register Pair DE. Fewer than 1535H turns means the pulses come too often: DESTINATION DISKETTE UNUSABLE! HARD-SECTORED!.

539C
LD BC,00CDH 01 CD 00
Load Register Pair BC with 00CDH, the loop turns allowed for the index pulse to end. 5394H jumps here.
539F
LD HL,60B7H 21 B7 60
Point Register Pair HL to 60B7H, the message NO DISKETTE IN DESTINATION DRIVE!.
53A2
DEC BC 0B
Wait for the Pulse to End
DECrement Register Pair BC (the turns left) by 1. 53ADH loops back here.
53A3
LD A,B 78
Copy Register B (the high byte of the turns left) into Register A.
53A4
OR C B1
OR Register A with Register C: the Z FLAG is set when no turns are left.
53A5
If the Z FLAG is set (out of time), JUMP to 43A3H to show the message at Register Pair HL, wait for ENTER and halt.
53A8
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A.
53AB
AND 02H E6 02
AND Register A with 02H, keeping bit 1, the index pulse.
53AD
If the NZ FLAG is set (the pulse is still there), LOOP BACK to 53A2H.
53AF
LD BC,199DH 01 9D 19
Load Register Pair BC with 199DH, the loop turns allowed for the next pulse to come.
53B2
LD HL,60D9H 21 D9 60
Point Register Pair HL to 60D9H, the message DOOR NOT CLOSED ON DESTINATION DRIVE!.
53B5
DEC BC 0B
Wait for the Next Pulse
DECrement Register Pair BC (the turns left) by 1. 53C0H loops back here.
53B6
LD A,B 78
Copy Register B (the high byte of the turns left) into Register A.
53B7
OR C B1
OR Register A with Register C: the Z FLAG is set when no turns are left.
53B8
If the Z FLAG is set (no pulse came), JUMP to 43A3H to show the message at Register Pair HL and halt.
53BB
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A.
53BE
AND 02H E6 02
AND Register A with 02H, keeping bit 1, the index pulse.
53C0
If the Z FLAG is set (no pulse yet), LOOP BACK to 53B5H.
53C2
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, the count of loop turns for one revolution.
53C5
LD BC,00BAH 01 BA 00
Load Register Pair BC with 00BAH, the turns allowed for this pulse to end.
53C8
LD HL,60B7H 21 B7 60
Point Register Pair HL to 60B7H, the message NO DISKETTE IN DESTINATION DRIVE!.
53CB
DEC BC 0B
Count the Pulse
DECrement Register Pair BC (the turns left) by 1. 53D7H loops back here.
53CC
LD A,B 78
Copy Register B (the high byte of the turns left) into Register A.
53CD
OR C B1
OR Register A with Register C: the Z FLAG is set when no turns are left.
53CE
If the Z FLAG is set (the pulse did not end), JUMP to 43A3H to show the message at Register Pair HL and halt.
53D1
INC DE 13
INCrement Register Pair DE (the turns counted) by 1.
53D2
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A.
53D5
AND 02H E6 02
AND Register A with 02H, keeping bit 1, the index pulse.
53D7
If the NZ FLAG is set (still in the pulse), LOOP BACK to 53CBH.
53D9
LD BC,1720H 01 20 17
Load Register Pair BC with 1720H, the turns allowed for the gap before the next pulse.
53DC
LD HL,60D9H 21 D9 60
Point Register Pair HL to 60D9H, the message DOOR NOT CLOSED ON DESTINATION DRIVE!.
53DF
DEC BC 0B
Count the Gap
DECrement Register Pair BC (the turns left) by 1. 53EBH loops back here.
53E0
LD A,B 78
Copy Register B (the high byte of the turns left) into Register A.
53E1
OR C B1
OR Register A with Register C: the Z FLAG is set when no turns are left.
53E2
If the Z FLAG is set (no next pulse), JUMP to 43A3H to show the message at Register Pair HL and halt.
53E5
INC DE 13
INCrement Register Pair DE (the turns counted) by 1.
53E6
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A.
53E9
AND 02H E6 02
AND Register A with 02H, keeping bit 1, the index pulse.
53EB
If the Z FLAG is set (still in the gap), LOOP BACK to 53DFH.
53ED
LD HL,EACBH 21 CB EA
Load Register Pair HL with EACBH, 10000H minus 1535H.
53F0
ADD HL,DE 19
ADD Register Pair DE (the turns of one revolution) to Register Pair HL: the CARRY FLAG is set when the count is 1535H or more.
53F1
LD HL,60FFH 21 FF 60
Point Register Pair HL to 60FFH, the message DESTINATION DISKETTE UNUSABLE! HARD-SECTORED!; LD does not change the flags.
53F4
If the NO CARRY FLAG is set (the pulses come too often), JUMP to 43A3H to show the message at Register Pair HL and halt.

53F7H - Format: Build and Write Each Track

For each track 0-34, shows FORMATTING TRACK tt, builds the track's image at 6300H (gaps, ten ID fields with the sectors in the order of the table at 6293H, ten data fields of 256 E5H bytes with the data mark FAH on the directory track and FBH elsewhere), writes it with WRITE TRACK (54A3H), and steps the head in.

53F7
XOR A AF
Set Register A to ZERO with XOR A, track 0, the first track to format.
53F8
LD (5435H),A 32 35 54
Store Register A (00H) into 5435H, the operand of LD C,nn at 5434H: the track being formatted.
53FB
LD A,(5435H) 3A 35 54
Track Loop
Fetch the track being formatted from 5435H into Register A. 54A0H jumps here.
53FE
GOSUB to 4402H to turn Register A into two digits: Register C = the tens, Register B = the units.
5401
LD (6176H),BC ED 43 76 61
Store Register Pair BC (the two digits, tens first) into 6176H, the track number in FORMATTING TRACK 00.
5405
LD HL,6164H 21 64 61
Point Register Pair HL to 6164H, the text FORMATTING TRACK tt.
5408
GOSUB to 457BH to display the text at Register Pair HL; it starts with 1DH (cursor to the start of the line) and ends with 03H.
540B
LD A,(5435H) 3A 35 54
Fetch the track being formatted from 5435H into Register A.
540E
LD B,A 47
Copy the track from Register A into Register B.
540F
LD A,(4709H) 3A 09 47
Fetch the directory track from 4709H into Register A.
5412
CP B B8
Compare Register A (the directory track) against Register B (the track being formatted).
5413
LD B,FAH 06 FA
Load Register B with FAH, the data mark of directory sectors; LD does not change the flags.
5415
If the Z FLAG is set (the directory track), JUMP to 5419H with FAH.
5417
LD B,FBH 06 FB
Load Register B with FBH, the normal data mark.
5419
LD A,B 78
Copy the data mark from Register B into Register A. 5415H jumps here.
541A
LD (545FH),A 32 5F 54
Store Register A (the data mark) into 545FH, the operand of LD C,nn at 545EH.
541D
LD HL,6300H 21 00 63
Point Register Pair HL to 6300H, the buffer for the track image.
5420
LD DE,6293H 11 93 62
Point Register Pair DE to 6293H, the sector order table 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, ending with FFH.
5423
LD B,0EH 06 0E
Load Register B with 0EH, fourteen bytes of gap at the start of the track.
5425
GOSUB to 440FH to store Register B bytes of FFH at (HL), moving Register Pair HL on.
5428
LD B,06H 06 06
Sector Loop
Load Register B with 06H, six bytes of sync before the ID mark. 547CH loops back here.
542A
LD C,00H 0E 00
Load Register C with 00H, the byte of the sync field before the ID.
542C
GOSUB to 4411H to store Register B (6) bytes of Register C (00H) at (HL).
542F
LD C,FEH 0E FE
Load Register C with FEH, the ID address mark.
5431
GOSUB to 4417H to store Register C (FEH) at (HL) and move Register Pair HL on.
5434
LD C,00H 0E 00
Load Register C with the track being formatted, the operand at 5435H stored by 53F8H and 548AH.
5436
GOSUB to 4417H to store Register C (the track number) at (HL), the first byte of the ID.
5439
LD C,00H 0E 00
Load Register C with 00H, the second byte of the ID.
543B
GOSUB to 4417H to store Register C (00H) at (HL).
543E
LD A,(DE) 1A
Fetch the sector number from (DE) (Register Pair DE = the sector order table) into Register A.
543F
LD C,A 4F
Copy the sector number from Register A into Register C.
5440
GOSUB to 4417H to store Register C (the sector number) at (HL).
5443
LD C,01H 0E 01
Load Register C with 01H, the length code of a 256-byte sector.
5445
GOSUB to 4417H to store Register C (01H) at (HL), the last byte of the ID.
5448
LD C,F7H 0E F7
Load Register C with F7H, which makes WRITE TRACK write the two CRC bytes of the ID.
544A
GOSUB to 4417H to store Register C (F7H) at (HL).
544D
LD C,FFH 0E FF
Load Register C with FFH, one byte of the gap after the ID field.
544F
GOSUB to 4417H to store Register C (FFH) at (HL).
5452
LD B,0BH 06 0B
Load Register B with 0BH, eleven more bytes of gap.
5454
GOSUB to 440FH to store Register B bytes of FFH at (HL).
5457
LD B,06H 06 06
Load Register B with 06H, six bytes of sync before the data mark.
5459
LD C,00H 0E 00
Load Register C with 00H, the byte of the sync field before the data.
545B
GOSUB to 4411H to store Register B (6) bytes of Register C (00H) at (HL).
545E
LD C,00H 0E 00
Load Register C with the data mark stored at 545FH by 541AH (FAH or FBH; 00H in the file).
5460
GOSUB to 4417H to store Register C (the data mark) at (HL).
5463
LD B,00H 06 00
Load Register B with 00H, which makes the loop of 4411H run 256 times.
5465
LD C,E5H 0E E5
Load Register C with E5H, the byte that fills a new sector.
5467
GOSUB to 4411H to store 256 bytes of Register C (E5H) at (HL), the sector's data.
546A
LD C,F7H 0E F7
Load Register C with F7H, which makes WRITE TRACK write the two CRC bytes of the data.
546C
GOSUB to 4417H to store Register C (F7H) at (HL).
546F
LD C,FFH 0E FF
Load Register C with FFH, one byte of the gap after the data field.
5471
GOSUB to 4417H to store Register C (FFH) at (HL).
5474
LD B,0BH 06 0B
Load Register B with 0BH, eleven more bytes of gap.
5476
GOSUB to 440FH to store Register B bytes of FFH at (HL).
5479
INC DE 13
INCrement Register Pair DE (the sector order pointer) by 1.
547A
LD A,(DE) 1A
Fetch the next sector number from (DE) (Register Pair DE = the sector order pointer) into Register A.
547B
INC A 3C
INCrement Register A by 1: the Z FLAG is set for FFH, the end of the table.
547C
Sector Loop End
If the NZ FLAG is set (another sector), LOOP BACK to 5428H.
547E
LD B,5BH 06 5B
Load Register B with 5BH, 91 bytes of gap at the end of the track.
5480
GOSUB to 440FH to store Register B bytes of FFH at (HL).
5483
GOSUB to 54A3H to write the image to the track with WRITE TRACK and check how many bytes went.
5486
LD A,(5435H) 3A 35 54
Fetch the track just formatted from 5435H into Register A.
5489
INC A 3C
INCrement Register A (the track just formatted) by 1, to the next track.
548A
LD (5435H),A 32 35 54
Store Register A (the next track) into 5435H, the operand of LD C,nn at 5434H.
548D
CP 23H FE 23
Compare Register A against 23H: the Z FLAG is set after track 34.
548F
If the Z FLAG is set (all 35 tracks formatted), JUMP to 54EDH to verify them.
5491
LD A,5BH 3E 5B
Load Register A with 5BH, STEP IN with the track register updated.
1771 FDC Command: 5BH (01011011)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
01011011Command=Step In (bits 7-5 = 010)
u = 1: update the track register
h = 1: head load and settle delay
V = 0: no verify
r1 r0 = 11: 15 ms stepping rate
5493
LD (37ECH),A 32 EC 37
Store Register A (5BH) into 37ECH, the controller's command register: the head moves to the next track.
5496
PUSH AF F5
Save Register Pair AF onto the stack, a delay before the status is read.
5497
POP AF F1
Restore Register Pair AF from the stack, part of the delay.
5498
PUSH AF F5
Save Register Pair AF onto the stack again, more delay.
5499
POP AF F1
Restore Register Pair AF from the stack: the controller has had time to set BUSY.
549A
LD A,(37ECH) 3A EC 37
Wait While Busy
Fetch the controller's status from 37ECH into Register A. 549EH loops back here.
549D
RRCA 0F
Rotate Register A right: bit 0, BUSY, goes into the CARRY FLAG.
549E
Wait Loop End
If the CARRY FLAG is set (busy), LOOP BACK to 549AH.
54A0
JUMP to 53FBH to build and write the image of the next track.

54A3H - Format: Write One Track

Calls 54A7H, and calls it a second time when it returns the NZ FLAG; 54A7H can only return with the Z FLAG (it halts on the errors it finds), so the second call never runs. 54A7H selects the destination (on one drive, asking for its diskette), sends WRITE TRACK and feeds the image at 6300H to the data register until the controller is done. Lost data halts with CAN'T FORMAT, DISK TRANSFER RATE TOO FAST!; then the number of bytes taken is checked: fewer than 0BEDH gives CAN'T FORMAT, MOTOR SPEED TOO SLOW! and 0C69H or more gives CAN'T FORMAT, MOTOR SPEED TOO FAST!. The image holds 0C21H bytes.

54A3
GOSUB to 54A7H to write the track. 5483H calls here.
54A6
RET Z C8
If the Z FLAG is set (always, see above), RETURN to 5486H.
54A7
GOSUB to 449CH to select the destination drive (asking for its diskette on one drive) and halt when it is write protected. 54A3H calls here, and runs on into here a second time only after an NZ FLAG return.
54AA
LD BC,6300H 01 00 63
Point Register Pair BC to 6300H, the track image.
54AD
LD HL,37ECH 21 EC 37
Point Register Pair HL to 37ECH, the controller's command and status register.
54B0
LD (HL),F4H 36 F4
Store F4H, WRITE TRACK, at (HL) (Register Pair HL = 37ECH).
1771 FDC Command: F4H (11110100)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
11110100Command=Write Track (bits 7-4 = 1111)
E = 1: head load delay
In the data, F7H writes the two CRC bytes and F8H-FEH are written as address marks
54B2
LD DE,37EFH 11 EF 37
Point Register Pair DE to 37EFH, the controller's data register.
54B5
PUSH BC C5
Save Register Pair BC onto the stack, a delay before the status is read.
54B6
POP BC C1
Restore Register Pair BC from the stack, part of the delay.
54B7
PUSH BC C5
Save Register Pair BC onto the stack again, more delay.
54B8
POP BC C1
Restore Register Pair BC (6300H) from the stack.
54B9
DI F3
Disable interrupts for the transfer (they are already off since 5200H).
54BA
JUMP to 54BFH to look at the status for the first data request.
54BC
RRCA 0F
Not Asking for Data
Rotate Register A (the status) right: bit 0, BUSY, goes into the CARRY FLAG. 54C2H jumps here.
54BD
If the NO CARRY FLAG is set (no longer busy, the track is written), JUMP to 54CAH.
54BF
LD A,(HL) 7E
Transfer Loop
Fetch the controller's status from (HL) (Register Pair HL = 37ECH) into Register A. 54BAH and 54C7H come here.
54C0
BIT 1,A CB 4F
Test bit 1 of Register A (the status), DATA REQUEST.
54C2
If the Z FLAG is set (no request), JUMP to 54BCH to test BUSY.
54C4
LD A,(BC) 0A
Fetch the next byte of the image from (BC) (Register Pair BC = the image pointer) into Register A.
54C5
LD (DE),A 12
Store Register A at (DE) (Register Pair DE = 37EFH), the data register.
54C6
INC BC 03
INCrement Register Pair BC (the image pointer) by 1.
54C7
Transfer Loop End
JUMP to 54BFH for the next status.
54CA
LD A,(HL) 7E
Fetch the controller's final status from (HL) (Register Pair HL = 37ECH) into Register A. 54BDH jumps here.
54CB
LD HL,6179H 21 79 61
Point Register Pair HL to 6179H, the message CAN'T FORMAT, DISK TRANSFER RATE TOO FAST!.
54CE
BIT 2,A CB 57
Test bit 2 of Register A (the status), LOST DATA.
54D0
If the NZ FLAG is set (a byte came too late), JUMP to 43A3H to show the message at Register Pair HL and halt.
54D3
LD HL,9D00H 21 00 9D
Load Register Pair HL with 9D00H, 10000H minus 6300H.
54D6
ADD HL,BC 09
ADD Register Pair BC (the image pointer) to Register Pair HL: Register Pair HL = the bytes the controller took.
54D7
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the bytes taken.
54D8
LD HL,F413H 21 13 F4
Load Register Pair HL with F413H, 10000H minus 0BEDH.
54DB
ADD HL,DE 19
ADD Register Pair DE (the bytes taken) to Register Pair HL: the CARRY FLAG is set for 0BEDH or more.
54DC
LD HL,61A5H 21 A5 61
Point Register Pair HL to 61A5H, the message CAN'T FORMAT, MOTOR SPEED TOO SLOW!; LD does not change the flags.
54DF
If the NO CARRY FLAG is set (fewer than 0BEDH bytes), JUMP to 43A3H to show the message at Register Pair HL and halt.
54E2
LD HL,F397H 21 97 F3
Load Register Pair HL with F397H, 10000H minus 0C69H.
54E5
ADD HL,DE 19
ADD Register Pair DE (the bytes taken) to Register Pair HL: the CARRY FLAG is set for 0C69H or more.
54E6
LD HL,61CAH 21 CA 61
Point Register Pair HL to 61CAH, the message CAN'T FORMAT, MOTOR SPEED TOO FAST!; LD does not change the flags.
54E9
If the CARRY FLAG is set (0C69H bytes or more), JUMP to 43A3H to show the message at Register Pair HL and halt.
54EC
RET C9
RETURN to 54A6H; the Z FLAG is still the one BIT 2 set at 54CEH.

54EDH - Format: Verify the Tracks

Reads every sector of every track not yet locked out, showing VERIFYING TRACK tt, SECTOR ss. RECORD NOT FOUND or a CRC error shows its message and locks the track out (43F5H puts FFH in its byte at 4A00H) and goes on with the next track; lost data halts. The finished table is copied to 4A60H, the lockout table's place in an allocation table.

54ED
LD A,0DH 3E 0D
Load Register A with 0DH, ENTER, to end the FORMATTING line. 548FH jumps here.
54EF
GOSUB to ROM routine at 0033H to display Register A (0DH).
54F2
LD D,00H 16 00
Load Register D with 00H, track 0, the first track to verify.
54F4
LD L,D 6A
Track Loop
Copy the track from Register D into Register L. 5540H loops back here.
54F5
LD H,4AH 26 4A
Load Register H with 4AH: Register Pair HL = 4A00H plus the track, its byte in the lockout table.
54F7
LD A,(HL) 7E
Fetch the track's lockout byte from (HL) (Register Pair HL = 4A00H plus the track) into Register A.
54F8
INC A 3C
INCrement Register A by 1: the Z FLAG is set for FFH, a locked out track.
54F9
If the Z FLAG is set (locked out), JUMP to 553CH to go to the next track.
54FC
LD A,D 7A
Copy the track from Register D into Register A.
54FD
GOSUB to 4402H to turn Register A into two digits: Register C = the tens, Register B = the units.
5500
LD (45BBH),BC ED 43 BB 45
Store Register Pair BC (the track's digits) into 45BBH, the track in VERIFYING TRACK 00, SECTOR 00.
5504
LD E,00H 1E 00
Load Register E with 00H, sector 0, the first sector of the track.
5506
PUSH DE D5
Sector Loop
Save Register Pair DE (Register D = track, Register E = sector) onto the stack. 5539H loops back here.
5507
LD A,D 7A
Copy the track from Register D into Register A; the next instruction replaces it, so this has no effect.
5508
LD A,E 7B
Copy the sector from Register E into Register A.
5509
GOSUB to 4402H to turn Register A into two digits: Register C = the tens, Register B = the units.
550C
LD (45C6H),BC ED 43 C6 45
Store Register Pair BC (the sector's digits) into 45C6H, the sector in VERIFYING TRACK 00, SECTOR 00.
5510
LD HL,45AAH 21 AA 45
Point Register Pair HL to 45AAH, the text VERIFYING TRACK tt, SECTOR ss.
5513
GOSUB to 457BH to display the text at Register Pair HL; it starts with 1DH and ends with 03H, so it is rewritten on the same line each time.
5516
POP DE D1
Restore Register Pair DE (Register D = track, Register E = sector) from the stack.
5517
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
551A
GOSUB to 453CH to read track Register D, sector Register E into (BC); after two failed tries it returns the NZ FLAG with Register A = the status AND 5CH.
551D
LD HL,61EFH 21 EF 61
Point Register Pair HL to 61EFH, the text : NOT FOUND! TRACK LOCKED OUT!.
5520
BIT 4,A CB 67
Test bit 4 of Register A (the read status), RECORD NOT FOUND.
5522
If the NZ FLAG is set (not found), JUMP to 43F5H to show the text at Register Pair HL, lock the track out and go on with the next one.
5525
LD HL,620EH 21 0E 62
Point Register Pair HL to 620EH, the text : CRC ERROR! TRACK LOCKED OUT!.
5528
BIT 3,A CB 5F
Test bit 3 of Register A (the read status), CRC ERROR.
552A
If the NZ FLAG is set (a CRC error), JUMP to 43F5H to show the text at Register Pair HL, lock the track out and go on.
552D
LD HL,6260H 21 60 62
Point Register Pair HL to 6260H, the message CAN'T VERIFY FORMAT, DISK TRANSFER RATE TOO FAST!.
5530
BIT 2,A CB 57
Test bit 2 of Register A (the read status), LOST DATA.
5532
If the NZ FLAG is set (lost data), JUMP to 43A3H to show the message at Register Pair HL, wait for ENTER and halt.
5535
INC E 1C
INCrement Register E (the sector) by 1, to the next sector of the track.
5536
LD A,E 7B
Copy the sector from Register E into Register A.
5537
CP 0AH FE 0A
Compare Register A against 0AH: the Z FLAG is set after sector 9.
5539
Sector Loop End
If the NZ FLAG is set, JUMP back to 5506H for the next sector.
553C
INC D 14
Next Track
INCrement Register D (the track) by 1. 54F9H jumps here, and 43FFH comes back here after locking a track out.
553D
LD A,D 7A
Copy the track from Register D into Register A.
553E
CP 23H FE 23
Compare Register A against 23H: the Z FLAG is set after track 34.
5540
Track Loop End
If the NZ FLAG is set, JUMP back to 54F4H for the next track.
5543
LD A,0DH 3E 0D
Load Register A with 0DH, ENTER, to end the VERIFYING line.
5545
GOSUB to ROM routine at 0033H to display Register A (0DH).
5548
LD HL,4A00H 21 00 4A
Point Register Pair HL to 4A00H, the lockout table the format built.
554B
LD DE,4A60H 11 60 4A
Point Register Pair DE to 4A60H, where 5553H expects the destination's lockout table.
554E
LD BC,0023H 01 23 00
Load Register Pair BC with 0023H, one byte for each of the 35 tracks.
5551
LDIR ED B0
Copy the table: LDIR moves 23H bytes from (HL) (Register Pair HL = 4A00H) to (DE) (Register Pair DE = 4A60H), counting Register Pair BC down.

5553H - Check the Destination's Flaws and Size the Buffer

For each track, the granules the source uses (allocation byte at 4900H, without the granules its own lockout table at 4960H marks) must not fall on a locked out track of the destination (4A60H): BACKUP REJECTED DUE TO FLAWS ON DESTINATION DISK! otherwise. On two drives the copy starts at once. On one drive BACKUP finds the top of memory in 4K steps from FFFFH down and works out how many whole tracks (ten 256-byte pages each) fit from 4D00H up to the start of the top 256-byte page found; that number goes to 4713H.

5553
LD HL,4A60H 21 60 4A
Point Register Pair HL to 4A60H, the destination's lockout table. 537DH jumps here.
5556
LD DE,4960H 11 60 49
Point Register Pair DE to 4960H, the source's lockout table (bytes 60H-82H of its allocation table).
5559
LD B,23H 06 23
Load Register B with 23H, the 35 tracks to check.
555B
LD A,(DE) 1A
Track Loop
Fetch the source's lockout byte from (DE) (Register Pair DE = 4960H plus the track) into Register A. 5571H loops back here.
555C
CPL 2F
Complement Register A: the granules the source does not lock out.
555D
LD C,A 4F
Copy Register A (the granules not locked out on the source) into Register C.
555E
PUSH DE D5
Save Register Pair DE (the source lockout pointer) onto the stack.
555F
LD A,E 7B
Copy Register E (60H plus the track) into Register A.
5560
SUB 60H D6 60
SUBtract 60H from Register A: the low byte of 4900H plus the track.
5562
LD E,A 5F
Copy Register A into Register E: Register Pair DE = 4900H plus the track, the source's allocation byte.
5563
LD A,(DE) 1A
Fetch the source's allocation byte from (DE) (Register Pair DE = 4900H plus the track) into Register A.
5564
POP DE D1
Restore Register Pair DE (the source lockout pointer) from the stack.
5565
AND C A1
AND Register A with Register C: the granules the source uses and does not lock out.
5566
AND (HL) A6
AND Register A with the destination's lockout byte at (HL) (Register Pair HL = 4A60H plus the track): not zero when a used granule falls on a locked out destination track (FFH).
5567
PUSH HL E5
Save Register Pair HL (the destination pointer) onto the stack.
5568
LD HL,622DH 21 2D 62
Point Register Pair HL to 622DH, the message BACKUP REJECTED DUE TO FLAWS ON DESTINATION DISK!; LD does not change the flags.
556B
If the NZ FLAG is set (a flaw under used data), JUMP to 43A3H to show the message at Register Pair HL and halt.
556E
POP HL E1
Restore Register Pair HL (the destination pointer) from the stack.
556F
INC DE 13
INCrement Register Pair DE (the source lockout pointer) by 1.
5570
INC HL 23
INCrement Register Pair HL (the destination pointer) by 1.
5571
Track Loop End
DECrement Register B and LOOP BACK to 555BH for the next track.
5573
LD A,(44EFH) 3A EF 44
Fetch the one-drive flag from 44EFH into Register A.
5576
OR A B7
OR Register A with itself: the NZ FLAG is set for two drives.
5577
If the NZ FLAG is set (two drives: one track at a time), JUMP to 4200H to start the copy.
557A
LD HL,FFFH 21 FF 0F
Load Register Pair HL with 0FFFH; the first step down makes it FFFFH.
557D
LD A,H 7C
Memory Loop
Copy Register H into Register A. 5587H loops back here.
557E
SUB 10H D6 10
SUBtract 10H from Register A: 4K lower (0FH wraps to FFH).
5580
LD H,A 67
Copy Register A into Register H: Register Pair HL = the last byte of the 4K block to try.
5581
LD A,(HL) 7E
Fetch the byte at (HL) (Register Pair HL = the address tried) into Register A.
5582
LD B,A 47
Copy the byte from Register A into Register B, to put it back.
5583
CPL 2F
Complement Register A, a test value that differs from the byte in every bit.
5584
LD (HL),A 77
Store Register A (the complement) at (HL) (Register Pair HL = the address tried).
5585
CP (HL) BE
Compare Register A against the byte at (HL) (Register Pair HL = the address tried): the Z FLAG is set when the memory kept it, RAM.
5586
LD (HL),B 70
Store Register B (the original byte) back at (HL) (Register Pair HL = the address tried).
5587
Memory Loop End
If the NZ FLAG is set (no RAM there), LOOP BACK to 557DH to try 4K lower.
5589
LD A,H 7C
Copy Register H (the page of the top of memory) into Register A.
558A
SUB 4DH D6 4D
SUBtract 4DH from Register A: the pages from 4D00H up to, but not including, the top page.
558C
LD B,00H 06 00
Load Register B with 00H, the count of whole tracks plus one.
558E
INC B 04
Divide Loop
INCrement Register B by 1. 5591H loops back here.
558F
SUB 0AH D6 0A
SUBtract 0AH from Register A: ten pages, one track of ten sectors.
5591
Divide Loop End
If the NO CARRY FLAG is set (ten more pages), LOOP BACK to 558EH.
5593
LD A,B 78
Copy the count from Register B into Register A.
5594
DEC A 3D
DECrement Register A by 1: the whole tracks that fit in the pages counted.
5595
LD (4713H),A 32 13 47
Store Register A into 4713H, the tracks loaded in one pass on one drive.
5598
JUMP to 4200H to start the copy with the track count in 4713H.

4200H - The Copy (Runs at 4200H, Loaded at 559BH)

The rows from here to 4714H show the bytes the file loads at 559BH-5AAFH, at the addresses they run at after 52CAH has copied them to 4200H: file address = address shown plus 139BH. The copy first marks the destination's boot sector by writing 76H (HALT) as its first byte, so a destination left half copied does not start; the real first byte is written back at the end (438CH). Then, pass by pass, tracks that hold data are read from the source into memory from 4D00H (one track per pass on two drives, as many as fit on one drive), written to the destination and read back.

4200
559BH
GOSUB to 449CH to select the destination drive (asking for its diskette on one drive) and halt when it is write protected. 5577H and 5598H jump here.
4203
559EH
GOSUB to 441AH to send RESTORE and wait: the destination's head goes to track 0.
4206
55A1H
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
4209
55A4H
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: track 0, sector 0, the boot sector.
420C
55A7H
GOSUB to 453CH to read track Register D, sector Register E into (BC) (Register Pair BC = 4B00H); the NZ FLAG after two failed tries.
420F
55AAH
LD HL,4601H 21 01 46
Point Register Pair HL to 4601H, the message DESTINATION DISK READ ERROR!; LD does not change the flags.
4212
55ADH
If the NZ FLAG is set (the read failed), JUMP to 43A3H to show the message at Register Pair HL, wait for ENTER and halt.
4215
55B0H
LD A,76H 3E 76
Load Register A with 76H, the HALT instruction.
4217
55B2H
LD (4B00H),A 32 00 4B
Store Register A (76H) into 4B00H, the first byte of the destination's boot sector: the mark 44DBH looks for and the instruction a half-copied destination would start with.
421A
55B5H
LD A,A8H 3E A8
Load Register A with A8H, WRITE SECTOR with the normal FBH data mark.
1771 FDC Command: A8H (10101000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
10101000Command=Write Sector (bits 7-5 = 101)
m = 0: one sector
b = 1: IBM sector length
E = 0: no head load delay
a1 a0 = 00: data mark FBH (normal)
421C
55B7H
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the changed boot sector.
421F
55BAH
GOSUB to 43B3H to write (BC) to track Register D, sector Register E (0, 0) with the command in Register A; the NZ FLAG after two failed tries.
4222
55BDH
LD HL,461FH 21 1F 46
Point Register Pair HL to 461FH, the message DESTINATION DISK WRITE ERROR!; LD does not change the flags.
4225
55C0H
If the NZ FLAG is set (the write failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
4228
55C3H
GOSUB to 4437H to select the source drive; on one drive it asks for the source diskette and checks that it is the same source (pack ID).
422B
55C6H
GOSUB to 441AH to send RESTORE and wait: the source's head goes to track 0.
422E
55C9H
XOR A AF
Set Register A to ZERO with XOR A: no track loaded yet.
422F
55CAH
LD (4714H),A 32 14 47
Store Register A (00H) into 4714H, the count of tracks loaded and not yet written.
4232
55CDH
LD D,00H 16 00
Load Register D with 00H, track 0, the first track.
4234
55CFH
LD BC,4D00H 01 00 4D
Load Pass
Point Register Pair BC to 4D00H, the start of the track buffer. 434CH jumps here.
4237
55D2H
LD A,(37EDH) 3A ED 37
Fetch the controller's track register from 37EDH into Register A: where the head of the drive used last stands.
423A
55D5H
LD (42ADH),A 32 AD 42
Store Register A into 42ADH, the operand of LD A,nn at 42ACH, put back into the track register before the write pass.
423D
55D8H
LD A,D 7A
Copy the first track of this pass from Register D into Register A.
423E
55D9H
LD (42B2H),A 32 B2 42
Store Register A into 42B2H, the operand of LD D,nn at 42B1H, where the write pass starts.
4241
55DCH
PUSH BC C5
Load: Track Loop
Save Register Pair BC (the buffer pointer) onto the stack. 429FH jumps here.
4242
55DDH
LD H,49H 26 49
Load Register H with 49H, the page of the source's allocation table.
4244
55DFH
LD L,D 6A
Copy the track from Register D into Register L: Register Pair HL = 4900H plus the track, its allocation byte.
4245
55E0H
LD C,(HL) 4E
Fetch the source's allocation byte from (HL) (Register Pair HL = 4900H plus the track) into Register C: bits 0 and 1 set for granules in use.
4246
55E1H
LD A,D 7A
Copy the track from Register D into Register A.
4247
55E2H
ADD A,60H C6 60
ADD 60H to Register A, the offset of the lockout table.
4249
55E4H
LD L,A 6F
Copy Register A into Register L: Register Pair HL = 4960H plus the track, the source's lockout byte.
424A
55E5H
LD A,(HL) 7E
Fetch the source's lockout byte from (HL) (Register Pair HL = 4960H plus the track) into Register A.
424B
55E6H
CPL 2F
Complement Register A: the granules the source does not lock out.
424C
55E7H
AND C A1
AND Register A with Register C (the allocation byte): the granules in use and not locked out.
424D
55E8H
LD H,4AH 26 4A
Load Register H with 4AH: Register Pair HL = 4A60H plus the track, the destination's lockout byte.
424F
55EAH
LD C,(HL) 4E
Fetch the destination's lockout byte from (HL) (Register Pair HL = 4A60H plus the track) into Register C.
4250
55EBH
OR C B1
OR Register A with Register C (the destination's lockout byte).
4251
55ECH
CP C B9
Compare Register A against Register C: the Z FLAG is set when every bit left in Register A is also set in the destination's lockout byte, that is when the source uses no granule of this track (a locked out destination track under data was refused at 5553H).
4252
55EDH
POP BC C1
Restore Register Pair BC (the buffer pointer) from the stack; POP does not change the flags.
4253
55EEH
If the Z FLAG is set (nothing to copy on this track), JUMP to 429BH to go to the next track.
4256
55F1H
GOSUB to 4437H to make sure the source diskette is in its drive and selected.
4259
55F4H
LD E,00H 1E 00
Load Register E with 00H, sector 0, the first sector of the track.
425B
55F6H
PUSH BC C5
Load: Sector Loop
Save Register Pair BC (the buffer pointer) onto the stack: 4402H uses Register Pair BC. 4282H loops back here.
425C
55F7H
LD A,D 7A
Copy the track from Register D into Register A.
425D
55F8H
GOSUB to 4402H to turn Register A into two digits: Register C = the tens, Register B = the units.
4260
55FBH
LD (45DAH),BC ED 43 DA 45
Store Register Pair BC (the track's digits) into 45DAH, the track in LOADING TRACK 00, SECTOR 00.
4264
55FFH
LD A,E 7B
Copy the sector from Register E into Register A.
4265
5600H
GOSUB to 4402H to turn Register A into two digits.
4268
5603H
LD (45E5H),BC ED 43 E5 45
Store Register Pair BC (the sector's digits) into 45E5H, the sector in LOADING TRACK 00, SECTOR 00.
426C
5607H
POP BC C1
Restore Register Pair BC (the buffer pointer) from the stack.
426D
5608H
PUSH DE D5
Save Register Pair DE (track and sector) onto the stack.
426E
5609H
LD HL,45C9H 21 C9 45
Point Register Pair HL to 45C9H, the text LOADING TRACK tt, SECTOR ss.
4271
560CH
GOSUB to 457BH to display the text at Register Pair HL on the current line.
4274
560FH
POP DE D1
Restore Register Pair DE (Register D = track, Register E = sector) from the stack.
4275
5610H
GOSUB to 453CH to read track Register D, sector Register E of the source into (BC); Register Pair BC comes back 256 higher, at the next sector's place.
4278
5613H
LD HL,45E8H 21 E8 45
Point Register Pair HL to 45E8H, the message SOURCE DISK READ ERROR!; LD does not change the flags.
427B
5616H
If the NZ FLAG is set (the read failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
427E
5619H
INC E 1C
INCrement Register E (the sector) by 1, to the next sector of the track.
427F
561AH
LD A,E 7B
Copy the sector from Register E into Register A.
4280
561BH
CP 0AH FE 0A
Compare Register A against 0AH: the Z FLAG is set after sector 9.
4282
561DH
Load: Sector Loop End
If the NZ FLAG is set, LOOP BACK to 425BH for the next sector.
4284
561FH
LD A,(37ECH) 3A EC 37
Fetch the controller's status after the last read (sector 9) from 37ECH into Register A: bits 5 and 6 are the data mark that sector had.
4287
5622H
LD L,D 6A
Copy the track from Register D into Register L.
4288
5623H
LD H,48H 26 48
Load Register H with 48H: Register Pair HL = 4800H plus the track.
428A
5625H
LD (HL),A 77
Store Register A (the status) at (HL) (Register Pair HL = 4800H plus the track): the whole track will be written with sector 9's data mark.
428B
5626H
LD HL,4714H 21 14 47
Point Register Pair HL to 4714H, the count of tracks loaded.
428E
5629H
INC (HL) 34
INCrement the count at (HL) (Register Pair HL = 4714H) by 1.
428F
562AH
LD A,(44EFH) 3A EF 44
Fetch the one-drive flag from 44EFH into Register A.
4292
562DH
OR A B7
OR Register A with itself: the NZ FLAG is set for two drives.
4293
562EH
If the NZ FLAG is set (two drives), JUMP to 42A9H to write the track now.
4295
5630H
LD A,(4713H) 3A 13 47
Fetch the tracks that fit in memory from 4713H (set by 5595H) into Register A.
4298
5633H
CP (HL) BE
Compare Register A against the count at (HL) (Register Pair HL = 4714H): the Z FLAG is set when memory is full.
4299
5634H
If the Z FLAG is set (full), JUMP to 42A9H to write the tracks loaded.
429B
5636H
INC D 14
Load: Next Track
INCrement Register D (the track) by 1. 4253H jumps here.
429C
5637H
LD A,D 7A
Copy the track from Register D into Register A.
429D
5638H
CP 23H FE 23
Compare Register A against 23H: the Z FLAG is set after track 34.
429F
563AH
If the NZ FLAG is set, JUMP back to 4241H for the next track.
42A2
563DH
LD A,(4714H) 3A 14 47
Fetch the count of tracks loaded from 4714H into Register A.
42A5
5640H
OR A B7
OR Register A with itself: the Z FLAG is set when none is waiting.
42A6
5641H
If the Z FLAG is set (nothing left to write), JUMP to 434FH to finish.

42A9H - The Copy: Write and Verify the Tracks Loaded

Puts back the track register value saved at 4237H, then for each track of the pass that holds data: selects the destination (on one drive asking for its diskette and checking the 76H mark), writes the ten sectors from the buffer with the data mark saved at 4800H plus the track, and reads them back into the same buffer to check that they can be read. The data read back is not compared with what was written.

42A9
5644H
LD BC,4D00H 01 00 4D
Point Register Pair BC to 4D00H, the start of the track buffer. 4293H and 4299H jump here.
42AC
5647H
LD A,00H 3E 00
Load Register A with the track register saved at 42ADH by 423AH (00H in the file).
42AE
5649H
LD (37EDH),A 32 ED 37
Store Register A into 37EDH, the controller's track register: on two drives the destination's head is still where the last write pass left it.
42B1
564CH
LD D,00H 16 00
Load Register D with the first track of the pass, stored at 42B2H by 423EH (00H in the file).
42B3
564EH
PUSH BC C5
Write: Track Loop
Save Register Pair BC (the buffer pointer) onto the stack. 4349H jumps here.
42B4
564FH
LD H,49H 26 49
Load Register H with 49H, the page of the source's allocation table.
42B6
5651H
LD L,D 6A
Copy the track from Register D into Register L: Register Pair HL = 4900H plus the track.
42B7
5652H
LD C,(HL) 4E
Fetch the source's allocation byte from (HL) (Register Pair HL = 4900H plus the track) into Register C.
42B8
5653H
LD A,D 7A
Copy the track from Register D into Register A.
42B9
5654H
ADD A,60H C6 60
ADD 60H to Register A, the offset of the lockout table.
42BB
5656H
LD L,A 6F
Copy Register A into Register L: Register Pair HL = 4960H plus the track.
42BC
5657H
LD A,(HL) 7E
Fetch the source's lockout byte from (HL) (Register Pair HL = 4960H plus the track) into Register A.
42BD
5658H
CPL 2F
Complement Register A: the granules the source does not lock out.
42BE
5659H
AND C A1
AND Register A with Register C (the allocation byte): the granules in use and not locked out.
42BF
565AH
LD H,4AH 26 4A
Load Register H with 4AH: Register Pair HL = 4A60H plus the track.
42C1
565CH
LD C,(HL) 4E
Fetch the destination's lockout byte from (HL) (Register Pair HL = 4A60H plus the track) into Register C.
42C2
565DH
OR C B1
OR Register A with Register C (the destination's lockout byte).
42C3
565EH
LD L,D 6A
Copy the track from Register D into Register L: Register Pair HL = 4A00H plus the track.
42C4
565FH
LD (HL),A 77
Store Register A at (HL) (Register Pair HL = 4A00H plus the track); nothing reads 4A00H after this.
42C5
5660H
CP C B9
Compare Register A against Register C: the Z FLAG is set when the track holds no data (the same test as 4251H).
42C6
5661H
POP BC C1
Restore Register Pair BC (the buffer pointer) from the stack; POP does not change the flags.
42C7
5662H
If the Z FLAG is set (the track was not loaded), JUMP to 433FH to go to the next track.
42CA
5665H
GOSUB to 44B4H to select the destination drive; on one drive it asks for the destination diskette and checks the 76H mark of its boot sector.
42CD
5668H
LD E,00H 1E 00
Load Register E with 00H, sector 0, the first sector of the track.
42CF
566AH
LD A,D 7A
Copy the track from Register D into Register A.
42D0
566BH
OR E B3
OR Register A with Register E (the sector): the Z FLAG is set for track 0, sector 0, the boot sector.
42D1
566CH
If the NZ FLAG is set (another track), JUMP to 42DAH.
42D3
566EH
LD A,(BC) 0A
Fetch the first byte of the source's boot sector from (BC) (Register Pair BC = 4D00H) into Register A.
42D4
566FH
LD (4390H),A 32 90 43
Store Register A into 4390H, the operand of LD A,nn at 438FH, written back at the end.
42D7
5672H
LD A,76H 3E 76
Load Register A with 76H, the HALT instruction.
42D9
5674H
LD (BC),A 02
Store Register A (76H) at (BC) (Register Pair BC = 4D00H): the destination's boot sector keeps its mark until the copy is done.
42DA
5675H
PUSH BC C5
Write: Sector Loop
Save Register Pair BC (the start of this track's data) onto the stack, for the read back at 430FH. 42D1H jumps here.
42DB
5676H
PUSH BC C5
Save Register Pair BC (the sector's data) onto the stack: 4402H uses Register Pair BC. 430DH loops back here.
42DC
5677H
LD A,D 7A
Copy the track from Register D into Register A.
42DD
5678H
GOSUB to 4402H to turn Register A into two digits: Register C = the tens, Register B = the units.
42E0
567BH
LD (459CH),BC ED 43 9C 45
Store Register Pair BC (the track's digits) into 459CH, the track in COPYING TRACK 00, SECTOR 00.
42E4
567FH
LD A,E 7B
Copy the sector from Register E into Register A.
42E5
5680H
GOSUB to 4402H to turn Register A into two digits.
42E8
5683H
LD (45A7H),BC ED 43 A7 45
Store Register Pair BC (the sector's digits) into 45A7H, the sector in COPYING TRACK 00, SECTOR 00.
42EC
5687H
POP BC C1
Restore Register Pair BC (the sector's data) from the stack.
42ED
5688H
PUSH DE D5
Save Register Pair DE (track and sector) onto the stack.
42EE
5689H
LD HL,458BH 21 8B 45
Point Register Pair HL to 458BH, the text COPYING TRACK tt, SECTOR ss.
42F1
568CH
GOSUB to 457BH to display the text at Register Pair HL on the current line.
42F4
568FH
POP DE D1
Restore Register Pair DE (Register D = track, Register E = sector) from the stack.
42F5
5690H
LD L,D 6A
Copy the track from Register D into Register L.
42F6
5691H
LD H,48H 26 48
Load Register H with 48H: Register Pair HL = 4800H plus the track.
42F8
5693H
LD A,(HL) 7E
Fetch the status saved for the track from (HL) (Register Pair HL = 4800H plus the track) into Register A.
42F9
5694H
AND 60H E6 60
AND Register A with 60H, keeping bits 5 and 6, the data mark the source's sector 9 had.
42FB
5696H
RLCA 07
Rotate Register A (the data mark bits) left, circularly.
42FC
5697H
RLCA 07
Rotate Register A (the data mark bits) left again.
42FD
5698H
RLCA 07
Rotate Register A left a third time: bits 5 and 6 are now bits 0 and 1, the a0 and a1 of a write command.
42FE
5699H
OR A8H F6 A8
OR Register A with A8H, WRITE SECTOR: A8H for FBH, A9H for FAH, AAH for F9H, ABH for F8H.
1771 FDC Command: A8H (10101000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
10101000Command=Write Sector (bits 7-5 = 101)
m = 0: one sector
b = 1: IBM sector length
E = 0: no head load delay
a1 a0 = 00: data mark FBH (normal)
4300
569BH
GOSUB to 43B3H to write (BC) to track Register D, sector Register E of the destination with the command in Register A; Register Pair BC comes back 256 higher.
4303
569EH
LD HL,461FH 21 1F 46
Point Register Pair HL to 461FH, the message DESTINATION DISK WRITE ERROR!; LD does not change the flags.
4306
56A1H
If the NZ FLAG is set (the write failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
4309
56A4H
INC E 1C
INCrement Register E (the sector) by 1, to the next sector of the track.
430A
56A5H
LD A,E 7B
Copy the sector from Register E into Register A.
430B
56A6H
CP 0AH FE 0A
Compare Register A against 0AH: the Z FLAG is set after sector 9.
430D
56A8H
Write: Sector Loop End
If the NZ FLAG is set, LOOP BACK to 42DBH for the next sector.
430F
56AAH
POP BC C1
Restore Register Pair BC (the start of this track's data) from the stack, pushed at 42DAH.
4310
56ABH
LD E,00H 1E 00
Load Register E with 00H, sector 0, the first sector of the track.
4312
56ADH
PUSH BC C5
Verify: Sector Loop
Save Register Pair BC (the buffer pointer) onto the stack: 4402H uses Register Pair BC. 4339H loops back here.
4313
56AEH
LD A,D 7A
Copy the track from Register D into Register A.
4314
56AFH
GOSUB to 4402H to turn Register A into two digits.
4317
56B2H
LD (45BBH),BC ED 43 BB 45
Store Register Pair BC (the track's digits) into 45BBH, the track in VERIFYING TRACK 00, SECTOR 00.
431B
56B6H
LD A,E 7B
Copy the sector from Register E into Register A.
431C
56B7H
GOSUB to 4402H to turn Register A into two digits.
431F
56BAH
LD (45C6H),BC ED 43 C6 45
Store Register Pair BC (the sector's digits) into 45C6H, the sector in VERIFYING TRACK 00, SECTOR 00.
4323
56BEH
POP BC C1
Restore Register Pair BC (the buffer pointer) from the stack.
4324
56BFH
PUSH DE D5
Save Register Pair DE (track and sector) onto the stack.
4325
56C0H
LD HL,45AAH 21 AA 45
Point Register Pair HL to 45AAH, the text VERIFYING TRACK tt, SECTOR ss.
4328
56C3H
GOSUB to 457BH to display the text at Register Pair HL on the current line.
432B
56C6H
POP DE D1
Restore Register Pair DE (Register D = track, Register E = sector) from the stack.
432C
56C7H
GOSUB to 453CH to read the sector just written back into (BC), over the data it was written from.
432F
56CAH
LD HL,4601H 21 01 46
Point Register Pair HL to 4601H, the message DESTINATION DISK READ ERROR!; LD does not change the flags.
4332
56CDH
If the NZ FLAG is set (it cannot be read back), JUMP to 43A3H to show the message at Register Pair HL and halt.
4335
56D0H
INC E 1C
INCrement Register E (the sector) by 1, to the next sector of the track.
4336
56D1H
LD A,E 7B
Copy the sector from Register E into Register A.
4337
56D2H
CP 0AH FE 0A
Compare Register A against 0AH: the Z FLAG is set after sector 9.
4339
56D4H
Verify: Sector Loop End
If the NZ FLAG is set, LOOP BACK to 4312H for the next sector.
433B
56D6H
LD HL,4714H 21 14 47
Point Register Pair HL to 4714H, the count of tracks loaded and not yet written.
433E
56D9H
DEC (HL) 35
DECrement the count at (HL) (Register Pair HL = 4714H) by 1: one track fewer to write.
433F
56DAH
INC D 14
Write: Next Track
INCrement Register D (the track) by 1. 42C7H jumps here.
4340
56DBH
LD A,D 7A
Copy the track from Register D into Register A.
4341
56DCH
CP 23H FE 23
Compare Register A against 23H: the Z FLAG is set after track 34.
4343
56DEH
If the Z FLAG is set (the last track is done), JUMP to 434FH to finish.
4345
56E0H
LD A,(4714H) 3A 14 47
Fetch the count of tracks still to write from 4714H into Register A.
4348
56E3H
OR A B7
OR Register A with itself: the NZ FLAG is set while tracks of this pass remain.
4349
56E4H
If the NZ FLAG is set, JUMP back to 42B3H for the next track of the pass.
434C
56E7H
JUMP to 4234H to load the next pass, starting at track Register D.

434FH - The Copy: Finish

Puts the backup date into the source's allocation table (bytes D8H-DFH of the copy at 4900H) and writes that table to the destination's directory track, sector 0, with the FAH data mark; reads it back; reads the destination's boot sector and writes it again with its real first byte (saved at 42D4H) in place of the 76H mark. The destination's allocation table is therefore the source's with the new date: the lockout table it carries is the source's, not the one the format made. Then RESTORE and BACKUP COMPLETE.

434F
56EAH
LD HL,470AH 21 0A 47
Point Register Pair HL to 470AH, the backup date MM/DD/YY (entered at 5294H-52C8H into 5AA5H and moved here by 52CAH). 42A6H and 4343H jump here.
4352
56EDH
LD DE,49D8H 11 D8 49
Point Register Pair DE to 49D8H, bytes D8H-DFH of the source's allocation table, the diskette's date.
4355
56F0H
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H, the eight characters of the date.
4358
56F3H
LDIR ED B0
Copy the date: LDIR moves 8 bytes from (HL) (Register Pair HL = 470AH) to (DE) (Register Pair DE = 49D8H), counting Register Pair BC down.
435A
56F5H
GOSUB to 44B4H to select the destination drive (on one drive, asking for its diskette and checking the 76H mark).
435D
56F8H
LD A,(4709H) 3A 09 47
Fetch the directory track from 4709H into Register A.
4360
56FBH
LD D,A 57
Copy the directory track from Register A into Register D.
4361
56FCH
LD E,00H 1E 00
Load Register E with 00H, sector 0, the allocation table.
4363
56FEH
LD BC,4900H 01 00 49
Point Register Pair BC to 4900H, the source's allocation table with the new date.
4366
5701H
LD A,A9H 3E A9
Load Register A with A9H, WRITE SECTOR with the FAH data mark of directory sectors.
1771 FDC Command: A9H (10101001)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
10101001Command=Write Sector (bits 7-5 = 101)
m = 0: one sector
b = 1: IBM sector length
E = 0: no head load delay
a1 a0 = 01: data mark FAH
4368
5703H
GOSUB to 43B3H to write (BC) to track Register D, sector Register E of the destination with the command in Register A.
436B
5706H
LD HL,461FH 21 1F 46
Point Register Pair HL to 461FH, the message DESTINATION DISK WRITE ERROR!; LD does not change the flags.
436E
5709H
If the NZ FLAG is set (the write failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
4371
570CH
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
4374
570FH
GOSUB to 453CH to read the allocation table just written (track Register D, sector Register E) into (BC), to check it.
4377
5712H
LD HL,4601H 21 01 46
Point Register Pair HL to 4601H, the message DESTINATION DISK READ ERROR!; LD does not change the flags.
437A
5715H
If the NZ FLAG is set (it cannot be read), JUMP to 43A3H to show the message at Register Pair HL and halt.
437D
5718H
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
4380
571BH
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: track 0, sector 0, the boot sector.
4383
571EH
GOSUB to 453CH to read the destination's boot sector into (BC) (Register Pair BC = 4B00H).
4386
5721H
LD HL,4601H 21 01 46
Point Register Pair HL to 4601H, the message DESTINATION DISK READ ERROR!; LD does not change the flags.
4389
5724H
If the NZ FLAG is set (it cannot be read), JUMP to 43A3H to show the message at Register Pair HL and halt.
438C
5727H
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the boot sector just read.
438F
572AH
LD A,00H 3E 00
Load Register A with the source boot sector's first byte, saved at 4390H by 42D4H (00H in the file).
4391
572CH
LD (BC),A 02
Store Register A at (BC) (Register Pair BC = 4B00H), over the 76H mark.
4392
572DH
LD A,A8H 3E A8
Load Register A with A8H, WRITE SECTOR with the normal FBH data mark.
1771 FDC Command: A8H (10101000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
10101000Command=Write Sector (bits 7-5 = 101)
m = 0: one sector
b = 1: IBM sector length
E = 0: no head load delay
a1 a0 = 00: data mark FBH (normal)
4394
572FH
GOSUB to 43B3H to write the boot sector back (track Register D, sector Register E = 0, 0).
4397
5732H
LD HL,461FH 21 1F 46
Point Register Pair HL to 461FH, the message DESTINATION DISK WRITE ERROR!; LD does not change the flags.
439A
5735H
If the NZ FLAG is set (the write failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
439D
5738H
GOSUB to 441AH to send RESTORE and wait: the head goes back to track 0.
43A0
573BH
LD HL,46DEH 21 DE 46
Point Register Pair HL to 46DEH, the message BACKUP COMPLETE, and go on into 43A3H.

43A3H - Show a Message and Halt

Every end of BACKUP comes here, the successful one included, with Register Pair HL = the message. Shows it, shows HIT 'ENTER' TO CONTINUE, waits until ENTER is pressed and executes HALT with interrupts disabled: the processor stops until RESET is pressed. SYS0/SYS was overwritten at 52CAH, so there is nothing to go back to.

43A3
573EH
GOSUB to 457BH to display the message at Register Pair HL. 32 places jump here.
43A6
5741H
LD HL,46EFH 21 EF 46
Point Register Pair HL to 46EFH, the text HIT 'ENTER' TO CONTINUE.
43A9
5744H
GOSUB to 457BH to display the text at Register Pair HL.
43AC
5747H
LD A,(3840H) 3A 40 38
Wait for ENTER
Fetch keyboard row 6 from 3840H into Register A; bit 0 is ENTER. 43B0H loops back here.
43AF
574AH
RRCA 0F
Rotate Register A right: bit 0, ENTER, goes into the CARRY FLAG.
43B0
574BH
Wait Loop End
If the NO CARRY FLAG is set (ENTER not pressed), LOOP BACK to 43ACH.
43B2
574DH
HALT 76
HALT: with interrupts disabled the processor stops here until RESET.

43B3H - Write a Sector

Register A = the write command, Register Pair BC = the data, Register D = track, Register E = sector. Tries 43BEH twice. 43BEH selects the drive (4527H), seeks the track, sends the command and gives the controller each byte it asks for, then returns the Z FLAG when the status AND 7CH is 0; on an error it sends FORCE INTERRUPT and returns the NZ FLAG. Register Pair BC comes back past the sector after a success.

43B3
574EH
LD (43D4H),A 32 D4 43
Store Register A (the write command) into 43D4H, the operand of LD (HL),nn at 43D3H. 421FH, 4300H, 4368H and 4394H call here.
43B6
5751H
PUSH BC C5
Save Register Pair BC (the data address) onto the stack, for a second try.
43B7
5752H
GOSUB to 43BEH to write the sector once, the first of the two tries.
43BA
5755H
POP HL E1
Restore the data address into Register Pair HL from the stack.
43BB
5756H
RET Z C8
If the Z FLAG is set (written), RETURN with Register Pair BC past the sector.
43BC
5757H
LD B,H 44
Copy Register H (the high byte of the data address) into Register B.
43BD
5758H
LD C,L 4D
Copy Register L into Register C: Register Pair BC = the data address again for the second try, which runs on into 43BEH.
43BE
5759H
LD (37EEH),DE ED 53 EE 37
Store Register Pair DE into 37EEH: Register E into the sector register (37EEH) and Register D, the track, into the data register (37EFH), where SEEK finds its target. 43B7H calls here.
43C2
575DH
PUSH DE D5
Save Register Pair DE (track and sector) onto the stack.
43C3
575EH
GOSUB to 4527H to select the drive in 44E8H, waiting when it was not ready.
43C6
5761H
LD HL,37ECH 21 EC 37
Point Register Pair HL to 37ECH, the controller's command and status register.
43C9
5764H
LD (HL),1BH 36 1B
Store 1BH, SEEK, at (HL) (Register Pair HL = 37ECH): the head moves to the track in the data register.
1771 FDC Command: 1BH (00011011)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
00011011Command=Seek (bits 7-4 = 0001)
h = 1: head load and settle delay
V = 0: no verify
r1 r0 = 11: 15 ms stepping rate
43CB
5766H
PUSH AF F5
Save Register Pair AF onto the stack, a delay before the status is read.
43CC
5767H
POP AF F1
Restore Register Pair AF from the stack, part of the delay.
43CD
5768H
PUSH AF F5
Save Register Pair AF onto the stack again, more delay.
43CE
5769H
POP AF F1
Restore Register Pair AF from the stack: the controller has had time to set BUSY.
43CF
576AH
LD A,(HL) 7E
Wait for the Seek
Fetch the controller's status from (HL) (Register Pair HL = 37ECH) into Register A. 43D1H loops back here.
43D0
576BH
RRCA 0F
Rotate Register A right: bit 0, BUSY, goes into the CARRY FLAG.
43D1
576CH
Wait Loop End
If the CARRY FLAG is set (busy), LOOP BACK to 43CFH.
43D3
576EH
LD (HL),00H 36 00
Store the write command at (HL) (Register Pair HL = 37ECH), the operand at 43D4H stored by 43B3H (00H in the file).
43D5
5770H
LD DE,37EFH 11 EF 37
Point Register Pair DE to 37EFH, the controller's data register.
43D8
5773H
PUSH BC C5
Save Register Pair BC onto the stack, a delay before the status is read.
43D9
5774H
POP BC C1
Restore Register Pair BC from the stack, part of the delay.
43DA
5775H
PUSH BC C5
Save Register Pair BC onto the stack again, more delay.
43DB
5776H
POP BC C1
Restore Register Pair BC (the data address) from the stack.
43DC
5777H
DI F3
Disable interrupts for the transfer (they are already off since 5200H).
43DD
5778H
JUMP to 43E2H to look at the status for the first data request.
43DF
577AH
RRCA 0F
Not Asking for Data
Rotate Register A (the status) right: bit 0, BUSY, goes into the CARRY FLAG. 43E5H jumps here.
43E0
577BH
If the NO CARRY FLAG is set (no longer busy), JUMP to 43EDH.
43E2
577DH
LD A,(HL) 7E
Transfer Loop
Fetch the controller's status from (HL) (Register Pair HL = 37ECH) into Register A. 43DDH and 43EAH come here.
43E3
577EH
BIT 1,A CB 4F
Test bit 1 of Register A (the status), DATA REQUEST.
43E5
5780H
If the Z FLAG is set (no request), JUMP to 43DFH to test BUSY.
43E7
5782H
LD A,(BC) 0A
Fetch the next data byte from (BC) (Register Pair BC = the data pointer) into Register A.
43E8
5783H
LD (DE),A 12
Store Register A at (DE) (Register Pair DE = 37EFH), the data register.
43E9
5784H
INC BC 03
INCrement Register Pair BC (the data pointer) by 1.
43EA
5785H
Transfer Loop End
JUMP to 43E2H for the next status.
43ED
5788H
LD A,(HL) 7E
Fetch the controller's final status from (HL) (Register Pair HL = 37ECH) into Register A. 43E0H jumps here.
43EE
5789H
AND 7CH E6 7C
AND Register A with 7CH, keeping the error bits of a write: the Z FLAG for success.
1771 Status after Read/Write Sector, AND 7CHFunction Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
01111100Bits kept by AND 7CH:
6: F9H/F8H mark (read), write protect
5: FAH/F8H mark (read), write fault
4: record not found
3: CRC error
2: lost data
43F0
578BH
POP DE D1
Restore Register Pair DE (track and sector) from the stack.
43F1
578CH
RET Z C8
If the Z FLAG is set (no error), RETURN to 43BAH or to the caller.
43F2
578DH
LD (HL),D0H 36 D0
Store D0H, FORCE INTERRUPT, at (HL) (Register Pair HL = 37ECH): the controller stops and its status shows the Type I bits again.
1771 FDC Command: D0H (11010000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
11010000Command=Force Interrupt (bits 7-4 = 1101)
I3-I0 = 0000: end the command, no interrupt
43F4
578FH
RET C9
RETURN with the NZ FLAG from the AND at 43EEH.

43F5H - Format Verify: Lock a Track Out

Reached from 5522H or 552AH with Register Pair HL = the message and Register D = the track. Shows the message (: NOT FOUND! or : CRC ERROR! TRACK LOCKED OUT!), puts FFH in the track's byte at 4A00H and goes on with the next track at 553CH.

43F5
5790H
PUSH DE D5
Save Register Pair DE (Register D = track) onto the stack. 5522H and 552AH jump here.
43F6
5791H
GOSUB to 457BH to display the message at Register Pair HL, after the VERIFYING TRACK tt, SECTOR ss already on the line.
43F9
5794H
POP DE D1
Restore Register Pair DE (Register D = track) from the stack.
43FA
5795H
LD L,D 6A
Copy the track from Register D into Register L.
43FB
5796H
LD H,4AH 26 4A
Load Register H with 4AH: Register Pair HL = 4A00H plus the track.
43FD
5798H
LD (HL),FFH 36 FF
Store FFH at (HL) (Register Pair HL = 4A00H plus the track): the track is locked out.
43FF
579AH
JUMP to 553CH in the format verify loop to verify the next track.

4402H - Two Decimal Digits

Register A = a number 0-99. Returns Register C = the tens digit and Register B = the units digit as characters, so that LD (nn),BC stores them in reading order.

4402
579DH
LD C,30H 0E 30
Load Register C with 30H, the digit 0 for the tens. 53FEH, 54FDH, 5509H and the copy's display code call here.
4404
579FH
SUB 0AH D6 0A
Tens Loop
SUBtract 0AH from Register A (the number); the CARRY FLAG is set when it goes below zero. 4409H loops back here.
4406
57A1H
If the CARRY FLAG is set, JUMP to 440BH: Register A = the units minus 10.
4408
57A3H
INC C 0C
INCrement Register C (the tens digit) by 1 for the ten just taken off.
4409
57A4H
Tens Loop End
LOOP BACK to 4404H to subtract another ten.
440B
57A6H
ADD A,3AH C6 3A
ADD 3AH to Register A (the units minus 10): the units digit as a character (30H-39H).
440D
57A8H
LD B,A 47
Copy the units digit from Register A into Register B.
440E
57A9H
RET C9
RETURN with Register C = the tens digit and Register B = the units digit.

440FH - Store Bytes into the Track Image

440FH stores Register B bytes of FFH, 4411H stores Register B bytes of Register C (256 when Register B is 00H), 4417H stores one byte of Register C; each at (HL), moving Register Pair HL on.

440F
57AAH
LD C,FFH 0E FF
Load Register C with FFH, the gap byte. 5425H, 5454H, 5476H and 5480H call here.
4411
57ACH
Store Loop
GOSUB to 4417H to store Register C at (HL) and move Register Pair HL on. 542CH, 545BH and 5467H call here; 4414H loops back here.
4414
57AFH
Store Loop End
DECrement Register B and LOOP BACK to 4411H until Register B bytes are stored.
4416
57B1H
RET C9
RETURN to the format code with Register Pair HL past the bytes stored.
4417
57B2H
LD (HL),C 71
Store Register C at (HL) (Register Pair HL = the image pointer). The format code calls here for single bytes.
4418
57B3H
INC HL 23
INCrement Register Pair HL (the image pointer) by 1.
4419
57B4H
RET C9
RETURN with Register Pair HL at the next byte of the image.

441AH - Restore

Sends RESTORE to the controller (the selected drive's head goes to track 0) and waits until BUSY clears; there is no time limit.

441A
57B5H
LD A,0BH 3E 0B
Load Register A with 0BH, RESTORE.
1771 FDC Command: 0BH (00001011)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
00001011Command=Restore (bits 7-4 = 0000)
h = 1: head load and settle delay
V = 0: no verify
r1 r0 = 11: 15 ms stepping rate
441C
57B7H
LD (37ECH),A 32 EC 37
Store Register A (0BH) into 37ECH, the controller's command register.
441F
57BAH
PUSH AF F5
Save Register Pair AF onto the stack, a delay before the status is read.
4420
57BBH
POP AF F1
Restore Register Pair AF from the stack, part of the delay.
4421
57BCH
PUSH AF F5
Save Register Pair AF onto the stack again, more delay.
4422
57BDH
POP AF F1
Restore Register Pair AF from the stack: the controller has had time to set BUSY.
4423
57BEH
LD A,(37ECH) 3A EC 37
Wait While Busy
Fetch the controller's status from 37ECH into Register A. 4427H loops back here.
4426
57C1H
RRCA 0F
Rotate Register A right: bit 0, BUSY, goes into the CARRY FLAG.
4427
57C2H
Wait Loop End
If the CARRY FLAG is set (busy), LOOP BACK to 4423H.
4429
57C4H
RET C9
RETURN with the head on track 0 and the status in the controller.

442AH - Select the Source Drive

Register A = the source's select bit (the operand at 442BH stored at 5257H) with bit 7 set, the mark of the source; 44E7H asks for the source diskette on one drive when it is not the one in place, and selects the drive.

442A
57C5H
LD A,00H 3E 00
Load Register A with the source drive's select bit, the operand at 442BH stored by 5257H (00H in the file). 52E3H and 443EH call here; 443CH jumps here.
442C
57C7H
OR 80H F6 80
OR Register A with 80H: bit 7 marks the source diskette.
442E
57C9H
PUSH HL E5
Save Register Pair HL (the caller's value) onto the stack.
442F
57CAH
LD HL,4664H 21 64 46
Point Register Pair HL to 4664H, the prompt INSERT SOURCE DISK (ENTER).
4432
57CDH
GOSUB to 44E7H to ask for the diskette when needed and select the drive.
4435
57D0H
POP HL E1
Restore Register Pair HL (the caller's value) from the stack.
4436
57D1H
RET C9
RETURN with the source drive selected and its diskette in place.

4437H - Make Sure the Source Diskette Is In

When the source is the diskette in place (bit 7 of 44E8H) it is only selected. Otherwise the source is asked for (one drive) and selected; on two drives that is all. On one drive the diskette inserted is checked: its boot sector must start with 00H (a destination started by BACKUP starts with 76H) and its allocation table must carry the source's pack ID (bytes CEH-D7H); a different diskette shows W A K E U P !!! THAT'S NOT THE SAME SOURCE DISK ! and the source is asked for again.

4437
57D2H
LD A,(44E8H) 3A E8 44
Fetch the drive and diskette in place from 44E8H into Register A. 4228H and 4256H call here; 449AH loops back here.
443A
57D5H
BIT 7,A CB 7F
Test bit 7 of Register A, set when the source diskette is the one in place.
443C
57D7H
If the NZ FLAG is set (it is), JUMP to 442AH to select the source drive only.
443E
57D9H
GOSUB to 442AH to ask for the source diskette (one drive) and select the drive.
4441
57DCH
LD A,(44EFH) 3A EF 44
Fetch the one-drive flag from 44EFH into Register A.
4444
57DFH
OR A B7
OR Register A with itself: the NZ FLAG is set for two drives.
4445
57E0H
RET NZ C0
If the NZ FLAG is set (two drives: nothing to check), RETURN.
4446
57E1H
GOSUB to 441AH to send RESTORE: the new diskette's track 0.
4449
57E4H
PUSH BC C5
Save Register Pair BC (the caller's value) onto the stack while the boot sector is read.
444A
57E5H
PUSH DE D5
Save Register Pair DE (the caller's track and sector) onto the stack while the boot sector is read.
444B
57E6H
PUSH HL E5
Save Register Pair HL (the caller's value) onto the stack while the boot sector is read.
444C
57E7H
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
444F
57EAH
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: track 0, sector 0, the boot sector.
4452
57EDH
GOSUB to 453CH to read the boot sector of the diskette inserted into (BC) (Register Pair BC = 4B00H).
4455
57F0H
LD HL,45E8H 21 E8 45
Point Register Pair HL to 45E8H, the message SOURCE DISK READ ERROR!; LD does not change the flags.
4458
57F3H
If the NZ FLAG is set (the read failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
445B
57F6H
POP HL E1
Restore Register Pair HL (the caller's value) from the stack after the boot sector read.
445C
57F7H
POP DE D1
Restore Register Pair DE (the caller's track and sector) from the stack after the boot sector read.
445D
57F8H
POP BC C1
Restore Register Pair BC (the caller's value) from the stack after the boot sector read.
445E
57F9H
LD A,(4B00H) 3A 00 4B
Fetch the boot sector's first byte from 4B00H into Register A.
4461
57FCH
OR A B7
OR Register A with itself: the NZ FLAG is set when it is not 00H (for example the 76H mark of a destination).
4462
57FDH
If the NZ FLAG is set (not a source), JUMP to 4496H to ask again.
4464
57FFH
PUSH BC C5
Save Register Pair BC (the caller's value) onto the stack while the allocation table is read.
4465
5800H
PUSH DE D5
Save Register Pair DE (the caller's track and sector) onto the stack while the table is read.
4466
5801H
PUSH HL E5
Save Register Pair HL (the caller's value) onto the stack while the table is read.
4467
5802H
LD A,(4709H) 3A 09 47
Fetch the directory track from 4709H into Register A.
446A
5805H
LD D,A 57
Copy the directory track from Register A into Register D.
446B
5806H
LD E,00H 1E 00
Load Register E with 00H, sector 0, the allocation table.
446D
5808H
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
4470
580BH
GOSUB to 453CH to read the inserted diskette's allocation table into (BC) (Register Pair BC = 4B00H).
4473
580EH
LD HL,45E8H 21 E8 45
Point Register Pair HL to 45E8H, the message SOURCE DISK READ ERROR!; LD does not change the flags.
4476
5811H
If the NZ FLAG is set (the read failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
4479
5814H
LD HL,49CEH 21 CE 49
Point Register Pair HL to 49CEH, the source's pack ID (bytes CEH-D7H of its table, read at 531AH).
447C
5817H
LD DE,4BCEH 11 CE 4B
Point Register Pair DE to 4BCEH, the same bytes of the diskette inserted.
447F
581AH
LD B,0AH 06 0A
Load Register B with 0AH, the ten bytes to compare.
4481
581CH
LD A,(DE) 1A
Compare Loop
Fetch the inserted diskette's byte from (DE) (Register Pair DE = the pointer into 4BCEH) into Register A. 4487H loops back here.
4482
581DH
CP (HL) BE
Compare Register A against the source's byte at (HL) (Register Pair HL = the pointer into 49CEH).
4483
581EH
If the NZ FLAG is set (different), JUMP to 448DH.
4485
5820H
INC DE 13
INCrement Register Pair DE (the pointer into 4BCEH) by 1, to the next byte.
4486
5821H
INC HL 23
INCrement Register Pair HL (the pointer into 49CEH) by 1, to the next byte.
4487
5822H
Compare Loop End
DECrement Register B and LOOP BACK to 4481H for the next byte.
4489
5824H
POP HL E1
Restore Register Pair HL (the caller's value) from the stack: the pack IDs match.
448A
5825H
POP DE D1
Restore Register Pair DE (the caller's track and sector) from the stack.
448B
5826H
POP BC C1
Restore Register Pair BC (the caller's value, for the copy the buffer pointer) from the stack.
448C
5827H
RET C9
RETURN: the right source diskette is in and selected.
448D
5828H
LD HL,46A7H 21 A7 46
Not the Same Source
Point Register Pair HL to 46A7H, the message W A K E U P !!! THAT'S NOT THE SAME SOURCE DISK !. 4483H jumps here.
4490
582BH
GOSUB to 457BH to display the message at Register Pair HL.
4493
582EH
POP HL E1
Restore Register Pair HL (the caller's value) from the stack after the message.
4494
582FH
POP DE D1
Restore Register Pair DE (the caller's track and sector) from the stack after the message.
4495
5830H
POP BC C1
Restore Register Pair BC (the caller's value) from the stack after the message.
4496
5831H
XOR A AF
Set Register A to ZERO with XOR A: no diskette is known to be in place. 4462H jumps here.
4497
5832H
LD (44E8H),A 32 E8 44
Store Register A (00H) into 44E8H, the operand of CP nn at 44E7H, so the next call asks for the diskette.
449A
5835H
LOOP BACK to 4437H to ask for the source diskette again.

449CH - Select the Destination Drive

Register A = the destination's select bit (the operand at 449DH stored at 5291H) with bit 6 set, the mark of the destination; 44E7H asks for the destination diskette on one drive when it is not the one in place, and selects the drive. The status is then tested for WRITE PROTECT.

449C
5837H
LD A,00H 3E 00
Load Register A with the destination drive's select bit, the operand at 449DH stored by 5291H (00H in the file). 4200H, 5323H and 54A7H call here.
449E
5839H
OR 40H F6 40
OR Register A with 40H: bit 6 marks the destination diskette.
44A0
583BH
PUSH HL E5
Save Register Pair HL (the caller's value) onto the stack: Register Pair HL carries the prompt.
44A1
583CH
LD HL,4683H 21 83 46
Point Register Pair HL to 4683H, the prompt INSERT DESTINATION DISK (ENTER).
44A4
583FH
GOSUB to 44E7H to ask for the diskette when needed and select the drive.
44A7
5842H
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A.
44AA
5845H
LD HL,463EH 21 3E 46
Point Register Pair HL to 463EH, the message DESTINATION DISK IS WRITE PROTECTED!.
44AD
5848H
BIT 6,A CB 77
Test bit 6 of Register A (the status), WRITE PROTECT.
44AF
584AH
If the NZ FLAG is set (protected), JUMP to 43A3H to show the message at Register Pair HL and halt.
44B2
584DH
POP HL E1
Restore Register Pair HL (the caller's value) from the stack: the destination is not write protected.
44B3
584EH
RET C9
RETURN with the destination drive selected and its diskette writable.

44B4H - Make Sure the Destination Diskette Is In

When the destination is the diskette in place (bit 6 of 44E8H) it is only selected. Otherwise it is asked for (one drive) and selected; on one drive the diskette inserted must have the 76H mark that 4217H wrote in its boot sector, else it is asked for again.

44B4
584FH
LD A,(44E8H) 3A E8 44
Fetch the drive and diskette in place from 44E8H into Register A. 42CAH and 435AH call here; 44E5H loops back here.
44B7
5852H
BIT 6,A CB 77
Test bit 6 of Register A, set when the destination diskette is the one in place.
44B9
5854H
If the NZ FLAG is set (it is), JUMP to 449CH to select the destination drive only.
44BB
5856H
GOSUB to 449CH to ask for the destination diskette (one drive) and select the drive.
44BE
5859H
LD A,(44EFH) 3A EF 44
Fetch the one-drive flag from 44EFH into Register A.
44C1
585CH
OR A B7
OR Register A with itself: the NZ FLAG is set for two drives.
44C2
585DH
RET NZ C0
If the NZ FLAG is set (two drives: no diskette change to check), RETURN.
44C3
585EH
GOSUB to 441AH to send RESTORE: the new diskette's track 0.
44C6
5861H
PUSH BC C5
Save Register Pair BC (the caller's value, for the copy the buffer pointer) onto the stack.
44C7
5862H
PUSH DE D5
Save Register Pair DE (the caller's track and sector) onto the stack.
44C8
5863H
PUSH HL E5
Save Register Pair HL (the caller's value) onto the stack while the boot sector is read.
44C9
5864H
LD BC,4B00H 01 00 4B
Point Register Pair BC to 4B00H, the sector buffer.
44CC
5867H
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: track 0, sector 0, the boot sector.
44CF
586AH
GOSUB to 453CH to read the boot sector of the diskette inserted into (BC) (Register Pair BC = 4B00H).
44D2
586DH
POP HL E1
Restore Register Pair HL (the caller's value) from the stack; POP does not change the flags.
44D3
586EH
POP DE D1
Restore Register Pair DE (the caller's track and sector) from the stack.
44D4
586FH
POP BC C1
Restore Register Pair BC (the caller's value) from the stack.
44D5
5870H
LD HL,4601H 21 01 46
Point Register Pair HL to 4601H, the message DESTINATION DISK READ ERROR!; LD does not change the flags.
44D8
5873H
If the NZ FLAG is set (the read failed), JUMP to 43A3H to show the message at Register Pair HL and halt.
44DB
5876H
LD A,(4B00H) 3A 00 4B
Fetch the boot sector's first byte from 4B00H into Register A.
44DE
5879H
CP 76H FE 76
Compare Register A against 76H, the mark of the destination being written.
44E0
587BH
RET Z C8
If the Z FLAG is set (the destination), RETURN.
44E1
587CH
XOR A AF
Set Register A to ZERO with XOR A: no diskette is known to be in place.
44E2
587DH
LD (44E8H),A 32 E8 44
Store Register A (00H) into 44E8H, so the next call asks for the diskette.
44E5
5880H
LOOP BACK to 44B4H to ask for the destination diskette again.

44E7H - Ask for a Diskette and Select the Drive

Register A = the drive's select bit with bit 7 (source) or bit 6 (destination), Register Pair HL = the prompt. When Register A equals 44E8H, the diskette wanted is in place and the drive is only selected (4527H). Otherwise Register A is stored in 44E8H; on two drives the drive is selected; on one drive the prompt is shown and BACKUP waits for ENTER, blinking the prompt: it is shown, ENTER is awaited for 4000H loop turns, the line is erased and after a pause the prompt is shown again.

44E7
5882H
CP 00H FE 00
Compare Register A against the drive and diskette in place, the operand at 44E8H (00H in the file, set by 52D6H, 44EBH, 4497H and 44E2H). 4432H and 44A4H call here.
44E9
5884H
If the Z FLAG is set (already in place), JUMP to 4527H to select the drive.
44EB
5886H
LD (44E8H),A 32 E8 44
Store Register A into 44E8H: this diskette is now the one in place.
44EE
5889H
LD A,00H 3E 00
Load Register A with the one-drive flag, the operand at 44EFH stored by 52E0H (00H in the file and for one drive).
44F0
588BH
OR A B7
OR Register A with itself: the NZ FLAG is set for two drives.
44F1
588CH
If the NZ FLAG is set (two drives), JUMP to 4527H to select the drive without asking.
44F3
588EH
PUSH BC C5
Save Register Pair BC (the caller's value) onto the stack: the wait loop uses Register Pair BC.
44F4
588FH
PUSH DE D5
Save Register Pair DE (the caller's value) onto the stack: the ROM's 0033H changes Register Pair DE.
44F5
5890H
PUSH HL E5
Save Register Pair HL (the prompt) onto the stack.
44F6
5891H
LD A,0DH 3E 0D
Load Register A with 0DH, ENTER, to start a new line.
44F8
5893H
GOSUB to ROM routine at 0033H to display Register A (0DH).
44FB
5896H
Prompt Loop
GOSUB to 457BH to display the prompt at Register Pair HL. 451DH loops back here.
44FE
5899H
LD A,(3840H) 3A 40 38
Wait for ENTER to Be Released
Fetch keyboard row 6 from 3840H into Register A; bit 0 is ENTER. 4502H loops back here.
4501
589CH
RRCA 0F
Rotate Register A right: bit 0, ENTER, goes into the CARRY FLAG.
4502
589DH
If the CARRY FLAG is set (ENTER still down), LOOP BACK to 44FEH.
4504
589FH
LD BC,4000H 01 00 40
Load Register Pair BC with 4000H, the loop turns the prompt stays on the screen.
4507
58A2H
LD A,(3840H) 3A 40 38
Wait for ENTER
Fetch keyboard row 6 from 3840H into Register A. 4510H loops back here.
450A
58A5H
RRCA 0F
Rotate Register A right: bit 0, ENTER, goes into the CARRY FLAG.
450B
58A6H
If the CARRY FLAG is set (ENTER pressed), JUMP to 451FH.
450D
58A8H
DEC BC 0B
DECrement Register Pair BC (the turns left) by 1.
450E
58A9H
LD A,B 78
Copy Register B (the high byte of the turns left) into Register A.
450F
58AAH
OR C B1
OR Register A with Register C: the Z FLAG is set when no turns are left.
4510
58ABH
If the NZ FLAG is set (turns left), LOOP BACK to 4507H to look at ENTER again.
4512
58ADH
LD A,1EH 3E 1E
Load Register A with 1EH, the display code that erases to the end of the line.
4514
58AFH
GOSUB to ROM routine at 0033H to display Register A (1EH): the prompt disappears (it begins with 1DH, so the cursor is at the start of its line).
4517
58B2H
LD BC,3333H 01 33 33
Load Register Pair BC with 3333H, the length of the pause.
451A
58B5H
GOSUB to ROM routine at 0060H to wait Register Pair BC times its delay unit.
451D
58B8H
JUMP to 44FBH to show the prompt again and go on waiting for ENTER.
451F
58BAH
LD A,1EH 3E 1E
Load Register A with 1EH, the display code that erases to the end of the line. 450BH jumps here.
4521
58BCH
GOSUB to ROM routine at 0033H to display Register A (1EH): the prompt is erased.
4524
58BFH
POP HL E1
Restore Register Pair HL (the prompt address) from the stack.
4525
58C0H
POP DE D1
Restore Register Pair DE (the caller's value) from the stack.
4526
58C1H
POP BC C1
Restore Register Pair BC from the stack, and go on into 4527H.

4527H - Select the Drive

Writes 44E8H (the drive's select bit, with the source or destination mark in bit 7 or 6) to the drive select latch at 37E1H. When the controller's status had bit 7 (NOT READY) set before the select, waits with the ROM's 0060H and Register Pair BC = 0000H, its longest delay, for the motor to come up to speed.

4527
58C2H
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A. 43C3H and 4544H call here; 44E9H and 44F1H jump here.
452A
58C5H
PUSH AF F5
Save Register Pair AF (Register A = the status) onto the stack.
452B
58C6H
LD A,(44E8H) 3A E8 44
Fetch the drive and diskette in place from 44E8H into Register A: the drive's select bit, with bit 7 or bit 6.
452E
58C9H
LD (37E1H),A 32 E1 37
Store Register A into 37E1H, the drive select latch: the drive is selected and its motor runs.
4531
58CCH
POP AF F1
Restore Register Pair AF (Register A = the status before the select) from the stack.
4532
58CDH
RLCA 07
Rotate Register A left, circularly: bit 7, NOT READY, goes into the CARRY FLAG.
4533
58CEH
PUSH BC C5
Save Register Pair BC (the caller's value) onto the stack: the delay uses Register Pair BC.
4534
58CFH
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H, which gives the ROM's delay its longest time.
4537
58D2H
If the CARRY FLAG is set (it was not ready), GOSUB to ROM routine at 0060H to wait Register Pair BC (0000H) delay units for the motor.
453A
58D5H
POP BC C1
Restore Register Pair BC (the caller's value) from the stack after the delay.
453B
58D6H
RET C9
RETURN with the drive selected and, when it had to start, up to speed.

453CH - Read a Sector

Register Pair BC = the buffer, Register D = track, Register E = sector. Tries 4544H twice. 4544H selects the drive, seeks the track, sends READ SECTOR and stores each byte the controller offers; it returns the Z FLAG when the status AND 5CH is 0 (an FAH data mark is accepted, an F9H or F8H mark is an error) and Register Pair BC past the sector. On an error it sends FORCE INTERRUPT and returns the NZ FLAG with Register A = the status AND 5CH.

453C
58D7H
PUSH BC C5
Save Register Pair BC (the buffer) onto the stack, for a second try. 13 places call here.
453D
58D8H
GOSUB to 4544H to read the sector once, the first of the two tries.
4540
58DBH
POP HL E1
Restore the buffer address into Register Pair HL from the stack.
4541
58DCH
RET Z C8
If the Z FLAG is set (read), RETURN with Register Pair BC past the sector.
4542
58DDH
LD B,H 44
Copy Register H (the high byte of the buffer address) into Register B.
4543
58DEH
LD C,L 4D
Copy Register L into Register C: Register Pair BC = the buffer again for the second try, which runs on into 4544H.
4544
58DFH
GOSUB to 4527H to select the drive in 44E8H, waiting when it was not ready. 453DH calls here.
4547
58E2H
LD (37EEH),DE ED 53 EE 37
Store Register Pair DE into 37EEH: Register E into the sector register and Register D, the track, into the data register for SEEK.
454B
58E6H
PUSH DE D5
Save Register Pair DE (track and sector) onto the stack.
454C
58E7H
LD HL,37ECH 21 EC 37
Point Register Pair HL to 37ECH, the controller's command and status register.
454F
58EAH
LD (HL),1BH 36 1B
Store 1BH, SEEK, at (HL) (Register Pair HL = 37ECH).
1771 FDC Command: 1BH (00011011)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
00011011Command=Seek (bits 7-4 = 0001)
h = 1: head load and settle delay
V = 0: no verify
r1 r0 = 11: 15 ms stepping rate
4551
58ECH
PUSH AF F5
Save Register Pair AF onto the stack, a delay before the status is read.
4552
58EDH
POP AF F1
Restore Register Pair AF from the stack, part of the delay.
4553
58EEH
PUSH AF F5
Save Register Pair AF onto the stack again, more delay.
4554
58EFH
POP AF F1
Restore Register Pair AF from the stack: the controller has had time to set BUSY.
4555
58F0H
LD A,(HL) 7E
Wait for the Seek
Fetch the controller's status from (HL) (Register Pair HL = 37ECH) into Register A. 4557H loops back here.
4556
58F1H
RRCA 0F
Rotate Register A right: bit 0, BUSY, goes into the CARRY FLAG.
4557
58F2H
Wait Loop End
If the CARRY FLAG is set (busy), LOOP BACK to 4555H.
4559
58F4H
LD (HL),88H 36 88
Store 88H, READ SECTOR, at (HL) (Register Pair HL = 37ECH).
1771 FDC Command: 88H (10001000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
10001000Command=Read Sector (bits 7-5 = 100)
m = 0: one sector
b = 1: IBM sector length
E = 0: no head load delay
455B
58F6H
LD DE,37EFH 11 EF 37
Point Register Pair DE to 37EFH, the controller's data register.
455E
58F9H
PUSH BC C5
Save Register Pair BC onto the stack, a delay before the status is read.
455F
58FAH
POP BC C1
Restore Register Pair BC from the stack, part of the delay.
4560
58FBH
PUSH BC C5
Save Register Pair BC onto the stack again, more delay.
4561
58FCH
POP BC C1
Restore Register Pair BC (the buffer) from the stack.
4562
58FDH
DI F3
Disable interrupts for the transfer (they are already off since 5200H).
4563
58FEH
JUMP to 4568H to look at the status for the first byte.
4565
5900H
RRCA 0F
Nothing Ready
Rotate Register A (the status) right: bit 0, BUSY, goes into the CARRY FLAG. 456BH jumps here.
4566
5901H
If the NO CARRY FLAG is set (no longer busy), JUMP to 4573H.
4568
5903H
LD A,(HL) 7E
Transfer Loop
Fetch the controller's status from (HL) (Register Pair HL = 37ECH) into Register A. 4563H and 4570H come here.
4569
5904H
BIT 1,A CB 4F
Test bit 1 of Register A (the status), DATA REQUEST: a byte is waiting.
456B
5906H
If the Z FLAG is set (no byte), JUMP to 4565H to test BUSY.
456D
5908H
LD A,(DE) 1A
Fetch the byte from (DE) (Register Pair DE = 37EFH), the data register, into Register A.
456E
5909H
LD (BC),A 02
Store Register A at (BC) (Register Pair BC = the buffer pointer).
456F
590AH
INC BC 03
INCrement Register Pair BC (the buffer pointer) by 1.
4570
590BH
Transfer Loop End
JUMP to 4568H for the next status.
4573
590EH
LD A,(HL) 7E
Fetch the controller's final status from (HL) (Register Pair HL = 37ECH) into Register A. 4566H jumps here.
4574
590FH
AND 5CH E6 5C
AND Register A with 5CH, keeping the error bits of a read: the Z FLAG for success.
1771 Status after Read Sector, AND 5CHFunction Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
01011100Bits kept by AND 5CH:
6: F9H or F8H data mark
4: record not found
3: CRC error
2: lost data
Bit 5 (FAH or F8H mark) is not kept
4576
5911H
POP DE D1
Restore Register Pair DE (track and sector) from the stack.
4577
5912H
RET Z C8
If the Z FLAG is set (no error), RETURN to 4540H or to the caller.
4578
5913H
LD (HL),D0H 36 D0
Store D0H, FORCE INTERRUPT, at (HL) (Register Pair HL = 37ECH): the controller stops and its status shows the Type I bits again.
1771 FDC Command: D0H (11010000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
11010000Command=Force Interrupt (bits 7-4 = 1101)
I3-I0 = 0000: end the command, no interrupt
457A
5915H
RET C9
RETURN with the NZ FLAG and Register A = the status AND 5CH.

457BH - Display a Message

Register Pair HL = the text. Shows each character through the ROM's 0033H until 03H (not shown) or 0DH (shown). Register Pair HL is returned unchanged.

457B
5916H
PUSH HL E5
Save Register Pair HL (the start of the text) onto the stack. 10 places call here.
457C
5917H
LD A,(HL) 7E
Character Loop
Fetch the next character from (HL) (Register Pair HL = the text pointer) into Register A. 4587H loops back here.
457D
5918H
CP 03H FE 03
Compare Register A against 03H, the end mark that is not shown.
457F
591AH
If the Z FLAG is set (03H), JUMP to 4589H to finish.
4581
591CH
GOSUB to ROM routine at 0033H to display the character in Register A; Register A is kept.
4584
591FH
INC HL 23
INCrement Register Pair HL (the text pointer) by 1.
4585
5920H
CP 0DH FE 0D
Compare Register A against 0DH, ENTER, the end mark that is shown.
4587
5922H
Character Loop End
If the NZ FLAG is set, LOOP BACK to 457CH.
4589
5924H
POP HL E1
Restore Register Pair HL (the start of the text) from the stack. 457FH jumps here.
458A
5925H
RET C9
RETURN to the caller with the message shown and Register Pair HL at its start.

458BH - Messages of the Copy

The texts the relocated code shows, at their run addresses (file 5926H-5AA3H). The progress lines start with 1DH (cursor to the start of the line) and end with 03H, so each new one is written over the last; their track and sector digits are filled in by 4402H.

458B-459B
5926H-5936H
DEFB 1DH / DEFM "COPYING TRACK " 1D 43 4F 50 59 49 4E 47 20 20 20 54 52 41 43 4B 20
Start of the progress line of the write pass, shown by 42F1H.
459C-459D
5937H-5938H
DEFM "00" 30 30
The track being written to the destination, stored by 42E0H.
459E-45A6
5939H-5941H
DEFM ", SECTOR " 2C 20 53 45 43 54 4F 52 20
Between the track and the sector of the COPYING line.
45A7-45A8
5942H-5943H
DEFM "00" 30 30
The sector being written to the destination, stored by 42E8H.
45A9
5944H
DEFB 03H 03
End of the COPYING line: 03H ends the text without moving to a new line.
45AA-45BA
5945H-5955H
DEFB 1DH / DEFM "VERIFYING TRACK " 1D 56 45 52 49 46 59 49 4E 47 20 54 52 41 43 4B 20
Start of the progress line of the read back (4328H) and of the format's verify (5513H).
45BB-45BC
5956H-5957H
DEFM "00" 30 30
The track being read back, stored by 4317H and 5500H.
45BD-45C5
5958H-5960H
DEFM ", SECTOR " 2C 20 53 45 43 54 4F 52 20
Between the track and the sector of the VERIFYING line.
45C6-45C7
5961H-5962H
DEFM "00" 30 30
The sector being read back, stored by 431FH and 550CH.
45C8
5963H
DEFB 03H 03
End of the VERIFYING line: 03H ends the text without moving to a new line.
45C9-45D9
5964H-5974H
DEFB 1DH / DEFM "LOADING TRACK " 1D 4C 4F 41 44 49 4E 47 20 20 20 54 52 41 43 4B 20
Start of the progress line of the load pass, shown by 4271H.
45DA-45DB
5975H-5976H
DEFM "00" 30 30
The track being loaded from the source, stored by 4260H.
45DC-45E4
5977H-597FH
DEFM ", SECTOR " 2C 20 53 45 43 54 4F 52 20
Between the track and the sector of the LOADING line.
45E5-45E6
5980H-5981H
DEFM "00" 30 30
The sector being loaded from the source, stored by 4268H.
45E7
5982H
DEFB 03H 03
End of the LOADING line: 03H ends the text without moving to a new line.
45E8-4600
5983H-599BH
DEFB 0AH / DEFM "SOURCE DISK READ ERROR!" / DEFB 0DH 0A 53 4F 55 52 43 45 20 44 49 53 4B 20 52 45 41 44 20 45 52 52 4F 52 21 0D
Shown by 43A3H when a source sector cannot be read in two tries (5305H, 531DH, 4278H, 4455H, 4473H).
4601-461E
599CH-59B9H
DEFB 0AH / DEFM "DESTINATION DISK READ ERROR!" / DEFB 0DH 0A 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 20 52 45 41 44 20 45 52 52 4F 52 21 0D
Shown when a destination sector cannot be read in two tries (535CH, 420FH, 432FH, 4377H, 4386H, 44D5H).
461F-463D
59BAH-59D8H
DEFB 0AH / DEFM "DESTINATION DISK WRITE ERROR!" / DEFB 0DH 0A 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 20 57 52 49 54 45 20 45 52 52 4F 52 21 0D
Shown when a destination sector cannot be written in two tries (4222H, 4303H, 436BH, 4397H).
463E-4663
59D9H-59FEH
DEFB 0AH / DEFM "DESTINATION DISK IS WRITE PROTECTED!" / DEFB 0DH 0A 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 20 49 53 20 57 52 49 54 45 20 50 52 4F 54 45 43 54 45 44 21 0D
Shown when the destination's status has WRITE PROTECT set (533CH, 44AAH).
4664-4682
59FFH-5A1DH
DEFB 1DH, 1EH / DEFM "INSERT SOURCE DISK (ENTER)" / DEFB 1DH, 03H 1D 1E 49 4E 53 45 52 54 20 53 4F 55 52 43 45 20 44 49 53 4B 20 20 28 45 4E 54 45 52 29 1D 03
The prompt of 442FH, blinked by 44E7H on one drive: cursor to the start of the line, erase it, the text, cursor back to the start.
4683-46A6
5A1EH-5A41H
DEFB 1DH, 1EH / DEFM "INSERT DESTINATION DISK (ENTER)" / DEFB 1DH, 03H 1D 1E 49 4E 53 45 52 54 20 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 20 20 28 45 4E 54 45 52 29 1D 03
The prompt of 44A1H, blinked by 44E7H on one drive.
46A7-46DD
5A42H-5A78H
DEFB 1DH, 1EH / DEFM "W A K E U P !!! THAT'S NOT THE SAME SOURCE DISK !" / DEFB 0DH 1D 1E 57 20 41 20 4B 20 45 20 20 20 55 20 50 20 21 21 21 20 20 54 48 41 54 27 53 20 4E 4F 54 20 54 48 45 20 53 41 4D 45 20 53 4F 55 52 43 45 20 44 49 53 4B 20 21 0D
Shown by 448DH when the diskette put in as the source has a different pack ID; the source is then asked for again.
46DE-46EE
5A79H-5A89H
DEFB 0AH / DEFM "BACKUP COMPLETE" / DEFB 0DH 0A 42 41 43 4B 55 50 20 43 4F 4D 50 4C 45 54 45 0D
Shown by 43A0H-43A3H when the copy is finished.
46EF-4708
5A8AH-5AA3H
DEFB 0AH, 0AH / DEFM "HIT 'ENTER' TO CONTINUE" / DEFB 0DH 0A 0A 48 49 54 20 27 45 4E 54 45 52 27 20 54 4F 20 43 4F 4E 54 49 4E 55 45 0D
Shown by 43A6H after every final message, before the HALT.

4709H - Variables of the Copy

4709H-4712H are not in the file (5AA4H-5AADH); 4713H-4714H come from a load record of their own, two bytes of 00H at 5AAEH-5AAFH.

4709
5AA4H
DEFS 1
Not in the file: the source's directory track, from byte 2 of its boot sector (530EH); read at 5311H, 5350H, 540FH, 435DH and 4467H.
470A-4711
5AA5H-5AACH
DEFS 8
Not in the file: the backup date MM/DD/YY, typed or taken from SYS0/SYS into 5AA5H-5AACH and moved here by 52CAH; 434FH copies it into the allocation table.
4712
5AADH
DEFS 1
Not in the file and not used: the byte after the date.
4713
5AAEH
DEFB 00H 00
The tracks that fit in memory in one pass on one drive, set by 5595H and compared at 4295H.
4714
5AAFH
DEFB 00H 00
The tracks loaded and not yet written: cleared at 422FH, counted up at 428EH and down at 433EH.

5AB0H - Messages of the Start and the Format

5AB0H-5F9AH are not in the file. 52CAH copies them, with the code before them and the messages after them up to 609AH, to 4715H-4CFFH; the copy of this unloaded area becomes the work tables 4800H (one status byte per track), 4900H (the source's allocation table), 4A00H (the lockout table and the destination's allocation table) and 4B00H (the sector buffer). The messages from 5F9BH on are used at their file addresses; their copy at 4C00H-4CFFH is not used. The sector order table at 6293H is used by the format.

5AB0-5F9A
DEFS 1259
Not in the file. Copied by 52CAH to 4715H-4BFFH, where 4800H-4822H, 4900H-49FFH, 4A00H-4AFFH and 4B00H-4BFFH are BACKUP's work tables.
5F9B-5FCF
DEFM "SINGLE DRIVE BACKUP INVALID DURING PROGRAM CHAINING!" / DEFB 0DH 53 49 4E 47 4C 45 20 44 52 49 56 45 20 42 41 43 4B 55 50 20 49 4E 56 41 4C 49 44 20 44 55 52 49 4E 47 20 50 52 4F 47 52 41 4D 20 43 48 41 49 4E 49 4E 47 21 0D
Shown by 5213H when bit 5 of the system flags at 430FH is set; the drives are not known yet at that point.
5FD0-5FF7
DEFB 1CH, 1FH / DEFM "TRSDOS DISK BACKUP UTILITY VER 2.3" / DEFB 0AH, 0DH 1C 1F 54 52 53 44 4F 53 20 44 49 53 4B 20 42 41 43 4B 55 50 20 55 54 49 4C 49 54 59 20 20 20 56 45 52 20 32 2E 33 0A 0D
The title shown by 521CH: cursor to the top left, erase to the end of the screen, the text, a line feed and 0DH.
5FF8-600E
DEFM "SOURCE DRIVE NUMBER ? " / DEFB 03H 53 4F 55 52 43 45 20 44 52 49 56 45 20 4E 55 4D 42 45 52 20 3F 20 03
The prompt of 5232H; 03H leaves the cursor after it for the answer.
600F-602A
DEFM "DESTINATION DRIVE NUMBER ? " / DEFB 03H 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 52 49 56 45 20 4E 55 4D 42 45 52 20 3F 20 03
The prompt of 526DH; 03H leaves the cursor after it for the answer.
602B-6044
DEFM "BACKUP DATE (MM/DD/YY) ? " / DEFB 03H 42 41 43 4B 55 50 20 44 41 54 45 20 28 4D 4D 2F 44 44 2F 59 59 29 20 3F 20 03
The prompt of 52A9H; 03H leaves the cursor after it for the answer.
6045-605C
DEFM "SOURCE DRIVE NOT READY!" / DEFB 0DH 53 4F 55 52 43 45 20 44 52 49 56 45 20 4E 4F 54 20 52 45 41 44 59 21 0D
Shown by 52F1H when the source's status has NOT READY set after RESTORE.
605D-6078
DEFM "SOURCE DRIVE NOT IN SYSTEM!" / DEFB 0DH 53 4F 55 52 43 45 20 44 52 49 56 45 20 4E 4F 54 20 49 4E 20 53 59 53 54 45 4D 21 0D
Shown by 52F9H when the source's head is not on track 0 after RESTORE.
6079-6095
DEFM "DESTINATION DRIVE NOT READY!" / DEFB 0DH 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 52 49 56 45 20 4E 4F 54 20 52 45 41 44 59 21 0D
Shown by 5331H when the destination's status has NOT READY set after RESTORE.
6096-60B6
DEFM "DESTINATION DRIVE NOT IN SYSTEM!" / DEFB 0DH 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 52 49 56 45 20 4E 4F 54 20 49 4E 20 53 59 53 54 45 4D 21 0D
Shown by 5339H when the destination's head is not on track 0 after RESTORE.
60B7-60D8
DEFM "NO DISKETTE IN DESTINATION DRIVE!" / DEFB 0DH 4E 4F 20 44 49 53 4B 45 54 54 45 20 49 4E 20 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 52 49 56 45 21 0D
Shown by 53A5H and 53CEH when the index pulse does not end in time.
60D9-60FE
DEFM "DOOR NOT CLOSED ON DESTINATION DRIVE!" / DEFB 0DH 44 4F 4F 52 20 4E 4F 54 20 43 4C 4F 53 45 44 20 4F 4E 20 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 52 49 56 45 21 0D
Shown by 53B8H and 53E2H when no next index pulse comes in time.
60FF-612C
DEFM "DESTINATION DISKETTE UNUSABLE! HARD-SECTORED!" / DEFB 0DH 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 45 54 54 45 20 55 4E 55 53 41 42 4C 45 21 20 48 41 52 44 2D 53 45 43 54 4F 52 45 44 21 0D
Shown by 53F4H when the index pulses come less than 1535H loop turns apart.
612D-6163
DEFM "BACKUP REJECTED, DISKETTES CONTAIN DIFFERENT PACK IDS!" / DEFB 0DH 42 41 43 4B 55 50 20 52 45 4A 45 43 54 45 44 2C 20 44 49 53 4B 45 54 54 45 53 20 43 4F 4E 54 41 49 4E 20 44 49 46 46 45 52 45 4E 54 20 50 41 43 4B 20 49 44 53 21 0D
Shown by 5380H when a readable destination's bytes CEH-D7H differ from the source's.
6164-6175
DEFB 1DH / DEFM "FORMATTING TRACK " 1D 46 4F 52 4D 41 54 54 49 4E 47 20 54 52 41 43 4B 20
Start of the format's progress line, shown by 5408H.
6176-6177
DEFM "00" 30 30
The track being formatted on the destination, stored by 5401H.
6178
DEFB 03H 03
End of the FORMATTING line: 03H ends the text without moving to a new line.
6179-61A4
DEFB 0AH / DEFM "CAN'T FORMAT, DISK TRANSFER RATE TOO FAST!" / DEFB 0DH 0A 43 41 4E 27 54 20 46 4F 52 4D 41 54 2C 20 44 49 53 4B 20 54 52 41 4E 53 46 45 52 20 52 41 54 45 20 54 4F 4F 20 46 41 53 54 21 0D
Shown by 54D0H when WRITE TRACK ends with LOST DATA.
61A5-61C9
DEFB 0AH / DEFM "CAN'T FORMAT, MOTOR SPEED TOO SLOW!" / DEFB 0DH 0A 43 41 4E 27 54 20 46 4F 52 4D 41 54 2C 20 4D 4F 54 4F 52 20 53 50 45 45 44 20 54 4F 4F 20 53 4C 4F 57 21 0D
Shown by 54DFH when WRITE TRACK took fewer than 0BEDH bytes.
61CA-61EE
DEFB 0AH / DEFM "CAN'T FORMAT, MOTOR SPEED TOO FAST!" / DEFB 0DH 0A 43 41 4E 27 54 20 46 4F 52 4D 41 54 2C 20 4D 4F 54 4F 52 20 53 50 45 45 44 20 54 4F 4F 20 46 41 53 54 21 0D
Shown by 54E9H when WRITE TRACK took 0C69H bytes or more.
61EF-620D
DEFM ": NOT FOUND! TRACK LOCKED OUT!" / DEFB 0DH 3A 20 4E 4F 54 20 46 4F 55 4E 44 21 20 54 52 41 43 4B 20 4C 4F 43 4B 45 44 20 4F 55 54 21 0D
Shown by 43F5H after the VERIFYING line when a sector of a new track is not found.
620E-622C
DEFM ": CRC ERROR! TRACK LOCKED OUT!" / DEFB 0DH 3A 20 43 52 43 20 45 52 52 4F 52 21 20 54 52 41 43 4B 20 4C 4F 43 4B 45 44 20 4F 55 54 21 0D
Shown by 43F5H after the VERIFYING line when a sector of a new track has a CRC error.
622D-625F
DEFB 0AH / DEFM "BACKUP REJECTED DUE TO FLAWS ON DESTINATION DISK!" / DEFB 0DH 0A 42 41 43 4B 55 50 20 52 45 4A 45 43 54 45 44 20 44 55 45 20 54 4F 20 46 4C 41 57 53 20 4F 4E 20 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 21 0D
Shown by 556BH when a granule the source uses lies on a locked out track of the destination.
6260-6292
DEFB 0AH / DEFM "CAN'T VERIFY FORMAT, DISK TRANSFER RATE TOO FAST!" / DEFB 0DH 0A 43 41 4E 27 54 20 56 45 52 49 46 59 20 46 4F 52 4D 41 54 2C 20 44 49 53 4B 20 54 52 41 4E 53 46 45 52 20 52 41 54 45 20 54 4F 4F 20 46 41 53 54 21 0D
Shown by 5532H when a sector of the new format ends with LOST DATA.
6293-629D
DEFB 00H, 05H, 01H, 06H, 02H, 07H, 03H, 08H, 04H, 09H, FFH 00 05 01 06 02 07 03 08 04 09 FF
The order of the sector numbers around a formatted track (5420H, 543EH): 0, 5, 1, 6, 2, 7, 3, 8, 4, 9; FFH ends the table.