TRS-80 DOS - NEWDOS/80 v2.0 for the Model III - SYS6/SYS Disassembled

Page Customization

Introduction/Summary

NEWDOS/80 v2.0 SYS6/SYS Disassembly - FORMAT, COPY and APPEND (Model III)

SYS6/SYS is the overlay that carries out the library commands FORMAT, COPY and APPEND (manual sections 2.22, 2.14 and 2.2). A diskette is backed up with COPY format 5 (sector by sector) or format 6 (file by file, CBF). SYS6/SYS is far larger than the overlay area: its 37 load records fill four address ranges, 4D00H-5185H, 5200H-6484H, 64A3H-65B2H and 65B7H-6FF8H (8,797 bytes), and its transfer address is 4D00H. SYS1/SYS runs it with RST 28H code 28H (FORMAT), 48H (COPY) or 68H (APPEND), and 4D00H sends each code to its command.

The page shows every byte of the file once, in address order. Bytes that are not in the file are shown as DEFS rows without a byte column.

Commands and Program Flow

COPY (4D1EH) parses the command to decide the format. A leading drive number followed by a second drive number is a diskette COPY (formats 5 and 6); a leading drive number followed by two filespecs is format 3 or 4 (4D8BH); otherwise it is format 1 or 2 (4D98H). A $ before the first filespec says that the system diskette must be swapped in and out of drive 0. The options are parsed by 4EA7H with the keyword table at 505CH.

Single file COPY (formats 1 to 4, 6377H): the drive of each filespec is found (6437H), the files are opened through the source FCB at 5AE5H and the destination FCB at 5B17H, and the COPY engine (5273H) copies the sectors. The destination is given its whole size at once by writing its last sector first (5360H) and is closed with the source's EOF at 54ACH.

Diskette COPY (format 5, 6291H): the source diskette's GAT is checked (SN, SPW, USD), the destination is checked and formatted if asked (67C5H), and the COPY engine copies every sector through FCBs that address sectors of the whole diskette. Unless BDU is given, the boot sectors are replaced by SYS6/SYS's own and the destination drive's PDRIVE record goes into the system data sector (52DBH). SYS17/SYS finishes the job at its 502CH, which 54D4H jumps to: the destination is verified and its GAT brought up to date.

COPY by file (format 6, 5D16H): the destination is formatted and given its system data (6643H) unless NFMT is given, the files to copy are chosen from the source directory (5D86H) with ILF, XLF, UPD, USR, /ext and CFWO, their directory entries are made on the destination (5EE4H, 60BFH), and then the COPY engine copies them one after another, opening each file by its directory entry code (DEC) through SYS2/SYS's FCB building code (56B9H).

FORMAT (65FAH) parses dn2[=tc2],name,date,password and the options, then uses the same code as a formatting COPY: 67C5H checks the old contents and formats the tracks (695AH), and 6643H reads the diskette back and writes the boot sectors, the PDRIVE sector, the GAT, the HIT and the FDE sectors.

APPEND (6F4AH) opens the second file, positions it to its end and copies the first file onto it byte by byte through the ROM routines at 0013H and 001BH.

Every error ends at 521AH, which puts the system diskette back in drive 0, restores the PDRIVE data changed by the command, and exits through SYS0/SYS 4409H. Disk errors during a COPY or FORMAT give the operator the choice C (cancel), R (retry) or P (proceed) (57DAH). Unless NDMW is given, holding the right arrow pauses and the up arrow cancels at any time (571BH).

Memory Use

SYS6/SYS reuses its own memory as it goes, so several addresses have more than one use.

Address RangeUse
4D00H-51FFHSYS6/SYS's command parsing code. After the options have been parsed, 4D3EH-4D8DH holds a copy of the command line (4DA6H), and SYS2/SYS, SYS3/SYS or SYS17/SYS is loaded into the overlay area (568BH). SYS6/SYS then calls into that overlay directly and changes some of its operands (SYS2/SYS 4F56H and 4F5EH, SYS3/SYS 4FB8H).
4300H-43FFHSector buffer: the GAT, HIT and directory sectors, the PDRIVE sector, and the read back buffer of the verify (5D10H).
5933H-5D15HVariables, control blocks, FCBs, messages, the patch lists and routines for a diskette with TI flag M, and 78 unused bytes at 5C9FH-5CECH.
(5D14H)-(593CH)Sector buffers of the COPY engine, 258 bytes each, up to 6FFFH, or up to HIMEM when COPY does not run under DOS-CALL. In a COPY by file the file list and the 24-byte copies of directory entries come first.
6291H-6390HCOPY setup code, then a copy of the HIT sector.
6391H-6490HCOPY setup code, then a copy of the destination's GAT sector.
6485H-64A2HNot in the file: the interleave table of the track being formatted (from 6485H) and the start of the COPY by file list (6491H).
64BAH-65B9HThe boot sector written to every new diskette (it runs at 4300H). 65B3H-65B6H is not in the file.
6EB4H-6FB3HCommand line parsing code and APPEND, replaced by 4DF3H with the PDRIVE sector that is written to the new diskette.

Diskette Control Blocks and Swapping

The three diskettes of a COPY or FORMAT each have a 10-byte control block: system 5942H, source 594CH, destination 5956H. It holds the drive number, a role bit (01H system, 02H source, 04H destination), the FCB address, the address of the working PDRIVE record, the address of the saved original PDRIVE record and the address of the diskette's name. 5585H switches to a diskette. 5940H holds the set of diskettes that share a drive and must be swapped, 5941H the set that is mounted now; when a diskette is needed that is not mounted, the operator is asked to mount it (PRESS "ENTER" WHEN ... DISKETTE MOUNTED IN DRIVE n).

PDRIVE Records

Sector 2 of a NEWDOS/80 system diskette (the third sector of BOOT/SYS) holds a 16-byte PDRIVE record for each of drives 0-9 (6424H reads it). SYS0/SYS keeps the first ten bytes of the record of each drive at 4291H (10 bytes per drive). When it selects a drive (4723H) it stores the address of that drive's entry at 42B9H and copies its first eight bytes to 4280H-4287H, where SYS6/SYS reads them through Index Register IY = 4280H. SYS6/SYS works with ten-byte records in the same format: saved originals at 5999H, 59A3H and 59ADH, and the working records of the source (59B7H) and destination (59C5H), each followed by two words of its own (the total sectors and the total granules, 6710H).

ByteContents
+0Starting lump of the directory of the diskette in the drive.
+1Number of lumps on the diskette.
+2Flags. Bits 0-1: the stepping rate, which SYS0/SYS ORs into the head positioning commands it sends through 46F7H. Bit 5: TI flag M (see Diskettes with TI Flag M). Bit 6: TI flag K, track 0 in the other density (68DBH). Bit 7: SYS0/SYS adds a delay after selecting a different drive (477AH).
+3TC, the track count.
+4SPT, the sectors per track.
+5GPL, the granules per lump.
+6The byte SYS0/SYS writes to the controller's sector register when it selects the drive (475EH). FORMAT copies it into the boot sector (6759H).
+7Disk I/O flags: bit 0 double density, bit 1 tracks numbered from 1 (TI flags J or K), bit 2 double step (TI flag L), bit 4 sectors numbered from 1 (TI flag I), bit 6 double sided, bit 7 8 inch.
+8DDSL, the default starting lump of the directory.
+9DDGA, the default granules of the directory.

Diskettes with TI Flag M

A drive whose PDRIVE entry has TI flag M (bit 5 of byte +2, 4282H for the current drive) holds a diskette with a directory layout of its own, which only COPY handles. Whenever the current drive's flag and the patches in memory disagree, 55FBH exchanges sets of patch bytes with bytes of SYS0/SYS, SYS2/SYS and SYS3/SYS (patch sets at 5B57H), so the same loop puts the patches in and takes them out. With the patches in, SYS0/SYS reverses the meaning of the two data address marks, reads the directory lump from byte 1 of the boot sector, handles five 48-byte directory entries to a sector, 13 extent elements and 3-sector granules, and does not mark a written file updated in its directory entry. Some patches jump to routines in SYS6/SYS (5C0BH). A patch set for SYS2/SYS or SYS3/SYS that is in while another overlay has replaced that module ends the command with error 33H (5608H).

A sector by sector diskette COPY with such a diskette, and formatting a destination with TI flag M, need BDU (674DH): SYS6/SYS does not write system data for it. A COPY by file does not copy system files to or from it (5E5EH), and SYS6/SYS's directory code counts its DECs 0-4FH one after another (61BAH) and divides sectors by 3 into granules when it is in double density (5CFBH).

Formatting a Track

695AH formats the tracks of the destination. The drive's disk I/O flags pick one of four 26-byte lines of the table at 6CC1H (5 or 8 inch, single or double density), whose values are stored into the operands of the track writer. For each track and side the sector numbers are laid out in the interleave table at 6485H (6A00H-6A66H), the select byte at 427FH is given the density (bit 7), write precompensation for the inner half of the tracks (bit 5) and the side (bit 4), and the track is written with the Write Track command (6AA7H).

The track writer sends every byte with OUT (C),D to port F3H after sending the select byte with bit 6 set to port F4H: bit 6 turns on the wait states, so the CPU is held on the OUT until the controller asks for the byte. Only the first two bytes are written after polling the status. The end of the track comes as an NMI (vector 4049H set to JP 6BA5H, NMI mask C0H at port E4H): 6BA5H drops the return address, stores the bytes of a RETN at 4049H and takes the final status. The gap bytes written after the last sector (Register Pair HL) tell whether the diskette turns at the right speed (MOTOR FAST or MOTOR SLOW, 6BCAH-6BD9H).

Every sector of the track is then read back (6BDCH) with SYS0/SYS's own read routine at 466FH: the transfer loop is set for a read (469EH, 5C96H), the track register is loaded with the track number written into the ID fields, the bytes go to 0000H (the ROM), and a RET stored over the POP AF at 46C9H makes SYS0/SYS's NMI routine return at once with the status in Register B. A track that fails is written again up to 10 times (6C94H).

Option Flags

Each option found in the table at 505CH sets one bit in 5994H-5997H.

Bit5994H5995H5996H5997H
7NNDMWSN (COPY), RWF (FORMAT)SPDN
6YCFWOSPWDPDN
5DDNDNDPWUBBXLF
4ODNUSDUSRILF
3KDNDFOCBFNFMT
2NDNDDSLsingle file COPYFMT
1BDUDDGA/extPFST
0KDDODPWUPDPFTC

Variables

SYS0/SYS Memory Used by SYS6/SYS

Address
Size
Contents
3C3FH
1 byte
Screen, Top Right Corner
The progress asterisk blinked by 571BH once for each sector.
4049H-404AH
2 bytes
NMI Vector
Set to JP 6BA5H by 6ACBH and 6AD0H for the end of a track write, and given the bytes EDH 45H (RETN) again by 6BAEH.
421AH-421CH
3 bytes
System Date
Read by 5C72H, 5C77H, 612FH and 6133H (the year at 421AH, the month at 421CH) for the dates put into new directory entries of a diskette with TI flag M.
427EH
1 byte
Current Drive
The drive SYS0/SYS selected last; 4720H selects it again (567CH, 6910H, 695DH, 6A6DH).
427FH
1 byte
Select Byte
The byte SYS0/SYS sends to port F4H (4715H). The track writer sets bit 7 (double density), bit 5 (write precompensation) and bit 4 (side 1) in it (6A74H-6A99H) and copies it with bit 6 (wait states) into its own operand (6AB0H).
4280H-4287H
8 bytes
Current Drive's PDRIVE Values
Copied by SYS0/SYS from the selected drive's entry, reached through Index Register IY = 4280H: 4282H the flags (bit 5 TI flag M, bit 6 TI flag K; 560DH, 5CEDH, 61F6H, 68DBH), 4283H the track count (4CA4H), 4284H the sectors per track (6CA3H) and 4287H the disk I/O flags (6961H, 6A59H, 6A77H, 6CAEH).
4288H
1 byte
Resident Overlay
The number of the overlay in 4D00H-51FFH (04H SYS2/SYS, 05H SYS3/SYS). 4D04H clears it because SYS6/SYS's own code is there; 54C9H and 5F86H store 05H after SYS3/SYS has cleared it.
4289H
1 byte
System Flags
Bit 3 is set by 4D0DH while FORMAT or COPY runs and cleared by the exit (5235H); the D-F-G, 1-2-3 and J-K-L key combinations are ignored while it is set.
428AH
1 byte
System Flags
Bit 6, a DOS-CALL is active: COPY then keeps below 7000H (4D21H), and a one-drive COPY ends with error 15H (4E36H).
428BH
1 byte
Temporary Flags
Bit 1 (538EH) stops SYS2/SYS taking extra granules; bit 2 (5F74H) makes SYS3/SYS leave the FCB alone when it frees space.
428CH
1 byte
System Options
Bit 7 (AA) and bit 1 (AR): when AA is set and AR is clear the diskette passwords are checked (62B3H, 6314H, 6814H).
42B9H-42BAH
2 bytes
PDRIVE Entry Address
The address of the selected drive's 10-byte PDRIVE entry (4291H + 10 x drive), read by 566DH, 6690H and 68E3H.
4300H-43FFH
256 bytes
Sector Buffer
The GAT, HIT and directory sectors, the PDRIVE sector of drive 0 and the read back buffer of the verify pass (5D10H).
4411H-4412H
2 bytes
HIMEM
The top of memory. 4D2BH copies it to 593CH when COPY does not run under DOS-CALL.
4480H-449FH
32 bytes
DOS FCB
Holds the ILF= or XLF= filespec (4FACH) and is used to read that list file (5D30H); 448CH is the middle byte of its EOF (5D33H).
45F5H
1 byte
SYS0/SYS Operand A2H
The high byte of the LD BC,A202H at 45F3H, the second byte of INI, which 6BE1H fetches for the read back.
4687H
1 byte
Controller Command
The operand of the LD A,nn at 4686H that SYS0/SYS's routine at 466FH sends to the controller: 6BDEH stores 88H (Read Sector), and 5C0FH reads it.
468FH, 469EH, 46A6H
3 bytes
SYS0/SYS Transfer Loop
The Register B operand of the LD BC at 468DH and the second bytes of the two INI instructions at 469DH and 46A5H, set for a read by 6BE4H and 5C96H.
46C9H
1 byte
SYS0/SYS POP AF
The POP AF after the Force Interrupt in SYS0/SYS's NMI routine: 6BFDH stores C9H (RET) there for the read back and 6C13H puts F1H back.
48D5H
1 byte
Directory Sector Held
The number of the directory sector in 4300H. 558AH stores FFH (none) whenever 5585H switches to a diskette.

SYS6/SYS Variables

Address
Size
Contents
5933H-593AH
8 bytes
Powers of Ten
-10000, -1000, -100 and -10 for the decimal display routine at 5909H.
593BH
1 byte
SYS6/SYS Flags
Bit 7 is set by 63BDH once the drives' PDRIVE data has been saved; from then on each diskette gets its own data and the exit puts the drives' data back.
593CH-593DH
2 bytes
Top of the Buffers
6FFFH as loaded, or HIMEM (4D2EH): the highest address COPY may use.
593EH-593FH
2 bytes
Current Control Block
5942H, 594CH or 5956H, stored by 5585H.
5940H
1 byte
Swap Set
Bit 0 system, bit 1 source, bit 2 destination: the diskettes that share a drive and must be swapped.
5941H
1 byte
Mounted Set
The same bits for the diskettes that are in their drives now (07H as loaded).
5942H-595FH
30 bytes
Diskette Control Blocks
System 5942H, source 594CH, destination 5956H (see Diskette Control Blocks and Swapping).
5960H-5967H
8 bytes
Password Buffer
Used by the password encoder at 5025H.
5968H-596FH
8 bytes
SN Name
The source diskette name from SN=.
5970H-5977H
8 bytes
ODN Name
The old destination name from ODN=.
5978H-5979H
2 bytes
SPW Code
The encoded source diskette password from SPW=.
597AH-597BH
2 bytes
ODPW Code
The encoded old destination password from ODPW=.
597CH
1 byte
Source FDE Sectors
The number of FDE sectors in the source directory (5D8FH).
597DH
1 byte
Destination FDE Sectors
The number of FDE sectors in the destination directory (5EEDH).
597EH-5993H
22 bytes
New GAT System Data
Copied to GAT bytes CBH-E0H of a new diskette by 66A2H: the password code at 5981H, the name at 5983H, the date at 598BH and the AUTO byte at 5993H.
5994H-5997H
4 bytes
Option Flags
Set through the option table at 505CH (see Option Flags).
5999H-59D2H
58 bytes
PDRIVE Records and Sizes
The saved records of drive 0 (5999H), the source (59A3H) and the destination (59ADH), the working records of the source (59B7H) and destination (59C5H), and after each working record its total sectors and total granules.
5AE5H-5B16H
50 bytes
Source FCB
Opened by sector number on the diskette for a diskette COPY, or by filespec for a file COPY.
5B17H-5B48H
50 bytes
Destination FCB
Set up in the same way.
5B49H-5B56H
14 bytes
Drive 0 Sector FCB
Reads sector 2 of the system diskette in drive 0 into 4300H (6424H).
5B57H-5B63H
13 bytes
TI Flag M Patch Sets
Three 4-byte records for SYS0/SYS, SYS2/SYS and SYS3/SYS and the 00H that ends them (see Diskettes with TI Flag M).
5D10H-5D11H
2 bytes
Verify Buffer
4300H.
5D12H-5D13H
2 bytes
File List Start
The start of the COPY by file list (5D16H as loaded).
5D14H-5D15H
2 bytes
File List End
The end of the file list and the start of the sector buffers.
6485H-64A2H
30 bytes
Interleave Table
Not in the file: the sector numbers of the track being formatted, in the order they are written (6A14H-6A66H, 6AD3H, 6BEAH).
64A3H-64AFH
13 bytes
Override Table
The track counts, DDSL and DDGA typed in the command, put into the working records by 63DAH.

Operands Changed at Run Time

Address
Size
Contents
4DFAH
1 byte
Destination Drive for the PDRIVE Sector (Self-Modifying Code)
The operand of the instruction at 4DF9H. Stored by 639CH when the destination drive is parsed.
4F85H-4F86H
2 bytes
Option Handler (Self-Modifying Code)
The operand of the instruction at 4F84H. 0000H in the file; 4F7DH stores the handler address there for each option.
52BAH-52BBH
2 bytes
File List Entry Being Read (Self-Modifying Code)
The operand of the instruction at 52B9H. 0000H in the file; 56AAH stores the entry address there in a COPY by file.
52D2H
1 byte
Marker Byte (Self-Modifying Code)
The operand of the instruction at 52D1H. FFH in the file; in a COPY by file 56B1H stores the destination DEC of the file being read there.
5314H
1 byte
Sectors Read (Self-Modifying Code)
The operand of the instruction at 5313H. 00H in the file; 5316H stores the count there, and the write loop counts it down at 53F5H.
531AH
1 byte
Buffer Entries (Self-Modifying Code)
The operand of the instruction at 5319H. 0AH in the file; 528EH stores the number of entries that fit there.
53D7H
1 byte
Skip Flag (Self-Modifying Code)
The operand of the instruction at 53D6H. 00H in the file; 5368H stores 00H for each new file and 53CEH stores FFH when the file did not fit.
53ECH
1 byte
Sectors Written (Self-Modifying Code)
The operand of the instruction at 53EBH. 00H in the file; 533BH clears it, 53EEH counts up, and the verify pass counts it down at 545DH.
5401H-5402H
2 bytes
First Sector of the Pass (Self-Modifying Code)
The operand of the instruction at 5400H. 0000H in the file; 5336H stores the destination FCB's NEXT there at the start of the pass.
544FH-5450H
2 bytes
Entry Being Verified (Self-Modifying Code)
The operand of the instruction at 544EH. 0000H in the file; 532FH stores the first entry of the pass there and 5454H advances it.
570EH
1 byte
Changed Directory Sector (Self-Modifying Code)
The operand of the instruction at 570DH. FFH in the file; 5706H stores a sector number there and 5713H puts FFH back.
57EBH
1 byte
Operation for the Error Report (Self-Modifying Code)
The operand of the instruction at 57EAH. 00H in the file; it is stored before each operation: 80H reading the source (52A5H), 40H writing the destination (547EH), 20H verifying the destination (540EH, 578CH).
586AH
1 byte
COPY by File Flag (Self-Modifying Code)
The operand of the instruction at 5869H. 00H in the file; 615CH stores FFH there when a COPY by file starts copying.
5F1EH-5F1FH
2 bytes
Destination Entry (Self-Modifying Code)
The operand of the instruction at 5F1DH. 0000H in the file; 5F04H stores the entry's address there.
6028H
1 byte
DEC Being Tested (Self-Modifying Code)
The operand of the instruction at 6027H. 00H in the file; 5FE1H stores the DEC there.
6078H-6079H
2 bytes
Extent Destination (Self-Modifying Code)
The operand of the instruction at 6077H. 0000H in the file; 5FF6H stores the address of the entry's byte 22 there.
60C3H
1 byte
Files Without an Entry (Self-Modifying Code)
The operand of the instruction at 60C2H. 00H in the file; 608CH stores a value that is not 0 there when a file still needs an entry.
61D8H-61D9H
2 bytes
Next 24-Byte Space (Self-Modifying Code)
The operand of the instruction at 61D7H. 0000H in the file; 6190H stores the end of the file list there and 61E4H advances it.
61DBH-61DCH
2 bytes
Limit of the 24-Byte Spaces (Self-Modifying Code)
The operand of the instruction at 61DAH. 0000H in the file; 5D9DH stores the top of memory less 24 there.
63CAH
1 byte
SPDN Number (Self-Modifying Code)
The operand of the instruction at 63C9H. FFH in the file (none); 500BH stores the number there.
63D6H
1 byte
DPDN Number (Self-Modifying Code)
The operand of the instruction at 63D5H. FFH in the file (none); 500BH stores the number there.
64BCH
1 byte
Boot Sector: Directory Lump
Byte 2 of the boot sector (the data byte of the CP nn at 64BBH). 6799H stores the destination's DDSL.
64BFH-64C0H
2 bytes
Boot Sector: First Sector of SYS0/SYS
The operand of the LD DE,0005H at 64BEH. 6774H adds 1 to the sector when sectors are numbered from 1, 676CH adds 1 to the track when tracks are numbered from 1.
6506H
1 byte
Boot Sector: Side 0 Select Byte
The operand of the LD L,01H at 6505H. 6781H sets bit 7 (double density).
650BH
1 byte
Boot Sector: Sectors on One Side
The operand of the SUB nn at 650AH. 6793H stores the sectors per track, halved for a double sided drive.
6510H
1 byte
Boot Sector: Side 1 Select Byte
The operand of the LD L,11H at 650FH. 6786H sets bit 7 (double density).
6560H-6561H
2 bytes
Boot Sector: Saved Stack Pointer (Self-Modifying Code)
The operand of the LD SP,nnnn at 655FH (43A5H when the boot sector runs). 0000H in the file; the boot code's 4372H stores the Stack Pointer there.
6571H
1 byte
Boot Sector: Sectors per Track
The operand of the SUB nn at 6570H. 678DH stores the sectors per track of both sides.
6576H
1 byte
Boot Sector: First Sector Number
The operand of the LD E,nn at 6575H. 6778H stores 01H when the drive's sectors are numbered from 1.
65B7H-65B9H
3 bytes
Boot Sector: PDRIVE Bytes
Bytes FDH-FFH of the boot sector: 675CH stores byte +6, 67A8H the flags (+2) and 6762H the disk I/O flags (+7) of the destination's working record.
65F0H-65F1H
2 bytes
DIR/SYS Extent
The first extent element of the DIR/SYS entry for a new diskette: 67A2H stores the directory lump and the granule count less 1.
670CH
1 byte
Directory Sectors (Self-Modifying Code)
The operand of the instruction at 670BH. 0AH in the file; 66E1H stores the real number there when the HIT is made.
68ADH-68AEH
2 bytes
Tracks to Format (Self-Modifying Code)
The operand of the instruction at 68ACH. 0001H in the file (one track from track 0); 4FD1H stores PFTC= at 68ADH and 4FD9H stores PFST= at 68AEH.
69D7H-69D8H
2 bytes
Second Tolerance (Self-Modifying Code)
The operand of the instruction at 69D6H. 0000H in the file; 69B5H stores bytes 14-15 of the table line there.
69DBH-69DCH
2 bytes
Track Size (Self-Modifying Code)
The operand of the instruction at 69DAH. 0000H in the file; 69A5H stores bytes 10-11 of the table line there.
69F3H-69F4H
2 bytes
First Tolerance (Self-Modifying Code)
The operand of the instruction at 69F2H. 0000H in the file; 69ADH stores bytes 12-13 of the table line there.
6A01H
1 byte
Sector Skew (Self-Modifying Code)
The operand of the instruction at 6A00H. 02H in the file; 69BBH stores byte 16 of the table line there.
6A03H
1 byte
Previous First Sector (Self-Modifying Code)
The operand of the instruction at 6A02H. 00H in the file; 69C8H clears it and 6A0BH and 6A44H store into it. 6C6BH jumps here with Register A = 0 for the back side.
6A34H
1 byte
Interleave (Self-Modifying Code)
The operand of the instruction at 6A33H. 02H in the file; 69C0H stores byte 17 of the table line there.
6AF0H
1 byte
Select Byte with Wait States (Self-Modifying Code)
The operand of the instruction at 6AEFH. 00H in the file; 6AB0H stores it.
6AF2H
1 byte
Sector Counter (Self-Modifying Code)
The operand of the instruction at 6AF1H. 00H in the file; 6AA8H stores it.
6B04H
1 byte
Zero Bytes Before the ID Mark (Self-Modifying Code)
The operand of the instruction at 6B03H. 01H in the file; 6990H stores table byte 5 there.
6B10H
1 byte
ID Address Mark Lead-In (Self-Modifying Code)
The operand of the instruction at 6B0FH. 00H in the file; 6979H stores table byte 1 there.
6B24H
1 byte
Track Number (Self-Modifying Code)
The operand of the instruction at 6B23H. 00H in the file; 68C3H stores the first track there and 6C71H counts it up.
6B2AH
1 byte
Side Number (Self-Modifying Code)
The operand of the instruction at 6B29H. 00H in the file; 6A9BH stores 00H or 01H there.
6B42H
1 byte
Gap Byte After the ID Field (Self-Modifying Code)
The operand of the instruction at 6B41H. FFH in the file; 6971H stores table byte 0 there.
6B48H
1 byte
Gap Between the ID and Data Fields (Self-Modifying Code)
The operand of the instruction at 6B47H. 0AH in the file; 6995H stores table byte 6 there.
6B5AH
1 byte
Zero Bytes Before the Data Mark (Self-Modifying Code)
The operand of the instruction at 6B59H. 04H in the file; 699AH stores table byte 7 there.
6B66H
1 byte
Data Address Mark Lead-In (Self-Modifying Code)
The operand of the instruction at 6B65H. 00H in the file; 697DH stores table byte 1 there.
6B7CH
1 byte
First Data Pattern Byte (Self-Modifying Code)
The operand of the instruction at 6B7BH. E5H in the file; 6981H stores table byte 2 there.
6B82H
1 byte
Second Data Pattern Byte (Self-Modifying Code)
The operand of the instruction at 6B81H. E5H in the file; 6986H stores table byte 3 there.
6B90H
1 byte
Gap Byte After the Data Field (Self-Modifying Code)
The operand of the instruction at 6B8FH. FFH in the file; 6975H stores table byte 0 there.
6B96H
1 byte
Gap Before the Next ID Field (Self-Modifying Code)
The operand of the instruction at 6B95H. 0AH in the file; 698BH stores table byte 4 there.
6BA9H-6BAAH
2 bytes
Saved Stack Pointer (Self-Modifying Code)
The operand of the instruction at 6BA8H. 0000H in the file; 6AC4H stores it.
6BCBH-6BCCH
2 bytes
Fewest End Gap Bytes (Self-Modifying Code)
The operand of the instruction at 6BCAH. 0000H in the file; 69F6H stores it.
6BD4H-6BD5H
2 bytes
End Gap Range (Self-Modifying Code)
The operand of the instruction at 6BD3H. 007DH in the file; 69FDH stores it.
6C62H
1 byte
Side Just Formatted (Self-Modifying Code)
The operand of the instruction at 6C61H. 00H in the file; 69CBH clears it and 6C65H changes it.
6C74H
1 byte
Track to Stop At (Self-Modifying Code)
The operand of the instruction at 6C73H. 23H in the file; 695AH stores the end track there.
6C94H
1 byte
Tries Left (Self-Modifying Code)
The operand of the instruction at 6C93H. 00H in the file; 6A6AH stores 10 there.

Operands Changed in SYS2/SYS and SYS3/SYS

Address
Size
Contents
4F56H
1 byte
SYS2/SYS: DEC Operand
Inside SYS2/SYS's FCB building code in the overlay area: 56B9H stores the DEC there before calling SYS2/SYS at 4F2EH, and 5DF1H reads back the DEC that a SYS2/SYS open left there.
4F5EH
1 byte
SYS2/SYS: Record Length Operand
56C0H stores 00H there, so the file is handled in whole sectors.
4FB8H
1 byte
SYS3/SYS: Mode Operand
The operand of SYS3/SYS's LD A,nn at 4FB7H: 60ADH stores 00H there, so SYS3/SYS works in its CLOSE mode.

Outside Routines Called

AddressContents
0013H, 001BHROM: read a byte from a file, write a byte to a file (6F73H, 6F79H).
002BH, 0033HROM: scan the keyboard (572CH), display a character (58BFH).
0060HROM: delay, through SYS0/SYS 4C92H (55DDH, 6CB9H).
4409HSYS0/SYS: error exit (521FH, 5854H).
4420H, 4424H, 4428HSYS0/SYS: open a new or existing file, open an existing file, close a file (5556H, 554EH, 54C3H).
4436H, 4439H, 443CHSYS0/SYS: read, write, and write with read back a sector of a file (57CBH, 5CF8H, 57D7H).
4448HSYS0/SYS: position a file to its end (6F62H).
4467HSYS0/SYS: display a message (4D5AH and others).
4470HSYS0/SYS: the system date as MM/DD/YY (6FDFH).
4548HSYS0/SYS: upper case (572FH).
466FHSYS0/SYS: send the command at 4687H and transfer a sector (6C08H).
46F5H, 46F7H, 46FFHSYS0/SYS: Restore, a command with the stepping rate, wait until not busy (689FH, 68CAH, 6CBEH, 6AA1H).
4715H, 471BH, 4720H, 4723HSYS0/SYS: send the select byte, select the drive of an FCB, the current drive, or the drive in Register A (6A9EH, 689CH, 695DH, 55B6H).
4789H, 4791HSYS0/SYS: short delay and status, select and wait for the index hole (6ADEH, 55EDH).
47B8H, 47DDH, 485DHSYS0/SYS: inside its sector mapping code, jumped to from the TI flag M routines (5C58H, 5C40H, 5C4AH).
48AFH, 48C4H, 48C7H, 48D4H, 48DBH, 48ECH, 48F0HSYS0/SYS: directory sector and entry routines (56FAH, 5528H, 5701H, 56EFH, 56F4H, 5C3BH, 56DDH).
4925H, 4982HSYS0/SYS: run code as a DOS function, call SYS2/SYS to allocate (60A9H, 5C55H).
4C37H, 4C39H, 4C57H, 4C59HSYS0/SYS: multiply, divide by 5 or by Register A (6969H, 69D3H, 5D05H, 6733H).
4C6AH, 4C7AH, 4C7EHSYS0/SYS: command line compare and separator routines (6FECH, 4E90H, 6EB8H).
4C92H, 4CA4HSYS0/SYS: delay, half the track count (55DDH, 6A84H).
4E21H, 4F2EHSYS2/SYS in the overlay area: FCB building code (56C4H, 56CCH).
502CHSYS17/SYS in the overlay area: the end of a diskette COPY (54D4H).

Disassembly

4D00H - SYS6/SYS Entry: Command Dispatcher

SYS0/SYS loads SYS6/SYS into 4D00H-6FF8H and enters it at 4D00H when SYS1/SYS runs the FORMAT, COPY or APPEND command. Register A holds the RST 28H code from SYS1/SYS's command table (bits 5-7 = function number, bits 0-4 = 08H, the directory slot of SYS6/SYS): 28H = FORMAT (function 1), 48H = COPY (function 2), 68H = APPEND (function 3). Register Pair HL points to the command line just past the command name.

4D00
LD IY,4280H FD 21 80 42
Point Index Register IY to 4280H. The SYS0/SYS variables at 4288H and 4289H are reached through it as IY+08H and IY+09H.
4D04
LD (IY+08H),00H FD 36 08 00
Store 00H at (IY+08H): Index Register IY = 4280H, so this is 4288H, the directory slot of the overlay in 4D00H-51FFH. The code of SYS6/SYS in that area is about to be overwritten, so marking it empty makes SYS0/SYS load from the diskette the next overlay that is asked for.
4D08
CP 68H FE 68
Compare Register A (the RST 28H code) against 68H, function 3, APPEND.
4D0A
If the Z FLAG is set (APPEND), JUMP to 6F4AH.
4D0D
SET 3,(IY+09H) FD CB 09 DE
Set bit 3 of (IY+09H): Index Register IY = 4280H, so this is 4289H, the system flags. The bit shows that FORMAT or COPY is running; while any of bits 2, 3, 5 or 6 of 4289H is set, the key combination check of SYS0/SYS (459DH-45A1H) ignores the D-F-G (MINI-DOS), 1-2-3 (DEBUG) and J-K-L (screen print) combinations. The bit is cleared again at 5238H.
4D11
CP 28H FE 28
Compare Register A (the RST 28H code) against 28H, function 1, FORMAT.
4D13
If the Z FLAG is set (FORMAT), JUMP to 65FAH.
4D16
CP 48H FE 48
Compare Register A (the RST 28H code) against 48H, function 2, COPY.
4D18
If the Z FLAG is set (Register A held 48H, the COPY code), JUMP to 4D1EH to start the COPY command.
4D1B
Any other function code: JUMP to 5208H to leave with error 2AH (ILLEGAL DOS FUNCTION).

4D1EH - COPY: Memory Limit and First Drive Number

Entered with Register Pair HL pointing to the COPY parameters. The manual lists six formats. Formats 1 and 2 start with a filespec (2 has a leading $). Formats 3 and 4 start with a drive number and copy one file between two diskettes on that drive. Formats 5 and 6 name two drives and copy a whole diskette (sector by sector, or file by file with CBF). This part sets the memory limit and decides which kind of COPY it is.

4D1E
LD A,(428AH) 3A 8A 42
Fetch the system flags from 428AH into Register A. 4D18H comes here.
4D21
BIT 6,A CB 77
Test bit 6 of Register A (428AH): a DOS-CALL is active, for example COPY run from BASIC.
4D23
If the NZ FLAG is set (under DOS-CALL), JUMP to 4D32H: COPY may use only memory below 7000H, which is the value already at 593CH (6FFFH).
4D25
PUSH HL E5
Save Register Pair HL (the command line pointer) onto the stack.
4D26
LD HL,5996H 21 96 59
Point Register Pair HL to 5996H, the option flags.
4D29
SET 5,(HL) CB EE
Set bit 5 of the byte at Register Pair HL (5996H): the UBB flag, use memory up to HIMEM. Since version 2 this is automatic unless COPY runs under DOS-CALL.
4D2B
LD HL,(4411H) 2A 11 44
Fetch the top of memory (HIMEM) from 4411H into Register Pair HL.
4D2E
LD (593CH),HL 22 3C 59
Store Register Pair HL (HIMEM) at 593CH, the highest address COPY may use for its buffers.
4D31
POP HL E1
Restore Register Pair HL from the stack: the command line pointer.
4D32
PUSH HL E5
Save Register Pair HL (the command line pointer) onto the stack again, for 4D98H if no drive number follows. 4D23H comes here.
4D33
GOSUB to 6ECAH to parse a drive number at Register Pair HL (an optional colon and a decimal number), which also selects the drive through SYS0/SYS 4723H to check that it exists. It returns the CARRY FLAG and the number in Register A, or the NO CARRY FLAG if the parameter does not start with a digit.
4D36
If the NO CARRY FLAG is set (no drive number: format 1 or 2, COPY filespec1 filespec2), JUMP to 4D98H with the saved pointer on the stack.
4D39
POP DE D1
A drive number was given: drop the saved pointer from the stack into Register Pair DE.
4D3A
LD (5AEBH),A 32 EB 5A
Store Register A (the drive number) at 5AEBH, the drive byte (FCB+6) of the source FCB at 5AE5H.
4D3D
LD (594CH),A 32 4C 59
Store Register A (the drive number) at 594CH, the source drive.
4D40
LD (5956H),A 32 56 59
Store Register A (the drive number) at 5956H, the destination drive too, in case this is format 3 or 4 (one drive).
4D43
PUSH HL E5
Save Register Pair HL (the command line, just past the drive number) onto the stack.
4D44
LD DE,64A6H 11 A6 64
Point Register Pair DE to 64A6H, the source track count slot of the override table at 64A3H.
4D47
GOSUB to 63A3H: if =tc1 follows at Register Pair HL, parse it and store the source track count at Register Pair DE (64A6H).
4D4A
GOSUB to 6FE4H to move Register Pair HL over the separator and an optional TO keyword.
4D4D
GOSUB to 6392H to parse a second drive number at Register Pair HL, stored as the destination drive. The CARRY FLAG returns if there is one.
4D50
If the NO CARRY FLAG is set (not a drive number: format 3 or 4, COPY dn1 filespec1 filespec2), JUMP to 4D8BH.

Formats 5 and 6: COPY dn1[=tc1] [TO] dn2[=tc2] [,mm/dd/yy] [,options].

4D53
GOSUB to 63A0H: if =tc2 follows at Register Pair HL, parse it and store the destination track count at 64A9H.
4D56
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer): the current command line pointer goes onto the stack, and the old pointer now in Register Pair HL is not needed.
4D57
LD HL,6E0BH 21 0B 6E
Point Register Pair HL to 6E0BH, the message STARTING DISKETTE COPY.
4D5A
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
4D5D
POP HL E1
Restore Register Pair HL from the stack: the command line pointer.
4D5E
GOSUB to 6FB7H to parse the date parameter at Register Pair HL into 598BH (the system date is used when it is null or missing).
4D61
LD B,20H 06 20
Load Register B with 20H, the option table bit for COPY formats 5 and 6.
4D63
GOSUB to 4EA7H to parse the options at Register Pair HL and check them against each other.
4D66
LD HL,5994H 21 94 59
Point Register Pair HL to 5994H, the first option flag byte.
4D69
LD A,(HL) 7E
Fetch the option flags at Register Pair HL (5994H) into Register A.
4D6A
AND F9H E6 F9
AND Register A with F9H, keeping bits 7 (N), 6 (Y), 5 (DDND), 4 (ODN), 3 (KDN) and 0 (KDD).
4D6C
INC HL 23
INCrement Register Pair HL to 5995H. INC HL does not change the flags.
4D6D
If the NZ FLAG is set (one of them was given), JUMP to 4D72H with the NZ FLAG still set.
4D6F
LD A,(HL) 7E
Fetch the option flags at Register Pair HL (5995H) into Register A.
4D70
AND 01H E6 01
AND Register A with 01H, keeping bit 0 (ODPW).
4D72
If the NZ FLAG is set (an option that excludes Y was given), JUMP to 4D79H. 4D6DH comes here.
4D74
DEC HL 2B
DECrement Register Pair HL from 5995H back to 5994H, the first option flag byte, which receives the default Y.
4D75
LD A,(HL) 7E
Fetch the option flags at Register Pair HL (5994H) into Register A.
4D76
OR 40H F6 40
OR Register A with 40H, setting bit 6: Y is the default for COPY when none of N, ODN, ODPW, DDND, KDN or KDD is given.
4D78
LD (HL),A 77
Store Register A (the flags) back at Register Pair HL (5994H).
4D79
GOSUB to 63B3H to save the PDRIVE entries of the drives used and load the source and destination drive specifications into their working records. 4D72H comes here.
4D7C
LD HL,59B7H 21 B7 59
Point Register Pair HL to 59B7H, the source drive specification (working PDRIVE record).
4D7F
GOSUB to 6713H to work out the sector, granule and lump counts of the diskette whose record is at Register Pair HL (the source).
4D82
GOSUB to 6710H to do the same for the destination diskette (record at 59C5H).
4D85
GOSUB to 4DF3H to build the destination PDRIVE sector and work out which diskettes will have to be swapped.
4D88
JUMP to 6291H to go on with the diskette COPY.

4D8BH - COPY Formats 3 and 4: One Drive, Two Diskettes

The source and destination files are on different diskettes in the same drive. 5940H is the set of diskettes that have to be swapped (bit 0 = system, bit 1 = source, bit 2 = destination) and 5941H the set that is mounted now.

4D8B
LD HL,5940H 21 40 59
Point Register Pair HL to 5940H, the diskette swap flags. 4D50H comes here.
4D8E
LD (HL),06H 36 06
Store 06H at Register Pair HL (5940H): the source and destination diskettes share a drive and must be swapped.
4D90
INC HL 23
INCrement Register Pair HL to 5941H, the set of mounted diskettes.
4D91
LD (HL),01H 36 01
Store 01H at Register Pair HL (5941H): only the system diskette is mounted now.
4D93
POP HL E1
Restore Register Pair HL from the stack: the command line, just past the drive number and =tc1.
4D94
GOSUB to 6EC3H to move Register Pair HL over the separator before the first filespec (error 34H if there is none).
4D97
PUSH HL E5
Save Register Pair HL (the command line pointer) onto the stack for the POP at 4D98H.

4D98H - COPY Formats 1 to 4: Parse the Two Filespecs

Formats 1 and 2 arrive here from 4D36H and formats 3 and 4 from 4D97H, with the command line pointer on the stack.

4D98
POP HL E1
Restore Register Pair HL from the stack: the command line, now at the first filespec. 4D36H comes here.
4D99
LD A,(HL) 7E
Fetch the first character at Register Pair HL into Register A.
4D9A
CP 24H FE 24
Compare Register A (the first character of the first filespec) against 24H, the $ that marks formats 2 and 4.
4D9C
If the NZ FLAG is set (the first character is not a $), JUMP to 4DA6H with Register Pair HL still on the filespec.
4D9E
PUSH HL E5
Save Register Pair HL (the command line pointer) onto the stack.
4D9F
LD HL,5940H 21 40 59
Point Register Pair HL to 5940H, the diskette swap flags.
4DA2
SET 0,(HL) CB C6
Set bit 0 of the byte at Register Pair HL (5940H): a $ means that the source or destination diskette on drive 0 is not the system diskette, so the system diskette has to be swapped in and out as well (formats 2 and 4).
4DA4
POP HL E1
Restore Register Pair HL from the stack: the command line pointer.
4DA5
INC HL 23
INCrement Register Pair HL (the command line pointer) past the $ to the first character of the filespec itself.
4DA6
LD DE,4D3EH 11 3E 4D
Point Register Pair DE to 4D3EH. SYS6/SYS's code from 4D3EH to 4D8DH has already run and is used from here on as a copy of the command line. 4D9CH comes here.
4DA9
PUSH DE D5
Save Register Pair DE (4D3EH) onto the stack.
4DAA
LD BC,0050H 01 50 00
Load Register Pair BC with 0050H: 80 bytes, the length of the DOS command buffer.
4DAD
LDIR ED B0
Copy Register Pair BC (80) bytes from Register Pair HL (the rest of the command line) to Register Pair DE (4D3EH-4D8DH). The copy lets 4DD8H write in front of the second filespec.
4DAF
POP HL E1
Restore Register Pair HL from the stack: 4D3EH, the copy.
4DB0
LD DE,5AE5H 11 E5 5A
Point Register Pair DE to 5AE5H, the source FCB.
4DB3
GOSUB to 4E8DH to copy the first filespec at Register Pair HL into the FCB at Register Pair DE.
4DB6
GOSUB to 6FE4H to move Register Pair HL over the separator and an optional TO.
4DB9
LD A,(HL) 7E
Fetch the first character of the second filespec at Register Pair HL into Register A.
4DBA
CP 3AH FE 3A
Compare Register A (the first character of the second filespec) against 3AH, the : that starts a drive number.
4DBC
If the Z FLAG is set (a drive only), JUMP to 4DC6H to borrow the start of the first filespec.
4DBE
CP 2EH FE 2E
Compare Register A (the first character of the second filespec) against 2EH, the . that starts a password.
4DC0
If the Z FLAG is set (a password only), JUMP to 4DC6H.
4DC2
CP 2FH FE 2F
Compare Register A (the first character of the second filespec) against 2FH, the / that starts an extension.
4DC4
If the NZ FLAG is set (not an extension either: the second filespec is complete), JUMP to 4DDEH.

The second filespec starts with :, . or /. Everything in the first filespec before the same character is copied in front of it, so COPY USERFILE/DAT:0 :1 becomes USERFILE/DAT:1.

4DC6
LD C,A 4F
Copy Register A (the character) into Register C. 4DBCH and 4DC0H come here.
4DC7
LD B,00H 06 00
Load Register B with 00H, the length of the part to borrow.
4DC9
LD DE,5AE5H 11 E5 5A
Point Register Pair DE to 5AE5H, the first filespec in the source FCB.

Search Loop

4DCC
LD A,(DE) 1A
Fetch a character of the first filespec at Register Pair DE into Register A.
4DCD
CP 03H FE 03
Compare Register A against 03H, the end of the filespec.
4DCF
If the Z FLAG is set (the first filespec does not contain the character), JUMP to 4DDEH to use the second filespec as it is.
4DD1
CP C B9
Compare Register A against Register C (the character wanted).
4DD2
If the Z FLAG is set (Register A, the character of the first filespec, equals Register C), JUMP to 4DD8H to copy the part in front of it.
4DD4
INC DE 13
INCrement Register Pair DE to the next character of the first filespec.
4DD5
INC B 04
INCrement Register B, the length of the part to borrow.
4DD6
LOOP BACK to 4DCCH to compare the next character of the first filespec (Register Pair DE) with Register C.

Borrow Loop

4DD8
DEC HL 2B
DECrement Register Pair HL to the byte in front of the second filespec. 4DD2H comes here.
4DD9
DEC DE 1B
DECrement Register Pair DE to the previous character of the first filespec.
4DDA
LD A,(DE) 1A
Fetch that character at Register Pair DE into Register A.
4DDB
LD (HL),A 77
Store Register A at Register Pair HL, in front of the second filespec.
4DDC
DECrement Register B and LOOP BACK to 4DD8H until the whole leading part has been copied. Register Pair HL now points to the completed second filespec.
4DDE
GOSUB to 4E8AH to copy the second filespec at Register Pair HL into the destination FCB at 5B17H. 4DC4H and 4DCFH come here.
4DE1
PUSH HL E5
Save Register Pair HL (the command line pointer) onto the stack.
4DE2
LD HL,5996H 21 96 59
Point Register Pair HL to 5996H, the option flags.
4DE5
SET 2,(HL) CB D6
Set bit 2 of the byte at Register Pair HL (5996H): this is a single file COPY (formats 1 to 4).
4DE7
INC HL 23
INCrement Register Pair HL from 5996H to 5997H, the next option flag byte.
4DE8
SET 3,(HL) CB DE
Set bit 3 of the byte at Register Pair HL (5997H), NFMT: a single file COPY never formats.
4DEA
POP HL E1
Restore Register Pair HL from the stack: the command line pointer.
4DEB
LD B,08H 06 08
Load Register B with 08H, the option table bit for COPY formats 1 to 4.
4DED
GOSUB to 4EA7H to parse the options at Register Pair HL.
4DF0
JUMP to 6377H to find the drives and open the two files.

4DF3H - Build the Destination PDRIVE Sector and the Swap Flags

Called from 4D85H (COPY formats 5 and 6) and 663CH (FORMAT). Reads sector 2 of the system diskette in drive 0 (the PDRIVE sector, 16 bytes for each of drives 0-9) and builds from it at 6EB4H the PDRIVE sector that will be written to the new diskette, then works out which diskettes share a drive.

4DF3
GOSUB to 6424H to read the PDRIVE sector of the system diskette into 4300H. Register Pair HL returns 4300H. 4D85H and 663CH call here.
4DF6
LD BC,000AH 01 0A 00
Load Register Pair BC with 000AH: 10 bytes, the length of an in-memory PDRIVE record such as the one at 59C5H.
4DF9
LD A,00H 3E 00
Load Register A with the destination drive number (00H in the file). Self-Modifying Code
The operand at 4DFAH is stored by 639CH when the destination drive is parsed.
4DFB
RLCA 07
Rotate Register A left (the first of four RLCAs: the drive number times 16 is the offset of its record in the PDRIVE sector).
4DFC
RLCA 07
Rotate Register A left (the second of four RLCAs).
4DFD
RLCA 07
Rotate Register A left (the third of four RLCAs).
4DFE
RLCA 07
Rotate Register A left (the fourth): Register A = the drive number times 16.
4DFF
ADD A,C 81
ADD Register C (10) to Register A: the offset of bytes 10-15 of the destination drive's record.
4E00
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = 4300H, the start of the sector.
4E01
LD HL,59C5H 21 C5 59
Point Register Pair HL to 59C5H, the destination drive specification (10 bytes, in the in-memory PDRIVE format).
4E04
LDIR ED B0
Copy Register Pair BC (10) bytes from Register Pair HL (59C5H) to Register Pair DE (4300H): over bytes 0-9 of the drive 0 record.
4E06
LD H,D 62
Copy Register D (43H after the copy) into Register H.
4E07
LD L,A 6F
Copy Register A (the offset) into Register L: Register Pair HL = bytes 10-15 of the destination drive's own record.
4E08
LD C,06H 0E 06
Load Register C with 06H: Register Pair BC = 0006H (Register B is 0 after the LDIR).
4E0A
LDIR ED B0
Copy Register Pair BC (6) bytes from Register Pair HL to Register Pair DE (430AH-430FH). The drive 0 record now describes the destination diskette.
4E0C
LD L,C 69
Copy Register C (00H after the copy) into Register L: Register Pair HL = 4300H.
4E0D
LD B,01H 06 01
Load Register B with 01H: Register Pair BC = 0100H, 256 bytes.
4E0F
LD DE,6EB4H 11 B4 6E
Point Register Pair DE to 6EB4H. The command line parsing code from there to 6FB3H is not needed any more.
4E12
LDIR ED B0
Copy Register Pair BC (256) bytes from Register Pair HL (4300H) to Register Pair DE (6EB4H-6FB3H), from where 6667H writes it to sector 2 of the new diskette (the third sector of its BOOT/SYS). 5309H also takes the drive 0 record from here.

Work out which diskettes must be swapped. Register E collects the set that shares a drive (bit 0 = system, bit 1 = source, bit 2 = destination) and Register D the set that is mounted at the start.

4E14
LD DE,0100H 11 00 01
Load Register Pair DE with 0100H: Register D = 01H (the system diskette is mounted), Register E = 00H (no swaps).
4E17
LD A,(594CH) 3A 4C 59
Fetch the source drive number from 594CH into Register A.
4E1A
OR A B7
OR Register A with itself: the Z FLAG for drive 0.
4E1B
LD B,A 47
Copy Register A (the source drive) into Register B. LD does not change the flags.
4E1C
If the NZ FLAG is set (not drive 0), JUMP to 4E22H.
4E1E
LD A,E 7B
Copy Register E (the swap set) into Register A.
4E1F
OR 03H F6 03
OR Register A with 03H, setting bits 0 and 1: the source diskette uses drive 0, where the system diskette is.
4E21
LD E,A 5F
Copy Register A into Register E, the swap set.
4E22
LD A,(5956H) 3A 56 59
Fetch the destination drive number from 5956H into Register A. 4E1CH comes here.
4E25
OR A B7
OR Register A with itself: the Z FLAG for drive 0.
4E26
If the NZ FLAG is set (not drive 0), JUMP to 4E2CH.
4E28
SET 0,E CB C3
Set bit 0 of Register E (the system diskette).
4E2A
SET 2,E CB D3
Set bit 2 of Register E: the destination diskette uses drive 0 too.
4E2C
CP B B8
Compare Register A (the destination drive) against Register B (the source drive). 4E26H comes here.
4E2D
If the NZ FLAG is set (different drives), JUMP to 4E3DH.
4E2F
LD A,E 7B
Copy Register E (the swap set) into Register A.
4E30
OR 06H F6 06
OR Register A with 06H, setting bits 1 and 2: source and destination share the drive.
4E32
LD E,A 5F
Copy Register A into Register E, the swap set.
4E33
LD A,(428AH) 3A 8A 42
Fetch the system flags from 428AH into Register A.
4E36
BIT 6,A CB 77
Test bit 6 of Register A (428AH): a DOS-CALL is active.
4E38
LD A,15H 3E 15
Load Register A with error code 15H (ILLEGAL FUNCTION UNDER DOS-CALL). LD does not change the flags.
4E3A
If the NZ FLAG is set (under DOS-CALL), JUMP to 521AH with error 15H: a one-drive COPY would need too many diskette swaps with memory limited to 7000H.
4E3D
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H into Register A. 4E2DH comes here.
4E40
BIT 7,A CB 7F
Test bit 7 of Register A (5995H): NDMW, no diskette mount waits.
4E42
If the Z FLAG is set (NDMW not given), JUMP to 4E4DH.
4E44
LD A,E 7B
Copy Register E (the swap set) into Register A.
4E45
CP 06H FE 06
Compare Register A against 06H: the NO CARRY FLAG when the source and destination share a drive.
4E47
If the NO CARRY FLAG is set, JUMP to 5208H with error 2AH: with NDMW no swap prompt can be given.
4E4A
LD DE,0700H 11 00 07
Load Register Pair DE with 0700H: nothing is swapped (Register E = 00H) and all three diskettes are taken as mounted (Register D = 07H).
4E4D
LD A,E 7B
Copy Register E (the swap set) into Register A. 4E42H comes here.
4E4E
CP 03H FE 03
Compare Register A against 03H: the source diskette shares drive 0 with the system diskette and nothing else is swapped.
4E50
LD B,80H 06 80
Load Register B with 80H, the SPDN bit of 5997H. LD does not change the flags.
4E52
LD HL,5A3CH 21 3C 5A
Point Register Pair HL to 5A3CH, the word SOURCE.
4E55
If the Z FLAG is set, GOSUB to 4E68H to ask whether the system diskette is the source diskette.
4E58
LD A,E 7B
Copy Register E (the swap set) into Register A.
4E59
CP 05H FE 05
Compare Register A against 05H: the destination diskette shares drive 0 with the system diskette.
4E5B
LD B,40H 06 40
Load Register B with 40H, the DPDN bit of 5997H. LD does not change the flags.
4E5D
LD HL,5A44H 21 44 5A
Point Register Pair HL to 5A44H, the word DESTINATION.
4E60
If the Z FLAG is set, GOSUB to 4E68H to ask whether the system diskette is the destination diskette.
4E63
LD (5940H),DE ED 53 40 59
Store Register Pair DE at 5940H: Register E (the swap set) at 5940H, Register D (the mounted set) at 5941H.
4E67
RET C9
RETurn to the caller (4D88H or 663FH) with the swap set at 5940H and the mounted set at 5941H.

4E68H - Ask Whether the System Diskette Is Also the Source or Destination

Entered with Register A = 03H (source) or 05H (destination), Register B = the SPDN or DPDN bit and Register Pair HL pointing to the word SOURCE or DESTINATION. If the operator says the system diskette is that diskette, nothing has to be swapped.

4E68
DEC A 3D
DECrement Register A: 02H (source) or 04H (destination). 4E55H and 4E60H call here.
4E69
OR D B2
OR Register D (01H, the system diskette) into Register A: 03H or 05H.
4E6A
LD C,A 4F
Copy Register A into Register C: the mounted set to use if the answer is yes.
4E6B
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A.
4E6E
AND B A0
AND Register A with Register B, keeping the SPDN or DPDN bit.
4E6F
RET NZ C0
If the NZ FLAG is set (that PDRIVE override was given, so the two diskettes need different PDRIVE data and cannot be the same), RETurn without asking.
4E70
PUSH HL E5
Save Register Pair HL (the word) onto the stack.
4E71
LD HL,6E22H 21 22 6E
Point Register Pair HL to 6E22H, the message ARE SYSTEM AND.
4E74
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
4E77
POP HL E1
Restore Register Pair HL from the stack: the word SOURCE or DESTINATION.
4E78
GOSUB to 4467H (SYS0/SYS) to display the word at Register Pair HL.
4E7B
LD HL,6E32H 21 32 6E
Point Register Pair HL to 6E32H, the question THE SAME DISKETTE?
4E7E
GOSUB to 58DEH to display the question at Register Pair HL and wait for Y or N. The Z FLAG returns for N.
4E81
RET Z C8
If the Z FLAG is set (N), RETurn with the sets unchanged.
4E82
LD E,00H 1E 00
Y: load Register E with 00H, nothing is swapped.
4E84
LD D,C 51
Copy Register C (system plus source, or system plus destination) into Register D, the mounted set.
4E85
RET C9
RETurn to 4E58H or 4E63H with Register E = 00H (no swaps) and Register D = the mounted set from Register C.

4E86H - Unreferenced Code

Nothing jumps or calls to 4E86H. The four bytes would OR Register C into Register D and return.

4E86
LD A,D 7A
Copy Register D into Register A. Nothing reaches this row.
4E87
OR C B1
OR Register C into Register A. Nothing reaches this row.
4E88
LD D,A 57
Copy Register A into Register D. Nothing reaches this row.
4E89
RET C9
RETurn. Nothing reaches this row; nothing calls 4E86H.

4E8AH - Copy a Filespec from the Command Line into an FCB

Enter at 4E8AH for the destination FCB at 5B17H, or at 4E8DH with Register Pair DE pointing to any FCB (4DB3H and 6F4DH pass the source FCB at 5AE5H). Register Pair HL points to the filespec in the command line. Up to 32 characters are copied into the FCB, followed by 03H. On return Register Pair DE again points to the FCB and Register Pair HL to the separator that ended the filespec; the Z FLAG is set when the line ended there.

4E8A
LD DE,5B17H 11 17 5B
Point Register Pair DE to 5B17H, the destination FCB, which receives the second filespec. 4DDEH and 6F53H call here.
4E8D
LD B,20H 06 20
Load Register B with 20H: at most 32 characters of filespec fit in the 32-byte FCB at Register Pair DE. 4DB3H and 6F4DH call here.
4E8F
PUSH DE D5
Save Register Pair DE (the address of the FCB) onto the stack, for the POP at 4EA3H.

Copy Loop: Register Pair HL walks the command line, Register Pair DE the FCB, Register B counts the room left.

4E90
GOSUB to 4C7AH (SYS0/SYS) to look at the character at Register Pair HL: it returns the Z FLAG at the end of the line (0DH), the NO CARRY FLAG after stepping over a separator (a comma or spaces) and the CARRY FLAG for any other character, with Register A = 34H in the first two cases.
4E93
If the NO CARRY FLAG is set (the end of the line or a separator ends the filespec), JUMP to 4EA0H with Register Pair HL past the separator.
4E95
LD A,(HL) 7E
Fetch the filespec character at Register Pair HL (the command line) into Register A.
4E96
LD (DE),A 12
Store Register A (the filespec character) into the FCB at Register Pair DE.
4E97
INC DE 13
INCrement Register Pair DE to the next byte of the FCB.
4E98
INC HL 23
INCrement Register Pair HL to the next character of the command line.
4E99
DECrement Register B (the room left in the FCB) and LOOP BACK to 4E90H until 32 characters have been copied.
4E9B
LD A,30H 3E 30
32 characters and no end yet: load Register A with error code 30H (BAD FILESPEC). The FCB address is left on the stack; 521AH resets the Stack Pointer.
4E9D
JUMP to 521AH to end the command with the error code in Register A (30H).
4EA0
LD A,03H 3E 03
Load Register A with 03H, the byte that ends a filespec in an FCB. 4E93H comes here, with the flags from 4C7AH still set.
4EA2
LD (DE),A 12
Store Register A (03H) at Register Pair DE, just after the last filespec character in the FCB.
4EA3
POP DE D1
Restore Register Pair DE from the stack: the address of the FCB that now holds the filespec.
4EA4
RET Z C8
If the Z FLAG is set (4C7AH found 0DH, the end of the line), RETurn with Register Pair HL on the 0DH.
4EA5
DEC HL 2B
A separator was stepped over: DECrement Register Pair HL back onto its last character, so that the next separator test (4C7EH in 6EC3H) finds a separator there again.
4EA6
RET C9
RETurn with the NZ FLAG (from 4C7AH) and Register Pair HL on the separator.

4EA7H - Parse the Options and Check Their Combinations

Entered with Register Pair HL pointing to the command line and Register B holding the command's bit in the option table's attribute bytes (08H = COPY formats 1 to 4 from 4DEBH, 20H = COPY formats 5 and 6 from 4D61H, 40H = FORMAT from 6621H). Each option is looked up at 4F1DH, which records it in the flag bytes 5994H-5997H and jumps back here. At the end of the line the combinations are checked: options that select files need CBF, options that change the diskette's name, date or password cannot be used when CBF copies onto an existing diskette, and the FORMAT DISKETTE? question decides between FMT and NFMT when neither was given.

4EA7
GOSUB to 6EBFH: if the character at Register Pair HL is 0DH it returns the Z FLAG; otherwise it steps over the separator in front of the next option (error 34H if there is none) and returns the NZ FLAG with Register Pair HL on the option. 4D63H, 4DEDH, 4F88H and 6621H come here.
4EAA
If the NZ FLAG is set (an option follows at Register Pair HL), JUMP to 4F1DH to look it up with Register B still holding the command's bit.
4EAD
LD HL,5997H 21 97 59
The end of the line. Point Register Pair HL to 5997H, the fourth option flag byte (SPDN, DPDN, XLF, ILF, NFMT, FMT, PFST, PFTC).
4EB0
LD A,(HL) 7E
Fetch the option flags at Register Pair HL (5997H) into Register A.
4EB1
AND 0CH E6 0C
AND Register A (the 5997H flags) with 0CH, keeping bit 2 (FMT) and bit 3 (NFMT).
4EB3
If the NZ FLAG is set (FMT or NFMT is already known: a single file COPY has NFMT from 4DE8H, FORMAT has FMT), JUMP to 4ECAH without asking.
4EB5
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H (NDMW, CFWO, NDPW, USD, DFO, DDSL, DDGA, ODPW) into Register A.
4EB8
AND 80H E6 80
AND Register A (the 5995H flags) with 80H, keeping bit 7 (NDMW, no diskette mount waits). The Z FLAG is set when NDMW was not given.
4EBA
PUSH HL E5
Save Register Pair HL (5997H) onto the stack. PUSH does not change the flags.
4EBB
LD HL,6E45H 21 45 6E
Point Register Pair HL to 6E45H, the question FORMAT DISKETTE?.
4EBE
If the Z FLAG is set (no NDMW, so the operator may be asked), GOSUB to 58DEH to display the question at Register Pair HL and wait for Y or N. It returns the Z FLAG for N and the NZ FLAG for Y. With NDMW the NZ FLAG from 4EB8H stays, which counts as Y.
4EC1
POP HL E1
Restore Register Pair HL from the stack: 5997H. POP does not change the flags.
4EC2
SET 3,(HL) CB DE
Set bit 3 (NFMT) of the option flags at Register Pair HL (5997H). SET does not change the flags.
4EC4
If the Z FLAG is set (the answer was N), JUMP to 4ECAH with NFMT set: the destination is not formatted.
4EC6
LD A,(HL) 7E
The answer was Y, or NDMW was given: fetch the option flags at Register Pair HL (5997H, NFMT now set, FMT clear) into Register A.
4EC7
XOR 0CH EE 0C
XOR Register A (the 5997H flags) with 0CH, flipping bits 2 and 3: NFMT off and FMT on.
4EC9
LD (HL),A 77
Store Register A (the 5997H flags with FMT) back at Register Pair HL (5997H).
4ECA
LD DE,(5996H) ED 5B 96 59
Load Register Pair DE from 5996H: Register E = the 5996H flags (SN or RWF, SPW, UBB, USR, CBF, single file COPY, /ext, UPD) and Register D = the 5997H flags. 4EB3H and 4EC4H come here.
4ECE
LD HL,(5994H) 2A 94 59
Load Register Pair HL from 5994H: Register L = the 5994H flags (N, Y, DDND, ODN, KDN, NDN, BDU, KDD) and Register H = the 5995H flags.
4ED1
LD A,D 7A
Copy Register D (the 5997H flags) into Register A.
4ED2
AND 02H E6 02
AND Register A (the 5997H flags) with 02H, keeping bit 1 (PFST, a partial format from a given track).
4ED4
If the Z FLAG is set (no PFST), JUMP to 4EDAH.
4ED6
LD A,L 7D
Copy Register L (the 5994H flags) into Register A.
4ED7
OR 42H F6 42
OR Register A (the 5994H flags) with 42H, setting bit 6 (Y) and bit 1 (BDU): a partial format does not ask about the diskette's old contents and does not rewrite its system data.
4ED9
LD L,A 6F
Copy Register A (the 5994H flags with Y and BDU) back into Register L; 4F15H stores it.
4EDA
LD A,E 7B
Copy Register E (the 5996H flags) into Register A. 4ED4H comes here.
4EDB
AND 13H E6 13
AND Register A (the 5996H flags) with 13H, keeping bit 0 (UPD), bit 1 (/ext) and bit 4 (USR): options that choose which files are copied.
4EDD
If the NZ FLAG is set (one of them was given), JUMP to 4EE2H with the NZ FLAG still set.
4EDF
LD A,D 7A
Copy Register D (the 5997H flags) into Register A.
4EE0
AND 30H E6 30
AND Register A (the 5997H flags) with 30H, keeping bit 4 (ILF) and bit 5 (XLF), the include and exclude lists.
4EE2
If the NZ FLAG is set (a file selecting option was given), JUMP to 4EE7H with the NZ FLAG still set. 4EDDH comes here.
4EE4
LD A,H 7C
Copy Register H (the 5995H flags) into Register A.
4EE5
AND 08H E6 08
AND Register A (the 5995H flags) with 08H, keeping bit 3 (DFO, destination files only).
4EE7
If the Z FLAG is set (none of UPD, /ext, USR, ILF, XLF or DFO), JUMP to 4EEDH. 4EE2H comes here.
4EE9
BIT 3,E CB 5B
Test bit 3 of Register E (the 5996H flags): CBF, copy by file. The file selecting options only work in a copy by file.
4EEB
If the Z FLAG is set (no CBF), JUMP to 4F49H for error 2FH (BAD PARAMETER(S)).
4EED
LD A,H 7C
Copy Register H (the 5995H flags) into Register A. 4EE7H comes here.
4EEE
AND 06H E6 06
AND Register A (the 5995H flags) with 06H, keeping bit 1 (DDGA) and bit 2 (DDSL), the directory size and place on the destination.
4EF0
If the Z FLAG is set (neither DDGA nor DDSL), JUMP to 4EFAH.
4EF2
BIT 2,D CB 52
Test bit 2 of Register D (the 5997H flags): FMT, the destination will be formatted, so a new directory can be placed. With this test DDSL and DDGA are accepted whenever the diskette is formatted.
4EF4
If the NZ FLAG is set (FMT is set in Register D, the 5997H flags), JUMP to 4EFAH: DDGA and DDSL are allowed.
4EF6
BIT 3,E CB 5B
Test bit 3 of Register E (the 5996H flags): CBF.
4EF8
If the Z FLAG is set (DDGA or DDSL without FMT or CBF), JUMP to 4F49H for error 2FH.
4EFA
BIT 3,E CB 5B
Test bit 3 of Register E (the 5996H flags): CBF. 4EF0H and 4EF4H come here.
4EFC
If the Z FLAG is set (not a copy by file), JUMP to 4F0CH.
4EFE
BIT 3,D CB 5A
Test bit 3 of Register D (the 5997H flags): NFMT.
4F00
If the Z FLAG is set (no NFMT: the destination will be formatted), JUMP to 4F0CH.

CBF with NFMT copies files onto an existing diskette, so its name, date, password and directory cannot be changed.

4F02
LD A,L 7D
Copy Register L (the 5994H flags) into Register A.
4F03
AND 0DH E6 0D
AND Register A (the 5994H flags) with 0DH, keeping bit 0 (KDD), bit 2 (NDN) and bit 3 (KDN).
4F05
If the NZ FLAG is set (one of them was given), JUMP to 4F49H for error 2FH.
4F07
LD A,H 7C
Copy Register H (the 5995H flags) into Register A.
4F08
AND 36H E6 36
AND Register A (the 5995H flags) with 36H, keeping bit 1 (DDGA), bit 2 (DDSL), bit 4 (USD) and bit 5 (NDPW).
4F0A
If the NZ FLAG is set (one of them was given), JUMP to 4F49H for error 2FH.
4F0C
LD A,H 7C
Copy Register H (the 5995H flags) into Register A. 4EFCH and 4F00H come here.
4F0D
AND 41H E6 41
AND Register A (the 5995H flags) with 41H, keeping bit 0 (ODPW, the old destination password) and bit 6 (CFWO, copy files that are only on the source).
4F0F
If the Z FLAG is set (neither given), JUMP to 4F15H.
4F11
BIT 3,E CB 5B
Test bit 3 of Register E (the 5996H flags): CBF, which ODPW and CFWO need.
4F13
If the Z FLAG is set (no CBF), JUMP to 4F49H for error 2FH.
4F15
LD (5994H),HL 22 94 59
Store Register Pair HL at 5994H: Register L (the 5994H flags, with Y and BDU added for PFST) at 5994H and Register H at 5995H. 4F0FH comes here.
4F18
LD (5996H),DE ED 53 96 59
Store Register Pair DE at 5996H: Register E at 5996H and Register D (the 5997H flags with FMT or NFMT) at 5997H.
4F1C
RET C9
RETurn to the caller (4D66H, 4DF0H or 6624H) with the options recorded in 5994H-5997H.

4F1DH - Look Up One Option in the Option Table

Entered from 4EAAH with Register Pair HL pointing to an option word and Register B holding the command's bit. The table at 505CH is searched for a keyword that matches the start of the word. Each entry holds the keyword, an attribute byte (bit 7 always set; bit 3 allowed in COPY formats 1 to 4, bit 5 in COPY formats 5 and 6, bit 6 in FORMAT; bit 4 a handler address follows; bit 2 four exclusion bytes follow; bits 0-1 the flag byte 5994H-5997H), a flag mask, the optional exclusion bytes and the optional handler address. The option's bit is set, the exclusion bytes are checked against the options already given, the handler (if any) parses the option's value, and the search goes back to 4EA7H.

4F1D
PUSH BC C5
Save Register Pair BC onto the stack: Register B is the command's bit (08H, 20H or 40H). 4EAAH comes here.
4F1E
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE now points to the option word in the command line.
4F1F
LD HL,505CH 21 5C 50
Point Register Pair HL to 505CH, the first entry of the option keyword table.

Entry Loop: Register Pair HL walks the table, Register Pair DE the option word.

4F22
PUSH DE D5
Save Register Pair DE (the start of the option word) onto the stack, so that each entry is compared from the word's first character. 4F44H comes here.
4F23
LD A,(DE) 1A
Fetch a character of the option word at Register Pair DE into Register A. 4F29H comes here.
4F24
CP (HL) BE
Compare Register A (the option word's character) against the table byte at Register Pair HL.
4F25
If the NZ FLAG is set (they differ: either the keyword does not match or the whole keyword matched and Register Pair HL is on the attribute byte), JUMP to 4F4CH.
4F27
INC DE 13
INCrement Register Pair DE to the next character of the option word.
4F28
INC HL 23
INCrement Register Pair HL to the next byte of the keyword.
4F29
JUMP to 4F23H to compare the next pair of characters.
4F2B
INC HL 23
The keyword did not match: INCrement Register Pair HL to the next byte of the entry. 4F2EH and 4F4EH come here.
4F2C
BIT 7,(HL) CB 7E
Test bit 7 of the table byte at Register Pair HL: only the attribute byte has it set.
4F2E
If the Z FLAG is set (still in the keyword), LOOP BACK to 4F2BH.
4F30
LD A,(HL) 7E
Fetch the attribute byte at Register Pair HL into Register A.
4F31
BIT 2,A CB 57
Test bit 2 of Register A (the attribute byte): four exclusion bytes follow the flag mask.
4F33
INC HL 23
INCrement Register Pair HL to the flag mask. INC HL does not change the flags.
4F34
If the Z FLAG is set (no exclusion bytes), JUMP to 4F3AH.
4F36
INC HL 23
INCrement Register Pair HL past the flag mask to the first exclusion byte.
4F37
INC HL 23
INCrement Register Pair HL to the second exclusion byte.
4F38
INC HL 23
INCrement Register Pair HL to the third exclusion byte.
4F39
INC HL 23
INCrement Register Pair HL to the fourth exclusion byte.
4F3A
BIT 4,A CB 67
Test bit 4 of Register A (the attribute byte): a 2-byte handler address follows. 4F34H comes here.
4F3C
If the Z FLAG is set (no handler), JUMP to 4F40H.
4F3E
INC HL 23
INCrement Register Pair HL to the low byte of the handler address.
4F3F
INC HL 23
INCrement Register Pair HL to the high byte of the handler address.
4F40
POP DE D1
Restore Register Pair DE from the stack: the start of the option word. 4F3CH comes here.
4F41
INC HL 23
INCrement Register Pair HL to the first byte of the next table entry.
4F42
LD A,(HL) 7E
Fetch the first byte of the next entry at Register Pair HL into Register A.
4F43
OR A B7
OR Register A with itself: the Z FLAG is set for 00H, the end of the table (5185H).
4F44
If the NZ FLAG is set (another entry), LOOP BACK to 4F22H.
4F46
No keyword matches: JUMP to 5214H to end the command with error 34H (ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR).
4F49
JUMP to 5218H to end the command with error 2FH (BAD PARAMETER(S)). The checks at 4EEBH, 4EF8H, 4F05H, 4F0AH, 4F13H, 4F53H and 4F75H and the handlers (4F9BH, 4FCBH) come here.
4F4C
BIT 7,(HL) CB 7E
Test bit 7 of the table byte at Register Pair HL that did not match the option word. 4F25H comes here.
4F4E
If the Z FLAG is set (it is a keyword character, so the keyword is different), JUMP to 4F2BH to skip to the next entry.

The whole keyword matched (the byte that differs is the attribute byte). Register Pair DE points just past the keyword in the command line, Register Pair HL to the attribute byte.

4F50
POP AF F1
Discard the saved start of the option word from the stack into Register Pair AF; the flags it gives are not used.
4F51
LD A,B 78
Copy Register B (the command's bit: 08H, 20H or 40H) into Register A.
4F52
AND (HL) A6
AND Register A (the command's bit) with the attribute byte at Register Pair HL.
4F53
If the Z FLAG is set (this option is not allowed with this command), JUMP to 4F49H for error 2FH.
4F55
LD B,(HL) 46
Load Register B with the attribute byte at Register Pair HL.
4F56
INC HL 23
INCrement Register Pair HL from the attribute byte to the flag mask of the matched entry.
4F57
LD C,(HL) 4E
Load Register C with the flag mask at Register Pair HL: the option's bit in its flag byte.
4F58
INC HL 23
INCrement Register Pair HL past the flag mask, to the exclusion bytes or the handler address.
4F59
PUSH DE D5
Save Register Pair DE (the command line just past the keyword) onto the stack.
4F5A
LD A,B 78
Copy Register B (the attribute byte) into Register A.
4F5B
AND 03H E6 03
AND Register A (the attribute byte) with 03H, keeping bits 0-1: which of the four flag bytes the option uses.
4F5D
LD E,A 5F
Copy Register A (the flag byte number 0-3) into Register E.
4F5E
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the flag byte number.
4F60
PUSH HL E5
Save Register Pair HL (the table pointer, past the mask) onto the stack.
4F61
LD HL,5994H 21 94 59
Point Register Pair HL to 5994H, the first option flag byte.
4F64
PUSH HL E5
Save Register Pair HL (5994H) onto the stack, for the exclusion check.
4F65
ADD HL,DE 19
ADD Register Pair DE (the flag byte number) to Register Pair HL: the option's flag byte, 5994H-5997H.
4F66
LD A,(HL) 7E
Fetch the option's flag byte at Register Pair HL into Register A.
4F67
OR C B1
OR Register C (the flag mask) into Register A (the flag byte).
4F68
LD (HL),A 77
Store Register A back at Register Pair HL: the option is now recorded. Its own bit is set before the exclusion check, and no exclusion byte names an option's own bit.
4F69
POP DE D1
Restore Register Pair DE from the stack: 5994H, the first flag byte.
4F6A
POP HL E1
Restore Register Pair HL from the stack: the table pointer just past the flag mask.
4F6B
BIT 2,B CB 50
Test bit 2 of Register B (the attribute byte): exclusion bytes follow.
4F6D
If the Z FLAG is set (none), JUMP to 4F7AH with Register Pair HL on the handler address.
4F6F
LD C,04H 0E 04
Load Register C with 04H: one exclusion byte for each flag byte 5994H-5997H.

Exclusion Loop: Register Pair DE walks 5994H-5997H, Register Pair HL the four exclusion bytes, Register C counts.

4F71
LD A,(DE) 1A
Fetch a flag byte at Register Pair DE (5994H-5997H) into Register A. 4F78H comes here.
4F72
AND (HL) A6
AND Register A (the flag byte) with the exclusion byte at Register Pair HL: a bit is left only for an option already given that may not be combined with this one.
4F73
INC DE 13
INCrement Register Pair DE to the next flag byte. INC DE does not change the flags.
4F74
INC HL 23
INCrement Register Pair HL to the next exclusion byte. INC HL does not change the flags.
4F75
If the NZ FLAG is set (a conflicting option), JUMP to 4F49H for error 2FH.
4F77
DEC C 0D
DECrement Register C, the number of flag bytes left to check.
4F78
If the NZ FLAG is set (Register C is not 0), LOOP BACK to 4F71H.
4F7A
LD E,(HL) 5E
Load Register E with the low byte of the handler address at Register Pair HL. Without a handler these two bytes belong to the next entry and the result is not used. 4F6DH comes here.
4F7B
INC HL 23
INCrement Register Pair HL to the high byte of the handler address.
4F7C
LD D,(HL) 56
Load Register D with the high byte of the handler address at Register Pair HL.
4F7D
LD (4F85H),DE ED 53 85 4F
Store Register Pair DE (the handler address) at 4F85H, the operand of the CALL NZ at 4F84H.
4F81
POP HL E1
Restore Register Pair HL from the stack: the command line just past the keyword, where the option's value starts.
4F82
BIT 4,B CB 60
Test bit 4 of Register B (the attribute byte): the option has a handler.
4F84
If the NZ FLAG is set, GOSUB to the handler stored in the operand, with Register Pair HL on the option's value. The handler leaves Register Pair HL past the value. Self-Modifying Code
The operand at 4F85H-4F86H is 0000H in the file; 4F7DH stores the handler address there for each option.
4F87
POP BC C1
Restore Register Pair BC from the stack: Register B = the command's bit, pushed at 4F1DH.
4F88
JUMP to 4EA7H to look for the next option at Register Pair HL.

4F8BH - Option Value Handlers

Called from 4F84H with Register Pair HL pointing to the value that follows the option keyword (and its =). Each one stores the value where the command will use it and returns with Register Pair HL past it. A missing or bad value ends the command with error 2FH at 4F49H. FORMAT also calls 4F95H and 4FE5H for its name and password parameters.

4F8B
LD DE,5970H 11 70 59
ODN=name: point Register Pair DE to 5970H, the 8-byte buffer for the name the destination diskette must have.
4F8E
JUMP to 4F98H to copy the name at Register Pair HL to Register Pair DE (5970H).
4F90
LD DE,5968H 11 68 59
SN=name: point Register Pair DE to 5968H, the 8-byte buffer for the name the source diskette must have.
4F93
JUMP to 4F98H to copy the name at Register Pair HL to Register Pair DE (5968H).
4F95
LD DE,5983H 11 83 59
NDN=name, and the FORMAT name parameter (660DH): point Register Pair DE to 5983H, the 8-byte name for the new or destination diskette's GAT.
4F98
GOSUB to 6F8EH to copy a name of up to 8 letters and digits (the first a letter) from Register Pair HL to Register Pair DE and pad it with spaces. It returns the Z FLAG when no name was there. 4F8EH and 4F93H come here.
4F9B
If the Z FLAG is set (no name), JUMP to 4F49H for error 2FH.
4F9D
RET C9
RETurn to 4F87H (or 6610H) with Register Pair HL past the name.
4F9E
LD A,(HL) 7E
DDGA=gc: fetch the character at Register Pair HL (the value) into Register A.
4F9F
SUB 32H D6 32
SUBtract 32H (the character 2) from Register A: 0-4 for the digits 2-6.
4FA1
CP 05H FE 05
Compare Register A against 05H: the NO CARRY FLAG for anything that was not 2-6.
4FA3
INC HL 23
INCrement Register Pair HL past the digit. INC HL does not change the flags.
4FA4
If the NO CARRY FLAG is set (not 2-6), JUMP to 4FCBH for error 2FH.
4FA6
ADD A,02H C6 02
ADD 02H to Register A, giving back the directory size in granules, 2-6.
4FA8
LD (64AFH),A 32 AF 64
Store Register A (the directory granule count) at 64AFH, the value byte of the DDGA entry in the override table at 64A3H.
4FAB
RET C9
RETurn to 4F87H with Register Pair HL past the digit.
4FAC
LD DE,4480H 11 80 44
ILF=filespec or XLF=filespec: point Register Pair DE to 4480H, the DOS FCB in SYS0/SYS, which holds the list file's filespec until 5D16H opens it.
4FAF
LD B,20H 06 20
Load Register B with 20H: at most 32 characters.

Copy Loop for the list filespec.

4FB1
LD A,0DH 3E 0D
Load Register A with 0DH, the end marker. 4FBFH comes here.
4FB3
LD (DE),A 12
Store Register A (0DH) at Register Pair DE, ending the filespec copied so far.
4FB4
GOSUB to 4C7AH (SYS0/SYS) to test the character at Register Pair HL: the Z FLAG at the end of the line, the NO CARRY FLAG after stepping over a separator, the CARRY FLAG for a filespec character.
4FB7
RET Z C8
If the Z FLAG is set (the end of the line), RETurn to 4F87H with Register Pair HL on the 0DH.
4FB8
DEC HL 2B
DECrement Register Pair HL, back onto the separator if one was stepped over. DEC HL does not change the flags.
4FB9
RET NC D0
If the NO CARRY FLAG is set (a separator ended the filespec), RETurn to 4F87H with Register Pair HL on the separator for 4EA7H.
4FBA
INC HL 23
INCrement Register Pair HL back to the filespec character.
4FBB
LD A,(HL) 7E
Fetch the filespec character at Register Pair HL into Register A.
4FBC
LD (DE),A 12
Store Register A (the character) at Register Pair DE in the DOS FCB.
4FBD
INC DE 13
INCrement Register Pair DE to the next byte of the DOS FCB.
4FBE
INC HL 23
INCrement Register Pair HL to the next character of the command line.
4FBF
DECrement Register B (the room left) and LOOP BACK to 4FB1H until 32 characters have been copied.
4FC1
The filespec is longer than 32 characters: JUMP to 4FCBH for error 2FH.
4FC3
DDSL=ln: GOSUB to 6EE6H to parse a decimal number of 0-255 at Register Pair HL into Register A.
4FC6
LD (64ACH),A 32 AC 64
Store Register A (the lump number for the directory) at 64ACH, the value byte of the DDSL entry in the override table at 64A3H.
4FC9
OR A B7
OR Register A (the value just stored) with itself: the Z FLAG for 0. 4FD4H comes here.
4FCA
RET NZ C0
If the NZ FLAG is set (not 0), RETurn to 4F87H.
4FCB
JUMP to 4F49H for error 2FH: a value of 0 (DDSL, PFTC), a bad digit (DDGA), a filespec that is too long or a PDRIVE number over 9. 4FA4H, 4FC1H and 5008H come here.
4FCE
PFTC=tc: GOSUB to 6EE1H to parse a decimal or hexadecimal number of 0-255 at Register Pair HL into Register A.
4FD1
LD (68ADH),A 32 AD 68
Store Register A (the number of tracks to format) at 68ADH, the low byte of the operand of the LD DE,nnnn at 68ACH, which loads it into Register E as the partial format track count (0001H in the file: one track).
4FD4
JUMP to 4FC9H: a track count of 0 is an error.
4FD6
PFST=tn: GOSUB to 6EE1H to parse the track number at Register Pair HL into Register A.
4FD9
LD (68AEH),A 32 AE 68
Store Register A (the track to start formatting at) at 68AEH, the high byte of the operand of the LD DE,nnnn at 68ACH, which loads it into Register D as the partial format starting track.
4FDC
RET C9
RETurn to 4F87H with Register Pair HL past the number.
4FDD
SPW=password: GOSUB to 5025H to encode the password at Register Pair HL; the code returns in Register Pair DE.
4FE0
LD (5978H),DE ED 53 78 59
Store Register Pair DE (the source diskette's password code) at 5978H, which is compared with the source GAT's password code.
4FE4
RET C9
RETurn to 4F87H with Register Pair HL past the password.
4FE5
NDPW=password, and the FORMAT password parameter (6618H): GOSUB to 5025H to encode the password at Register Pair HL into Register Pair DE.
4FE8
LD (5981H),DE ED 53 81 59
Store Register Pair DE (the new password code) at 5981H, which goes into GAT bytes CEH-CFH of the new or destination diskette.
4FEC
RET C9
RETurn to 4F87H (or 661BH) with Register Pair HL past the password.
4FED
ODPW=password: GOSUB to 5025H to encode the password at Register Pair HL into Register Pair DE.
4FF0
LD (597AH),DE ED 53 7A 59
Store Register Pair DE (the destination diskette's present password code) at 597AH, which is compared with the destination GAT's password code.
4FF4
RET C9
RETurn to 4F87H with Register Pair HL past the password.
4FF5
LD DE,63D6H 11 D6 63
DPDN=dn: point Register Pair DE to 63D6H, the operand of the LD A,nn at 63D5H, which supplies the destination's PDRIVE number.
4FF8
GOSUB to 5002H to parse the PDRIVE number at Register Pair HL and store it at Register Pair DE (63D6H). It returns the number in Register A.
4FFB
LD (4DFAH),A 32 FA 4D
Store Register A (the PDRIVE number) at 4DFAH as well, the operand of the LD A,nn at 4DF9H, so that 4DF3H takes bytes 10-15 of that PDRIVE record for the new diskette.
4FFE
RET C9
RETurn to 4F87H with Register Pair HL past the number.
4FFF
LD DE,63CAH 11 CA 63
SPDN=dn: point Register Pair DE to 63CAH, the operand of the LD A,nn at 63C9H, which supplies the source's PDRIVE number.
5002
PUSH DE D5
Save Register Pair DE (where the PDRIVE number goes) onto the stack. 4FF8H calls here.
5003
GOSUB to 6EE6H to parse a decimal number of 0-255 at Register Pair HL into Register A.
5006
CP 0AH FE 0A
Compare Register A (the number) against 0AH: PDRIVE records are numbered 0-9.
5008
If the NO CARRY FLAG is set (10 or more), JUMP to 4FCBH for error 2FH.
500A
POP DE D1
Restore Register Pair DE from the stack: 63CAH or 63D6H.
500B
LD (DE),A 12
Store Register A (the PDRIVE number) at Register Pair DE.
500C
RET C9
RETurn to 4F87H or 4FFBH with Register A = the PDRIVE number.
500D
LD DE,624CH 11 4C 62
/ext: point Register Pair DE to 624CH, the 3-byte extension that 5D86H compares (three spaces in the file).
5010
LD B,03H 06 03
Load Register B with 03H: at most three characters.

Copy Loop: letters and digits are copied until a different character or the third one.

5012
LD A,(HL) 7E
Fetch a character at Register Pair HL (the command line) into Register A. 5022H comes here.
5013
SUB 30H D6 30
SUBtract 30H (the character 0) from Register A.
5015
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG for a digit 0-9.
5017
If the CARRY FLAG is set (a digit), JUMP to 501EH to copy it.
5019
SUB 11H D6 11
SUBtract 11H from Register A: the letter A now gives 0.
501B
CP 1AH FE 1A
Compare Register A against 1AH: the CARRY FLAG for a letter A-Z.
501D
RET NC D0
If the NO CARRY FLAG is set (neither a digit nor a letter), RETurn to 4F87H: the extension ends here and the rest of the 3 bytes at 624CH keep their spaces.
501E
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A again (the SUBs changed it). 5017H comes here.
501F
LD (DE),A 12
Store Register A (the extension character) at Register Pair DE (624CH-624EH).
5020
INC DE 13
INCrement Register Pair DE to the next byte of the extension.
5021
INC HL 23
INCrement Register Pair HL to the next character of the command line.
5022
DECrement Register B (the characters left) and LOOP BACK to 5012H until three have been copied.
5024
RET C9
RETurn to 4F87H with Register Pair HL past the extension.

5025H - Encode a Password

Entered with Register Pair HL pointing to a password in the command line. The password (up to 8 letters and digits) is copied to 5960H-5967H, padded with spaces, and turned into the 16-bit code that NEWDOS/80 keeps in the GAT and the directory. Each character is mixed in from the last to the first, and each is set back to a space as it is used, so the buffer is all spaces again at the end. On return Register Pair DE holds the code and Register Pair HL points past the password. A blank password gives 4296H.

5025
LD DE,5960H 11 60 59
Point Register Pair DE to 5960H, the 8-byte password buffer. 4FDDH, 4FE5H, 4FEDH and 6618H call here.
5028
GOSUB to 6F8EH to copy the password at Register Pair HL to Register Pair DE (5960H) and pad it to 8 characters with spaces. Register Pair DE returns 5968H and Register Pair HL past the password.
502B
PUSH HL E5
Save Register Pair HL (the command line pointer) onto the stack.
502C
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = 5968H, just past the buffer.
502D
LD DE,FFFFH 11 FF FF
Load Register Pair DE with FFFFH, the starting value of the code (Register D high byte, Register E low byte).
5030
LD B,08H 06 08
Load Register B with 08H: one pass for each of the 8 characters.

Encoding Loop: Register Pair DE is the code, Register Pair HL steps back through the buffer, Register B counts the characters.

5032
PUSH BC C5
Save Register Pair BC (Register B, the count) onto the stack, since Register B is used below. 5058H comes here.
5033
LD A,E 7B
Copy Register E (the low byte of the code) into Register A.
5034
AND 07H E6 07
AND Register A with 07H, keeping bits 0-2 of the low byte.
5036
LD C,A 4F
Copy Register A (bits 0-2 of the low byte) into Register C.
5037
LD A,E 7B
Copy Register E (the low byte of the code) into Register A again.
5038
RLCA 07
Rotate Register A (the low byte) left, the first of three.
5039
RLCA 07
Rotate Register A (the low byte of the code) left, the second of three.
503A
RLCA 07
Rotate Register A left, the third: the low byte rotated left three places.
503B
XOR C A9
XOR Register C (bits 0-2 of the low byte) into Register A.
503C
RLCA 07
Rotate Register A (the low byte, rotated and XORed) left once more: the mixed byte.
503D
LD C,A 4F
Copy Register A (the mixed byte) into Register C.
503E
AND F0H E6 F0
AND Register A (the mixed byte) with F0H, keeping its upper four bits.
5040
LD B,A 47
Copy Register A (the upper four bits) into Register B.
5041
LD A,C 79
Copy Register C (the mixed byte) into Register A.
5042
RLCA 07
Rotate Register A (the mixed byte from Register C) left one place.
5043
AND 1FH E6 1F
AND Register A with 1FH, keeping the lower five bits.
5045
XOR B A8
XOR Register B (the upper four bits of the mixed byte) into Register A.
5046
XOR D AA
XOR Register D (the high byte of the code) into Register A.
5047
LD E,A 5F
Copy Register A into Register E: the new low byte of the code.
5048
LD A,C 79
Copy Register C (the mixed byte) into Register A.
5049
AND 0FH E6 0F
AND Register A with 0FH, keeping its lower four bits.
504B
LD B,A 47
Copy Register A (the lower four bits) into Register B.
504C
LD A,C 79
Copy Register C (the mixed byte) into Register A.
504D
RLCA 07
Rotate Register A (the mixed byte) left, the first of four.
504E
RLCA 07
Rotate Register A (the mixed byte) left, the second of four.
504F
RLCA 07
Rotate Register A (the mixed byte) left, the third of four.
5050
RLCA 07
Rotate Register A left, the fourth: its two halves are swapped.
5051
XOR B A8
XOR Register B (the lower four bits) into Register A.
5052
POP BC C1
Restore Register Pair BC from the stack: Register B = the count of characters left.
5053
DEC HL 2B
DECrement Register Pair HL to the previous character of the password buffer (5967H on the first pass, 5960H on the last).
5054
XOR (HL) AE
XOR the password character at Register Pair HL into Register A.
5055
LD D,A 57
Copy Register A into Register D: the new high byte of the code.
5056
LD (HL),20H 36 20
Store 20H (a space) at Register Pair HL over the character just used.
5058
DECrement Register B (the characters left) and LOOP BACK to 5032H until all 8 have been mixed in.
505A
POP HL E1
Restore Register Pair HL from the stack: the command line just past the password.
505B
RET C9
RETurn to the caller with Register Pair DE = the password code.

505CH - Option Keyword Table (Data)

Searched by 4F1DH. One row for each option: the keyword (including the = of options that take a value), the attribute byte, the flag mask, the four exclusion bytes if attribute bit 2 is set, and the handler address if attribute bit 4 is set. Attribute bits: 7 always set (marks the end of the keyword), 6 allowed in FORMAT, 5 in COPY formats 5 and 6, 3 in COPY formats 1 to 4, 4 handler follows, 2 exclusion bytes follow, 1-0 the flag byte (0 = 5994H, 1 = 5995H, 2 = 5996H, 3 = 5997H). Longer keywords come before shorter ones that start the same way (NDMW, NFMT and NDN= before N). The flag bits are: 5994H bit 7 N, 6 Y, 5 DDND, 4 ODN, 3 KDN, 2 NDN, 1 BDU, 0 KDD; 5995H bit 7 NDMW, 6 CFWO, 5 NDPW, 4 USD, 3 DFO, 2 DDSL, 1 DDGA, 0 ODPW; 5996H bit 7 SN (COPY) or RWF (FORMAT), 6 SPW, 5 UBB, 4 USR, 3 CBF, 2 single file COPY (4DE5H), 1 /ext, 0 UPD; 5997H bit 7 SPDN, 6 DPDN, 5 XLF, 4 ILF, 3 NFMT, 2 FMT, 1 PFST, 0 PFTC.

505C-5061
DEFM "CFWO" / DEFB A1H, 40H 43 46 57 4F A1 40
CFWO (check file with operator: ask before each file): attribute A1H, allowed in COPY formats 5 and 6 only. Sets bit 6 of 5995H.
5062-506E
DEFM "DDGA=" / DEFB F5H, 02H, 00H, 00H, 00H, 0AH / DEFW 4F9EH 44 44 47 41 3D F5 02 00 00 00 0A 9E 4F
DDGA= (directory size in granules): attribute F5H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 1 of 5995H. Exclusion byte 0AH against 5997H: error 2FH if PFST or NFMT has already been given. Handler 4F9EH (value 2-6 to 64AFH).
506F-507B
DEFM "ODPW=" / DEFB B5H, 01H, C0H, 00H, 00H, 00H / DEFW 4FEDH 4F 44 50 57 3D B5 01 C0 00 00 00 ED 4F
ODPW= (old destination password): attribute B5H, allowed in COPY formats 5 and 6 only. Sets bit 0 of 5995H. Exclusion byte C0H against 5994H: error 2FH if Y or N has already been given. Handler 4FEDH (code to 597AH).
507C-5088
DEFM "NDPW=" / DEFB B5H, 20H, 02H, 00H, 00H, 00H / DEFW 4FE5H 4E 44 50 57 3D B5 20 02 00 00 00 E5 4F
NDPW= (new destination password): attribute B5H, allowed in COPY formats 5 and 6 only. Sets bit 5 of 5995H. Exclusion byte 02H against 5994H: error 2FH if BDU has already been given. Handler 4FE5H (code to 5981H).
5089-5095
DEFM "DDSL=" / DEFB F5H, 04H, 00H, 00H, 00H, 0AH / DEFW 4FC3H 44 44 53 4C 3D F5 04 00 00 00 0A C3 4F
DDSL= (directory starting lump): attribute F5H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 2 of 5995H. Exclusion byte 0AH against 5997H: error 2FH if PFST or NFMT has already been given. Handler 4FC3H (value to 64ACH).
5096-509E
DEFM "SPDN=" / DEFB BBH, 80H / DEFW 4FFFH 53 50 44 4E 3D BB 80 FF 4F
SPDN= (source PDRIVE number): attribute BBH, allowed in every COPY format. Sets bit 7 of 5997H. Handler 4FFFH (number 0-9 to 63CAH).
509F-50A7
DEFM "DPDN=" / DEFB FBH, 40H / DEFW 4FF5H 44 50 44 4E 3D FB 40 F5 4F
DPDN= (destination PDRIVE number): attribute FBH, allowed in every COPY format and in FORMAT. Sets bit 6 of 5997H. Handler 4FF5H (number 0-9 to 63D6H and 4DFAH).
50A8-50B4
DEFM "PFST=" / DEFB D7H, 02H, B9H, 86H, 00H, 00H / DEFW 4FD6H 50 46 53 54 3D D7 02 B9 86 00 00 D6 4F
PFST= (partial format, starting track): attribute D7H, allowed in FORMAT only. Sets bit 1 of 5997H. Exclusion bytes B9H against 5994H and 86H against 5995H: error 2FH if N, DDND, ODN, KDN, KDD, NDMW, DDSL or DDGA has already been given. Handler 4FD6H (track to 68AEH).
50B5-50BD
DEFM "PFTC=" / DEFB D3H, 01H / DEFW 4FCEH 50 46 54 43 3D D3 01 CE 4F
PFTC= (partial format, track count): attribute D3H, allowed in FORMAT only. Sets bit 0 of 5997H. Handler 4FCEH (count to 68ADH).
50BE-50C9
DEFM "NDN=" / DEFB B4H, 04H, 0AH, 00H, 00H, 00H / DEFW 4F95H 4E 44 4E 3D B4 04 0A 00 00 00 95 4F
NDN= (new destination name): attribute B4H, allowed in COPY formats 5 and 6 only. Sets bit 2 of 5994H. Exclusion byte 0AH against 5994H: error 2FH if KDN or BDU has already been given. Handler 4F95H (name to 5983H).
50CA-50D5
DEFM "ODN=" / DEFB F4H, 10H, C0H, 00H, 00H, 02H / DEFW 4F8BH 4F 44 4E 3D F4 10 C0 00 00 02 8B 4F
ODN= (old destination name): attribute F4H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 4 of 5994H. Exclusion bytes C0H against 5994H and 02H against 5997H: error 2FH if N, Y or PFST has already been given. Handler 4F8BH (name to 5970H).
50D6-50DF
DEFM "DDND" / DEFB E4H, 20H, C0H, 80H, 00H, 02H 44 44 4E 44 E4 20 C0 80 00 02
DDND (display the destination's old name and date): attribute E4H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 5 of 5994H. Exclusion bytes C0H against 5994H, 80H against 5995H and 02H against 5997H: error 2FH if N, Y, NDMW or PFST has already been given.
50E0-50E9
DEFM "NDMW" / DEFB E5H, 80H, 20H, 00H, 00H, 00H 4E 44 4D 57 E5 80 20 00 00 00
NDMW (no diskette mount waits): attribute E5H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 7 of 5995H. Exclusion byte 20H against 5994H: error 2FH if DDND has already been given.
50EA-50F1
DEFM "SPW=" / DEFB B2H, 40H / DEFW 4FDDH 53 50 57 3D B2 40 DD 4F
SPW= (source password): attribute B2H, allowed in COPY formats 5 and 6 only. Sets bit 6 of 5996H. Handler 4FDDH (code to 5978H).
50F2-50FB
DEFM "NFMT" / DEFB A7H, 08H, 00H, 06H, 00H, 04H 4E 46 4D 54 A7 08 00 06 00 04
NFMT (do not format): attribute A7H, allowed in COPY formats 5 and 6 only. Sets bit 3 of 5997H. Exclusion bytes 06H against 5995H and 04H against 5997H: error 2FH if DDSL, DDGA or FMT has already been given.
50FC-5107
DEFM "XLF=" / DEFB B7H, 20H, 00H, 00H, 00H, 10H / DEFW 4FACH 58 4C 46 3D B7 20 00 00 00 10 AC 4F
XLF= (exclude list file): attribute B7H, allowed in COPY formats 5 and 6 only. Sets bit 5 of 5997H. Exclusion byte 10H against 5997H: error 2FH if ILF has already been given. Handler 4FACH (filespec to 4480H).
5108-5113
DEFM "ILF=" / DEFB B7H, 10H, 00H, 00H, 00H, 20H / DEFW 4FACH 49 4C 46 3D B7 10 00 00 00 20 AC 4F
ILF= (include list file): attribute B7H, allowed in COPY formats 5 and 6 only. Sets bit 4 of 5997H. Exclusion byte 20H against 5997H: error 2FH if XLF has already been given. Handler 4FACH (filespec to 4480H).
5114-511C
DEFM "KDN" / DEFB E4H, 08H, C6H, 00H, 00H, 02H 4B 44 4E E4 08 C6 00 00 02
KDN (keep the destination name): attribute E4H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 3 of 5994H. Exclusion bytes C6H against 5994H and 02H against 5997H: error 2FH if N, Y, NDN, BDU or PFST has already been given.
511D-5123
DEFM "SN=" / DEFB B2H, 80H / DEFW 4F90H 53 4E 3D B2 80 90 4F
SN= (source name): attribute B2H, allowed in COPY formats 5 and 6 only. Sets bit 7 of 5996H, which RWF also uses (RWF is accepted only by FORMAT). Handler 4F90H (name to 5968H).
5124-512C
DEFM "KDD" / DEFB E4H, 01H, C2H, 10H, 00H, 02H 4B 44 44 E4 01 C2 10 00 02
KDD (keep the destination date): attribute E4H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 0 of 5994H. Exclusion bytes C2H against 5994H, 10H against 5995H and 02H against 5997H: error 2FH if N, Y, BDU, USD or PFST has already been given.
512D-5135
DEFM "USD" / DEFB A5H, 10H, 03H, 00H, 00H, 00H 55 53 44 A5 10 03 00 00 00
USD (use the source date): attribute A5H, allowed in COPY formats 5 and 6 only. Sets bit 4 of 5995H. Exclusion byte 03H against 5994H: error 2FH if KDD or BDU has already been given.
5136-513E
DEFM "BDU" / DEFB E4H, 02H, 0CH, 30H, 08H, 00H 42 44 55 E4 02 0C 30 08 00
BDU (bypass the destination directory update): attribute E4H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 1 of 5994H. Exclusion bytes 0CH against 5994H, 30H against 5995H and 08H against 5996H: error 2FH if KDN, NDN, NDPW, USD or CBF has already been given.
513F-5143
DEFM "UBB" / DEFB A2H, 20H 55 42 42 A2 20
UBB (use big buffer: memory up to HIMEM): attribute A2H, allowed in COPY formats 5 and 6 only. Sets bit 5 of 5996H, which 4D29H also sets unless COPY runs under DOS-CALL.
5144-514C
DEFM "CBF" / DEFB A6H, 08H, 02H, 00H, 00H, 00H 43 42 46 A6 08 02 00 00 00
CBF (copy by file): attribute A6H, allowed in COPY formats 5 and 6 only. Sets bit 3 of 5996H. Exclusion byte 02H against 5994H: error 2FH if BDU has already been given.
514D-5151
DEFM "UPD" / DEFB A2H, 01H 55 50 44 A2 01
UPD (copy only files whose updated flag is set): attribute A2H, allowed in COPY formats 5 and 6 only. Sets bit 0 of 5996H.
5152-5156
DEFM "USR" / DEFB A2H, 10H 55 53 52 A2 10
USR (copy only user files: system and invisible files are left out): attribute A2H, allowed in COPY formats 5 and 6 only. Sets bit 4 of 5996H.
5157-515F
DEFM "DFO" / DEFB A5H, 08H, 00H, 00H, 00H, 04H 44 46 4F A5 08 00 00 00 04
DFO (destination files only: copy a file only if it already exists on both diskettes): attribute A5H, allowed in COPY formats 5 and 6 only. Sets bit 3 of 5995H. Exclusion byte 04H against 5997H: error 2FH if FMT has already been given.
5160-5168
DEFM "RWF" / DEFB C6H, 80H, 09H, 06H, 00H, 02H 52 57 46 C6 80 09 06 00 02
RWF (R&W format: ignore errors and format each track once): attribute C6H, allowed in FORMAT only. Sets bit 7 of 5996H (shared with SN=, which only COPY accepts). Exclusion bytes 09H against 5994H, 06H against 5995H and 02H against 5997H: error 2FH if KDN, KDD, DDSL, DDGA or PFST has already been given.
5169-5171
DEFM "FMT" / DEFB A7H, 04H, 00H, 08H, 00H, 08H 46 4D 54 A7 04 00 08 00 08
FMT (format the destination): attribute A7H, allowed in COPY formats 5 and 6 only. Sets bit 2 of 5997H. Exclusion bytes 08H against 5995H and 08H against 5997H: error 2FH if DFO or NFMT has already been given.
5172-5176
DEFM "/" / DEFB B2H, 02H / DEFW 500DH 2F B2 02 0D 50
/ext (copy only files with this extension): attribute B2H, allowed in COPY formats 5 and 6 only. Sets bit 1 of 5996H. Handler 500DH (extension to 624CH).
5177-517D
DEFM "Y" / DEFB E4H, 40H, B9H, 01H, 00H, 00H 59 E4 40 B9 01 00 00
Y (the operator does not care what is on the destination): attribute E4H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 6 of 5994H. Exclusion bytes B9H against 5994H and 01H against 5995H: error 2FH if N, DDND, ODN, KDN, KDD or ODPW has already been given.
517E-5184
DEFM "N" / DEFB E4H, 80H, 79H, 01H, 00H, 02H 4E E4 80 79 01 00 02
N (the destination must hold no recognizable data): attribute E4H, allowed in COPY formats 5 and 6 and in FORMAT. Sets bit 7 of 5994H. Exclusion bytes 79H against 5994H, 01H against 5995H and 02H against 5997H: error 2FH if Y, DDND, ODN, KDN, KDD, ODPW or PFST has already been given.
5185
DEFB 00H 00
The 00H that ends the option table: 4F43H stops the search here and 4F46H reports error 34H.

5186H - End of the Overlay Area (Not in the File)

SYS6/SYS's first load block ends at 5185H. These 122 bytes of the DOS overlay area are not loaded. From 4DA6H on the whole overlay area is reused: the command line is copied to 4D3EH, and SYS2/SYS, SYS3/SYS or SYS17/SYS is loaded into 4D00H-51FFH (568DH) when SYS6/SYS needs its code.

5186-51FF
DEFS 122
Not in the file: 5186H-51FFH, the rest of the overlay area 4D00H-51FFH. SYS6/SYS neither reads nor writes these bytes; an overlay loaded by 568DH fills them.

5200H - Error Exits

Each entry loads a DOS error code into Register A and joins the common exit at 521AH. 5210H is a check used by APPEND: nothing may follow the last parameter.

5200
LD A,20H 3E 20
Load Register A with error code 20H (ILLEGAL OR MISSING DRIVE #). 6482H comes here.
5202
JUMP to 521AH to end the command with the error code in Register A (20H).
5204
LD A,3CH 3E 3C
Load Register A with error code 3CH (INCOMPATIBLE DRIVES OR DISKETTES). 634CH and 6362H come here.
5206
JUMP to 521AH to end the command with the error code in Register A (3CH).
5208
LD A,2AH 3E 2A
Load Register A with error code 2AH (ILLEGAL DOS FUNCTION). 4D1BH (an unknown function code) and 4E47H (a swap needed with NDMW) come here.
520A
JUMP to 521AH to end the command with the error code in Register A (2AH).
520C
LD A,2CH 3E 2C
Load Register A with error code 2CH (BAD DIRECTORY DATA). Nothing in SYS6/SYS jumps or calls here.
520E
JUMP to 521AH to end the command with the error code in Register A (2CH). Nothing reaches this row.
5210
LD A,(HL) 7E
Fetch the character at Register Pair HL (the command line after the last parameter) into Register A. 6F56H calls here.
5211
CP 0DH FE 0D
Compare Register A (the character) against 0DH, the end of the command line.
5213
RET Z C8
If the Z FLAG is set (nothing follows), RETurn to 6F59H.
5214
LD A,34H 3E 34
Something follows that should not, or no option keyword matched (4F46H): load Register A with error code 34H (ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR).
5216
JUMP to 521AH to end the command with the error code in Register A (34H).
5218
LD A,2FH 3E 2F
Load Register A with error code 2FH (BAD PARAMETER(S)). 4F49H, 63B0H, 65FDH, 68B8H, 6EEDH and 6FDAH come here, and it falls through into 521AH.

521AH - Common Exit

521AH ends the command with the error code in Register A: it starts a new line and continues at 521EH, which is also entered directly (with the error code on the stack) when the cursor is already at the start of a line. 5222H is entered with Register Pair HL holding the SYS0/SYS exit to use: 4409H displays the error in Register A, 4030H (error already displayed) and 402DH (no error) go to DOS READY. Every exit switches back to the system diskette in drive 0, puts back the drives' own PDRIVE data if COPY or FORMAT changed it, and clears the FORMAT/COPY bit of 4289H.

521A
PUSH AF F5
Save Register Pair AF (Register A = the error code) onto the stack. 4E3AH, 4E9DH, 5202H-5216H, 54CBH, 5553H, 55B9H, 560AH, 5688H, 56FEH, 574CH, 584FH, 58DBH, 5DEEH, 5F7EH, 6111H, 6329H, 6434H, 6670H, 6706H, 67DFH, 67FBH, 683FH, 68A2H, 692AH, 6EC7H and 6F7FH come here.
521B
GOSUB to 5881H to display a carriage return (Register A = 0DH), starting a new line on the display. 5D6EH jumps here.
521E
POP AF F1
Restore Register Pair AF from the stack: Register A = the error code. 53A4H, 53B0H and 5823H jump here with the code already on the stack.
521F
LD HL,4409H 21 09 44
Point Register Pair HL to 4409H, the SYS0/SYS error exit that displays the message for the code in Register A and goes to DOS READY.
5222
PUSH HL E5
Save Register Pair HL (the exit address: 4409H, 4030H or 402DH) onto the stack, where the RET at 523BH finds it. 524CH and 54D1H jump here.
5223
PUSH AF F5
Save Register Pair AF (Register A = the error code, or whatever the caller left for 4030H and 402DH) onto the stack.
5224
GOSUB to 5582H to switch to the system diskette (control block 5942H), asking for it to be mounted in drive 0 if it was swapped out.
5227
LD A,(593BH) 3A 3B 59
Fetch the SYS6/SYS flags at 593BH into Register A (00H as loaded; bit 7 is set by 63BDH).
522A
BIT 7,A CB 7F
Test bit 7 of Register A (593BH): set by 63BDH once COPY or FORMAT has saved the drives' PDRIVE data and put its own in.
522C
If the Z FLAG is set (the PDRIVE data was never changed), JUMP to 5235H.
522E
LD B,05H 06 05
Load Register B with 05H, the mode for 5658H: bit 0 set = the saved original copies (control block +6), bit 1 clear = copy them into the drives' PDRIVE entries, bit 2 set = ignore errors.
5230
GOSUB to 5646H to put the original PDRIVE data back for the system, source and destination drives (Register B = 05H). 5646H returns with the Z FLAG set (its DEC C reached 0).
5233
If the NZ FLAG is set, JUMP to 523CH. 5646H always returns the Z FLAG, so this jump is never taken.
5235
LD HL,4289H 21 89 42
Point Register Pair HL to 4289H, the SYS0/SYS system flags. 522CH comes here.
5238
RES 3,(HL) CB 9E
Clear bit 3 of the byte at Register Pair HL (4289H): FORMAT or COPY is no longer running, so the D-F-G, 1-2-3 and J-K-L key combinations work again (set at 4D0DH).
523A
POP AF F1
Restore Register Pair AF from the stack: Register A = the error code pushed at 5223H.
523B
RET C9
RETurn to the exit address pushed at 5222H (Register A = the error code for 4409H).
523C
PUSH AF F5
Save Register Pair AF onto the stack. Only the JR NZ at 5233H leads here, and it is never taken, so this row never runs.
523D
LD A,46H 3E 46
Load Register A with 46H. This row never runs (see 523CH).
523F
RST 18H DF
RST 18H, the ROM routine that compares Register Pair HL with Register Pair DE. This row never runs (see 523CH); the next byte starts the routine at 5240H.

5240H - Display a Message and Exit

5240H reports DISKETTE/GAT OVERFLOW. 5243H is entered with Register Pair HL pointing to any message. Either way the message is shown on a new line and the command ends through 4030H (error already displayed), with the clean-up at 5222H.

5240
LD HL,5AC2H 21 C2 5A
Point Register Pair HL to 5AC2H, the message DISKETTE/GAT OVERFLOW (more lumps than the GAT can describe). 5768H, 606DH and 6249H come here.
5243
GOSUB to 5881H to start a new line on the display. 556DH, 674AH and 692DH come here with Register Pair HL pointing to their own message.
5246
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
5249
LD HL,4030H 21 30 40
Point Register Pair HL to 4030H, the SYS0/SYS exit for an error that has already been displayed. 58CDH comes here (a C, R or P question that cannot be asked under NDMW).
524C
JUMP to 5222H with Register Pair HL = 4030H, the exit to use.

524EH - COPY by File: Compact the File List and Start Copying

Reached by the JP 524EH at 615FH, in the code at 6157H whose address 60F1H pushes as a return address, once the destination directory entries have been made. The list of files to copy (three bytes for each file, from (5D12H) to (5D14H)) is moved down to 5D16H, so that all memory after it can be used for sector buffers, the source diskette is selected and the first file to copy is opened.

524E
LD HL,(5D14H) 2A 14 5D
Fetch the end of the file list from 5D14H into Register Pair HL. 615FH comes here.
5251
LD DE,(5D12H) ED 5B 12 5D
Fetch the start of the file list from 5D12H into Register Pair DE.
5255
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
5256
SBC HL,DE ED 52
SUBtract Register Pair DE (the start of the list) from Register Pair HL (its end): Register Pair HL = the length of the list in bytes.
5258
LD B,H 44
Copy Register H (the high byte of the length) into Register B.
5259
LD C,L 4D
Copy Register L (the low byte of the length) into Register C: Register Pair BC = the length of the list.
525A
PUSH DE D5
Save Register Pair DE (the old start of the list) onto the stack.
525B
LD HL,5D16H 21 16 5D
Point Register Pair HL to 5D16H, the new start of the list, just after the pointers at 5D10H-5D15H.
525E
LD (5D12H),HL 22 12 5D
Store Register Pair HL (5D16H) at 5D12H as the start of the list.
5261
PUSH HL E5
Save Register Pair HL (5D16H) onto the stack, for 526CH.
5262
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the old start of the list, Register Pair DE = 5D16H.
5263
LDIR ED B0
Copy Register Pair BC (the length) bytes from Register Pair HL (the old list) to Register Pair DE (5D16H). The list is moved down; Register Pair DE ends just past it.
5265
LD (5D14H),DE ED 53 14 5D
Store Register Pair DE (the end of the moved list) at 5D14H. The sector buffers of the COPY engine start there.
5269
GOSUB to 5578H to switch to the source diskette (control block 594CH).
526C
POP HL E1
Restore Register Pair HL from the stack: 5D16H, the first entry of the list.
526D
GOSUB to 56A6H to find the first entry from Register Pair HL on that is marked to be copied (bit 5) and open its file through the source FCB at 5AE5H. It returns the Z FLAG when no entry is marked.
5270
If the Z FLAG is set (no file to copy), JUMP to 552DH to display DONE and end the command.

5273H - COPY Engine: Read a Batch of Source Sectors

Used by the diskette COPY (format 5), the COPY by file (format 6, from 5270H) and the single file COPY (formats 1 to 4, from 638FH, entering at 5279H). The free memory from (5D14H) to (593CH) is divided into entries of 258 bytes: a marker byte, a record type byte and the 256 bytes of a sector. As many source sectors as fit are read, then 5324H writes and verifies them. The marker byte is FFH, or in a COPY by file the destination DEC of the file the sector belongs to; the record type is 00H for a normal sector and 06H for a sector written with the directory mark. In a diskette COPY the boot sectors and the drive 0 record of the system data sector are replaced on the way (52DBH).

5273
LD HL,627BH 21 7B 62
Point Register Pair HL to 627BH, the message COPYING. 6374H comes here.
5276
GOSUB to 587EH to display the message at Register Pair HL (COPYING) and start a new line.
5279
LD HL,(593CH) 2A 3C 59
Fetch the highest address COPY may use from 593CH into Register Pair HL: 6FFFH as loaded, or HIMEM stored by 4D2EH when COPY does not run under DOS-CALL. 638FH comes here.
527C
LD DE,(5D14H) ED 5B 14 5D
Fetch the start of the buffer area from 5D14H into Register Pair DE (just past the file list, or 5D16H when there is none).
5280
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
5281
SBC HL,DE ED 52
SUBtract Register Pair DE (the start of the buffers) from Register Pair HL (the top): Register Pair HL = the number of free bytes.
5283
LD DE,0102H 11 02 01
Load Register Pair DE with 0102H, 258 bytes, the size of one sector entry.
5286
LD A,FFH 3E FF
Load Register A with FFH, so that the first INC makes the entry count 0.

Count Loop: Register A counts how many 258-byte entries fit in Register Pair HL bytes.

5288
INC A 3C
INCrement Register A, the number of entries that fit. 528CH comes here.
5289
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
528A
SBC HL,DE ED 52
SUBtract Register Pair DE (258) from Register Pair HL (the bytes left).
528C
If the NO CARRY FLAG is set (another whole entry fitted), LOOP BACK to 5288H.
528E
LD (531AH),A 32 1A 53
Store Register A (the number of entries that fit) at 531AH, the operand of the CP at 5319H that ends a batch.
5291
LD HL,594CH 21 4C 59
Point Register Pair HL to 594CH, the source diskette's control block. 5321H comes here for every batch.
5294
GOSUB to 5538H to switch to the source diskette (asking for it to be mounted if needed) and open the source FCB if it is not open yet. Index Register IX returns pointing to the source FCB at 5AE5H.
5297
XOR A AF
Set Register A to 00H: no sectors read into this batch yet.
5298
LD HL,(5D14H) 2A 14 5D
Point Register Pair HL to the first entry, whose address is fetched from 5D14H.
529B
JUMP to 5316H to store the count (0) and start the loop.

Read Loop: Register Pair HL is the entry being filled; 5314H counts the sectors read.

529D
PUSH HL E5
Save Register Pair HL (the address of the entry being filled) onto the stack. 52C8H and 531BH come here.
529E
INC HL 23
INCrement Register Pair HL past the entry's marker byte.
529F
INC HL 23
INCrement Register Pair HL past the record type byte, to the 256 data bytes.
52A0
LD (5AE8H),HL 22 E8 5A
Store Register Pair HL (the entry's data area) at 5AE8H, the buffer address (FCB+3) of the source FCB, so the sector is read straight into the entry.
52A3
LD A,80H 3E 80
Load Register A with 80H, the operation bit for READING SOURCE.
52A5
LD (57EBH),A 32 EB 57
Store Register A (80H) at 57EBH, the operand of the LD B,nn at 57EAH, so that an error report says READING SOURCE.
52A8
GOSUB to 57C8H to read the sector at the source FCB's NEXT through SYS0/SYS 4436H (Register Pair DE = Index Register IX = 5AE5H). It returns the Z FLAG and Register A = 0, or the NZ FLAG with the error code in Register A. 52CDH comes here for a retry.
52AB
If the Z FLAG is set (read without error), JUMP to 52CFH to record type 00H.
52AD
CP 06H FE 06
Compare Register A (the error code) against 06H: the sector was written with the directory mark (TRIED TO READ LOCKED/DELETED RECORD). Its data has still been read.
52AF
If the Z FLAG is set (a sector with the directory mark), JUMP to 52D0H with Register A = 06H as its record type, so that it is written back with the same mark.
52B1
CP 1CH FE 1C
Compare Register A (the error code) against 1CH (END OF FILE ENCOUNTERED).
52B3
If the Z FLAG is set (the source has ended), JUMP to 52B9H.
52B5
CP 1DH FE 1D
Compare Register A (the error code) against 1DH (PAST END OF FILE).
52B7
If the NZ FLAG is set (any other error), JUMP to 52CAH to report it.
52B9
LD HL,0000H 21 00 00
The source file, or the source diskette, has ended. Load Register Pair HL with the address of the file list entry of the file just read. 52B3H comes here. Self-Modifying Code
The operand at 52BAH-52BBH is 0000H in the file; 56AAH stores the entry address there in a COPY by file.
52BC
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
52BF
AND 08H E6 08
AND Register A (the 5996H flags) with 08H, keeping bit 3 (CBF).
52C1
If the NZ FLAG is set (a COPY by file), GOSUB to 56A2H to step past the file list entry at Register Pair HL to the next one marked to be copied and open its file. It returns the Z FLAG when there are no more. In the other kinds of COPY the Z FLAG from the AND stays set.
52C4
If the Z FLAG is set (nothing more to read), JUMP to 549CH to write the last batch and finish. The entry address is still on the stack.
52C7
POP HL E1
Restore Register Pair HL from the stack: the entry being filled.
52C8
LOOP BACK to 529DH to read the next file's first sector into the same entry.
52CA
GOSUB to 585AH to report the error in Register A (READING SOURCE SECTOR n) and ask C, R or P. It returns the NZ FLAG for R (retry) and the Z FLAG for P (proceed: the source FCB's NEXT is moved past the sector). 52B7H comes here.
52CD
If the NZ FLAG is set (R), JUMP to 52A8H to read the sector again.
52CF
XOR A AF
P, or read without error: set Register A to 00H, the record type of a normal sector. With P the entry keeps whatever its buffer held. 52ABH comes here.
52D0
POP HL E1
Restore Register Pair HL from the stack: the entry just filled. 52AFH comes here with Register A = 06H.
52D1
LD (HL),FFH 36 FF
Store the marker byte at Register Pair HL (the entry's first byte). Self-Modifying Code
The operand at 52D2H is FFH in the file; in a COPY by file 56B1H stores the destination DEC of the file being read there.
52D3
INC HL 23
INCrement Register Pair HL to the entry's record type byte.
52D4
LD (HL),A 77
Store Register A (the record type: 00H normal, 06H directory mark) at Register Pair HL.
52D5
INC HL 23
INCrement Register Pair HL to the entry's 256 data bytes.
52D6
GOSUB to 571BH to blink the progress asterisk at 3C3FH and check the right arrow (pause) and up arrow (cancel) keys.
52D9
PUSH HL E5
Save Register Pair HL (the entry's data) onto the stack.
52DA
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the entry's data.

A diskette COPY replaces the boot sectors with SYS6/SYS's own boot sector and puts the destination drive's PDRIVE record into the system data sector, unless BDU was given.

52DB
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
52DE
AND 0CH E6 0C
AND Register A (the 5996H flags) with 0CH, keeping bit 2 (single file COPY) and bit 3 (CBF).
52E0
If the NZ FLAG is set (not a diskette COPY), JUMP to 5311H and keep the sector as read.
52E2
LD A,(5994H) 3A 94 59
Fetch the option flags from 5994H into Register A.
52E5
BIT 1,A CB 4F
Test bit 1 of Register A (5994H): BDU, bypass the destination directory update.
52E7
If the NZ FLAG is set (BDU), JUMP to 5311H and copy every sector unchanged.
52E9
LD HL,(5AEFH) 2A EF 5A
Fetch the source FCB's NEXT from 5AEFH (FCB+10) into Register Pair HL: the read moved it one past the sector just read.
52EC
DEC HL 2B
DECrement Register Pair HL: the number of the sector just read, counted from the start of the diskette.
52ED
LD A,H 7C
Copy Register H (the high byte of the sector number) into Register A.
52EE
OR A B7
OR Register A with itself: the Z FLAG when Register H is 0.
52EF
If the NZ FLAG is set (sector 256 or higher), JUMP to 5311H.
52F1
LD A,L 7D
Copy Register L (the low byte of the sector number) into Register A.
52F2
CP 02H FE 02
Compare Register A (the sector number) against 02H.
52F4
If the NO CARRY FLAG is set (sector 2 or higher), JUMP to 52FEH with the Z FLAG telling whether it is sector 2.
52F6
LD HL,64BAH 21 BA 64
Sector 0 or 1, the boot sector and its copy: point Register Pair HL to 64BAH, SYS6/SYS's boot sector image, which goes onto the destination instead.
52F9
GOSUB to 5C80H with Register A = the sector number and Register Pair DE = the source sector: it returns Register Pair BC = 0100H, and for sector 0 it first copies the source's directory starting lump (byte 2) into the image at 64BCH.
52FC
JUMP to 530FH to copy Register Pair BC (256) bytes from the image at Register Pair HL over the sector at Register Pair DE.
52FE
If the NZ FLAG is set (sector 3 or higher), JUMP to 5311H. 52F4H comes here.
5300
LD HL,00EFH 21 EF 00
Sector 2, the system data sector. Load Register Pair HL with 00EFH, the offset of its validity byte.
5303
ADD HL,DE 19
ADD Register Pair DE (the sector's data) to Register Pair HL: Register Pair HL points to byte EFH of the sector.
5304
LD A,(HL) 7E
Fetch byte EFH at Register Pair HL into Register A.
5305
CP A5H FE A5
Compare Register A (byte EFH) against A5H, the value that marks a valid NEWDOS/80 system data sector.
5307
If the NZ FLAG is set (no system data on the source), JUMP to 5311H and copy the sector unchanged.
5309
LD HL,6EB4H 21 B4 6E
Point Register Pair HL to 6EB4H, the PDRIVE sector built by 4DF3H, whose drive 0 record describes the destination diskette.
530C
LD BC,0010H 01 10 00
Load Register Pair BC with 0010H: 16 bytes, one PDRIVE record.
530F
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL to Register Pair DE: the 16-byte record over the drive 0 record of the system data sector, or the whole 256-byte boot sector image over sector 0 or 1. 52FCH comes here.
5311
POP HL E1
Restore Register Pair HL from the stack: the data of the entry just filled. 52E0H, 52E7H, 52EFH, 52FEH and 5307H come here.
5312
INC H 24
INCrement Register H: Register Pair HL + 256 = the start of the next entry (258 bytes after the last one).
5313
LD A,00H 3E 00
Load Register A with the number of sectors read into this batch. Self-Modifying Code
The operand at 5314H is 00H in the file; 5316H stores the count there, and the write loop counts it down at 53F5H.
5315
INC A 3C
INCrement Register A: one more sector in the batch.
5316
LD (5314H),A 32 14 53
Store Register A (the count) at 5314H, the operand of the LD A,nn at 5313H. 529BH comes here with Register A = 0.
5319
CP 0AH FE 0A
Compare Register A (the count) against the number of entries that fit. Self-Modifying Code
The operand at 531AH is 0AH in the file; 528EH stores the number of entries that fit there.
531B
If the CARRY FLAG is set (room for another entry), JUMP to 529DH to read the next sector into Register Pair HL.
531E
The buffer is full: GOSUB to 5324H to write the batch to the destination and verify it.
5321
JUMP to 5291H to read the next batch from the source.

5324H - COPY Engine: Write the Batch

Writes the entries read by 5291H-5321H (their number is at 5314H) to the destination, then verifies them at 53FBH. In a single file COPY and a COPY by file the whole destination file is first allocated by writing its last sector (5367H), so that it gets its space in one piece. In a COPY by file a change of the marker byte means that the sector belongs to the next file: the sectors written so far are verified and the next destination file is opened.

5324
GOSUB to 5535H to switch to the destination diskette (asking for it to be mounted if needed) and open the destination FCB if it is not open yet. Index Register IX returns pointing to the destination FCB at 5B17H. 531EH and 549DH call here.
5327
LD A,(5314H) 3A 14 53
Fetch the number of sectors in the batch from 5314H (the operand of the LD A,nn at 5313H) into Register A.
532A
OR A B7
OR Register A (the sector count) with itself: the Z FLAG when the batch is empty.
532B
RET Z C8
If the Z FLAG is set (nothing to write), RETurn to the caller.
532C
LD HL,(5D14H) 2A 14 5D
Point Register Pair HL to the first entry of the batch, whose address is fetched from 5D14H.
532F
LD (544FH),HL 22 4F 54
Store Register Pair HL (the first entry to be verified) at 544FH, the operand of the LD HL,nnnn at 544EH used by the verify pass. 535EH comes here when a new file starts.
5332
LD DE,(5B21H) ED 5B 21 5B
Fetch the destination FCB's NEXT from 5B21H (FCB+10) into Register Pair DE: the sector this pass starts writing at.
5336
LD (5401H),DE ED 53 01 54
Store Register Pair DE (the first sector of the pass) at 5401H, the operand of the LD HL,nnnn at 5400H, where the verify pass starts reading.
533A
XOR A AF
Set Register A to 00H (XOR A), the starting count of sectors written in this pass.
533B
LD (53ECH),A 32 EC 53
Store Register A (00H) at 53ECH, the operand of the LD A,nn at 53EBH: no sectors written in this pass yet.

Write Loop: Register Pair HL is the entry being written; 5314H counts the entries left.

533E
PUSH HL E5
Save Register Pair HL (the entry address) onto the stack. 53F8H comes here.
533F
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
5342
AND 0CH E6 0C
AND Register A (the 5996H flags) with 0CH, keeping bit 2 (single file COPY) and bit 3 (CBF).
5344
If the Z FLAG is set (a diskette COPY: the destination is written sector for sector), JUMP to 53D5H to write the sector.
5347
AND 08H E6 08
AND Register A (bits 2 and 3 of 5996H) with 08H, keeping bit 3 (CBF).
5349
If the Z FLAG is set (a single file COPY), JUMP to 5360H.
534B
LD A,(HL) 7E
COPY by file: fetch the entry's marker byte at Register Pair HL into Register A, the destination DEC of the file the sector belongs to.
534C
CP (IX+07H) DD BE 07
Compare Register A (the entry's destination DEC) against (IX+07H), the DEC in the destination FCB (Index Register IX = 5B17H, so this is 5B1EH): the file now open.
534F
If the Z FLAG is set (the same file), JUMP to 5360H.
5351
PUSH AF F5
The sector starts the next file: save Register Pair AF (Register A = its DEC) onto the stack.
5352
GOSUB to 53FBH to verify the sectors already written to the previous file.
5355
POP AF F1
Restore Register Pair AF from the stack: Register A = the next file's destination DEC.
5356
LD IX,5B17H DD 21 17 5B
Point Index Register IX to 5B17H, the destination FCB, again after the verify pass called at 5352H.
535A
GOSUB to 56B9H to open the destination file whose DEC is in Register A through the FCB at Index Register IX, using SYS2/SYS's FCB building code. It returns the NZ FLAG.
535D
POP HL E1
Restore Register Pair HL from the stack: the entry address.
535E
JUMP to 532FH to start a new pass (and a new verify range) at this entry.
5360
LD HL,(5B21H) 2A 21 5B
Fetch the destination FCB's NEXT from 5B21H into Register Pair HL. 5349H and 534FH come here.
5363
LD A,H 7C
Copy Register H (the high byte of NEXT) into Register A.
5364
OR L B5
OR Register L (the low byte of NEXT) into Register A: the Z FLAG when NEXT is 0.
5365
If the NZ FLAG is set (not the file's first sector), JUMP to 53D5H to write it.

First sector of a destination file: allocate the whole file at once by writing the sector at its end, so that DOS gives it its granules in one search.

5367
XOR A AF
Set Register A to 00H (XOR A), the skip flag value meaning the sectors are written.
5368
LD (53D7H),A 32 D7 53
Store Register A (00H) at 53D7H, the operand of the LD A,nn at 53D6H: this file's sectors are to be written.
536B
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
536E
BIT 3,A CB 5F
Test bit 3 of Register A (5996H): CBF. The Z FLAG is kept for 5377H.
5370
PUSH HL E5
Save Register Pair HL (NEXT, which is 0) onto the stack, for 53D1H.
5371
LD HL,(5AF1H) 2A F1 5A
Fetch the source FCB's EOF from 5AF1H (FCB+12, the EOF sector count) into Register Pair HL, for a single file COPY. LD does not change the flags.
5374
LD A,(5AEDH) 3A ED 5A
Fetch the source FCB's EOF byte offset from 5AEDH (FCB+8) into Register A.
5377
If the Z FLAG is set (not a COPY by file), JUMP to 537FH with the source file's EOF.
5379
LD HL,(5B23H) 2A 23 5B
COPY by file: fetch the EOF sector count that 56B9H put into the destination FCB from 5B23H (FCB+12) into Register Pair HL.
537C
LD A,(5B1FH) 3A 1F 5B
Fetch the destination FCB's EOF byte offset from 5B1FH (FCB+8) into Register A.
537F
OR A B7
OR Register A (the EOF byte offset) with itself: the Z FLAG when the file ends on a sector boundary. 5377H comes here.
5380
If the NZ FLAG is set (the last sector is partly used, so Register Pair HL is already its number), JUMP to 5383H.
5382
DEC HL 2B
The file ends on a sector boundary: DECrement Register Pair HL to the number of its last sector.
5383
LD A,H 7C
Copy Register H (the high byte of the last sector number) into Register A. 5380H comes here.
5384
AND L A5
AND Register L (the low byte) into Register A: FFH only if Register Pair HL is FFFFH.
5385
INC A 3C
INCrement Register A: the Z FLAG when Register Pair HL is FFFFH (an EOF of 0, an empty file).
5386
If the Z FLAG is set (the file is empty and needs no space), JUMP to 53D1H.
5388
LD (5B21H),HL 22 21 5B
Store Register Pair HL (the last sector number) at 5B21H as the destination FCB's NEXT.
538B
LD HL,428BH 21 8B 42
Point Register Pair HL to 428BH, the SYS0/SYS temporary flags.
538E
SET 1,(HL) CB CE
Set bit 1 of the byte at Register Pair HL (428BH) while this write is done: SYS2/SYS's allocator then takes no extra granules for the file.
5390
GOSUB to 57CEH to write the destination FCB's buffer as the last sector (its contents do not matter: the sector is written again when the file's data gets there). It returns the Z FLAG, or the NZ FLAG with the error code in Register A.
5393
RES 1,(HL) CB 8E
Clear bit 1 of the byte at Register Pair HL (428BH). RES does not change the flags.
5395
If the Z FLAG is set (the space was allocated), JUMP to 53D1H.
5397
PUSH AF F5
Save Register Pair AF (Register A = the error code) onto the stack.
5398
LD HL,5995H 21 95 59
Point Register Pair HL to 5995H, the option flags.
539B
BIT 7,(HL) CB 7E
Test bit 7 of the byte at Register Pair HL (5995H): NDMW.
539D
If the NZ FLAG is set (NDMW), JUMP to 53ADH to end the command with the error.
539F
LD HL,5996H 21 96 59
Point Register Pair HL to 5996H, the option flags.
53A2
BIT 2,(HL) CB 56
Test bit 2 of the byte at Register Pair HL (5996H): a single file COPY.
53A4
If the NZ FLAG is set (single file COPY), JUMP to 521EH to end the command with the error code on the stack.
53A7
SUB 1AH D6 1A
COPY by file: SUBtract 1AH from Register A (the error code).
53A9
CP 02H FE 02
Compare Register A against 02H: the CARRY FLAG for error 1AH (DIRECTORY SPACE FULL) or 1BH (DISKETTE SPACE FULL).
53AB
If the CARRY FLAG is set (the file does not fit), JUMP to 53B3H to give it an EOF of 0 and go on with the next file.
53AD
GOSUB to 5868H to display WITHIN FILE and the name of the destination file, in a COPY by file. 539DH comes here.
53B0
JUMP to 521EH to end the command with the error code on the stack.
53B3
GOSUB to 56DDH to read the destination file's directory entry (SYS0/SYS 48F0H with the FCB at Index Register IX). Register Pair HL returns pointing to the entry in 4300H. 53ABH comes here.
53B6
INC HL 23
INCrement Register Pair HL to byte 1 of the directory entry.
53B7
INC HL 23
INCrement Register Pair HL to byte 2 of the directory entry.
53B8
INC HL 23
INCrement Register Pair HL to byte 3, the low byte of the EOF.
53B9
XOR A AF
Set Register A to 00H (XOR A), the value for the three EOF bytes of the entry.
53BA
LD (HL),A 77
Store Register A (00H) at Register Pair HL: the EOF low byte becomes 0.
53BB
LD DE,0011H 11 11 00
Load Register Pair DE with 0011H, the distance from byte 3 to byte 20.
53BE
ADD HL,DE 19
ADD Register Pair DE (17) to Register Pair HL: byte 20 of the entry, the middle byte of the EOF.
53BF
LD (HL),A 77
Store Register A (00H) at Register Pair HL: the EOF middle byte becomes 0.
53C0
INC HL 23
INCrement Register Pair HL to byte 21, the high byte of the EOF.
53C1
LD (HL),A 77
Store Register A (00H) at Register Pair HL: the destination file's EOF is now 0. The space it already has is kept.
53C2
GOSUB to 5711H to write the directory sector in 4300H back (SYS0/SYS 48C4H) and mark no changed sector at 570EH.
53C5
POP HL E1
Discard the error code pushed at 5397H from the stack into Register Pair HL.
53C6
LD HL,5AD8H 21 D8 5A
Point Register Pair HL to 5AD8H, the message DISK FULL - .
53C9
GOSUB to 586FH to display the message at Register Pair HL followed by the destination file's name and a new line.
53CC
LD A,FFH 3E FF
Load Register A with FFH, the skip flag value meaning the sectors are not written.
53CE
LD (53D7H),A 32 D7 53
Store Register A (FFH) at 53D7H, the operand of the LD A,nn at 53D6H: the rest of this file's sectors are skipped.
53D1
POP HL E1
Restore Register Pair HL from the stack: the NEXT value pushed at 5370H (0). 5386H and 5395H come here.
53D2
LD (5B21H),HL 22 21 5B
Store Register Pair HL (0) at 5B21H as the destination FCB's NEXT: the file is written from its first sector.
53D5
POP HL E1
Restore Register Pair HL from the stack: the entry address pushed at 533EH. 5344H and 5365H come here.
53D6
LD A,00H 3E 00
Load Register A with the skip flag. Self-Modifying Code
The operand at 53D7H is 00H in the file; 5368H stores 00H for each new file and 53CEH stores FFH when the file did not fit.
53D8
OR A B7
OR Register A (the skip flag) with itself: the Z FLAG when the sector is to be written.
53D9
If the Z FLAG is set, JUMP to 53DFH to write it.
53DB
Skip it: GOSUB to 585EH to advance the destination FCB's NEXT past the sector. It returns Register A = 00H and the Z FLAG.
53DE
DEC A 3D
DECrement Register A (00H) to FFH: the NZ FLAG, so the CALL Z below is not made.
53DF
If the Z FLAG is set, GOSUB to 546DH to write the entry at Register Pair HL to the destination. It returns the Z FLAG if the sector was written, or the NZ FLAG with Register A = FFH if the operator chose P. 53D9H comes here.
53E2
INC HL 23
INCrement Register Pair HL to the entry's record type byte. INC HL does not change the flags.
53E3
If the Z FLAG is set (written), JUMP to 53E6H.
53E5
LD (HL),A 77
Not written: store Register A (FFH) as the record type at Register Pair HL, so that the verify pass skips the entry.
53E6
INC HL 23
INCrement Register Pair HL to the entry's data. 53E3H comes here.
53E7
INC H 24
INCrement Register H: Register Pair HL + 256 = the next entry.
53E8
GOSUB to 571BH to blink the progress asterisk at 3C3FH and check the pause and cancel keys.
53EB
LD A,00H 3E 00
Load Register A with the number of sectors written in this pass. Self-Modifying Code
The operand at 53ECH is 00H in the file; 533BH clears it, 53EEH counts up, and the verify pass counts it down at 545DH.
53ED
INC A 3C
INCrement Register A: one more sector in the pass (a skipped one counts too; the verify pass steps over it).
53EE
LD (53ECH),A 32 EC 53
Store Register A (the count of sectors in the pass) back at 53ECH.
53F1
LD A,(5314H) 3A 14 53
Fetch the number of entries left in the batch from 5314H into Register A.
53F4
DEC A 3D
DECrement Register A, the number of entries left in the batch.
53F5
LD (5314H),A 32 14 53
Store Register A (the entries left) back at 5314H.
53F8
If the NZ FLAG is set (more entries), JUMP to 533EH to write the next one. Otherwise fall into the verify pass with 5314H = 0.

53FBH - COPY Engine: Verify the Sectors Just Written

Reads back every sector written in this pass into the buffer at (5D10H) (4300H) and compares the record type and the 256 data bytes with the entry it was written from. A sector that does not match is reported with the C, R or P question: R on a read error or wrong record type writes the sector again and checks it again, R on a data mismatch reads it again.

53FB
LD A,(53ECH) 3A EC 53
Fetch the number of sectors written in this pass from 53ECH (the operand of the LD A,nn at 53EBH) into Register A. 5352H calls here; 53F8H falls in.
53FE
OR A B7
OR Register A (the count) with itself: the Z FLAG when no sector was written.
53FF
RET Z C8
If the Z FLAG is set (nothing to verify), RETurn to the caller.
5400
LD HL,0000H 21 00 00
Load Register Pair HL with the first destination sector of the pass. Self-Modifying Code
The operand at 5401H-5402H is 0000H in the file; 5336H stores the destination FCB's NEXT there at the start of the pass.
5403
LD (5B21H),HL 22 21 5B
Store Register Pair HL (the first sector of the pass) at 5B21H, setting the destination FCB's NEXT back to it.

Verify Loop: 544FH holds the entry being checked, 53ECH the sectors left.

5406
LD HL,(5D10H) 2A 10 5D
Fetch the verify buffer address from 5D10H (4300H) into Register Pair HL. 543EH, 545EH and 546BH come here.
5409
LD (5B1AH),HL 22 1A 5B
Store Register Pair HL (4300H) at 5B1AH, the destination FCB's buffer address (FCB+3), so the sector is read back into 4300H and not over the entry.
540C
LD A,20H 3E 20
Load Register A with 20H, the operation bit for VERIFYING DESTINATION.
540E
LD (57EBH),A 32 EB 57
Store Register A (20H) at 57EBH, the operand of the LD B,nn at 57EAH, so that an error report says VERIFYING DESTINATION.
5411
LD HL,(544FH) 2A 4F 54
Load Register Pair HL from 544FH, the operand of the LD HL,nnnn at 544EH: the entry being verified.
5414
INC HL 23
INCrement Register Pair HL to the entry's record type byte.
5415
LD A,(HL) 7E
Fetch the record type at Register Pair HL into Register A: 00H, 06H, or FFH for a sector that was not written.
5416
INC A 3C
INCrement Register A: the Z FLAG when the record type was FFH.
5417
If the Z FLAG is set (the sector was not written), GOSUB to 585EH to advance the destination FCB's NEXT past it. It returns the Z FLAG.
541A
If the Z FLAG is set (not written), JUMP to 544EH for the next entry.
541C
GOSUB to 57C8H to read the sector at the destination FCB's NEXT into 4300H (SYS0/SYS 4436H with Register Pair DE = Index Register IX = 5B17H). It returns the Z FLAG and Register A = 0, or the NZ FLAG with the error code.
541F
If the NZ FLAG is set (an error), JUMP to 5422H with the error code in Register A.
5421
XOR A AF
Read without error: set Register A to 00H, the record type read.
5422
If the Z FLAG is set (record type 00H), JUMP to 5428H. 541FH comes here.
5424
CP 06H FE 06
Compare Register A (the error code) against 06H: the sector has the directory mark, which is record type 06H.
5426
If the NZ FLAG is set (any other error), JUMP to 5430H to report it with Register A = the error code.
5428
CP (HL) BE
Compare Register A (the record type read: 00H or 06H) against the record type byte at Register Pair HL (the type the sector was written with). 5422H comes here.
5429
If the Z FLAG is set (the same type), JUMP to 5440H to compare the data.
542B
GOSUB to 5492H to step the destination FCB's NEXT back to this sector, which the read moved past.
542E
LD A,31H 3E 31
Load Register A with error code 31H (WRONG DISKETTE RECORD TYPE).
5430
DEC HL 2B
DECrement Register Pair HL back to the entry's marker byte, the start of the entry. 5426H comes here.
5431
GOSUB to 585AH to report the error in Register A (VERIFYING DESTINATION SECTOR n) and ask C, R or P. It returns the NZ FLAG for R, or the Z FLAG for P after moving NEXT past the sector.
5434
If the Z FLAG is set (P), JUMP to 544EH for the next entry.
5436
R: GOSUB to 546DH to write the entry at Register Pair HL to the sector again. It returns the Z FLAG if it was written.
5439
If the NZ FLAG is set (the operator chose P on the write error), JUMP to 544EH for the next entry.
543B
GOSUB to 5492H to step the destination FCB's NEXT back to the sector just written.
543E
LOOP BACK to 5406H to read the sector back and verify it again.
5440
LD B,00H 06 00
Load Register B with 00H: 256 bytes to compare (DJNZ counts down from 0). 5429H comes here.
5442
LD DE,(5D10H) ED 5B 10 5D
Point Register Pair DE to the sector just read, at the address fetched from 5D10H (4300H).

Compare Loop: Register Pair HL walks the entry's copy, Register Pair DE the sector read back, Register B counts.

5446
INC HL 23
INCrement Register Pair HL to the next byte of the entry (the first pass moves it from the record type byte to the first data byte). 544CH comes here.
5447
LD A,(DE) 1A
Fetch the byte read back at Register Pair DE into Register A.
5448
CP (HL) BE
Compare Register A (the byte read back) against the byte written, at Register Pair HL.
5449
INC DE 13
INCrement Register Pair DE to the next byte read back. INC DE does not change the flags.
544A
If the NZ FLAG is set (different), JUMP to 5461H to report DATA COMPARE MISMATCH.
544C
DECrement Register B and LOOP BACK to 5446H until all 256 bytes have been compared.
544E
LD HL,0000H 21 00 00
Load Register Pair HL with the address of the entry just verified. Self-Modifying Code
The operand at 544FH-5450H is 0000H in the file; 532FH stores the first entry of the pass there and 5454H advances it. 541AH, 5434H, 5439H and 5469H come here.
5451
INC HL 23
INCrement Register Pair HL past the entry's marker byte.
5452
INC HL 23
INCrement Register Pair HL past the record type byte.
5453
INC H 24
INCrement Register H: Register Pair HL + 256 = the next entry.
5454
LD (544FH),HL 22 4F 54
Store Register Pair HL (the next entry) at 544FH.
5457
GOSUB to 571BH to blink the progress asterisk and check the pause and cancel keys.
545A
LD HL,53ECH 21 EC 53
Point Register Pair HL to 53ECH, the count of sectors in this pass.
545D
DEC (HL) 35
DECrement the count at Register Pair HL (53ECH).
545E
If the NZ FLAG is set (more sectors to verify), LOOP BACK to 5406H.
5460
RET C9
RETurn to the caller with the count at 53ECH back to 0.
5461
GOSUB to 5492H to step the destination FCB's NEXT back to the sector that did not match. 544AH comes here.
5464
LD A,3AH 3E 3A
Load Register A with error code 3AH (DATA COMPARE MISMATCH).
5466
GOSUB to 585AH to report the error in Register A and ask C, R or P.
5469
If the Z FLAG is set (P, NEXT moved past the sector), JUMP to 544EH for the next entry.
546B
R: JUMP to 5406H to read the same sector back and compare it again (it is not written again).

546DH - Write One Sector from a Buffer Entry

Entered with Register Pair HL pointing to an entry (marker byte, record type byte, 256 data bytes) and Index Register IX to the destination FCB. The sector is written at the FCB's NEXT, with the directory mark if its record type is 06H. On a write error C, R or P is asked. Returns the Z FLAG if the sector was written, or the NZ FLAG and Register A = FFH for P. Register Pair HL is kept.

546D
PUSH HL E5
Save Register Pair HL (the entry address) onto the stack. 53DFH, 5436H and 548DH come here.
546E
INC HL 23
INCrement Register Pair HL to the entry's record type byte.
546F
LD A,(HL) 7E
Fetch the record type at Register Pair HL into Register A.
5470
CP 06H FE 06
Compare Register A (the record type) against 06H, the type of a sector with the directory mark.
5472
INC HL 23
INCrement Register Pair HL to the entry's 256 data bytes. INC HL does not change the flags.
5473
If the NZ FLAG is set (a normal sector), JUMP to 5479H.
5475
SET 0,(IX+00H) DD CB 00 C6
Set bit 0 of (IX+00H), the first byte of the destination FCB (Index Register IX = 5B17H): SYS0/SYS writes the sector with the directory mark.
5479
GOSUB to 5C8EH to make the data at Register Pair HL the destination FCB's buffer (5B1AH) and set bit 6 of its second byte, so that the EOF moves only when a write goes past it. 5473H comes here.
547C
LD A,40H 3E 40
Load Register A with 40H, the operation bit for WRITING DESTINATION.
547E
LD (57EBH),A 32 EB 57
Store Register A (40H) at 57EBH, the operand of the LD B,nn at 57EAH, so that an error report says WRITING DESTINATION.
5481
GOSUB to 57CEH to write the sector at the destination FCB's NEXT (through 5CEDH and SYS0/SYS 4439H). It returns the Z FLAG, or the NZ FLAG with the error code in Register A.
5484
RES 0,(IX+00H) DD CB 00 86
Clear bit 0 of (IX+00H), the first byte of the destination FCB (Index Register IX = 5B17H), again. RES does not change the flags.
5488
POP HL E1
Restore Register Pair HL from the stack: the entry address.
5489
RET Z C8
If the Z FLAG is set (written), RETurn with the Z FLAG.
548A
GOSUB to 585AH to report the error in Register A (WRITING DESTINATION SECTOR n) and ask C, R or P.
548D
If the NZ FLAG is set (R), LOOP BACK to 546DH to write it again.
548F
OR FFH F6 FF
P: OR Register A with FFH, giving Register A = FFH and the NZ FLAG: the sector was not written.
5491
RET C9
RETurn with the NZ FLAG and Register A = FFH.

5492H - Step the Destination NEXT Back One Sector

DECrements the destination FCB's NEXT (5B21H), which the last read or write moved on. Register Pair HL is kept.

5492
PUSH HL E5
Save Register Pair HL (the caller's entry pointer) onto the stack. 542BH, 543BH and 5461H call here.
5493
LD HL,(5B21H) 2A 21 5B
Fetch the destination FCB's NEXT from 5B21H into Register Pair HL.
5496
DEC HL 2B
DECrement Register Pair HL: back to the sector just read or written.
5497
LD (5B21H),HL 22 21 5B
Store Register Pair HL (the new NEXT) back at 5B21H.
549A
POP HL E1
Restore Register Pair HL from the stack: the caller's entry pointer.
549B
RET C9
RETurn to the caller with Register Pair HL unchanged.

549CH - COPY Engine: End of the Source

Reached from 52C4H when the source file, the last file to copy, or the source diskette has ended. The last batch is written and verified, then each kind of COPY finishes in its own way: a COPY by file displays DONE, a single file COPY closes the destination file with the source's EOF, and a diskette COPY continues in SYS17/SYS.

549C
POP HL E1
Discard the entry address pushed at 529DH from the stack into Register Pair HL. 52C4H comes here.
549D
GOSUB to 5324H to write and verify the last batch.
54A0
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
54A3
BIT 3,A CB 5F
Test bit 3 of Register A (the 5996H flags): CBF, a COPY by file.
54A5
If the NZ FLAG is set (a COPY by file), JUMP to 552DH to display DONE and end the command.
54A8
BIT 2,A CB 57
Test bit 2 of Register A (5996H): a single file COPY.
54AA
If the Z FLAG is set (a diskette COPY), JUMP to 54D4H.
54AC
LD A,05H 3E 05
Single file COPY: load Register A with 05H, the number of SYS3/SYS (the overlay that closes files).
54AE
GOSUB to 568DH to switch to the system diskette and load the overlay number in Register A (SYS3/SYS) into 4D00H-51FFH, so that the close below does not need the system diskette.
54B1
GOSUB to 5535H to switch back to the destination diskette (Index Register IX = the destination FCB at 5B17H).
54B4
LD HL,(5AF1H) 2A F1 5A
Fetch the source FCB's EOF sector count from 5AF1H (FCB+12) into Register Pair HL.
54B7
LD (5B23H),HL 22 23 5B
Store Register Pair HL (the source file's EOF sectors) at 5B23H, the destination FCB's EOF (FCB+12).
54BA
LD A,(5AEDH) 3A ED 5A
Fetch the source FCB's EOF byte offset from 5AEDH (FCB+8) into Register A.
54BD
LD (5B1FH),A 32 1F 5B
Store Register A (the EOF byte offset) at 5B1FH, the destination FCB's EOF byte (FCB+8). The copy now has exactly the source's length.
54C0
LD DE,5B17H 11 17 5B
Point Register Pair DE to 5B17H, the destination FCB.
54C3
GOSUB to 4428H (SYS0/SYS) to close the destination file at Register Pair DE, which writes its EOF into the directory (through SYS3/SYS). It returns the Z FLAG, or the NZ FLAG with the error code in Register A.
54C6
LD HL,4288H 21 88 42
Point Register Pair HL to 4288H, the number of the overlay in 4D00H-51FFH.
54C9
LD (HL),05H 36 05
Store 05H (SYS3/SYS) at Register Pair HL (4288H). SYS3/SYS's close clears 4288H; with 05H there the patch exchange in 5585H, run again by the exit, finds SYS3/SYS resident and takes out any SYS3/SYS patches put in for a TI flag M diskette instead of reporting error 33H. LD does not change the flags.
54CB
If the NZ FLAG is set (the close failed), JUMP to 521AH to end the command with the error code in Register A. SYS17/SYS's end of a diskette COPY jumps here too.
54CE
LD HL,402DH 21 2D 40
Point Register Pair HL to 402DH, the SYS0/SYS exit for a command that ended without an error. 5533H comes here.
54D1
JUMP to 5222H with Register Pair HL = 402DH, the exit to use.
54D4
Diskette COPY: JUMP to 502CH in SYS17/SYS, which 62ADH loaded into the overlay area, to verify the destination and bring its GAT up to date. SYS17/SYS ends through 552DH or 54CBH.

54D7H - Unreachable Remains of the Diskette COPY Ending

Nothing jumps or calls to 54D7H and the JP at 54D4H does not return, so 54D7H-552CH never run. They are an earlier form of the code that SYS17/SYS runs from its 502FH on (its first instructions are the same bytes): verify the destination, copy the name, date and password into the GAT and free the granules a larger destination has beyond the copied area.

54D7
LD DE,(59C1H) ED 5B C1 59
Fetch the source's sector count from 59C1H into Register Pair DE, the first sector to verify. Never runs.
54DB
GOSUB to 5784H to verify the destination diskette from sector Register Pair DE to its end. Never runs.
54DE
LD BC,(5994H) ED 4B 94 59
Fetch the option flags from 5994H-5995H into Register Pair BC: Register C = the 5994H flags, Register B = the 5995H flags. Never runs.
54E2
BIT 1,C CB 49
Test bit 1 of Register C (the 5994H flags): BDU, the system data is bypassed. Never runs.
54E4
If the NZ FLAG is set (BDU), JUMP to 552DH to display DONE and end. Never runs.
54E6
GOSUB to 56F9H to read the GAT (directory sector 0) of the destination into 4300H. Never runs.
54E9
BIT 5,B CB 68
Test bit 5 of Register B (the 5995H flags): NDPW, a new destination password was given. Never runs.
54EB
If the Z FLAG is set (no NDPW), JUMP to 54F3H. Never runs.
54ED
LD HL,(5981H) 2A 81 59
Fetch the new password code from 5981H into Register Pair HL. Never runs.
54F0
LD (43CEH),HL 22 CE 43
Store Register Pair HL (the password code) at 43CEH-43CFH, bytes CEH-CFH of the GAT in 4300H. Never runs.
54F3
LD A,C 79
Copy Register C (the 5994H option flags) into Register A. 54EBH comes here. Never runs.
54F4
AND 0CH E6 0C
AND Register A with 0CH, keeping bits 2 (NDN) and 3 (KDN) of the 5994H flags. Never runs.
54F6
LD BC,0010H 01 10 00
Load Register Pair BC with 0010H: 16 bytes, the diskette name and date. Never runs.
54F9
LD DE,43D0H 11 D0 43
Point Register Pair DE to 43D0H, the name field (bytes D0H-D7H) of the GAT sector in 4300H. Never runs.
54FC
LD HL,5983H 21 83 59
Point Register Pair HL to 5983H, the diskette name followed by the date at 598BH. Never runs.
54FF
If the NZ FLAG is set (NDN or KDN), JUMP to 5508H to copy name and date. Never runs.
5501
LD HL,598BH 21 8B 59
Point Register Pair HL to 598BH, the diskette date only. Never runs.
5504
LD E,D8H 1E D8
Load Register E with D8H: Register Pair DE = 43D8H, the date field of the GAT. Never runs.
5506
LD C,08H 0E 08
Load Register C with 08H: Register Pair BC = 0008H, the date only. Never runs.
5508
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL to Register Pair DE (into the GAT). Never runs.
550A
LD HL,(59D1H) 2A D1 59
Fetch the destination's granule count from 59D1H into Register Pair HL. Never runs.
550D
LD DE,(59C3H) ED 5B C3 59
Fetch the source's granule count from 59C3H into Register Pair DE. Never runs.
5511
OR A B7
OR Register A with itself, clearing the CARRY FLAG. Never runs.
5512
SBC HL,DE ED 52
SUBtract Register Pair DE (source granules) from Register Pair HL (destination granules). Never runs.
5514
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the extra granules on the destination. Never runs.
5515
If the CARRY FLAG is set (the destination is smaller), JUMP to 5528H. Never runs.
5517
If the Z FLAG is set (the same size), JUMP to 5528H. Never runs.
5519
LD HL,(59C3H) 2A C3 59
Fetch the source's granule count from 59C3H into Register Pair HL, the first granule past the copied area. Never runs.
551C
LD A,(59BCH) 3A BC 59
Fetch the source's granules per lump from 59BCH (byte +5 of the working record at 59B7H) into Register A. Never runs.
551F
GOSUB to 4C59H (SYS0/SYS) to divide Register Pair HL by Register A: Register Pair HL = the lump, Register A = the granule in it. Never runs.
5522
LD H,43H 26 43
Load Register H with 43H: Register Pair HL = 4300H + the lump, its byte in the GAT. Never runs.
5524
LD C,A 4F
Copy Register A (the granule in the lump) into Register C. Never runs.
5525
GOSUB to 5762H to free Register Pair DE granules in the GAT at Register Pair HL from granule Register C on. Never runs.
5528
GOSUB to 48C4H (SYS0/SYS) to write the GAT sector in 4300H back. Never runs.
552B
If the NZ FLAG is set (a write error), JUMP to 54CBH. Never runs.

552DH - Display DONE and Exit

Reached when a COPY by file or a FORMAT has finished, and from SYS17/SYS (508CH) at the end of a diskette COPY.

552D
LD HL,5A1FH 21 1F 5A
Point Register Pair HL to 5A1FH, the message DONE followed by a carriage return. 5270H, 54A5H and 5EB9H jump here; 663CH-6642H reach it as FORMAT's return address.
5530
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL (DONE).
5533
JUMP to 54CEH to end the command through the SYS0/SYS exit 402DH (no error).

5535H - Switch to a Diskette and Open Its FCB

Enter at 5535H for the destination, or at 5538H with Register Pair HL pointing to a diskette control block. A control block is 10 bytes: +0 the drive number (FFH = not used), +1 the role bit (01H system, 02H source, 04H destination), +2/+3 the FCB address, +4/+5 the address of the working PDRIVE record, +6/+7 the address of the saved original record, +8/+9 the address of the diskette's name for the mount prompt. The diskette is switched in (5585H), Index Register IX is pointed to its FCB, and the FCB is opened if it is not open yet. An open sets the control block's drive number to the drive the file was found on.

5535
LD HL,5956H 21 56 59
Point Register Pair HL to 5956H, the destination diskette's control block. 5324H and 54B1H call here.
5538
GOSUB to 5585H to switch to the diskette of the control block at Register Pair HL (mounting it if needed, installing its PDRIVE data and exchanging the TI flag M patches). Register Pair HL is kept. 5294H and 647FH call here.
553B
INC HL 23
INCrement Register Pair HL to the control block's role bit (+1).
553C
INC HL 23
INCrement Register Pair HL to the low byte of the FCB address (+2).
553D
LD E,(HL) 5E
Load Register E with the low byte of the FCB address at Register Pair HL.
553E
INC HL 23
INCrement Register Pair HL to the high byte of the FCB address (+3).
553F
LD D,(HL) 56
Load Register D with the high byte of the FCB address at Register Pair HL: Register Pair DE = the FCB (5AE5H source, 5B17H destination).
5540
PUSH DE D5
Save Register Pair DE (the FCB address) onto the stack.
5541
POP IX DD E1
Restore the FCB address from the stack into Index Register IX.
5543
LD A,(DE) 1A
Fetch the FCB's first byte at Register Pair DE into Register A.
5544
BIT 7,A CB 7F
Test bit 7 of Register A (FCB+0): the FCB is open. The FCBs of a diskette COPY are open as loaded (82H).
5546
RET NZ C0
If the NZ FLAG is set (already open), RETurn with Index Register IX = the FCB.
5547
LD B,00H 06 00
Load Register B with 00H, the record length for the open (0 = 256-byte records: the file is read and written in whole sectors).
5549
LD A,17H 3E 17
Load Register A with 17H, the low byte of the destination FCB's address 5B17H.
554B
CP E BB
Compare Register A (17H) against Register E (the low byte of this FCB's address).
554C
If the Z FLAG is set (the destination FCB), JUMP to 5556H.
554E
GOSUB to 4424H (SYS0/SYS) to open the existing source file whose filespec is in the FCB at Register Pair DE. Register Pair HL (the control block +3) is passed as the buffer address, which is never used: 52A0H sets the buffer before every read. It returns the Z FLAG, or the NZ FLAG with the error code in Register A.
5551
If the Z FLAG is set (opened), JUMP to 5570H.
5553
JUMP to 521AH to end the command with the error code in Register A. 5559H comes here.
5556
GOSUB to 4420H (SYS0/SYS) to open the destination file in the FCB at Register Pair DE, creating it if it does not exist. The buffer address in Register Pair HL is not used (5C8EH sets it before every write). 554CH comes here.
5559
If the NZ FLAG is set (an error), JUMP to 5553H.
555B
LD DE,(5AEBH) ED 5B EB 5A
Fetch the source FCB's drive and DEC from 5AEBH (FCB+6, FCB+7) into Register Pair DE: Register E = the drive, Register D = the DEC.
555F
LD HL,(5B1DH) 2A 1D 5B
Fetch the destination FCB's drive and DEC from 5B1DH (FCB+6, FCB+7) into Register Pair HL.
5562
RST 18H DF
RST 18H, the ROM routine that compares Register Pair HL with Register Pair DE: the Z FLAG when both FCBs name the same directory entry on the same drive.
5563
If the NZ FLAG is set (different files), JUMP to 5570H.
5565
LD HL,5A24H 21 24 5A
Point Register Pair HL to 5A24H, the message SOURCE & DEST SAME FILE.
5568
LD A,(5940H) 3A 40 59
Fetch the swap set from 5940H into Register A.
556B
CP 06H FE 06
Compare Register A (the swap set) against 06H: the CARRY FLAG unless the source and destination diskettes are swapped in one drive (bits 1 and 2), where the same entry on the same drive is on two different diskettes.
556D
If the CARRY FLAG is set (it really is the same file), JUMP to 5243H to display the message at Register Pair HL and end the command.
5570
LD HL,(593EH) 2A 3E 59
Fetch the address of the current control block from 593EH into Register Pair HL (stored by 5585H). 5551H and 5563H come here.
5573
LD A,(IX+06H) DD 7E 06
Fetch the drive number from (IX+06H), byte 6 of the FCB at Index Register IX, into Register A: the drive the open found the file on (a filespec without a drive number is searched for on every drive).
5576
LD (HL),A 77
Store Register A (the drive) at Register Pair HL, as the control block's drive number (+0).
5577
RET C9
RETurn with Index Register IX = the open FCB.

5578H - Switch to the Source, Destination or System Diskette

5578H selects the source (594CH), 557DH the destination (5956H), 5582H the system diskette (5942H) and 5585H the control block at Register Pair HL. The drive gets the PDRIVE data needed for that diskette (once 63BDH has saved the drives' own data), the diskette is asked for if another one shares its drive, and the TI flag M patches in SYS0/SYS, SYS2/SYS and SYS3/SYS are put in or taken out to match the diskette now in use. Register Pairs HL, DE and BC are kept.

5578
LD HL,594CH 21 4C 59
Point Register Pair HL to 594CH, the source diskette's control block. 5269H, 5D86H, 5E0CH, 5EC5H, 60C8H and 62B0H call here.
557B
JUMP to 5585H with Register Pair HL = 594CH, the source control block.
557D
LD HL,5956H 21 56 59
Point Register Pair HL to 5956H, the destination diskette's control block. 5EE4H, 60F5H and 67CCH call here.
5580
JUMP to 5585H with Register Pair HL = 5956H, the destination control block.
5582
LD HL,5942H 21 42 59
Point Register Pair HL to 5942H, the system diskette's control block. 5224H, 5690H and 5833H call here.
5585
LD (593EH),HL 22 3E 59
Store Register Pair HL (the control block) at 593EH as the current one. 5538H, 557BH, 5580H and 5842H come here.
5588
LD A,FFH 3E FF
Load Register A with FFH, the value meaning no directory sector is held.
558A
LD (48D5H),A 32 D5 48
Store Register A (FFH) at 48D5H, the SYS0/SYS variable holding the number of the directory sector in 4300H: no sector is held, so SYS0/SYS reads the directory again from the diskette being switched in.
558D
LD A,(HL) 7E
Fetch the control block's drive number at Register Pair HL (+0) into Register A.
558E
INC A 3C
INCrement Register A: the Z FLAG when the drive number is FFH.
558F
RET Z C8
If the Z FLAG is set (no drive for this diskette), RETurn with nothing changed.
5590
PUSH HL E5
Save Register Pair HL (the control block) onto the stack.
5591
PUSH DE D5
Save Register Pair DE (the caller's value) onto the stack; it is restored at 5643H.
5592
PUSH BC C5
Save Register Pair BC (the caller's value) onto the stack; it is restored at 5642H.
5593
LD A,(593BH) 3A 3B 59
Fetch the SYS6/SYS flags from 593BH into Register A.
5596
BIT 7,A CB 7F
Test bit 7 of Register A (593BH): 63BDH has saved the drives' PDRIVE data, and each diskette's own data is installed when it is switched in.
5598
LD B,00H 06 00
Load Register B with 00H, the mode for 5658H: bit 0 clear = the working record (control block +4), bit 1 clear = copy it into the drive's PDRIVE entry, bit 2 clear = stop on an error. LD does not change the flags.
559A
If the NZ FLAG is set, GOSUB to 5658H to copy this diskette's working PDRIVE record into its drive's PDRIVE entry and reselect the drive. Register Pair HL is kept.
559D
LD C,(HL) 4E
Load Register C with the drive number at Register Pair HL (control block +0).
559E
INC HL 23
INCrement Register Pair HL to the role bit (+1).
559F
LD B,(HL) 46
Load Register B with the role bit at Register Pair HL: 01H system, 02H source, 04H destination.
55A0
LD DE,0007H 11 07 00
Load Register Pair DE with 0007H, the distance from +1 to the name address at +8.
55A3
ADD HL,DE 19
ADD Register Pair DE (7) to Register Pair HL (+1): the control block's name address (+8).
55A4
LD E,(HL) 5E
Load Register E with the low byte of the name address at Register Pair HL.
55A5
INC HL 23
INCrement Register Pair HL to the high byte (+9).
55A6
LD D,(HL) 56
Load Register D with the high byte at Register Pair HL: Register Pair DE = the diskette's name (5A51H for the system diskette, 5A3CH SOURCE, 5A44H DESTINATION).
55A7
LD HL,5940H 21 40 59
Point Register Pair HL to 5940H, the swap set.
55AA
LD A,(HL) 7E
Fetch the swap set at Register Pair HL (5940H) into Register A.
55AB
AND B A0
AND Register A (the swap set) with Register B (the role bit): the Z FLAG when this diskette does not share its drive with another.
55AC
LD A,(HL) 7E
Fetch the swap set at Register Pair HL into Register A again. LD does not change the flags.
55AD
INC HL 23
INCrement Register Pair HL to 5941H, the mounted set. INC HL does not change the flags.
55AE
If the Z FLAG is set (this diskette is not swapped), JUMP to 55B5H.
55B0
XOR B A8
XOR Register B (the role bit) into Register A (the swap set): the other diskettes that share the drive.
55B1
XOR FFH EE FF
XOR Register A with FFH: every bit set except those of the other swapped diskettes.
55B3
AND (HL) A6
AND Register A with the mounted set at Register Pair HL (5941H): the other diskettes in this drive are no longer counted as mounted.
55B4
LD (HL),A 77
Store Register A (the mounted set) back at Register Pair HL (5941H).
55B5
LD A,C 79
Copy Register C (the drive number) into Register A. 55AEH comes here.
55B6
GOSUB to 4723H (SYS0/SYS) to select the drive in Register A. It returns the NZ FLAG with error 20H if the drive is not available.
55B9
If the NZ FLAG is set, JUMP to 521AH to end the command with the error code in Register A.
55BC
PUSH HL E5
Save Register Pair HL (5941H, the mounted set) onto the stack.
55BD
LD A,(HL) 7E
Fetch the mounted set at Register Pair HL (5941H) into Register A.
55BE
AND B A0
AND Register A (the mounted set) with Register B (the role bit): the NZ FLAG when this diskette is known to be in its drive.
55BF
If the NZ FLAG is set (mounted), JUMP to 55ECH to check that a diskette is there.

Mount Prompt Loop: PRESS "ENTER" WHEN name DISKETTE MOUNTED IN DRIVE n, until ENTER is pressed and a diskette turns in the drive.

55C1
LD HL,59EEH 21 EE 59
Point Register Pair HL to 59EEH, the message PRESS "ENTER" WHEN . 55F0H comes here.
55C4
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
55C7
LD H,D 62
Copy Register D (the high byte of the diskette's name address) into Register H.
55C8
LD L,E 6B
Copy Register E (the low byte) into Register L: Register Pair HL = the diskette's name.
55C9
GOSUB to 4467H (SYS0/SYS) to display the diskette's name at Register Pair HL.
55CC
LD A,C 79
Copy Register C (the drive number) into Register A.
55CD
ADD A,30H C6 30
ADD 30H to Register A: the ASCII digit of the drive number.
55CF
LD (5A1DH),A 32 1D 5A
Store Register A (the drive digit) at 5A1DH, the last character of the message at 5A02H.
55D2
LD HL,5A02H 21 02 5A
Point Register Pair HL to 5A02H, the message DISKETTE MOUNTED IN DRIVE n.
55D5
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
55D8
PUSH BC C5
Save Register Pair BC (Register C = the drive, Register B = the role bit) onto the stack.
55D9
LD BC,8000H 01 00 80
Load Register Pair BC with 8000H, the count for the delay routine.
55DC
PUSH DE D5
Save Register Pair DE (the name address) onto the stack.
55DD
GOSUB to 4C92H (SYS0/SYS), which calls the ROM delay at 0060H with Register Pair BC = 8000H, so that a key still held from before is not taken as the reply.
55E0
POP DE D1
Restore Register Pair DE from the stack: the name address.
55E1
POP BC C1
Restore Register Pair BC from the stack: Register C = the drive, Register B = the role bit.
55E2
GOSUB to 572BH to read a key into Register A (00H if none, letters in upper case); it also handles the right arrow pause and up arrow cancel. 55E7H comes here.
55E5
CP 0DH FE 0D
Compare Register A (the key) against 0DH, ENTER.
55E7
If the NZ FLAG is set (not ENTER), LOOP BACK to 55E2H.
55E9
GOSUB to 5881H to start a new line on the display.
55EC
LD A,C 79
Copy Register C (the drive number) into Register A. 55BFH comes here.
55ED
GOSUB to 4791H (SYS0/SYS) to select the drive in Register A and wait for the index hole to pass. It returns the NZ FLAG (error 08H) when no diskette turns in the drive.
55F0
If the NZ FLAG is set (no diskette), JUMP to 55C1H to ask again.
55F2
POP HL E1
Restore Register Pair HL from the stack: 5941H, the mounted set.
55F3
LD A,(HL) 7E
Fetch the mounted set at Register Pair HL into Register A.
55F4
OR B B0
OR Register B (the role bit) into Register A: this diskette is now mounted.
55F5
LD (HL),A 77
Store Register A (the mounted set) back at Register Pair HL (5941H).
55F6
LD HL,5B57H 21 57 5B
Point Register Pair HL to 5B57H, the first TI flag M patch set record (the SYS0/SYS set).
55F9
JUMP to 563BH to read the first record's overlay number.

Patch Set Loop. Each record at 5B57H is four bytes: the overlay the patches belong to (02H SYS0/SYS, 04H SYS2/SYS, 05H SYS3/SYS, the numbers kept at 4288H), a flag byte whose bit 5 shows that the patches are in, and the address of the patch list. The patches are exchanged with the bytes they replace, so doing it again takes them out. They must be in exactly while the current drive's PDRIVE flags have TI flag M (bit 5 of 4282H). Register Pair HL points to the record's flag byte, Register C holds its overlay number and the Z FLAG is set for SYS0/SYS.

55FB
PUSH HL E5
Save Register Pair HL (the record's flag byte) onto the stack. 5640H comes here.
55FC
If the Z FLAG is set (the SYS0/SYS record: SYS0/SYS is always resident), JUMP to 560DH.
55FE
LD A,(4288H) 3A 88 42
Fetch the number of the overlay now in 4D00H-51FFH from 4288H into Register A.
5601
CP C B9
Compare Register A (the resident overlay) against Register C (the record's overlay).
5602
If the Z FLAG is set (that overlay is resident), JUMP to 560DH to bring its patches up to date.
5604
BIT 5,(HL) CB 6E
Test bit 5 of the record's flag byte at Register Pair HL: its patches are in.
5606
If the Z FLAG is set (the overlay is not resident and has no patches in), JUMP to 5637H.
5608
LD A,33H 3E 33
The patches are in but another overlay has replaced the one they were put into, so they can no longer be taken out: load Register A with error code 33H (DOS FATAL ERROR). 5F67H also jumps here.
560A
JUMP to 521AH to end the command with the error code in Register A (33H).
560D
LD A,(4282H) 3A 82 42
Fetch the current drive's PDRIVE flags from 4282H into Register A. 55FCH and 5602H come here.
5610
XOR (HL) AE
XOR the record's flag byte at Register Pair HL into Register A.
5611
AND 20H E6 20
AND Register A with 20H, keeping bit 5: set when the drive's TI flag M and the record's patches-in bit differ.
5613
If the Z FLAG is set (the patches already match the diskette), JUMP to 5637H.
5615
XOR (HL) AE
XOR the flag byte at Register Pair HL into Register A (20H): the flag byte with bit 5 flipped.
5616
LD (HL),A 77
Store Register A (the new flag byte) at Register Pair HL.
5617
INC HL 23
INCrement Register Pair HL to the low byte of the patch list address.
5618
LD A,(HL) 7E
Fetch the low byte of the patch list address at Register Pair HL into Register A.
5619
INC HL 23
INCrement Register Pair HL to the high byte of the patch list address.
561A
LD H,(HL) 66
Load Register H with the high byte of the patch list address at Register Pair HL.
561B
LD L,A 6F
Copy Register A (the low byte) into Register L: Register Pair HL = the patch list.
561C
JUMP to 562FH to read the first entry's address.

Patch List Loop: each entry is the address to patch (2 bytes, 0000H ends the list), a byte count and the bytes. Register Pair HL walks the list, Register Pair DE the memory patched, Register B counts.

561E
LD A,(HL) 7E
Fetch the entry's byte count at Register Pair HL into Register A. 5635H comes here.
561F
OR A B7
OR Register A (the count) with itself: the Z FLAG for a count of 0.
5620
LD B,A 47
Copy Register A (the count) into Register B. LD does not change the flags.
5621
INC HL 23
INCrement Register Pair HL to the entry's first patch byte.
5622
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the address to patch, Register Pair DE = the patch bytes.
5623
If the Z FLAG is set (a count of 0), JUMP to 562FH. No entry in the lists at 5B64H-5C09H has a count of 0, so this jump is never taken.
5625
EX DE,HL EB
Exchange Register Pairs DE and HL back: Register Pair HL = the patch bytes, Register Pair DE = the address to patch.
5626
LD C,(HL) 4E
Load Register C with the patch byte at Register Pair HL. 562DH comes here.
5627
LD A,(DE) 1A
Fetch the byte in memory at Register Pair DE into Register A.
5628
LD (HL),A 77
Store Register A (the memory byte) into the list at Register Pair HL.
5629
LD A,C 79
Copy Register C (the patch byte) into Register A.
562A
LD (DE),A 12
Store Register A (the patch byte) into memory at Register Pair DE: the two bytes are exchanged.
562B
INC HL 23
INCrement Register Pair HL to the next byte of the list.
562C
INC DE 13
INCrement Register Pair DE to the next byte of memory.
562D
DECrement Register B (the bytes left) and LOOP BACK to 5626H.
562F
LD E,(HL) 5E
Fetch the low byte of the next address to patch at Register Pair HL into Register E. 561CH comes here.
5630
INC HL 23
INCrement Register Pair HL to the high byte of the address to patch.
5631
LD D,(HL) 56
Load Register D with the high byte at Register Pair HL: Register Pair DE = the address to patch.
5632
INC HL 23
INCrement Register Pair HL to the entry's byte count.
5633
LD A,D 7A
Copy Register D (the high byte of the address) into Register A.
5634
OR E B3
OR Register E (the low byte) into Register A: the Z FLAG for 0000H, the end of the list.
5635
If the NZ FLAG is set (another entry), LOOP BACK to 561EH.
5637
POP HL E1
Restore Register Pair HL from the stack: the record's flag byte. 5606H and 5613H come here.
5638
INC HL 23
INCrement Register Pair HL to the low byte of the list address.
5639
INC HL 23
INCrement Register Pair HL to the high byte of the list address.
563A
INC HL 23
INCrement Register Pair HL to the next record's overlay byte.
563B
LD A,(HL) 7E
Fetch the record's overlay number at Register Pair HL into Register A. 55F9H comes here.
563C
CP 02H FE 02
Compare Register A (the overlay number) against 02H: the Z FLAG for SYS0/SYS, the CARRY FLAG for 00H (the end of the records at 5B63H).
563E
LD C,A 4F
Copy Register A (the overlay number) into Register C. LD does not change the flags.
563F
INC HL 23
INCrement Register Pair HL to the record's flag byte. INC HL does not change the flags.
5640
If the NO CARRY FLAG is set (a record), LOOP BACK to 55FBH.
5642
POP BC C1
Restore Register Pair BC from the stack: the caller's value saved at 5592H.
5643
POP DE D1
Restore Register Pair DE from the stack: the caller's value saved at 5591H.
5644
POP HL E1
Restore Register Pair HL from the stack: the control block.
5645
RET C9
RETurn with the diskette switched in and Register Pairs HL, DE and BC as they were.

5646H - Save or Restore the PDRIVE Data of All Three Diskettes

5646H calls 5658H for the system, source and destination control blocks that have a drive, with Register B unchanged. 5658H works on the control block at Register Pair HL, with Register B saying what to do: bit 0 clear = the working record (control block +4), set = the saved original (+6); bit 1 clear = copy that record into the drive's PDRIVE entry, set = copy the drive's entry into it; bit 2 set = ignore errors. After the copy SYS0/SYS reselects the drive so that 4280H-4287H follow the entry.

5646
LD HL,5942H 21 42 59
Point Register Pair HL to 5942H, the system diskette's control block. 5230H, 63B5H and 63BFH call here.
5649
LD C,03H 0E 03
Load Register C with 03H: three control blocks, 5942H, 594CH and 5956H.

Control Block Loop: Register Pair HL is the control block, Register C counts.

564B
LD A,(HL) 7E
Fetch the control block's drive number at Register Pair HL into Register A. 5655H comes here.
564C
INC A 3C
INCrement Register A: the Z FLAG when the drive number is FFH (not used).
564D
If the NZ FLAG is set (a drive), GOSUB to 5658H to copy the record as Register B says. Register Pairs HL and DE are kept.
5650
LD DE,000AH 11 0A 00
Load Register Pair DE with 000AH, the size of a control block.
5653
ADD HL,DE 19
ADD Register Pair DE (10) to Register Pair HL: the next control block.
5654
DEC C 0D
DECrement Register C, the control blocks left.
5655
If the NZ FLAG is set (more), LOOP BACK to 564BH.
5657
RET C9
RETurn with the Z FLAG set (from the DEC C that reached 0) and Register Pair HL past the last control block.
5658
LD A,(HL) 7E
Fetch the control block's drive number at Register Pair HL into Register A. 559AH and 564DH call here.
5659
PUSH HL E5
Save Register Pair HL (the control block) onto the stack.
565A
PUSH DE D5
Save Register Pair DE (the caller's value) onto the stack; it is restored at 5681H.
565B
GOSUB to 4723H (SYS0/SYS) to select the drive in Register A, which stores the address of its PDRIVE entry (4291H + 10 x drive) at 42B9H. It returns the NZ FLAG with an error code for a drive that is not available.
565E
If the NZ FLAG is set (the drive is not available), JUMP to 5684H.
5660
LD DE,0004H 11 04 00
Load Register Pair DE with 0004H, the offset of the working record's address in the control block.
5663
BIT 0,B CB 40
Test bit 0 of Register B (the mode): the saved original instead.
5665
If the Z FLAG is set (the working record), JUMP to 5669H.
5667
INC DE 13
INCrement Register Pair DE from offset 4 to offset 5.
5668
INC DE 13
INCrement Register Pair DE to offset 6, the saved original's address.
5669
ADD HL,DE 19
ADD Register Pair DE (4 or 6) to Register Pair HL (the control block): the address of the record's address. 5665H comes here.
566A
LD E,(HL) 5E
Load Register E with the low byte of the record's address at Register Pair HL.
566B
INC HL 23
INCrement Register Pair HL to the high byte of the record's address.
566C
LD D,(HL) 56
Load Register D with the high byte at Register Pair HL: Register Pair DE = the 10-byte record in SYS6/SYS.
566D
LD HL,(42B9H) 2A B9 42
Fetch the address of the drive's PDRIVE entry from 42B9H into Register Pair HL.
5670
BIT 1,B CB 48
Test bit 1 of Register B (the mode): copy from the drive's entry into SYS6/SYS's record.
5672
If the NZ FLAG is set, JUMP to 5675H with Register Pair HL = the entry (source) and Register Pair DE = the record (destination).
5674
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = SYS6/SYS's record, Register Pair DE = the drive's entry.
5675
PUSH BC C5
Save Register Pair BC (the mode and the count of 5646H) onto the stack. 5672H comes here.
5676
LD BC,000AH 01 0A 00
Load Register Pair BC with 000AH: 10 bytes, one in-memory PDRIVE record.
5679
LDIR ED B0
Copy Register Pair BC (10) bytes from Register Pair HL to Register Pair DE.
567B
POP BC C1
Restore Register Pair BC from the stack: Register B = the mode, Register C = 5646H's count.
567C
GOSUB to 4720H (SYS0/SYS) to select the current drive (427EH, the drive just selected) again, which reloads 4280H-4287H from its PDRIVE entry.
567F
If the NZ FLAG is set (an error), JUMP to 5684H.
5681
POP DE D1
Restore Register Pair DE from the stack. 5686H comes here.
5682
POP HL E1
Restore Register Pair HL from the stack: the control block.
5683
RET C9
RETurn with Register Pairs HL and DE as they were.
5684
BIT 2,B CB 50
Test bit 2 of Register B (the mode): ignore errors. 565EH and 567FH come here with the error code in Register A.
5686
If the NZ FLAG is set (ignore), JUMP to 5681H to return.
5688
JUMP to 521AH to end the command with the error code in Register A.

568BH - Load an Overlay into the Overlay Area

568BH loads SYS2/SYS. 568DH loads the overlay whose number is in Register A (04H SYS2/SYS, 05H SYS3/SYS, the code E5H for SYS3/SYS or F3H for SYS17/SYS; 00H = none, only switch to the system diskette). The system diskette is switched in first, so that SYS0/SYS can read the overlay from drive 0. The overlay is called as function 7 with Register C = FFH, a sub-function that SYS2/SYS, SYS3/SYS and SYS17/SYS do not have: each returns at once with error 2AH, and its code stays in 4D00H-51FFH for SYS6/SYS to call into and patch. The SYS0/SYS dispatcher discards the RST 28H's own return address, so the overlay's RETurn goes straight back to the caller of 568DH.

568B
LD A,04H 3E 04
Load Register A with 04H, the number of SYS2/SYS (directory slot 04H). 5D2AH, 60BFH and 638CH call here.
568D
LD C,FFH 0E FF
Load Register C with FFH, the function 7 sub-function that no overlay uses. 54AEH, 583EH, 5E09H and 62ADH call here.
568F
PUSH AF F5
Save Register Pair AF (Register A = the overlay number or code) onto the stack.
5690
GOSUB to 5582H to switch to the system diskette in drive 0.
5693
POP AF F1
Restore Register Pair AF from the stack: Register A = the overlay number or code.
5694
OR A B7
OR Register A with itself: the Z FLAG for 00H.
5695
RET Z C8
If the Z FLAG is set (no overlay to load), RETurn with the system diskette switched in.
5696
OR E0H F6 E0
OR Register A with E0H, setting bits 5-7: function 7 of that overlay (04H becomes E4H, 05H becomes E5H, F3H stays F3H).
5698
RST 28H EF
RST 28H with Register A = the code and Register C = FFH: SYS0/SYS reads the overlay into 4D00H-51FFH unless it is already there (4288H), stores its number at 4288H and calls it. The overlay returns with error 2AH, and the dispatcher returns straight to the caller of 568DH.

5699H - Step Through the COPY-by-File List

The file list (from (5D12H) to (5D14H)) holds three bytes for each source file: flags (bit 7 entry used, bit 6 system file, bit 5 to be copied, bit 4 already in the destination directory), the source DEC and the destination DEC. 5699H moves Register Pair HL to the next entry and returns the Z FLAG at the end of the list. 56A2H moves on to the next entry marked to be copied (56A6H tests the current one first) and opens its source file; it returns the Z FLAG when there are no more. 56B9H opens a file from its DEC through SYS2/SYS's FCB building code, which 568BH has loaded into the overlay area.

5699
INC HL 23
INCrement Register Pair HL from the entry's flag byte to its source DEC. 56A2H, 5EB6H, 5EDBH, 5F0AH, 5FA7H, 60CEH and 60FBH call here.
569A
INC HL 23
INCrement Register Pair HL to the entry's destination DEC.
569B
INC HL 23
INCrement Register Pair HL to the next entry's flag byte.
569C
LD DE,(5D14H) ED 5B 14 5D
Fetch the end of the file list from 5D14H into Register Pair DE.
56A0
RST 18H DF
RST 18H, the ROM routine that compares Register Pair HL (the next entry) with Register Pair DE (the end of the list): the Z FLAG at the end.
56A1
RET C9
RETurn with the Z FLAG at the end of the list and Register Pair HL on the next entry.

Search Loop for the next entry marked to be copied.

56A2
GOSUB to 5699H to step Register Pair HL to the next entry. 52C1H calls here; 56A8H comes here.
56A5
RET Z C8
If the Z FLAG is set (the end of the list), RETurn with the Z FLAG: no more files.
56A6
BIT 5,(HL) CB 6E
Test bit 5 of the entry's flag byte at Register Pair HL: the file is to be copied. 526DH calls here.
56A8
If the Z FLAG is set (not marked), LOOP BACK to 56A2H.
56AA
LD (52BAH),HL 22 BA 52
Store Register Pair HL (the entry's address) at 52BAH, the operand of the LD HL,nnnn at 52B9H, which takes it up again when this file has been read to its end.
56AD
INC HL 23
INCrement Register Pair HL to the entry's source DEC.
56AE
LD C,(HL) 4E
Load Register C with the source DEC at Register Pair HL.
56AF
INC HL 23
INCrement Register Pair HL to the entry's destination DEC.
56B0
LD A,(HL) 7E
Fetch the destination DEC at Register Pair HL into Register A.
56B1
LD (52D2H),A 32 D2 52
Store Register A (the destination DEC) at 52D2H, the operand of the LD (HL),nn at 52D1H: it becomes the marker byte of this file's sector entries, which 534BH compares to switch destination files.
56B4
LD IX,5AE5H DD 21 E5 5A
Point Index Register IX to 5AE5H, the source FCB.
56B8
LD A,C 79
Copy Register C (the source DEC) into Register A.
56B9
LD (4F56H),A 32 56 4F
Store Register A (the DEC) at 4F56H, inside SYS2/SYS's FCB building code in the overlay area: the operand of SYS2/SYS's LD (HL),nn at 4F55H, which stores the FCB's DEC (FCB+7). 535AH calls here with the destination DEC and Index Register IX = 5B17H.
56BC
GOSUB to 56F4H to read the directory sector of the DEC in Register A (SYS0/SYS 48DBH). Register Pair HL returns pointing to the directory entry in 4300H.
56BF
XOR A AF
Set Register A to 00H (XOR A), the record length and FCB+2 value for SYS2/SYS.
56C0
LD (4F5EH),A 32 5E 4F
Store Register A (00H) at 4F5EH, SYS2/SYS's operand for the FCB's record length (FCB+9): the file is handled in whole sectors.
56C3
INC HL 23
INCrement Register Pair HL to byte 1 of the directory entry, its second flag byte.
56C4
GOSUB to 4E21H in SYS2/SYS, which stores Register A (00H) as SYS2/SYS's value for FCB+2 and the entry's EOF low byte (byte 3) as the value for FCB+8, and returns Register Pair HL pointing to byte 4 of the entry.
56C7
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = byte 4 of the directory entry.
56C8
LD A,E 7B
Copy Register E (the low byte of the pointer) into Register A.
56C9
ADD A,10H C6 10
ADD 10H to Register A (the low byte of the pointer to byte 4): 16 bytes further on.
56CB
LD E,A 5F
Copy Register A into Register E: Register Pair DE points to byte 20 of the entry, the middle byte of the EOF (an entry never crosses a 256-byte boundary).
56CC
GOSUB to 4F2EH in SYS2/SYS to build the open FCB at Index Register IX from the entry: its EOF, its extents and the values just stored. It returns the Z FLAG, or the NZ FLAG with error 2CH for a bad EOF.
56CF
If the NZ FLAG is set (an error), JUMP to 56FEH to end the command with it.
56D1
OR FFH F6 FF
OR Register A with FFH: Register A = FFH and the NZ FLAG, a file has been opened.
56D3
RET C9
RETurn with the NZ FLAG and Index Register IX pointing to the open FCB.

56D4H - Unreferenced Code

Nothing jumps or calls to 56D4H. The four instructions would multiply Register A by the sectors per track at 4284H (IY+04H, with Index Register IY = 4280H from 4D00H) using the SYS0/SYS routine at 4C39H.

56D4
LD L,A 6F
Copy Register A into Register L. Nothing reaches this row.
56D5
LD H,00H 26 00
Load Register H with 00H: Register Pair HL = the value from Register A. Nothing reaches this row.
56D7
LD A,(IY+04H) FD 7E 04
Fetch the sectors per track from (IY+04H) (Index Register IY = 4280H, so this is 4284H, byte +4 of the current drive's PDRIVE values) into Register A. Nothing reaches this row.
56DA
JUMP to 4C39H (SYS0/SYS), which multiplies Register Pair HL by Register A. Nothing reaches this row.

56DDH - Directory Sector Helpers

Each routine ends the command at 56FEH on an error. 56DDH reads the directory entry of the file open in the FCB at Index Register IX (Register Pair HL = the entry). 56E2H points Register Pair HL to the entry of the DEC in Register A, reading its sector unless it is already in 4300H and first writing back a changed sector. 56F4H always reads the sector of the DEC in Register A. 56F9H reads the GAT (56FAH: directory sector A). 5701H writes directory sector A from 4300H. 5706H marks the sector in 4300H as changed, 570DH writes it back if one was marked and 5711H writes it back now. Directory sector 0 is the GAT, 1 the HIT and 2 onward the FDE sectors; a DEC's entry is in sector (DEC AND 1FH) + 2, entry DEC / 32.

56DD
GOSUB to 48F0H (SYS0/SYS) to read the directory entry of the file open in the FCB at Index Register IX. It returns Register Pair HL pointing to the entry in 4300H and the Z FLAG, or the NZ FLAG with error 2DH for an entry that does not belong to the FCB. 53B3H and 5872H call here.
56E0
JUMP to 56FDH to return or end the command with the error.
56E2
PUSH AF F5
Save Register Pair AF (Register A = the DEC) onto the stack. 5FE4H and 61B1H call here.
56E3
AND 1FH E6 1F
AND Register A (the DEC) with 1FH, keeping bits 0-4: the FDE sector minus 2.
56E5
INC A 3C
INCrement Register A (the DEC's bits 0-4), the first of two.
56E6
INC A 3C
INCrement Register A again: Register A = the directory sector that holds the DEC's entry.
56E7
LD HL,570EH 21 0E 57
Point Register Pair HL to 570EH, the operand of the LD A,nn at 570DH: the number of a changed directory sector not yet written (FFH = none).
56EA
CP (HL) BE
Compare Register A (the sector needed) against the changed sector at Register Pair HL (570EH).
56EB
If the NZ FLAG is set (a different sector, or none), GOSUB to 570DH to write the changed sector back first, if there is one. The SYS0/SYS patch list (5B9CH) exchanges the opcode at 56EBH (C4H) with CDH while the current drive has TI flag M, making this a CALL that is always made.
56EE
POP AF F1
Restore Register Pair AF from the stack: Register A = the DEC.
56EF
GOSUB to 48D4H (SYS0/SYS) to point Register Pair HL to the entry of the DEC in Register A, reading its sector into 4300H only if the sector held there (48D5H) is a different one. 5ED0H and 60E6H call here.
56F2
JUMP to 56FDH to return or end the command with the error.
56F4
GOSUB to 48DBH (SYS0/SYS) to read the directory sector of the DEC in Register A into 4300H whatever is held there, and point Register Pair HL to the entry. 56BCH calls here.
56F7
JUMP to 56FDH to return or end the command with the error.
56F9
XOR A AF
Set Register A to 00H, directory sector 0, the GAT. 5F98H and 62C3H call here.
56FA
GOSUB to 48AFH (SYS0/SYS) to read directory sector Register A into 4300H. A sector without the directory mark gives error 31H, a read error 11H. 6164H calls here.
56FD
RET Z C8
If the Z FLAG is set (no error), RETurn to the caller. 56E0H, 56F2H, 56F7H, 5704H and 5719H come here.
56FE
JUMP to 521AH to end the command with the error code in Register A. 56CFH comes here.
5701
GOSUB to 48C7H (SYS0/SYS) to write the sector in 4300H as directory sector Register A, with the directory mark, and verify it (error 12H on failure). 609EH and 60A6H call here.
5704
JUMP to 56FDH to return or end the command with the error.
5706
LD A,(48D5H) 3A D5 48
Fetch the number of the directory sector in 4300H from 48D5H (SYS0/SYS) into Register A. 6001H calls here.
5709
LD (570EH),A 32 0E 57
Store Register A (the sector number) at 570EH, the operand of the LD A,nn at 570DH: that sector has been changed and must be written back.
570C
RET C9
RETurn to the caller with the sector marked as changed.
570D
LD A,FFH 3E FF
Load Register A with the number of the changed directory sector. Self-Modifying Code
The operand at 570EH is FFH in the file; 5706H stores a sector number there and 5713H puts FFH back. 56EBH and 6092H call here.
570F
INC A 3C
INCrement Register A: the Z FLAG when it was FFH (no changed sector).
5710
RET Z C8
If the Z FLAG is set (nothing to write), RETurn.
5711
LD A,FFH 3E FF
Load Register A with FFH. 53C2H, 5F5FH and 614FH call here to write the sector now.
5713
LD (570EH),A 32 0E 57
Store Register A (FFH) at 570EH: no changed sector is held any more.
5716
GOSUB to 48C4H (SYS0/SYS) to write the directory sector in 4300H back to its own sector number (48D5H), with the directory mark and verify.
5719
JUMP to 56FDH to return or end the command with the error.

571BH - Progress Asterisk and Operator Keys

571BH blinks an asterisk in the top right corner of the screen (3C3FH) once for each sector. 572BH reads a key (00H if none) and changes it to upper case. Both then check the keyboard unless NDMW was given: holding the right arrow pauses until ENTER (continue) or the up arrow (cancel) is pressed, and the up arrow cancels the command with error 39H. Register Pair AF is returned as it was (572BH: the key); Register Pairs BC, DE and HL are not changed.

571B
LD A,(3C3FH) 3A 3F 3C
Fetch the character at 3C3FH, the last column of the top line of the screen, into Register A. 52D6H, 53E8H, 5457H and 57C0H call here.
571E
CP 2AH FE 2A
Compare Register A (the character on the screen) against 2AH, an asterisk.
5720
LD A,2AH 3E 2A
Load Register A with 2AH, an asterisk. LD does not change the flags.
5722
If the NZ FLAG is set (no asterisk there), JUMP to 5726H to show one.
5724
LD A,20H 3E 20
Load Register A with 20H, a space, to take the asterisk away.
5726
LD (3C3FH),A 32 3F 3C
Store Register A (the asterisk or the space) at 3C3FH on the screen. 5722H comes here.
5729
JUMP to 5733H to check the keyboard with Register A = the character shown.
572B
PUSH DE D5
Save Register Pair DE onto the stack (the ROM scan changes it). 55E2H and 58EEH call here.
572C
GOSUB to 002BH, the ROM keyboard scan: Register A = the key pressed, or 00H.
572F
GOSUB to 4548H (SYS0/SYS) to change Register A from a lower case letter to upper case.
5732
POP DE D1
Restore Register Pair DE from the stack: the caller's value.
5733
PUSH AF F5
Save Register Pair AF (the key, or the character from 571BH) onto the stack. 5729H and 6A71H come here.
5734
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H into Register A.
5737
BIT 7,A CB 7F
Test bit 7 of Register A (the 5995H flags): NDMW, no diskette mount waits.
5739
If the NZ FLAG is set (NDMW), JUMP to 574FH without looking at the keyboard.
573B
LD A,(3840H) 3A 40 38
Fetch keyboard row 6 from 3840H into Register A: bit 0 ENTER, bit 3 up arrow, bit 6 right arrow.
573E
AND 48H E6 48
AND Register A (keyboard row 6) with 48H, keeping bit 3 (up arrow) and bit 6 (right arrow).
5740
If the Z FLAG is set (neither held), JUMP to 574FH.

Pause Loop: wait for ENTER (continue) or the up arrow (cancel).

5742
LD A,(3840H) 3A 40 38
Fetch keyboard row 6 from 3840H into Register A again. 5747H comes here.
5745
AND 09H E6 09
AND Register A (keyboard row 6) with 09H, keeping bit 0 (ENTER) and bit 3 (up arrow).
5747
If the Z FLAG is set (neither yet), LOOP BACK to 5742H.
5749
RRCA 0F
Rotate Register A right: bit 0 (ENTER) goes into the CARRY FLAG.
574A
LD A,39H 3E 39
Load Register A with error code 39H (OPERATOR/PROGRAM/PARAMETER REQUIRE FUNCTION TERMINATION). LD does not change the flags.
574C
If the NO CARRY FLAG is set (the up arrow without ENTER), JUMP to 521AH to end the command with error 39H.
574F
POP AF F1
Restore Register Pair AF from the stack: the key or the character. 5739H and 5740H come here.
5750
RET C9
RETurn to the caller with Register Pair AF as it was.

5751H - Free Granules in the GAT

Entered at 5762H with Register Pair HL pointing to a lump's byte in the GAT sector at 4300H, Register C holding the first granule's number in the lump and Register Pair DE the number of granules. The bit of each granule is cleared (free) from there on, lump after lump. If the destination has no more than 96 lumps, the same bits are then cleared in the lockout table 60H bytes further on (5751H). Used by FORMAT (6684H) and by SYS17/SYS (5093H) at the end of a diskette COPY. Register Pairs HL, DE and BC are kept.

5751
LD A,L 7D
Copy Register L (the address of the last lump byte changed) into Register A. 5777H comes here when the count reaches 0.
5752
CP 60H FE 60
Compare Register A against 60H: the NO CARRY FLAG when the bits just cleared were in the lockout table (60H-BFH).
5754
POP BC C1
Restore Register Pair BC from the stack: the entry value (Register C = the first granule).
5755
POP DE D1
Restore Register Pair DE from the stack: the entry value (the granule count).
5756
POP HL E1
Restore Register Pair HL from the stack: the entry value (the first lump byte).
5757
RET NC D0
If the NO CARRY FLAG is set (the lockout table has been done too), RETurn.
5758
LD A,(59C6H) 3A C6 59
Fetch the destination's lump count from 59C6H (byte +1 of the working record at 59C5H) into Register A.
575B
CP 61H FE 61
Compare Register A (the lump count) against 61H.
575D
RET NC D0
If the NO CARRY FLAG is set (more than 96 lumps: bytes 60H-BFH are part of the allocation table, not a lockout table), RETurn.
575E
LD A,L 7D
Copy Register L (the first lump byte) into Register A.
575F
ADD A,60H C6 60
ADD 60H to Register A: the same lump's byte in the lockout table.
5761
LD L,A 6F
Copy Register A into Register L and fall into 5762H to clear the same granules there.
5762
PUSH HL E5
Save Register Pair HL (the lump byte) onto the stack. 5525H, 6684H and SYS17/SYS 5093H call here.
5763
PUSH DE D5
Save Register Pair DE (the granule count) onto the stack.
5764
PUSH BC C5
Save Register Pair BC (Register C = the first granule) onto the stack.

Lump Loop: Register L walks the lump bytes, Register C the granules in a lump, Register Pair DE counts the granules left.

5765
LD A,L 7D
Copy Register L (the lump byte's offset in the GAT) into Register A. 5782H comes here.
5766
CP C0H FE C0
Compare Register A against C0H: the NO CARRY FLAG past the end of the table (C0H on).
5768
If the NO CARRY FLAG is set (more lumps than the GAT can hold), GOSUB to 5240H, which displays DISKETTE/GAT OVERFLOW and ends the command.
576B
INC C 0C
INCrement Register C: the granule number plus 1, the number of rotations. 577DH comes here.
576C
LD B,C 41
Copy Register C into Register B, the rotation count.
576D
LD A,7FH 3E 7F
Load Register A with 7FH, a mask with only bit 7 clear.
576F
RLCA 07
Rotate Register A (the mask) left. 5770H comes here.
5770
DECrement Register B and LOOP BACK to 576FH: after granule + 1 rotations the clear bit is the granule's bit.
5772
AND (HL) A6
AND Register A (the mask) with the lump byte at Register Pair HL, clearing the granule's bit.
5773
LD (HL),A 77
Store Register A back at Register Pair HL: the granule is free.
5774
DEC DE 1B
DECrement Register Pair DE, the granules left.
5775
LD A,D 7A
Copy Register D (the high byte of the count) into Register A.
5776
OR E B3
OR Register E (the low byte) into Register A: the Z FLAG when no granules are left.
5777
If the Z FLAG is set (all freed), JUMP to 5751H.
5779
LD A,(59CAH) 3A CA 59
Fetch the destination's granules per lump from 59CAH (byte +5 of the working record at 59C5H) into Register A.
577C
CP C B9
Compare Register A (the granules per lump) against Register C (the next granule's number).
577D
If the NZ FLAG is set (more granules in this lump), LOOP BACK to 576BH.
577F
LD C,00H 0E 00
Load Register C with 00H: start again at granule 0.
5781
INC L 2C
INCrement Register L to the next lump's byte.
5782
LOOP BACK to 5765H to check the lump and go on.

5784H - Verify the Whole Destination Diskette

Entered with Register Pair DE = the first sector to read and Index Register IX pointing to the destination FCB (5B17H). Every sector from there to the end of the destination diskette is read into 4300H; a sector with the directory mark (error 06H) is correct, any other read error is reported with the C, R or P question. 5784H-5789H are six NOPs, so the verify is always done. Called by FORMAT (6655H) and by SYS17/SYS (5033H) after a diskette COPY.

5784
NOP 00
No operation, the first of the six NOPs at 5784H-5789H. 6655H and SYS17/SYS 5033H call here.
5785
NOP 00
No operation, the second of the six NOPs at 5784H-5789H.
5786
NOP 00
No operation, the third of the six NOPs at 5784H-5789H.
5787
NOP 00
No operation, the fourth of the six NOPs at 5784H-5789H.
5788
NOP 00
No operation, the fifth of the six NOPs at 5784H-5789H.
5789
NOP 00
No operation, the last of the six NOPs at 5784H-5789H; the verify starts at 578AH.
578A
LD A,20H 3E 20
Load Register A with 20H, the operation bit for VERIFYING DESTINATION.
578C
LD (57EBH),A 32 EB 57
Store Register A (20H) at 57EBH, the operand of the LD B,nn at 57EAH, so that an error report says VERIFYING DESTINATION.
578F
LD (5B21H),DE ED 53 21 5B
Store Register Pair DE (the first sector to read) at 5B21H, the destination FCB's NEXT.
5793
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the sector buffer.
5796
LD (5B1AH),HL 22 1A 5B
Store Register Pair HL (4300H) at 5B1AH, the destination FCB's buffer address.
5799
LD HL,(59CFH) 2A CF 59
Fetch the destination's total sector count from 59CFH (stored by 6721H) into Register Pair HL.
579C
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
579D
SBC HL,DE ED 52
SUBtract Register Pair DE (the first sector) from Register Pair HL (the total): the number of sectors to read.
579F
RET C D8
If the CARRY FLAG is set (the first sector is past the end), RETurn.
57A0
RET Z C8
If the Z FLAG is set (nothing to read), RETurn.
57A1
PUSH HL E5
Save Register Pair HL (the sector count) onto the stack.
57A2
LD HL,5A79H 21 79 5A
Point Register Pair HL to 5A79H, the message VERIFYING .
57A5
GOSUB to 587EH to display the message at Register Pair HL and start a new line.
57A8
LD HL,FFFFH 21 FF FF
Load Register Pair HL with FFFFH, the highest sector number, for the EOF.
57AB
LD (5B23H),HL 22 23 5B
Store Register Pair HL (FFFFH) at 5B23H, the destination FCB's EOF, so that no read is past the end.
57AE
SET 1,(IX+00H) DD CB 00 CE
Set bit 1 of (IX+00H), the first byte of the FCB at Index Register IX (5B17H): NEXT and EOF are sector numbers on the diskette, not in a file.
57B2
POP HL E1
Restore Register Pair HL from the stack: the sector count.

Verify Loop: Register Pair HL counts the sectors left.

57B3
GOSUB to 57C8H to read the sector at the destination FCB's NEXT into 4300H. It returns the Z FLAG, or the NZ FLAG with the error code in Register A. 57BDH and 57C5H come here.
57B6
If the Z FLAG is set (read correctly), JUMP to 57BAH with the Z FLAG, so that the CALL NZ there is not made.
57B8
CP 06H FE 06
Compare Register A (the error code) against 06H: a sector with the directory mark, which is correct; the Z FLAG then stops the call below.
57BA
If the NZ FLAG is set (a real read error), GOSUB to 585AH to report it and ask C, R or P. It returns the NZ FLAG for R, or the Z FLAG for P after moving NEXT past the sector. 57B6H comes here.
57BD
If the NZ FLAG is set (R), LOOP BACK to 57B3H to read the sector again.
57BF
DEC HL 2B
DECrement Register Pair HL, the sectors left.
57C0
GOSUB to 571BH to blink the progress asterisk and check the pause and cancel keys.
57C3
LD A,H 7C
Copy Register H (the high byte of the count) into Register A.
57C4
OR L B5
OR Register L (the low byte) into Register A: the Z FLAG when no sectors are left.
57C5
If the NZ FLAG is set (more sectors), LOOP BACK to 57B3H.
57C7
RET C9
RETurn to the caller with the whole destination read.

57C8H - Read, Write and Verify Through the FCB at IX

57C8H reads the sector at the FCB's NEXT (SYS0/SYS 4436H), 57CEH writes it (through 5CEDH) and 57D4H writes it and reads it back (SYS0/SYS 443CH). Register Pair DE is set to Index Register IX, the FCB. Each returns the Z FLAG, or the NZ FLAG with the error code in Register A.

57C8
PUSH IX DD E5
Save Index Register IX (the FCB) onto the stack. 52A8H, 541CH, 57B3H and 67D8H call here.
57CA
POP DE D1
Restore the FCB address from the stack into Register Pair DE.
57CB
JUMP to 4436H (SYS0/SYS) to read the sector at the NEXT of the FCB at Register Pair DE into its buffer.
57CE
PUSH IX DD E5
Save Index Register IX (the FCB) onto the stack. 5390H and 5481H call here.
57D0
POP DE D1
Restore the FCB address from the stack into Register Pair DE.
57D1
JUMP to 5CEDH, which marks the FCB for a TI flag M diskette and writes the sector through SYS0/SYS 4439H.
57D4
PUSH IX DD E5
Save Index Register IX (the FCB) onto the stack. 66FFH and 67C2H call here.
57D6
POP DE D1
Restore the FCB address from the stack into Register Pair DE.
57D7
JUMP to 443CH (SYS0/SYS) to write the sector at the NEXT of the FCB at Register Pair DE and read it back.

57DAH - Report a Disk Error and Ask C, R or P

Called from 585AH with the error code in Register A. The line ERROR WHILE READING/WRITING/VERIFYING SOURCE/DESTINATION SECTOR n is displayed (n = the FCB's NEXT), and in a COPY by file the file's name. A single file COPY ends here with the error. Otherwise the system diskette is switched in so that SYS4/SYS can display the DOS error message, the operator is asked, the overlay that was in the overlay area is loaded again and the diskette that was in use is switched back. Returns Register A = 1 and the Z FLAG for P, Register A = 2 and the NZ FLAG for R; C ends the command. Register Pairs HL, DE and BC are kept.

57DA
PUSH HL E5
Save Register Pair HL onto the stack. 585AH calls here.
57DB
PUSH DE D5
Save Register Pair DE (the caller's value) onto the stack; it is restored at 5847H.
57DC
PUSH BC C5
Save Register Pair BC (the caller's value) onto the stack; it is restored at 5846H.
57DD
PUSH AF F5
Save Register Pair AF (Register A = the error code) onto the stack.
57DE
GOSUB to 5881H to start a new line on the display.
57E1
LD HL,59D3H 21 D3 59
Point Register Pair HL to 59D3H, the message ERROR WHILE .
57E4
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
57E7
LD HL,5A67H 21 67 5A
Point Register Pair HL to 5A67H, the word READING .
57EA
LD B,00H 06 00
Load Register B with the operation bits: bit 7 source, bit 6 writing, bit 5 verifying. Self-Modifying Code
The operand at 57EBH is 00H in the file; it is stored before each operation: 80H reading the source (52A5H), 40H writing the destination (547EH), 20H verifying the destination (540EH, 578CH).
57EC
BIT 6,B CB 70
Test bit 6 of Register B (the operation): writing.
57EE
If the Z FLAG is set (not writing), JUMP to 57F3H with Register Pair HL = READING.
57F0
LD HL,5A70H 21 70 5A
Point Register Pair HL to 5A70H, the word WRITING .
57F3
BIT 5,B CB 68
Test bit 5 of Register B (the operation): verifying. 57EEH comes here.
57F5
If the Z FLAG is set (not verifying), JUMP to 57FAH.
57F7
LD HL,5A79H 21 79 5A
Point Register Pair HL to 5A79H, the word VERIFYING .
57FA
GOSUB to 4467H (SYS0/SYS) to display the word at Register Pair HL. 57F5H comes here.
57FD
LD HL,5A44H 21 44 5A
Point Register Pair HL to 5A44H, the word DESTINATION .
5800
LD DE,(5B21H) ED 5B 21 5B
Fetch the destination FCB's NEXT from 5B21H into Register Pair DE: the sector being worked on.
5804
BIT 7,B CB 78
Test bit 7 of Register B (the operation): the source.
5806
If the Z FLAG is set (the destination), JUMP to 580FH.
5808
LD HL,5A3CH 21 3C 5A
Point Register Pair HL to 5A3CH, the word SOURCE .
580B
LD DE,(5AEFH) ED 5B EF 5A
Fetch the source FCB's NEXT from 5AEFH into Register Pair DE.
580F
GOSUB to 4467H (SYS0/SYS) to display the word at Register Pair HL. 5806H comes here.
5812
LD HL,5A5FH 21 5F 5A
Point Register Pair HL to 5A5FH, the word SECTOR .
5815
GOSUB to 4467H (SYS0/SYS) to display the word at Register Pair HL.
5818
GOSUB to 5909H to display Register Pair DE (the sector number) in decimal.
581B
GOSUB to 5881H to end the line with a carriage return (Register A = 0DH).
581E
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
5821
BIT 2,A CB 57
Test bit 2 of Register A (5996H): a single file COPY.
5823
If the NZ FLAG is set (single file COPY), JUMP to 521EH, whose POP AF takes the error code pushed at 57DDH: the command ends with it.
5826
GOSUB to 5868H to display WITHIN FILE and the file's name if this is a COPY by file.
5829
POP BC C1
Restore the word pushed at 57DDH into Register Pair BC: Register B = the error code.
582A
LD HL,(593EH) 2A 3E 59
Fetch the current control block from 593EH into Register Pair HL: the diskette in use when the error happened.
582D
LD A,(4288H) 3A 88 42
Fetch the number of the overlay in 4D00H-51FFH from 4288H into Register A.
5830
LD C,A 4F
Copy Register A (the overlay number) into Register C.
5831
PUSH HL E5
Save Register Pair HL (the control block) onto the stack.
5832
PUSH BC C5
Save Register Pair BC (Register B = the error code, Register C = the overlay) onto the stack.
5833
GOSUB to 5582H to switch to the system diskette, from which SYS4/SYS is read to display the message.
5836
LD A,B 78
Copy Register B (the error code) into Register A.
5837
GOSUB to 584AH to display the DOS error message for Register A and ask C, R or P. It returns Register A = 1 with the Z FLAG for P, or 2 with the NZ FLAG for R.
583A
POP BC C1
Restore Register Pair BC from the stack: Register C = the overlay that was resident.
583B
POP DE D1
Restore Register Pair DE from the stack: the control block of the diskette that was in use.
583C
PUSH AF F5
Save Register Pair AF (the reply and its flags) onto the stack.
583D
LD A,C 79
Copy Register C (the overlay number) into Register A.
583E
GOSUB to 568DH to load that overlay into 4D00H-51FFH again (SYS4/SYS replaced it), or only switch to the system diskette if it was 00H. Register Pair DE is not changed.
5841
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the control block.
5842
GOSUB to 5585H to switch back to the diskette of the control block at Register Pair HL.
5845
POP AF F1
Restore Register Pair AF from the stack: the reply (1 P, 2 R) and its flags.
5846
POP BC C1
Restore Register Pair BC from the stack: the caller's value saved at 57DCH.
5847
POP DE D1
Restore Register Pair DE from the stack: the caller's value saved at 57DBH.
5848
POP HL E1
Restore Register Pair HL from the stack: the caller's value saved at 57DAH.
5849
RET C9
RETurn with the reply in Register A and the Z FLAG for P.

584AH - Display the DOS Error and Ask C, R or P

Entered with the error code in Register A. With NDMW the command ends with the error. Otherwise SYS4/SYS displays the error message and returns here, and the operator is asked.

584A
LD HL,5995H 21 95 59
Point Register Pair HL to 5995H, the option flags. 5837H calls here.
584D
BIT 7,(HL) CB 7E
Test bit 7 of the byte at Register Pair HL (5995H): NDMW.
584F
If the NZ FLAG is set (NDMW: no questions), JUMP to 521AH to end the command with the error code in Register A.
5852
OR C0H F6 C0
OR Register A (the error code) with C0H: bit 7 makes SYS4/SYS display the message and return to the caller of 4409H instead of going to DOS READY; SYS4/SYS takes the message number from bits 0-5 only.
5854
GOSUB to 4409H (SYS0/SYS), the error exit, which has SYS4/SYS display the message for Register A and return.
5857
JUMP to 58C8H to ask C, R or P; 58C8H returns to 583AH.

585AH - Disk Error: Retry, Proceed or Cancel

Entered with the error code in Register A and Index Register IX pointing to the FCB. Returns the NZ FLAG if the operator chose R (retry). For P (proceed) the FCB's NEXT is moved past the bad sector and the Z FLAG is returned with Register A = 0. 585EH only moves NEXT on.

585A
GOSUB to 57DAH to report the error in Register A and ask C, R or P. 52CAH, 5431H, 5466H, 548AH and 57BAH call here.
585D
RET NZ C0
If the NZ FLAG is set (R), RETurn with the NZ FLAG.
585E
INC (IX+0AH) DD 34 0A
INCrement (IX+0AH), the low byte of the NEXT of the FCB at Index Register IX. 53DBH and 5417H call here.
5861
If the NZ FLAG is set (no carry out of the low byte), JUMP to 5866H.
5863
INC (IX+0BH) DD 34 0B
INCrement (IX+0BH), the high byte of the NEXT of the FCB at Index Register IX.
5866
XOR A AF
Set Register A to 00H and the Z FLAG. 5861H comes here.
5867
RET C9
RETurn with the Z FLAG and NEXT moved past the sector.

5868H - Display the Name of the File Being Copied

Only in a COPY by file (the OR operand at 586AH is set to FFH by 615CH): WITHIN FILE and the name of the file open in the FCB at Index Register IX are displayed and the NZ FLAG is returned. 586FH displays the message at Register Pair HL followed by the file's name.

5868
XOR A AF
Set Register A to 00H. 53ADH and 5826H call here.
5869
OR 00H F6 00
OR Register A (00H) with the COPY by file flag: the Z FLAG when it is 00H. Self-Modifying Code
The operand at 586AH is 00H in the file; 615CH stores FFH there when a COPY by file starts copying.
586B
RET Z C8
If the Z FLAG is set (not a COPY by file), RETurn with the Z FLAG.
586C
LD HL,59E0H 21 E0 59
Point Register Pair HL to 59E0H, the message WITHIN FILE .
586F
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL. 53C9H calls here with DISK FULL - .
5872
GOSUB to 56DDH to read the directory entry of the file open in the FCB at Index Register IX. Register Pair HL returns pointing to it.
5875
GOSUB to 58A0H to display the name and extension of the directory entry at Register Pair HL.
5878
GOSUB to 5881H to end the line with a carriage return (Register A = 0DH).
587B
OR FFH F6 FF
OR Register A with FFH: Register A = FFH and the NZ FLAG.
587D
RET C9
RETurn with the NZ FLAG: a name was displayed.

587EH - Display Routines

587EH displays the message at Register Pair HL and starts a new line; 5881H only starts a new line. 5886H displays Register B characters from Register Pair HL, showing a space for control codes and graphics. 5898H displays Register B spaces. 58A0H displays the NAME/EXT of the directory entry at Register Pair HL. 58BDH displays the character in Register A through the ROM routine at 0033H, keeping Register Pairs DE and AF.

587E
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL. 5276H and 57A5H call here.
5881
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, which starts a new line. 521BH and others call here.
5883
JUMP to 58BDH to display the character in Register A (0DH).

Character Loop of 5886H: Register Pair HL walks the text, Register B counts.

5886
LD A,(HL) 7E
Fetch a character at Register Pair HL into Register A. 5895H, 694AH and 6954H come here.
5887
CP 20H FE 20
Compare Register A (the character) against 20H: the CARRY FLAG for a control code.
5889
INC HL 23
INCrement Register Pair HL to the next character. INC HL does not change the flags.
588A
If the CARRY FLAG is set (a control code), JUMP to 5890H.
588C
CP 80H FE 80
Compare Register A (the character) against 80H: the CARRY FLAG for an ordinary character.
588E
If the CARRY FLAG is set, JUMP to 5892H to display it.
5890
LD A,20H 3E 20
Load Register A with 20H: a space is shown for a control code or a graphics character. 588AH comes here.
5892
GOSUB to 58BDH to display the character in Register A. 588EH comes here.
5895
DECrement Register B (the characters left) and LOOP BACK to 5886H.
5897
RET C9
RETurn with Register Pair HL past the text and Register B = 0.
5898
LD A,20H 3E 20
Load Register A with 20H, a space. 589DH and 694FH come here.
589A
GOSUB to 58BDH to display the space in Register A.
589D
DECrement Register B (the spaces left) and LOOP BACK to 5898H.
589F
RET C9
RETurn with Register B = 0 and Register A = 20H (a space).
58A0
LD A,L 7D
Copy Register L (the low byte of the directory entry's address) into Register A. 5875H and 5E6CH call here.
58A1
ADD A,05H C6 05
ADD 05H to Register A: byte 5, the start of the file name.
58A3
LD L,A 6F
Copy Register A into Register L: Register Pair HL points to the name (an entry never crosses a 256-byte boundary).
58A4
LD B,08H 06 08
Load Register B with 08H, the length of the name field.
58A6
GOSUB to 58B3H to display the name at Register Pair HL without its padding spaces. Register Pair HL returns pointing to the extension.
58A9
LD A,(HL) 7E
Fetch the first character of the extension at Register Pair HL into Register A.
58AA
CP 20H FE 20
Compare Register A (the first extension character) against 20H: the Z FLAG when there is no extension.
58AC
LD B,03H 06 03
Load Register B with 03H, the length of the extension field. LD does not change the flags.
58AE
LD A,2FH 3E 2F
Load Register A with 2FH, a slash. LD does not change the flags.
58B0
If the NZ FLAG is set (there is an extension), GOSUB to 58BDH to display the slash in Register A.

Field Loop: Register B characters at Register Pair HL, spaces left out.

58B3
LD A,(HL) 7E
Fetch a character at Register Pair HL into Register A. 58A6H calls here; 58BAH comes here.
58B4
CP 20H FE 20
Compare Register A (the character) against 20H: the Z FLAG for a padding space.
58B6
INC HL 23
INCrement Register Pair HL to the next character. INC HL does not change the flags.
58B7
If the NZ FLAG is set (not a space), GOSUB to 58BDH to display the character in Register A.
58BA
DECrement Register B (the characters left) and LOOP BACK to 58B3H.
58BC
RET C9
RETurn with Register Pair HL past the field and Register B = 0.
58BD
PUSH DE D5
Save Register Pair DE onto the stack (the ROM display routine changes it). 5883H, 5892H, 589AH and others call here.
58BE
PUSH AF F5
Save Register Pair AF (Register A = the character, and the flags) onto the stack.
58BF
GOSUB to 0033H, the ROM routine that displays the character in Register A at the cursor.
58C2
POP AF F1
Restore Register Pair AF from the stack: the character and the flags.
58C3
POP DE D1
Restore Register Pair DE from the stack: the caller's value saved at 58BDH.
58C4
RET C9
RETurn with Register Pairs AF and DE as they were.

58C5H - Operator Questions

58C5H (not called) would display the message at Register Pair HL before 58C8H. 58C8H asks REPLY C (CANCEL), R (RETRY) OR P (PROCEED): C ends the command with error 39H, P returns Register A = 1 with the Z FLAG, R returns Register A = 2 with the NZ FLAG. With NDMW the command ends at once. 58DEH displays the question at Register Pair HL and asks (Y OR N), returning the Z FLAG for N. 58E4H is the general routine: Register Pair HL points to a list of allowed replies ending with 00H, followed by the prompt text; it returns Register A = the reply's position in the list, with the Z FLAG for the first one.

58C5
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL. Nothing calls or jumps to 58C5H, so this row never runs.
58C8
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H into Register A. 5857H, 630FH, 6882H and 6C48H come here.
58CB
BIT 7,A CB 7F
Test bit 7 of Register A (the 5995H flags): NDMW, no diskette mount waits.
58CD
If the NZ FLAG is set (NDMW: nobody may be asked), JUMP to 5249H to end the command through 4030H (the error has already been displayed).
58D0
LD HL,5A84H 21 84 5A
Point Register Pair HL to 5A84H, the replies CPR followed by the prompt REPLY C (CANCEL), R (RETRY) OR P (PROCEED).
58D3
GOSUB to 58E4H to ask: Register A returns 0 for C, 1 for P, 2 for R.
58D6
CP 01H FE 01
Compare Register A (the reply) against 01H: the CARRY FLAG for C, the Z FLAG for P.
58D8
RET NC D0
If the NO CARRY FLAG is set (P or R), RETurn with the Z FLAG for P and the NZ FLAG for R.
58D9
LD A,39H 3E 39
C: load Register A with error code 39H (OPERATOR/PROGRAM/PARAMETER REQUIRE FUNCTION TERMINATION).
58DB
JUMP to 521AH to end the command with the error code in Register A (39H).
58DE
GOSUB to 4467H (SYS0/SYS) to display the question at Register Pair HL. 4E7EH and 4EBEH call here.
58E1
LD HL,5AB3H 21 B3 5A
Point Register Pair HL to 5AB3H, the replies NY followed by the prompt (Y OR N).
58E4
PUSH BC C5
Save Register Pair BC onto the stack. 58D3H and 5E72H call here.
58E5
PUSH HL E5
Save Register Pair HL (the list of replies) onto the stack.

Skip Loop to the 00H that ends the list.

58E6
LD A,(HL) 7E
Fetch a byte of the list at Register Pair HL into Register A. 58E9H comes here.
58E7
OR A B7
OR Register A with itself: the Z FLAG for 00H, the end of the list.
58E8
INC HL 23
INCrement Register Pair HL. INC HL does not change the flags.
58E9
If the NZ FLAG is set (not the end), LOOP BACK to 58E6H.
58EB
GOSUB to 4467H (SYS0/SYS) to display the prompt text at Register Pair HL, after the list.

Key Loop: wait for a key that is in the list.

58EE
GOSUB to 572BH to read a key into Register A (00H if none, upper case). 58F8H comes here.
58F1
POP HL E1
Restore Register Pair HL from the stack: the list of replies.
58F2
LD C,FFH 0E FF
Load Register C with FFH, so that the first INC makes the reply number 0.
58F4
PUSH HL E5
Save Register Pair HL (the list) onto the stack again.
58F5
INC (HL) 34
INCrement the list byte at Register Pair HL. 58FCH comes here.
58F6
INC C 0C
INCrement Register C, the number of the reply being compared (0 = first).
58F7
DEC (HL) 35
DECrement the list byte at Register Pair HL back: the Z FLAG when it is 00H (the end), with Register A (the key) unchanged.
58F8
If the Z FLAG is set (the key is not in the list), LOOP BACK to 58EEH for another key.
58FA
CP (HL) BE
Compare Register A (the key) against the list byte at Register Pair HL.
58FB
INC HL 23
INCrement Register Pair HL to the next reply. INC HL does not change the flags.
58FC
If the NZ FLAG is set (not this reply), LOOP BACK to 58F5H.
58FE
GOSUB to 58BDH to display the key in Register A.
5901
GOSUB to 5881H to end the line with a carriage return (Register A = 0DH).
5904
LD A,C 79
Copy Register C (the reply number) into Register A.
5905
OR A B7
OR Register A with itself: the Z FLAG for the first reply in the list.
5906
POP HL E1
Restore Register Pair HL from the stack: the list.
5907
POP BC C1
Restore Register Pair BC from the stack: the caller's value saved at 58E4H.
5908
RET C9
RETurn with Register A = the reply number (0 = the first in the list).

5909H - Display a Number in Decimal

Displays Register Pair DE (0-65535) without leading zeros, using the table of negative powers of ten at 5933H. The last digit is always shown.

5909
LD BC,0400H 01 00 04
Load Register Pair BC with 0400H: Register B = 4 digits before the last one, Register C = 0 (no digit shown yet). 5818H and 6C42H call here.
590C
LD HL,5933H 21 33 59
Point Register Pair HL to 5933H, the table -10000, -1000, -100, -10.

Digit Loop: Register Pair DE is the rest of the number, Register Pair HL the table pointer.

590F
PUSH BC C5
Save Register Pair BC (the counts) onto the stack. 592BH comes here.
5910
LD C,(HL) 4E
Load Register C with the low byte of the negative power of ten at Register Pair HL.
5911
INC HL 23
INCrement Register Pair HL to the high byte of the table entry.
5912
LD B,(HL) 46
Load Register B with the high byte at Register Pair HL: Register Pair BC = -10000, -1000, -100 or -10.
5913
INC HL 23
INCrement Register Pair HL to the next table entry.
5914
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the number, Register Pair DE = the table pointer.
5915
LD A,2FH 3E 2F
Load Register A with 2FH, one less than the character 0.
5917
INC A 3C
INCrement Register A, the digit character. 5919H comes here.
5918
ADD HL,BC 09
ADD Register Pair BC (the negative power of ten) to Register Pair HL (the number). The CARRY FLAG is set as long as the result is not below 0.
5919
If the CARRY FLAG is set (the power of ten fitted once more), LOOP BACK to 5917H.
591B
SBC HL,BC ED 42
SUBtract Register Pair BC from Register Pair HL with the CARRY FLAG clear: this adds the power of ten back and undoes the last ADD.
591D
POP BC C1
Restore Register Pair BC from the stack: Register B = the digits left, Register C = whether a digit has been shown.
591E
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the rest of the number, Register Pair HL = the table pointer.
591F
CP 30H FE 30
Compare Register A (the digit) against 30H, the character 0.
5921
If the NZ FLAG is set (not 0), JUMP to 5927H to show it.
5923
INC C 0C
INCrement Register C (the digit shown flag), to test it for 0.
5924
DEC C 0D
DECrement Register C back: the Z FLAG when Register C is 0 (no digit shown yet).
5925
If the Z FLAG is set (a leading zero), JUMP to 592BH without showing it.
5927
INC C 0C
INCrement Register C: a digit has been shown, so later zeros are shown too. 5921H comes here.
5928
GOSUB to 58BDH to display the digit in Register A.
592B
DECrement Register B (the digits left) and LOOP BACK to 590FH. 5925H comes here.
592D
LD A,E 7B
Copy Register E (the units, 0-9, left in Register Pair DE) into Register A.
592E
ADD A,30H C6 30
ADD 30H to Register A (the units, 0-9): the ASCII digit.
5930
JUMP to 58BDH to display the last digit in Register A (always, even 0).

5933H - Variables, Control Blocks and Messages (Data)

The values shown are the ones in the file; the comments give their use at run time. The Variables section of the introduction lists them with their sizes.

5933-5934
DEFW D8F0H F0 D8
-10000, the first of the negative powers of ten that 5909H (pointed to by 590CH) adds to the number to find each decimal digit.
5935-5936
DEFW FC18H 18 FC
-1000, the second power of ten in 5909H's table, for the thousands digit.
5937-5938
DEFW FF9CH 9C FF
-100, the third power of ten in 5909H's table, for the hundreds digit.
5939-593A
DEFW FFF6H F6 FF
-10, the last power of ten in 5909H's table, for the tens digit; the units are shown from what is left.
593B
DEFB 00H 00
SYS6/SYS flags. Bit 7 is set by 63BDH once the drives' PDRIVE data has been saved; from then on 5585H installs each diskette's own data when it switches, and the exit (5227H) puts the drives' data back.
593C-593D
DEFW 6FFFH FF 6F
Highest address COPY may use for its sector buffers (read by 5279H and 5D96H): 6FFFH as loaded, or HIMEM from 4411H, stored by 4D2EH when COPY does not run under DOS-CALL.
593E-593F
DEFW 5942H 42 59
Address of the current diskette control block (5942H, 594CH or 5956H), stored by 5585H and read by 5570H and 582AH.
5940
DEFB 00H 00
Swap set: bit 0 system, bit 1 source, bit 2 destination diskette shares a drive with another and must be swapped in and out (set by 4D8EH, 4DA2H and 4E63H, read by 5568H and 55A7H).
5941
DEFB 07H 07
Mounted set: the same bits for the diskettes that are in their drives now (07H as loaded: all three), stored by 4D91H and 4E63H and kept up to date by 5585H.
5942-594B
DEFB 00H, 01H / DEFW 0000H, 5999H, 5999H, 5A51H 00 01 00 00 99 59 99 59 51 5A
System diskette control block (used by 5582H and 5646H): drive 0, role bit 01H, no FCB, working and saved PDRIVE records both at 5999H, name for the mount prompt at 5A51H.
594C-5955
DEFB FFH, 02H / DEFW 5AE5H, 59B7H, 59A3H, 5A3CH FF 02 E5 5A B7 59 A3 59 3C 5A
Source diskette control block: drive number (FFH until 4D3DH or 5576H stores it), role bit 02H, FCB 5AE5H, working PDRIVE record 59B7H, saved original 59A3H, name SOURCE at 5A3CH.
5956-595F
DEFB FFH, 04H / DEFW 5B17H, 59C5H, 59ADH, 5A44H FF 04 17 5B C5 59 AD 59 44 5A
Destination diskette control block: drive number (FFH until 4D40H, 6399H or 5576H stores it), role bit 04H, FCB 5B17H, working PDRIVE record 59C5H, saved original 59ADH, name DESTINATION at 5A44H.
5960-5967
DEFM " " 20 20 20 20 20 20 20 20
Password buffer (8 spaces) that 5025H copies a password into while it encodes it; every character is set back to a space as it is used.
5968-596F
DEFM " " 20 20 20 20 20 20 20 20
Source diskette name from SN= (stored by 4F90H), compared with the source GAT's name at 62FEH. Eight spaces when SN= is not given.
5970-5977
DEFM " " 20 20 20 20 20 20 20 20
Old destination name from ODN= (stored by 4F8BH), compared with the destination GAT's name at 6868H.
5978-5979
DEFW 0000H 00 00
Encoded source diskette password from SPW= (stored by 4FE0H), checked against the source GAT at 6320H.
597A-597B
DEFW 0000H 00 00
Encoded old destination password from ODPW= (stored by 4FF0H), checked against the destination GAT at 682EH.
597C
DEFB 08H 08
Number of FDE sectors in the source directory (8 + HIT byte 1FH), stored by 5D8FH and read by 5EAAH.
597D
DEFB 08H 08
Number of FDE sectors in the destination directory (8 + HIT byte 1FH), stored by 5EEDH and read by 5F89H and 5FC6H.
597E-5980
DEFB 82H, 00H, 00H 82 00 00
The first three of the 22 bytes 597EH-5993H that 66A2H copies to bytes CBH-E0H of a new GAT sector. NEWDOS/80's own code does not read GAT bytes CBH-CDH back.
5981-5982
DEFW 42E0H E0 42
Encoded password for the new diskette (GAT bytes CEH-CFH): 42E0H, the code of PASSWORD, unless NDPW= or the FORMAT password parameter (4FE8H, 661BH) or the source diskette (62D0H) gives another.
5983-598A
DEFM "NOTNAMED" 4E 4F 54 4E 41 4D 45 44
Diskette name for GAT bytes D0H-D7H: NOTNAMED, or the name from NDN= or the FORMAT name parameter (4F95H), or the source diskette's name (62DAH).
598B-5992
DEFM "2:/4:/::" 32 3A 2F 34 3A 2F 3A 3A
Diskette date for GAT bytes D8H-DFH. The file holds the highest character allowed in each position, which 6FB7H checks each typed digit against before storing it; the date typed or the system date (6FDFH) then replaces it.
5993
DEFB 0DH 0D
GAT byte E0H of a new diskette: 0DH, the start of an empty AUTO command.
5994
DEFB 00H 00
Option flags (set through the option table at 505CH): bit 0 KDD, 1 BDU, 2 NDN, 3 KDN, 4 ODN, 5 DDND, 6 Y, 7 N.
5995
DEFB 00H 00
Option flags: bit 0 ODPW, 1 DDGA, 2 DDSL, 3 DFO, 4 USD, 5 NDPW, 6 CFWO, 7 NDMW.
5996
DEFB 00H 00
Option flags: bit 0 UPD, 1 /ext, 2 single file COPY (4DE5H), 3 CBF, 4 USR, 5 UBB (also set by 4D29H), 6 SPW, 7 SN (COPY) or RWF (FORMAT).
5997
DEFB 00H 00
Option flags: bit 0 PFTC, 1 PFST, 2 FMT, 3 NFMT, 4 ILF, 5 XLF, 6 DPDN, 7 SPDN.
5998
DEFB 00H 00
Not used: no instruction in SYS6/SYS names 5998H, and the 10-byte record at 5999H starts after it.
5999-59A2
DEFB 00H x 10 00 x 10
Saved PDRIVE record of the system drive (drive 0), stored by 63B5H; the system control block uses it as its working record too.
59A3-59AC
DEFB 00H x 10 00 x 10
Saved original PDRIVE record of the source drive, stored by 63B5H and put back by the exit (5230H).
59AD-59B6
DEFB 00H x 10 00 x 10
Saved original PDRIVE record of the destination drive, stored by 63B5H and put back by the exit (5230H).
59B7-59C0
DEFB 00H x 10 00 x 10
Working PDRIVE record for the source diskette: taken from the drive (63BFH) or from SPDN= (63CBH), with the =tc1 override. 59B7H directory starting lump, 59B8H lump count, 59B9H flags (bit 5 TI flag M), 59BAH track count, 59BBH sectors per track, 59BCH granules per lump, 59BDH byte +6 (the byte SYS0/SYS writes to the controller's sector register when it selects the drive, 475EH), 59BEH disk I/O flags (bit 0 double density), 59BFH DDSL, 59C0H DDGA.
59C1-59C2
DEFW 0000H 00 00
Source diskette total sectors, stored by 6721H and read by 6345H and SYS17/SYS 501FH.
59C3-59C4
DEFW 0000H 00 00
Source diskette total granules, stored by 672AH and read by 633CH and SYS17/SYS.
59C5-59CE
DEFB 00H x 10 00 x 10
Working PDRIVE record for the destination diskette: from the drive or from DPDN= (63D7H), with the =tc2, DDSL and DDGA overrides. 59C5H directory lump, 59C6H lump count, 59C7H flags, 59C8H track count, 59C9H sectors per track, 59CAH granules per lump, 59CBH byte +6, 59CCH disk I/O flags, 59CDH DDSL, 59CEH DDGA.
59CF-59D0
DEFW 0000H 00 00
Destination diskette total sectors, stored by 6721H and read by 5799H and 634FH.
59D1-59D2
DEFW 0000H 00 00
Destination diskette total granules, stored by 672AH and read by 6339H, 6678H and SYS17/SYS.
59D3-59DF
DEFM "Error While ", 03H 45 72 72 6F 72 20 57 68 69 6C 65 20 03
The start of a disk error report, displayed by 57E1H; 03H ends it without a new line.
59E0-59ED
DEFM "Within File ", 03H 57 69 74 68 69 6E 20 46 69 6C 65 20 20 03
Displayed by 586CH in a COPY by file, before the name of the file being copied.
59EE-5A01
DEFM "Press ", 22H, "ENTER", 22H, " When ", 03H 50 72 65 73 73 20 22 45 4E 54 45 52 22 20 57 68 65 6E 20 03
The start of the mount prompt, displayed by 55C1H before the diskette's name.
5A02-5A1E
DEFM " Diskette Mounted In Drive 0", 0DH 20 44 69 73 6B 65 74 74 65 20 4D 6F 75 6E 74 65 64 20 49 6E 20 44 72 69 76 65 20 30 0D
The rest of the mount prompt, displayed by 55D2H. 55CFH stores the drive digit at 5A1DH first.
5A1F-5A23
DEFM "Done", 0DH 44 6F 6E 65 0D
Displayed by 552DH when a COPY by file or a FORMAT has finished.
5A24-5A3B
DEFM "Source & Dest Same File", 0DH 53 6F 75 72 63 65 20 26 20 44 65 73 74 20 53 61 6D 65 20 46 69 6C 65 0D
Displayed by 5565H when both filespecs of a single file COPY name the same file.
5A3C-5A43
DEFM "Source ", 03H 53 6F 75 72 63 65 20 03
The source diskette's name for the mount prompt and the error report (4E52H, 5808H, 6306H).
5A44-5A50
DEFM "Destination ", 03H 44 65 73 74 69 6E 61 74 69 6F 6E 20 03
The destination diskette's name for the mount prompt and the error report (4E5DH, 57FDH, 6837H, 6870H, 687CH).
5A51-5A5E
DEFM "** System ** ", 03H 2A 2A 20 53 79 73 74 65 6D 20 2A 2A 20 03
The system diskette's name for the mount prompt, through the control block at 5942H.
5A5F-5A66
DEFM "Sector ", 03H 53 65 63 74 6F 72 20 03
Displayed by 5812H in a disk error report, before the sector number.
5A67-5A6F
DEFM "Reading ", 03H 52 65 61 64 69 6E 67 20 03
Displayed by 57E7H in a disk error report for an error while reading the source.
5A70-5A78
DEFM "Writing ", 03H 57 72 69 74 69 6E 67 20 03
Displayed by 57F0H in a disk error report for an error while writing the destination.
5A79-5A83
DEFM "Verifying ", 03H 56 65 72 69 66 79 69 6E 67 20 03
Displayed by 57F7H in a disk error report, and by 57A2H when the whole destination is verified.
5A84-5A87
DEFM "CPR", 00H 43 50 52 00
The replies for 58C8H, in reply number order: C (0, cancel), P (1, proceed), R (2, retry); 00H ends the list.
5A88-5AB2
DEFM "Reply C (Cancel), R (Retry) or P (Proceed)", 0DH 52 65 70 6C 79 20 43 20 28 43 61 6E 63 65 6C 29 2C 20 52 20 28 52 65 74 72 79 29 20 6F 72 20 50 20 28 50 72 6F 63 65 65 64 29 0D
The prompt that 58E4H displays after the list at 5A84H.
5AB3-5AB5
DEFM "NY", 00H 4E 59 00
The replies for 58DEH: N (0) and Y (1); 00H ends the list.
5AB6-5AC1
DEFM " (Y or N) ", 03H 20 20 28 59 20 6F 72 20 4E 29 20 03
The prompt that 58E4H displays after the list at 5AB3H.
5AC2-5AD7
DEFM "Diskette/GAT Overflow", 0DH 44 69 73 6B 65 74 74 65 2F 47 41 54 20 4F 76 65 72 66 6C 6F 77 0D
Displayed by 5240H when a diskette has more lumps than the GAT can describe.
5AD8-5AE4
DEFM "Disk Full - ", 03H 44 69 73 6B 20 46 75 6C 6C 20 2D 20 03
Displayed by 53C6H in a COPY by file when a file does not fit, before its name.
5AE5-5B16
DEFB 82H, 20H, 00H / DEFW 4300H / DEFB 00H, 00H, FFH, 00H, 00H / DEFW 0000H, 015EH / DEFB 00H, 1FH, FFH x 34 82 20 00 00 43 00 00 FF 00 00 00 00 5E 01 00 1F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
Source FCB (50 bytes). As loaded it is open (bit 7) with bit 1 set, so that its NEXT (5AEFH) and EOF (5AF1H) are sector numbers on the diskette: that is how a diskette COPY uses it. Buffer address 4300H at 5AE8H, drive 5AEBH, DEC 5AECH, EOF byte offset 5AEDH. The first extent element (5AF3H) is lump 0 with granule byte 1FH. 6352H sets the EOF to the source diskette's size; a file COPY copies its filespec over it (4DB3H, 6F4DH) and opens it.
5B17-5B48
DEFB 82H, 60H, 00H / DEFW 0000H / DEFB 00H, 00H, FFH, 00H, 00H / DEFW 0000H, FFFFH / DEFB 00H, 1FH, FFH x 34 82 60 00 00 00 00 00 FF 00 00 00 00 FF FF 00 1F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
Destination FCB (50 bytes), set up the same way: buffer 5B1AH, drive 5B1DH, DEC 5B1EH, EOF byte offset 5B1FH, NEXT 5B21H, EOF 5B23H. A file COPY copies its filespec over it (4E8AH).
5B49-5B56
DEFB 82H, 60H, 00H / DEFW 4300H / DEFB 00H, 00H, FFH, 00H, 00H / DEFW 0000H, FFFFH 82 60 00 00 43 00 00 FF 00 00 00 00 FF FF
FCB (14 bytes) for reading sectors of the system diskette in drive 0 by their number on the diskette (bit 1 set): 6427H sets its NEXT (5B53H) to 2 to read the PDRIVE sector into 4300H (642DH points here).

5B57H - Patch Sets for TI Flag M (Data)

Three records of four bytes, then 00H. Each record: the directory slot of the module the patches belong to (02H SYS0/SYS, 04H SYS2/SYS, 05H SYS3/SYS), a flag byte whose bit 5 shows that the patches are in, and the address of the patch list. Each list entry is the address to patch, a byte count and the bytes; 0000H ends a list. The loop at 55F6H-5640H exchanges the listed bytes with memory whenever bit 5 of the current drive's PDRIVE flags (4282H, TI flag M) and the record's bit 5 differ, so the same call puts the patches in and takes them out.

5B57-5B5A
DEFB 02H, 00H / DEFW 5B64H 02 00 64 5B
Patch set for SYS0/SYS (slot 02H): the flag byte (bit 5 = the patches are in), and the patch list at 5B64H. Read first by the loop at 55FBH (55F6H points here).
5B5B-5B5E
DEFB 04H, 00H / DEFW 5BA3H 04 00 A3 5B
Patch set for SYS2/SYS (slot 04H): the flag byte (bit 5 = the patches are in), and the patch list at 5BA3H.
5B5F-5B62
DEFB 05H, 00H / DEFW 5BE1H 05 00 E1 5B
Patch set for SYS3/SYS (slot 05H): the flag byte (bit 5 = the patches are in), and the patch list at 5BE1H.
5B63
DEFB 00H 00
00H ends the patch sets: the CP 02H at 563CH gives the CARRY FLAG for it and the loop stops.

5B64H - Patch List for SYS0/SYS (Data)

Exchanged while SYS0/SYS is resident (always), when the current drive has TI flag M.

5B64-5B67
DEFW 45E8H / DEFB 01H, A8H E8 45 01 A8
SYS0/SYS 45E8H: the operand of the LD A,A9H at 45E7H (the controller command that writes a sector with the directory mark) is exchanged with A8H, the command for the normal mark.
5B68-5B6B
DEFW 45ECH / DEFB 01H, A9H EC 45 01 A9
SYS0/SYS 45ECH: the operand of the LD A,A8H at 45EBH (the command for a normal write) is exchanged with A9H, the command for the directory mark.
5B6C-5B71
DEFW 46E7H / DEFB 03H, C3H, 0BH, 5CH E7 46 03 C3 0B 5C
SYS0/SYS 46E7H-46E9H: the EI / POP BC / RET at the end of the sector routine are exchanged with JP 5C0BH, which reverses the read result for the two marks.
5B72-5B75
DEFW 47DCH / DEFB 01H, 0DH DC 47 01 0D
SYS0/SYS 47DCH: the operand of the LD A,08H at 47DBH, the number of extents looked at in the FCB, is exchanged with 0DH (13).
5B76-5B7B
DEFW 481CH / DEFB 03H, C3H, 3EH, 5CH 1C 48 03 C3 3E 5C
SYS0/SYS 481CH-481EH: the start of the BIT 3,(IX+01H) at 481CH is exchanged with JP 5C3EH, the end of the extent loop for 13 extents.
5B7C-5B81
DEFW 4837H / DEFB 03H, C3H, 43H, 5CH 37 48 03 C3 43 5C
SYS0/SYS 4837H-4839H: the LD BC,0000H at 4837H is exchanged with JP 5C43H, which allocates through SYS2/SYS when the file has no extent left.
5B82-5B85
DEFW 4893H / DEFB 01H, 00H 93 48 01 00
SYS0/SYS 4893H: the INC BC at 4893H (granule count of an extent is the stored count + 1) is exchanged with NOP.
5B86-5B89
DEFW 4899H / DEFB 01H, 01H 99 48 01 01
SYS0/SYS 4899H: the low byte of the LD A,(4302H) at 4898H is exchanged with 01H, so the directory lump is taken from byte 1 of the boot sector (4301H) instead of byte 2.
5B8A-5B8F
DEFW 48DDH / DEFB 03H, C3H, 1EH, 5CH DD 48 03 C3 1E 5C
SYS0/SYS 48DDH-48DFH: the PUSH AF / AND 1FH at 48DDH is exchanged with JP 5C1EH, which finds an entry among five 48-byte entries per directory sector.
5B90-5B93
DEFW 4C2DH / DEFB 01H, 03H 2D 4C 01 03
SYS0/SYS 4C2DH: the operand of the LD A,05H at 4C2CH (sectors per granule, for a granule to a sector number) is exchanged with 03H.
5B94-5B97
DEFW 4C58H / DEFB 01H, 03H 58 4C 01 03
SYS0/SYS 4C58H: the operand of the LD A,05H at 4C57H (the divide by 5, a sector to a granule) is exchanged with 03H.
5B98-5B9B
DEFW 4A24H / DEFB 01H, 21H 24 4A 01 21
SYS0/SYS 4A24H: the opcode of the CALL Z,48C4H at 4A24H (CCH) is exchanged with 21H, LD HL,48C4H, so the directory entry is not written to mark the file updated.
5B9C-5B9F
DEFW 56EBH / DEFB 01H, CDH EB 56 01 CD
SYS6/SYS 56EBH: the opcode of the CALL NZ,570DH at 56EBH (C4H) is exchanged with CDH, an unconditional CALL.
5BA0-5BA1
DEFW 0000H 00 00
0000H ends the SYS0/SYS patch list: the OR E at 5634H gives the Z FLAG for it.
5BA2
DEFB 00H 00
Not used: no instruction or list entry names 5BA2H.

5BA3H - Patch List for SYS2/SYS (Data)

Exchanged while SYS2/SYS is the overlay in 4D00H-51FFH (4288H = 04H).

5BA3-5BA6
DEFW 4EB2H / DEFB 01H, 50H B2 4E 01 50
SYS2/SYS 4EB2H: the operand 1FH of the LD BC,001FH at 4EB1H, the limit of the HIT scan, is exchanged with 50H, 80 HIT bytes.
5BA7-5BAC
DEFW 4ED0H / DEFB 03H, 00H, 00H, 00H D0 4E 03 00 00 00
SYS2/SYS 4ED0H-4ED2H: the operand 20H of the ADD A,20H at 4ECFH and the JR NC,4EBFH at 4ED1H are exchanged with 00H 00H 00H, so the HIT scan takes every byte in turn.
5BAD-5BB0
DEFW 4E20H / DEFB 01H, AFH 20 4E 01 AF
SYS2/SYS 4E20H: the LD A,(HL) at 4E20H (FPDE byte 1) is exchanged with XOR A, so byte 1 of the entry is taken as 00H.
5BB1-5BB4
DEFW 4F68H / DEFB 01H, 00H 68 4F 01 00
SYS2/SYS 4F68H: the operand 01H of the SUB 01H at 4F67H is exchanged with 00H, so the EOF middle and high bytes are taken as stored.
5BB5-5BB8
DEFW 4F7BH / DEFB 01H, 1AH 7B 4F 01 1A
SYS2/SYS 4F7BH: the operand 08H of the LD A,08H at 4F7AH (the bytes of extent elements copied) is exchanged with 1AH (26).
5BB9-5BBC
DEFW 4FAFH / DEFB 01H, 00H AF 4F 01 00
SYS2/SYS 4FAFH: the INC D at 4FAFH is exchanged with NOP.
5BBD-5BC0
DEFW 500AH / DEFB 01H, 00H 0A 50 01 00
SYS2/SYS 500AH: the DEC A at 500AH is exchanged with NOP.
5BC1-5BC6
DEFW 5061H / DEFB 03H, 3EH, 1AH, B7H 61 50 03 3E 1A B7
SYS2/SYS 5061H-5063H: the CALL 50CFH at 5061H (find a free entry for an FXDE) is exchanged with LD A,1AH / OR A, error 1AH (DIRECTORY SPACE FULL).
5BC7-5BCC
DEFW 50D6H / DEFB 03H, C3H, 5BH, 5CH D6 50 03 C3 5B 5C
SYS2/SYS 50D6H-50D8H: the LD A,(431FH) at 50D6H is exchanged with JP 5C5BH, the free entry search over 80 HIT bytes.
5BCD-5BD0
DEFW 5112H / DEFB 01H, 1AH 12 51 01 1A
SYS2/SYS 5112H: the high byte 0AH of the LD BC,0A16H at 5110H (the FFH bytes of a cleared entry) is exchanged with 1AH (26).
5BD1-5BD7
DEFW 5155H / DEFB 04H, 21H, EFH, 5CH, C9H 55 51 04 21 EF 5C C9
SYS2/SYS 5155H-5158H: the start of the password encoder is exchanged with LD HL,5CEFH / RET, so every password gives the code 5CEFH.
5BD8-5BDD
DEFW 4DEFH / DEFB 03H, CDH, 71H, 5CH EF 4D 03 CD 71 5C
SYS2/SYS 4DEFH-4DF1H: the CALL 4E1FH at 4DEFH is exchanged with CALL 5C71H, which first puts two bytes of the system date into the new entry.
5BDE-5BDF
DEFW 0000H 00 00
0000H ends the SYS2/SYS patch list: the OR E at 5634H gives the Z FLAG for it.
5BE0
DEFB 00H 00
Not used: no instruction or list entry names 5BE0H.

5BE1H - Patch List for SYS3/SYS (Data)

Exchanged while SYS3/SYS is the overlay in 4D00H-51FFH (4288H = 05H).

5BE1-5BE4
DEFW 4E3EH / DEFB 01H, 0DH 3E 4E 01 0D
SYS3/SYS 4E3EH: the operand 05H of the LD E,05H at 4E3DH, the extent elements of an entry, is exchanged with 0DH (13).
5BE5-5BE8
DEFW 4E49H / DEFB 01H, 00H 49 4E 01 00
SYS3/SYS 4E49H: the INC A at 4E49H is exchanged with NOP.
5BE9-5BEC
DEFW 4EABH / DEFB 01H, 18H AB 4E 01 18
SYS3/SYS 4EABH: the opcode of the JR Z,4EFFH at 4EABH (28H) is exchanged with 18H, JR.
5BED-5BF1
DEFW 4ECCH / DEFB 02H, 35H, 56H CC 4E 02 35 56
SYS3/SYS 4ECCH-4ECDH: the LD D,(HL) / DEC (HL) at 4ECCH are exchanged with DEC (HL) / LD D,(HL).
5BF2-5BF5
DEFW 4EB7H / DEFB 01H, 2FH B7 4E 01 2F
SYS3/SYS 4EB7H: the operand 1FH of the ADD A,1FH at 4EB6H is exchanged with 2FH.
5BF6-5BF9
DEFW 4E68H / DEFB 01H, 18H 68 4E 01 18
SYS3/SYS 4E68H: the opcode of the JR NZ,4E52H at 4E68H (20H) is exchanged with 18H, JR.
5BFA-5BFF
DEFW 4E4FH / DEFB 03H, C3H, 69H, 5CH 4F 4E 03 C3 69 5C
SYS3/SYS 4E4FH-4E51H: the DEC E / JR NZ,4E3FH at 4E4FH are exchanged with JP 5C69H.
5C00-5C03
DEFW 500FH / DEFB 01H, 00H 0F 50 01 00
SYS3/SYS 500FH: the INC DE at 500FH is exchanged with NOP.
5C04-5C07
DEFW 4E1DH / DEFB 01H, 13H 1D 4E 01 13
SYS3/SYS 4E1DH: the NOP at 4E1DH is exchanged with INC DE.
5C08-5C09
DEFW 0000H 00 00
0000H ends the SYS3/SYS patch list: the OR E at 5634H gives the Z FLAG for it.
5C0A
DEFB 00H 00
Not used: no instruction or list entry names 5C0AH.

5C0BH - Routines Patched into SYS0/SYS, SYS2/SYS and SYS3/SYS for TI Flag M

The patch lists at 5B64H-5C09H put jumps to these routines into SYS0/SYS, SYS2/SYS and SYS3/SYS while the current drive has TI flag M. They run as part of those modules, so their jumps go back into them. 5C0BH replaces the end of SYS0/SYS's sector routine at 46E7H for the read and write commands: a read that ends without an error now reports error 06H and a read that reports error 06H (the other mark) now has no error, so the meaning of the two data address marks is reversed.

5C0B
EI FB
Enable interrupts, as the EI at SYS0/SYS 46E7H that this jump replaced did. SYS0/SYS 46E7H jumps here.
5C0C
POP BC C1
Restore Register Pair BC from the stack, as the POP BC at SYS0/SYS 46E8H did.
5C0D
If the NZ FLAG is set (SYS0/SYS found an error, its code in Register A), JUMP to 5C19H.
5C0F
LD A,(4687H) 3A 87 46
No error. Fetch the controller command used from 4687H (SYS0/SYS), the operand of the LD A,nn at 4686H that issued it, into Register A.
5C12
AND 20H E6 20
AND Register A (the FDC command) with 20H, keeping bit 5, set in a write command (A8H, A9H) and clear in a read command (88H).
5C14
If the NZ FLAG is set (a write), JUMP to 5C1CH to return no error.
5C16
ADD A,06H C6 06
A read that found the normal mark: ADD 06H to Register A (00H), giving error 06H, the code for the directory mark.
5C18
RET C9
RETurn to SYS0/SYS's caller with Register A = 06H and the NZ FLAG.
5C19
CP 06H FE 06
Compare Register A (the error code) against 06H, the directory mark. 5C0DH comes here.
5C1B
RET NZ C0
If the NZ FLAG is set (any other error), RETurn with it.
5C1C
XOR A AF
Error 06H, or a write: set Register A to 00H and the Z FLAG, no error. 5C14H comes here.
5C1D
RET C9
RETurn to SYS0/SYS's caller with no error (Register A = 00H, the Z FLAG).

5C1EH replaces SYS0/SYS 48DDH (the jump to it is put at 48DDH): five 48-byte entries in each directory sector. Entered from SYS0/SYS 48DBH with Register A = the DEC and Register L = the number of the directory sector held in 4300H (FFH to force a read). Returns Register Pair HL pointing to the entry.

5C1E
PUSH BC C5
Save Register Pair BC onto the stack. SYS0/SYS 48DDH jumps here.
5C1F
PUSH HL E5
Save Register Pair HL (Register L = the sector held in 4300H) onto the stack.
5C20
LD L,A 6F
Copy Register A (the DEC) into Register L, the low byte of the dividend.
5C21
LD H,00H 26 00
Load Register H with 00H: Register Pair HL = the DEC.
5C23
LD A,05H 3E 05
Load Register A with 05H, the entries in each sector.
5C25
GOSUB to 4C59H (SYS0/SYS) to divide Register Pair HL (the DEC) by Register A (5): Register Pair HL = the FDE sector's position in the directory, Register A = the entry within the sector.
5C28
LD H,A 67
Copy Register A (the entry number) into Register H.
5C29
LD A,L 7D
Copy Register L (the FDE sector position) into Register A.
5C2A
LD L,H 6C
Copy Register H (the entry number) into Register L.
5C2B
EX (SP),HL E3
Exchange Register Pair HL with the word on top of the stack (Stack Pointer): the entry number goes onto the stack, and Register L gets back the sector held in 4300H.
5C2C
INC A 3C
INCrement Register A (the FDE sector position).
5C2D
INC A 3C
INCrement Register A again: the directory sector number, past the GAT (0) and the HIT (1).
5C2E
CP L BD
Compare Register A (the sector needed) against Register L (the sector held in 4300H).
5C2F
If the NZ FLAG is set (a different sector), GOSUB to 48AFH (SYS0/SYS) to read directory sector Register A into 4300H.
5C32
POP HL E1
Restore Register Pair HL from the stack: Register L = the entry number.
5C33
POP BC C1
Restore Register Pair BC from the stack: the value saved at 5C1EH.
5C34
RET NZ C0
If the NZ FLAG is set (a read error), RETurn with the error code in Register A.
5C35
LD A,30H 3E 30
Load Register A with 30H, 48, the size of an entry.
5C37
GOSUB to 4C37H (SYS0/SYS) to multiply Register L (the entry number) by Register A (48): Register Pair HL = the entry's offset in the sector.
5C3A
LD A,L 7D
Copy Register L (the offset) into Register A.
5C3B
JUMP to 48ECH (SYS0/SYS), which loads Register H with 43H, so Register Pair HL = 4300H plus the offset in Register L, and returns the Z FLAG.

5C3EH replaces SYS0/SYS 481CH and 5C43H replaces SYS0/SYS 4837H in the loop at SYS0/SYS 47DDH that goes through a file's extent elements; the element count (13 with the 47DCH patch) is kept in Register A'.

5C3E
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': Register A = the count of extent elements left (loaded at SYS0/SYS 47DBH and exchanged at 47DDH). SYS0/SYS 481CH jumps here.
5C3F
DEC A 3D
DECrement Register A, the extent elements left.
5C40
If the NZ FLAG is set (more elements), JUMP back to SYS0/SYS 47DDH to look at the next one.
5C43
POP AF F1
Discard a saved word from the stack into Register Pair AF. SYS0/SYS 4837H jumps here.
5C44
POP AF F1
Discard another saved word from the stack into Register Pair AF.
5C45
POP AF F1
Discard a third saved word from the stack into Register Pair AF.
5C46
LD A,(4860H) 3A 60 48
Fetch the byte at 4860H (SYS0/SYS) into Register A: the displacement of SYS0/SYS's JR at 485FH, which SYS0/SYS 47B5H set to 00H for an allocating call or B6H for a read.
5C49
OR A B7
OR Register A (the byte from 4860H) with itself: the Z FLAG for 00H.
5C4A
If the NZ FLAG is set (a read past the file's space), JUMP to SYS0/SYS 485DH, which gives error 3EH (CAN'T EXTEND FILE VIA READ).
5C4D
LD A,(IX+07H) DD 7E 07
Fetch the DEC of the FCB from (IX+07H), byte 7 of the FCB at Index Register IX, into Register A.
5C50
LD (480FH),A 32 0F 48
Store Register A (the DEC) at 480FH (SYS0/SYS), the operand that holds the DEC of the file's last directory entry for SYS2/SYS's allocation.
5C53
LD A,64H 3E 64
Load Register A with 64H, the RST 28H code of SYS2/SYS function 3 (allocate granules).
5C55
GOSUB to 4982H (SYS0/SYS), an RST 28H that calls SYS2/SYS to allocate the granules and returns here.
5C58
JUMP to SYS0/SYS 47B8H to select the FCB's drive and map the FCB's NEXT again, now that the granules exist.

5C5BH replaces SYS2/SYS 50D6H: look for a free entry in the first 80 bytes of the HIT sector at Register Pair HL.

5C5B
LD B,50H 06 50
Load Register B with 50H: 80 HIT bytes. SYS2/SYS 50D6H jumps here.
5C5D
LD A,(HL) 7E
Fetch a HIT byte at Register Pair HL into Register A. 5C63H comes here.
5C5E
OR A B7
OR Register A (the HIT byte) with itself: the Z FLAG for 00H, a free entry.
5C5F
If the Z FLAG is set (free), JUMP to SYS2/SYS 50FEH with Register Pair HL on the free HIT byte.
5C62
INC HL 23
INCrement Register Pair HL to the next HIT byte.
5C63
DECrement Register B (the bytes left) and LOOP BACK to 5C5DH.
5C65
LD A,1AH 3E 1A
No free entry: load Register A with error code 1AH (DIRECTORY SPACE FULL).
5C67
OR A B7
OR Register A (1AH) with itself: the NZ FLAG.
5C68
RET C9
RETurn to SYS2/SYS's caller with error 1AH in Register A and the NZ FLAG.

5C69H replaces SYS3/SYS 4E4FH (DEC E / JR NZ,4E3FH) in the loop over a file's extent elements.

5C69
DEC E 1D
DECrement Register E, the extent elements left (13 with the 4E3EH patch). SYS3/SYS 4E4FH jumps here.
5C6A
If the NZ FLAG is set (more elements), JUMP back to SYS3/SYS 4E3FH.
5C6D
INC HL 23
INCrement Register Pair HL, past one more byte of the entry.
5C6E
JUMP to SYS3/SYS 4E72H to go on after the elements.

5C71H is called in place of SYS2/SYS 4E1FH (the CALL at SYS2/SYS 4DEFH), when SYS2/SYS makes a new directory entry: it first puts two bytes of the system date into the entry.

5C71
INC HL 23
INCrement Register Pair HL to the next byte of the new entry. SYS2/SYS 4DEFH calls here.
5C72
LD A,(421CH) 3A 1C 42
Fetch the system date's month from 421CH (SYS0/SYS) into Register A.
5C75
LD (HL),A 77
Store Register A (the month) at Register Pair HL in the entry.
5C76
INC HL 23
INCrement Register Pair HL to the next byte of the entry.
5C77
LD A,(421AH) 3A 1A 42
Fetch the system date's year from 421AH (SYS0/SYS) into Register A.
5C7A
LD (HL),A 77
Store Register A (the year) at Register Pair HL in the entry.
5C7B
DEC HL 2B
DECrement Register Pair HL back one byte, from the year to the month.
5C7C
DEC HL 2B
DECrement Register Pair HL back to where it was on entry.
5C7D
JUMP to SYS2/SYS 4E1FH, the routine the patched CALL used to reach.

5C80H - Boot Sector Length and Directory Lump

Called from 52F9H while a diskette COPY replaces sector 0 or 1 with SYS6/SYS's boot sector. Register A = the sector number and Register Pair DE = the source sector's data. Returns Register Pair BC = 0100H for the LDIR. For sector 0 the source's directory starting lump (byte 2 of its boot sector) is first copied into the boot sector image, so that the copy finds its directory where the source had it.

5C80
LD BC,0100H 01 00 01
Load Register Pair BC with 0100H: 256 bytes, the whole boot sector for the LDIR at 530FH. 52F9H calls here.
5C83
OR A B7
OR Register A (the sector number, 0 or 1) with itself: the Z FLAG for sector 0.
5C84
RET NZ C0
If the NZ FLAG is set (sector 1), RETurn with Register Pair BC = 0100H.
5C85
INC DE 13
INCrement Register Pair DE to byte 1 of the source's boot sector.
5C86
INC DE 13
INCrement Register Pair DE to byte 2, the directory starting lump.
5C87
LD A,(DE) 1A
Fetch the directory starting lump at Register Pair DE into Register A.
5C88
LD (64BCH),A 32 BC 64
Store Register A (the lump) at 64BCH, byte 2 of SYS6/SYS's boot sector image.
5C8B
DEC DE 1B
DECrement Register Pair DE from byte 2 back to byte 1 of the sector.
5C8C
DEC DE 1B
DECrement Register Pair DE back to the start of the sector, for the LDIR.
5C8D
RET C9
RETurn with Register Pair BC = 0100H and Register Pair DE = the sector.

5C8EH - Set the Destination Buffer

Called from 5479H with Register Pair HL pointing to the sector data to write. Makes it the destination FCB's buffer and sets bit 6 of the FCB's second byte, so that SYS0/SYS moves the EOF only when a write goes past it. This stops a rewrite after a verify error from moving the EOF back.

5C8E
LD (5B1AH),HL 22 1A 5B
Store Register Pair HL (the sector data) at 5B1AH, the destination FCB's buffer address (FCB+3). 5479H calls here.
5C91
SET 6,(IX+01H) DD CB 01 F6
Set bit 6 of (IX+01H), the second byte of the FCB at Index Register IX (5B17H): the EOF only moves forward.
5C95
RET C9
RETurn to 547CH with the destination FCB's buffer set.

5C96H - Set the SYS0/SYS Transfer Loop for a Read

Called from 6BE7H with Register A = A2H, the second byte of INI (fetched from SYS0/SYS 45F5H). It does for the read back after a format what SYS0/SYS 46ABH does for a read: the transfer loop of SYS0/SYS then reads.

5C96
LD (46A6H),A 32 A6 46
Store Register A (A2H) at 46A6H (SYS0/SYS), the second byte of the instruction at 46A5H, which becomes INI. 6BE7H calls here.
5C99
LD A,02H 3E 02
Load Register A with 02H, the first byte count of a read.
5C9B
LD (468FH),A 32 8F 46
Store Register A (02H) at 468FH (SYS0/SYS), the Register B operand of the LD BC at 468DH.
5C9E
RET C9
RETurn to 6BEAH with the transfer loop of SYS0/SYS set for a read.

5C9FH - Unused Bytes

78 bytes of 00H.

5C9F-5CEC
DEFB 00H x 78 00 x 78
Not used: no instruction in SYS6/SYS names 5C9FH-5CECH.

5CEDH - Write a Sector

Reached from 57D1H with Register Pair DE = Index Register IX = the FCB. When the current drive's PDRIVE flags have TI flag M (bit 5 of 4282H), bit 5 of the FCB's third byte is set first, so that SYS0/SYS's write does not mark the file updated in its directory entry.

5CED
LD A,(4282H) 3A 82 42
Fetch the current drive's PDRIVE flags from 4282H (SYS0/SYS) into Register A. 57D1H jumps here.
5CF0
BIT 5,A CB 6F
Test bit 5 of Register A (the 4282H flags): TI flag M of the drive.
5CF2
If the Z FLAG is set (no TI flag M), JUMP to 5CF8H.
5CF4
SET 5,(IX+02H) DD CB 02 EE
Set bit 5 of (IX+02H), the third byte of the FCB at Index Register IX: the FPDE counts as already marked updated, so SYS0/SYS does not mark it.
5CF8
JUMP to 4439H (SYS0/SYS) to write the sector at the NEXT of the FCB at Register Pair DE. 5CF2H comes here.

5CFBH - Sectors to Granules

Called from 6727H with Register Pair HL = a number of sectors and Index Register IX pointing to a working PDRIVE record. Divides by 3 for a diskette with TI flag M in double density, otherwise by 5, the NEWDOS/80 granule size. Returns Register Pair HL = the granules, Register A = the sectors left over.

5CFB
BIT 5,(IX+02H) DD CB 02 6E
Test bit 5 of (IX+02H), the flags (+2) of the PDRIVE record at Index Register IX: TI flag M. 6727H calls here.
5CFF
If the Z FLAG is set (no TI flag M), JUMP to 5D05H with the Z FLAG.
5D01
BIT 0,(IX+07H) DD CB 07 46
Test bit 0 of (IX+07H), the disk I/O flags (+7) of the PDRIVE record at Index Register IX: double density.
5D05
If the Z FLAG is set (not TI flag M in double density), JUMP to 4C57H (SYS0/SYS) to divide Register Pair HL by 5. 5CFFH comes here.
5D08
LD A,03H 3E 03
Load Register A with 03H, three sectors per granule.
5D0A
JUMP to 4C59H (SYS0/SYS) to divide Register Pair HL by Register A (3).

5D0DH - Pointers for the Sector Buffers and File List

Three words that move as COPY runs, with three unused bytes before them.

5D0D-5D0F
DEFB 00H x 3 00 x 3
Not used: no instruction in SYS6/SYS names 5D0DH-5D0FH.
5D10-5D11
DEFW 4300H 00 43
The buffer for reading back a sector during the verify pass (read by 5406H and 5442H): 4300H.
5D12-5D13
DEFW 5D16H 16 5D
Start of the COPY by file list (5D16H as loaded), stored by 525EH and 5E12H and read by 5251H and 6196H.
5D14-5D15
DEFW 5D16H 16 5D
End of the file list, which is also the start of the sector buffers (5D16H as loaded), stored by 5265H and 5E15H and read by the COPY engine (527CH, 5298H, 532CH).

5D16H - COPY by File (Format 6): Format, Read the Include/Exclude List

Reached from 6336H when CBF was given. The destination is formatted first if required (6643H). The source and destination FCBs are then used for real files, so bit 1 of their first bytes is cleared. With ILF= or XLF= the list file (whose filespec 4FACH put into the DOS FCB at 4480H and which 629CH opened) is read into 6491H: one name/ext per line ended by 0DH, lines starting with a semicolon are comments, spaces and empty lines are skipped, each byte is taken modulo 128, and a 0DH on its own ends the list.

5D16
GOSUB to 6643H to check the destination, format it unless NFMT was given, and write its system data. 6336H comes here.
5D19
LD HL,5AE5H 21 E5 5A
Point Register Pair HL to 5AE5H, the source FCB.
5D1C
RES 1,(HL) CB 8E
Clear bit 1 of the byte at Register Pair HL (5AE5H): the source FCB's NEXT and EOF now count sectors within a file, not on the diskette.
5D1E
LD HL,5B17H 21 17 5B
Point Register Pair HL to 5B17H, the destination FCB.
5D21
RES 1,(HL) CB 8E
Clear bit 1 of the byte at Register Pair HL (5B17H): the destination FCB now works within a file too.
5D23
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A.
5D26
AND 30H E6 30
AND Register A (the 5997H flags) with 30H, keeping bit 4 (ILF) and bit 5 (XLF).
5D28
If the Z FLAG is set (no list file), JUMP to 5D86H to choose the files.
5D2A
GOSUB to 568BH to switch to the system diskette and load SYS2/SYS into the overlay area, so that the opens at 5DE3H find it there.
5D2D
LD HL,6491H 21 91 64
Point Register Pair HL to 6491H, where the names of the list file are collected.
5D30
LD DE,4480H 11 80 44
Point Register Pair DE to 4480H, the DOS FCB holding the open list file, for the ROM byte reads.
5D33
LD A,(448CH) 3A 8C 44
Fetch the middle byte of the list file's EOF from 448CH (FCB+12) into Register A: its length in sectors.
5D36
CP 0BH FE 0B
Compare Register A (the EOF sectors) against 0BH: the NO CARRY FLAG for 11 sectors or more.
5D38
If the NO CARRY FLAG is set (the list file is too long to fit below 7100H), JUMP to 5D65H for error 01H.

Line Loop: Register Pair HL is the end of the names collected, Register B counts the characters of one name.

5D3A
LD B,0DH 06 0D
Load Register B with 0DH: at most 13 characters in one name, counting the 0DH. 5D3FH, 5D43H, 5D4EH and 5D55H come here.
5D3C
GOSUB to 5D71H to read the next byte of the list file into Register A. It returns the Z FLAG for 0DH.
5D3F
If the Z FLAG is set (an empty line), LOOP BACK to 5D3AH.
5D41
CP 20H FE 20
Compare Register A (the first character) against 20H, a space.
5D43
If the Z FLAG is set (a space), LOOP BACK to 5D3AH and skip it.
5D45
CP 3BH FE 3B
Compare Register A (the first character) against 3BH, a semicolon.
5D47
If the NZ FLAG is set (not a comment), JUMP to 5D53H to store the character.
5D49
A comment: GOSUB to 5D71H to read the next byte into Register A. 5D4CH comes here.
5D4C
If the NZ FLAG is set (not 0DH yet), LOOP BACK to 5D49H.
5D4E
JUMP to 5D3AH for the next line, with Register Pair HL unchanged.
5D50
GOSUB to 5D71H to read the next byte of the name into Register A. 5D63H comes here.
5D53
LD (HL),A 77
Store Register A (the character, or the 0DH that ends the name) at Register Pair HL in the list. 5D47H comes here.
5D54
INC HL 23
INCrement Register Pair HL to the next byte of the list. INC HL does not change the flags.
5D55
If the Z FLAG is set (the 0DH has been stored), JUMP to 5D3AH for the next line.
5D57
SUB 2FH D6 2F
SUBtract 2FH from Register A (the character): a slash becomes 0, the digits 1 to 10.
5D59
CP 0BH FE 0B
Compare Register A against 0BH: the CARRY FLAG for a slash or a digit.
5D5B
If the CARRY FLAG is set, JUMP to 5D63H to count the character.
5D5D
SUB 12H D6 12
SUBtract 12H from Register A: the letter A now gives 0.
5D5F
CP 1AH FE 1A
Compare Register A against 1AH: the CARRY FLAG for a letter A-Z.
5D61
If the NO CARRY FLAG is set (not a letter either), JUMP to 5D65H for error 01H.
5D63
DECrement Register B (the characters left) and LOOP BACK to 5D50H. 5D5BH comes here.
5D65
LD A,01H 3E 01
A bad character or a name of more than 12 characters: load Register A with error code 01H (BAD FILE DATA). 5D38H and 5D61H come here.
5D67
PUSH AF F5
Save Register Pair AF (Register A = the error code) onto the stack. 5D7FH comes here, and 629FH when the list file cannot be opened.
5D68
LD HL,6283H 21 83 62
Point Register Pair HL to 6283H, the message ILF/XLF FILE .
5D6B
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
5D6E
JUMP to 521BH, which starts a new line and ends the command with the error code pushed at 5D67H.
5D71
GOSUB to 0013H, the ROM routine that reads a byte from the device or file at Register Pair DE (the list file's FCB at 4480H) into Register A. 5D3CH, 5D49H, 5D50H and 5D78H come here.
5D74
If the NZ FLAG is set (an error or the end of the file), JUMP to 5D7DH.
5D76
AND 7FH E6 7F
AND Register A (the byte) with 7FH, keeping bits 0-6: every byte is taken modulo 128.
5D78
If the Z FLAG is set (a 00H byte), LOOP BACK to 5D71H and skip it.
5D7A
CP 0DH FE 0D
Compare Register A (the byte) against 0DH: the Z FLAG at the end of a line.
5D7C
RET C9
RETurn with the byte in Register A and the Z FLAG for 0DH.
5D7D
CP 1CH FE 1C
Compare Register A (the error code) against 1CH (END OF FILE ENCOUNTERED). 5D74H comes here.
5D7F
If the NZ FLAG is set (any other error), JUMP to 5D67H to report it.
5D81
LD A,0DH 3E 0D
The end of the list file: load Register A with 0DH.
5D83
LD (HL),A 77
Store Register A (0DH) at Register Pair HL, ending any unfinished name.
5D84
INC HL 23
INCrement Register Pair HL to the next byte of the list.
5D85
LD (HL),A 77
Store Register A (0DH) at Register Pair HL again: an empty name ends the list. Execution falls into 5D86H; the return address of the call to 5D71H stays on the stack, and the command's exits reset the Stack Pointer.

5D86H - COPY by File: Choose the Source Files

The source directory's HIT sector (one byte per DEC: 00H free, otherwise the hash code of the file's name) is copied to 6291H and used as the table of candidates. ILF starts from an empty table and puts back the hash code of each listed file; XLF clears each listed file's byte. Then every directory entry is looked at in DEC order; the files that pass the USR, UPD, /ext and system file tests (and the operator's answer with CFWO) get a 3-byte entry in the file list from 6491H: flags (80H, plus bit 6 for a system file that must keep its DEC), the source DEC and the hash code.

5D86
GOSUB to 5578H to switch to the source diskette. 5D28H comes here.
5D89
GOSUB to 6162H to read the source HIT sector into 4300H and copy it to 6291H-6390H.
5D8C
GOSUB to 6178H to work out the size of the source directory: Register A = the FDE sectors, Register C = the directory granules.
5D8F
LD (597CH),A 32 7C 59
Store Register A (the FDE sector count) at 597CH, the source's directory size, read by 5EAAH.
5D92
LD A,C 79
Copy Register C (the directory granules) into Register A.
5D93
LD (59C0H),A 32 C0 59
Store Register A (the directory granules) at 59C0H, byte +9 (DDGA) of the source's working record.
5D96
LD HL,(593CH) 2A 3C 59
Fetch the highest address COPY may use from 593CH into Register Pair HL.
5D99
LD DE,FFE8H 11 E8 FF
Load Register Pair DE with FFE8H, -24, the size of one entry copy.
5D9C
ADD HL,DE 19
ADD Register Pair DE (-24) to Register Pair HL: the last address at which a 24-byte copy of a directory entry still fits.
5D9D
LD (61DBH),HL 22 DB 61
Store Register Pair HL (the limit) at 61DBH, the operand of the LD DE,nnnn at 61DAH that 61D6H compares with.
5DA0
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A.
5DA3
AND 30H E6 30
AND Register A (the 5997H flags) with 30H, keeping bit 4 (ILF) and bit 5 (XLF).
5DA5
If the Z FLAG is set (no list file), JUMP to 5E0FH.
5DA7
AND 10H E6 10
AND Register A (10H or 20H) with 10H, keeping bit 4 (ILF).
5DA9
LD C,A 4F
Copy Register A into Register C: 10H for ILF, 00H for XLF.
5DAA
If the Z FLAG is set (XLF), JUMP to 5DB5H with the HIT copy as it is.
5DAC
XOR A AF
ILF: set Register A to 00H (XOR A), the value of a DEC that is not a candidate.
5DAD
LD B,A 47
Copy Register A (00H) into Register B: 256 bytes for the DJNZ.
5DAE
LD HL,6291H 21 91 62
Point Register Pair HL to 6291H, the HIT copy.
5DB1
LD (HL),A 77
Store Register A (00H) at Register Pair HL: the DEC is not a candidate. 5DB3H comes here.
5DB2
INC HL 23
INCrement Register Pair HL to the next byte of the HIT copy.
5DB3
DECrement Register B and LOOP BACK to 5DB1H until all 256 bytes are cleared.
5DB5
LD HL,6491H 21 91 64
Point Register Pair HL to 6491H, the names read from the list file. 5DAAH comes here.

Name Loop: Register Pair HL walks the names; each is opened on the source diskette to find its DEC.

5DB8
LD A,(HL) 7E
Fetch the first character of the name at Register Pair HL into Register A. 5DEAH and 5E05H come here.
5DB9
CP 0DH FE 0D
Compare Register A (the first character) against 0DH: an empty name.
5DBB
If the Z FLAG is set (the end of the names), JUMP to 5E07H.
5DBD
LD DE,447FH 11 7F 44
Point Register Pair DE to 447FH, one byte before the DOS FCB at 4480H.
5DC0
INC DE 13
INCrement Register Pair DE to the next byte of the FCB. 5DC6H comes here.
5DC1
LD A,(HL) 7E
Fetch a character of the name at Register Pair HL into Register A.
5DC2
CP 0DH FE 0D
Compare Register A (the character) against 0DH, the end of the name.
5DC4
LD (DE),A 12
Store Register A (the character) in the FCB at Register Pair DE. LD does not change the flags.
5DC5
INC HL 23
INCrement Register Pair HL to the next character. INC HL does not change the flags.
5DC6
If the NZ FLAG is set (not the end), LOOP BACK to 5DC0H.
5DC8
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the 0DH just stored in the FCB, Register Pair DE = the next name.
5DC9
LD (HL),3AH 36 3A
Store 3AH, a colon, at Register Pair HL over the 0DH: a drive number follows.
5DCB
INC HL 23
INCrement Register Pair HL to the byte after the colon.
5DCC
LD A,(594CH) 3A 4C 59
Fetch the source drive number from 594CH into Register A.
5DCF
LD B,64H 06 64
Load Register B with 64H, 100, the value of a hundreds digit.
5DD1
GOSUB to 61CBH to store the hundreds digit of Register A at Register Pair HL if Register A is 100 or more. Register A returns the remainder.
5DD4
LD B,0AH 06 0A
Load Register B with 0AH, 10, the value of a tens digit.
5DD6
GOSUB to 61CBH to store the tens digit of Register A at Register Pair HL if Register A is 10 or more.
5DD9
ADD A,30H C6 30
ADD 30H to Register A (the units): the ASCII digit.
5DDB
LD (HL),A 77
Store Register A (the units digit) at Register Pair HL.
5DDC
INC HL 23
INCrement Register Pair HL past the units digit in the FCB.
5DDD
LD (HL),0DH 36 0D
Store 0DH at Register Pair HL, ending the filespec NAME/EXT:d.
5DDF
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the next name in the list again.
5DE0
LD DE,4480H 11 80 44
Point Register Pair DE to 4480H, the DOS FCB with the filespec.
5DE3
GOSUB to 4424H (SYS0/SYS) to open the file on the source diskette, only to find its directory entry. SYS2/SYS leaves the DEC at 4F56H and the hash code at 4D6EH.
5DE6
If the Z FLAG is set (the file was found and opened), JUMP to 5DF1H.
5DE8
CP 18H FE 18
Compare Register A (the error code) against 18H (FILE NOT IN DIRECTORY).
5DEA
If the Z FLAG is set (a listed file need not be on the source), LOOP BACK to 5DB8H for the next name.
5DEC
CP 19H FE 19
Compare Register A (the error code) against 19H (FILE ACCESS DENIED): the entry was found, only the password did not match.
5DEE
If the NZ FLAG is set (any other error), JUMP to 521AH to end the command with it.
5DF1
LD A,(4F56H) 3A 56 4F
Fetch the file's DEC from 4F56H, the operand inside SYS2/SYS's FCB building code where the open left it, into Register A. 5DE6H comes here.
5DF4
PUSH HL E5
Save Register Pair HL (the next name) onto the stack.
5DF5
LD HL,6291H 21 91 62
Point Register Pair HL to 6291H, the HIT copy.
5DF8
LD E,A 5F
Copy Register A (the DEC) into Register E, the low byte of the offset.
5DF9
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the DEC.
5DFB
ADD HL,DE 19
ADD Register Pair DE (the DEC) to Register Pair HL: the file's byte in the HIT copy.
5DFC
LD A,C 79
Copy Register C (10H for ILF, 00H for XLF) into Register A.
5DFD
OR A B7
OR Register A with itself: the Z FLAG for XLF.
5DFE
If the Z FLAG is set (XLF), JUMP to 5E03H with Register A = 00H, which takes the file out.
5E00
LD A,(4D6EH) 3A 6E 4D
ILF: fetch the file's hash code from 4D6EH, the operand inside SYS2/SYS where the open left it, into Register A.
5E03
LD (HL),A 77
Store Register A (the hash code for ILF, 00H for XLF) at Register Pair HL in the HIT copy. 5DFEH comes here.
5E04
POP HL E1
Restore Register Pair HL from the stack: the next name.
5E05
LOOP BACK to 5DB8H for the next name in the list at Register Pair HL.
5E07
LD A,05H 3E 05
Load Register A with 05H, the number of SYS3/SYS. 5DBBH comes here.
5E09
GOSUB to 568DH to switch to the system diskette and load SYS3/SYS into the overlay area again (SYS2/SYS replaced it).
5E0C
GOSUB to 5578H to switch back to the source diskette.
5E0F
LD HL,6491H 21 91 64
Point Register Pair HL to 6491H, where the file list is built (over the names, which are not needed any more). 5DA5H and 5E7FH come here.
5E12
LD (5D12H),HL 22 12 5D
Store Register Pair HL (6491H) at 5D12H, the start of the file list.
5E15
LD (5D14H),HL 22 14 5D
Store Register Pair HL (6491H) at 5D14H, the end of the file list: it is empty.
5E18
LD C,00H 0E 00
Load Register C with 00H, the first DEC to look at.

Entry Loop: Register C is the DEC being looked at.

5E1A
GOSUB to 619DH to look at the directory entry of DEC Register C. It returns the Z FLAG for a primary entry in use that is still a candidate, with Register Pair HL pointing to it and Register B = its hash code. 5EB0H comes here.
5E1D
If the NZ FLAG is set (free, BOOT/SYS or DIR/SYS, not a primary entry, or not a candidate), JUMP to 5EAAH for the next DEC.
5E20
GOSUB to 61F6H: Register A = bit 5 of 4282H, the NZ FLAG when the source drive has TI flag M.
5E23
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A. LD does not change the flags.
5E26
If the NZ FLAG is set (TI flag M: the updated flag is not kept on such a diskette), JUMP to 5E32H without the UPD test.
5E28
BIT 0,A CB 47
Test bit 0 of Register A (the 5996H flags): UPD, only updated files.
5E2A
If the Z FLAG is set (no UPD), JUMP to 5E32H.
5E2C
INC HL 23
INCrement Register Pair HL to byte 1 of the directory entry.
5E2D
BIT 5,(HL) CB 6E
Test bit 5 of the byte at Register Pair HL (entry byte 1): the updated flag, set by SYS0/SYS when the file is written.
5E2F
DEC HL 2B
DECrement Register Pair HL back to byte 0 of the entry. DEC HL does not change the flags.
5E30
If the Z FLAG is set (not updated), JUMP to 5EAAH and skip the file.
5E32
BIT 4,A CB 67
Test bit 4 of Register A (5996H): USR. 5E26H and 5E2AH come here.
5E34
If the Z FLAG is set (no USR), JUMP to 5E3EH.
5E36
BIT 6,(HL) CB 76
Test bit 6 of the entry's flag byte at Register Pair HL: a system file.
5E38
If the NZ FLAG is set (a system file), JUMP to 5EAAH and skip it.
5E3A
BIT 3,(HL) CB 5E
Test bit 3 of the entry's flag byte at Register Pair HL: an invisible file.
5E3C
If the NZ FLAG is set (invisible), JUMP to 5EAAH and skip it.
5E3E
BIT 1,A CB 4F
Test bit 1 of Register A (5996H): /ext. 5E34H comes here.
5E40
If the Z FLAG is set (no /ext), JUMP to 5E5BH.
5E42
PUSH HL E5
Save Register Pair HL (the entry) onto the stack.
5E43
PUSH DE D5
Save Register Pair DE (the caller's value) onto the stack for the comparison.
5E44
PUSH BC C5
Save Register Pair BC (Register C = the DEC, Register B = the hash code) onto the stack.
5E45
LD DE,000DH 11 0D 00
Load Register Pair DE with 000DH, the offset of the extension in a directory entry.
5E48
ADD HL,DE 19
ADD Register Pair DE (13) to Register Pair HL: the file's extension.
5E49
LD DE,624CH 11 4C 62
Point Register Pair DE to 624CH, the extension given with /ext.
5E4C
LD B,03H 06 03
Load Register B with 03H, the three extension characters.
5E4E
LD A,(DE) 1A
Fetch a character of the wanted extension at Register Pair DE into Register A. 5E54H comes here.
5E4F
CP (HL) BE
Compare Register A against the file's extension character at Register Pair HL.
5E50
INC DE 13
INCrement Register Pair DE to the next wanted character. INC DE does not change the flags.
5E51
INC HL 23
INCrement Register Pair HL to the next character of the file's extension. INC HL does not change the flags.
5E52
If the NZ FLAG is set (different), JUMP to 5E56H with the NZ FLAG.
5E54
DECrement Register B and LOOP BACK to 5E4EH for all three characters; at the end the Z FLAG remains.
5E56
POP BC C1
Restore Register Pair BC from the stack: Register C = the DEC, Register B = the hash code. 5E52H comes here.
5E57
POP DE D1
Restore Register Pair DE from the stack: the value saved at 5E43H.
5E58
POP HL E1
Restore Register Pair HL from the stack: the entry.
5E59
If the NZ FLAG is set (another extension), JUMP to 5EAAH and skip the file.
5E5B
LD D,(HL) 56
Load Register D with the entry's flag byte at Register Pair HL. 5E40H comes here.
5E5C
BIT 6,D CB 72
Test bit 6 of Register D (the flags): a system file.
5E5E
If the NZ FLAG is set (a system file), GOSUB to 61EAH, which returns the NZ FLAG when the source or destination has TI flag M.
5E61
If the NZ FLAG is set (a system file and a TI flag M diskette), JUMP to 5EAAH: system files are not copied then.
5E63
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H into Register A.
5E66
BIT 6,A CB 77
Test bit 6 of Register A (5995H): CFWO, check each file with the operator.
5E68
If the Z FLAG is set (no CFWO), JUMP to 5E87H to take the file.
5E6A
PUSH DE D5
Save Register Pair DE (Register D = the file's flags) onto the stack.
5E6B
PUSH BC C5
Save Register Pair BC (Register C = the DEC, Register B = the hash code) onto the stack.
5E6C
GOSUB to 58A0H to display the NAME/EXT of the directory entry at Register Pair HL.
5E6F
LD HL,625CH 21 5C 62
Point Register Pair HL to 625CH, the replies RQNY followed by the question COPY IT? (Y/N/R/Q).
5E72
GOSUB to 58E4H to ask. Register A returns 0 for R, 1 for Q, 2 for N, 3 for Y, with the Z FLAG for R.
5E75
POP BC C1
Restore Register Pair BC from the stack: Register C = the DEC, Register B = the hash code.
5E76
POP DE D1
Restore Register Pair DE from the stack: Register D = the file's flags.
5E77
If the NZ FLAG is set (not R), JUMP to 5E81H.
5E79
LD HL,6D5DH 21 5D 6D
R, restart the questions: point Register Pair HL to 6D5DH, the codes that clear the screen.
5E7C
GOSUB to 4467H (SYS0/SYS) to send the codes at Register Pair HL to the display, clearing the screen.
5E7F
JUMP to 5E0FH to empty the file list and start again from DEC 0.
5E81
DEC A 3D
DECrement Register A (the reply): 0 for Q. 5E77H comes here.
5E82
If the Z FLAG is set (Q, no more files), JUMP to 5EB3H to copy the files chosen so far.
5E84
DEC A 3D
DECrement Register A (the reply) again: 0 for N.
5E85
If the Z FLAG is set (N), JUMP to 5EAAH and skip the file.
5E87
LD HL,(5D14H) 2A 14 5D
Y, or no question: fetch the end of the file list from 5D14H into Register Pair HL. 5E68H comes here.
5E8A
LD (HL),80H 36 80
Store 80H at Register Pair HL, the flags of a new list entry (bit 7, entry used).
5E8C
BIT 6,D CB 72
Test bit 6 of Register D (the file's directory flags): a system file.
5E8E
If the Z FLAG is set (not a system file), JUMP to 5EA2H.
5E90
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A.
5E93
BIT 3,A CB 5F
Test bit 3 of Register A (the 5997H flags): NFMT, the destination is not formatted.
5E95
If the NZ FLAG is set (the destination is not formatted, so its entries stay where they are), JUMP to 5EA2H.
5E97
LD A,C 79
Copy Register C (the source DEC) into Register A for the position tests.
5E98
CP 80H FE 80
Compare Register A (the DEC) against 80H: the NO CARRY FLAG for entry 4 or higher in its sector (DEC bits 5-7).
5E9A
If the NO CARRY FLAG is set (entry 4 to 7 of its sector), JUMP to 5EA2H.
5E9C
AND 18H E6 18
AND Register A (the DEC) with 18H, keeping bits 3 and 4: not 0 for the ninth FDE sector or a later one.
5E9E
If the NZ FLAG is set (the ninth FDE sector or later), JUMP to 5EA2H.
5EA0
SET 6,(HL) CB F6
Set bit 6 of the list entry's flags at Register Pair HL: a system file in one of the first four entries of the first eight FDE sectors must get the same DEC on the destination.
5EA2
INC HL 23
INCrement Register Pair HL to the list entry's second byte. 5E8EH, 5E95H, 5E9AH and 5E9EH come here.
5EA3
LD (HL),C 71
Store Register C (the source DEC) at Register Pair HL.
5EA4
INC HL 23
INCrement Register Pair HL to the list entry's third byte.
5EA5
LD (HL),B 70
Store Register B (the hash code) at Register Pair HL; 5F5AH, 5FE0H or 6116H replace it with the destination DEC once the file has its destination entry.
5EA6
INC HL 23
INCrement Register Pair HL past the list entry.
5EA7
LD (5D14H),HL 22 14 5D
Store Register Pair HL (the new end of the list) at 5D14H.
5EAA
LD HL,597CH 21 7C 59
Point Register Pair HL to 597CH, the source's FDE sector count. 5E1DH, 5E30H, 5E38H, 5E3CH, 5E59H, 5E61H and 5E85H come here.
5EAD
GOSUB to 61BAH to step Register C to the next DEC. It returns the CARRY FLAG past the last one.
5EB0
If the NO CARRY FLAG is set (more entries), JUMP to 5E1AH.

5EB3H - COPY by File: Collect the Source Directory Entries

For each file in the list the first 24 bytes of its source directory entry are copied into memory after the list, 24 bytes per file (61D6H), and bit 4 of its list flags is set. When memory runs out the files collected so far are handled on the destination (5EE4H), and the collecting starts again in the same spaces. After the last file 5EE4H is entered once more with 60BFH as its return address.

5EB3
GOSUB to 6190H: 61D8H is set to the end of the file list (the first 24-byte space) and Register Pair HL to three bytes before the list's start. 5E82H comes here.
5EB6
GOSUB to 5699H to step Register Pair HL to the first list entry. It returns the Z FLAG if the list is empty.
5EB9
If the Z FLAG is set (no files chosen), JUMP to 552DH to display DONE and end the command.

Collect Loop: Register Pair HL is the list entry.

5EBC
PUSH HL E5
Save Register Pair HL (the list entry) onto the stack. 5ECCH and 5EDEH come here.
5EBD
GOSUB to 61D6H to take the next 24-byte space into Register Pair DE. It returns the CARRY FLAG if the space is below the limit at 61DBH.
5EC0
If the CARRY FLAG is set (room), JUMP to 5ECEH.
5EC2
Memory is full: GOSUB to 5EE4H to handle the files collected so far on the destination.
5EC5
GOSUB to 5578H to switch back to the source diskette.
5EC8
GOSUB to 6190H to start the 24-byte spaces again from the end of the list.
5ECB
POP HL E1
Restore Register Pair HL from the stack: the list entry that did not fit.
5ECC
JUMP to 5EBCH to collect the list entry at Register Pair HL again.
5ECE
INC HL 23
INCrement Register Pair HL to the list entry's source DEC. 5EC0H comes here.
5ECF
LD A,(HL) 7E
Fetch the source DEC at Register Pair HL into Register A.
5ED0
GOSUB to 56EFH to point Register Pair HL to the source directory entry of DEC Register A, reading its sector if needed.
5ED3
LD BC,0018H 01 18 00
Load Register Pair BC with 0018H: 24 bytes, the entry up to its first extent elements.
5ED6
LDIR ED B0
Copy Register Pair BC (24) bytes from Register Pair HL (the directory entry) to Register Pair DE (the space).
5ED8
POP HL E1
Restore Register Pair HL from the stack: the list entry.
5ED9
SET 4,(HL) CB E6
Set bit 4 of the list entry's flags at Register Pair HL: its directory bytes are in memory for this group.
5EDB
GOSUB to 5699H to step Register Pair HL to the next list entry. It returns the Z FLAG at the end.
5EDE
If the NZ FLAG is set (more files), LOOP BACK to 5EBCH.
5EE0
LD HL,60BFH 21 BF 60
Point Register Pair HL to 60BFH, where the COPY by file goes on after the last group.
5EE3
PUSH HL E5
Save Register Pair HL (60BFH) onto the stack as the return address, and fall into 5EE4H for the last group.

5EE4H - COPY by File: Make the Destination Directory Entries

Handles the files of the current group (list flag bit 4 set, their 24 source directory bytes collected after the list). With NFMT the destination directory is searched first, entry by entry, for files with the same name: such a file gets the source's EOF and record length and keeps its place, and its space past the new EOF is freed through SYS3/SYS (60A9H). Then, unless DFO was given, the remaining files of the group that are system files kept in place (list flag bit 6) get the same DEC as on the source and their granules at the same distance from the directory; the other files get their entries at 60BFH. The HIT and GAT copies are written back at 6092H.

5EE4
GOSUB to 557DH to switch to the destination diskette. 5EC2H calls here; 5EE3H falls in with 60BFH as the return address.
5EE7
GOSUB to 6162H to read the destination HIT sector into 4300H and copy it to 6291H-6390H.
5EEA
GOSUB to 6178H to work out the size of the destination directory: Register A = the FDE sectors, Register C = the directory granules.
5EED
LD (597DH),A 32 7D 59
Store Register A (the FDE sector count) at 597DH, the destination's directory size.
5EF0
LD A,C 79
Copy Register C (the directory granules) into Register A.
5EF1
LD (59CEH),A 32 CE 59
Store Register A (the directory granules) at 59CEH, byte +9 (DDGA) of the destination's working record.
5EF4
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A.
5EF7
BIT 3,A CB 5F
Test bit 3 of Register A (5997H): NFMT, copying onto an existing diskette.
5EF9
If the Z FLAG is set (a newly formatted destination with an empty directory), JUMP to 5F92H.
5EFC
LD C,00H 0E 00
Load Register C with 00H, the first destination DEC.

Destination Entry Loop: Register C is the destination DEC; each file in use is compared with the files of the group by name.

5EFE
GOSUB to 619DH to look at the destination entry of DEC Register C. It returns the Z FLAG for a primary entry in use, with Register Pair HL pointing to it. 5F8FH comes here.
5F01
If the NZ FLAG is set (no file there), JUMP to 5F89H for the next DEC.
5F04
LD (5F1EH),HL 22 1E 5F
Store Register Pair HL (the destination entry in 4300H) at 5F1EH, the operand of the LD HL,nnnn at 5F1DH.
5F07
GOSUB to 6190H to start the 24-byte spaces again (61D8H) and set Register Pair HL to three bytes before the list's start.
5F0A
GOSUB to 5699H to step Register Pair HL to the next list entry. It returns the Z FLAG at the end. 5F11H, 5F18H and 5F30H come here.
5F0D
If the Z FLAG is set (no file of the group has this name), JUMP to 5F89H for the next destination DEC.
5F0F
BIT 4,(HL) CB 66
Test bit 4 of the list entry's flags at Register Pair HL: the file belongs to the current group.
5F11
If the Z FLAG is set (not in this group), LOOP BACK to 5F0AH.
5F13
GOSUB to 61D6H to take this file's 24-byte copy into Register Pair DE (the spaces are taken in list order, as 5EB3H filled them).
5F16
BIT 5,(HL) CB 6E
Test bit 5 of the list entry's flags at Register Pair HL: the file already has its destination entry.
5F18
If the NZ FLAG is set (already has one), LOOP BACK to 5F0AH.
5F1A
PUSH HL E5
Save Register Pair HL (the list entry) onto the stack.
5F1B
LD B,05H 06 05
Load Register B with 05H, the offset of the name in a directory entry.
5F1D
LD HL,0000H 21 00 00
Load Register Pair HL with the address of the destination entry. Self-Modifying Code
The operand at 5F1EH-5F1FH is 0000H in the file; 5F04H stores the entry's address there.
5F20
PUSH HL E5
Save Register Pair HL (the destination entry) onto the stack.
5F21
PUSH DE D5
Save Register Pair DE (the 24-byte copy of the source entry) onto the stack.
5F22
INC HL 23
INCrement Register Pair HL, the destination entry pointer. 5F24H comes here.
5F23
INC DE 13
INCrement Register Pair DE, the source copy pointer.
5F24
DECrement Register B and LOOP BACK to 5F22H: after five steps both point to the name (byte 5).
5F26
LD B,0BH 06 0B
Load Register B with 0BH: 11 characters, the name and extension.
5F28
GOSUB to 6254H to compare Register B characters at Register Pair DE and Register Pair HL. It returns the Z FLAG when they are the same.
5F2B
POP HL E1
Restore Register Pair HL from the stack: the 24-byte source copy.
5F2C
POP DE D1
Restore Register Pair DE from the stack: the destination entry.
5F2D
If the Z FLAG is set (the same name), JUMP to 5F32H.
5F2F
POP HL E1
Restore Register Pair HL from the stack: the list entry.
5F30
JUMP to 5F0AH to try the next file of the group.
5F32
PUSH DE D5
Save Register Pair DE (the destination entry) onto the stack. 5F2DH comes here.
5F33
PUSH BC C5
Save Register Pair BC (Register C = the destination DEC) onto the stack.
5F34
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H, the offset of the EOF low byte.
5F37
ADD HL,BC 09
ADD Register Pair BC (3) to Register Pair HL: byte 3 of the source copy.
5F38
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the source copy's byte 3, Register Pair HL = the destination entry.
5F39
ADD HL,BC 09
ADD Register Pair BC (3) to Register Pair HL: byte 3 of the destination entry.
5F3A
LD A,(DE) 1A
Fetch the EOF low byte from the source copy at Register Pair DE into Register A.
5F3B
LD (HL),A 77
Store Register A (the EOF low byte) at Register Pair HL in the destination entry.
5F3C
INC HL 23
INCrement Register Pair HL to byte 4 of the destination entry, the record length.
5F3D
PUSH AF F5
Save Register Pair AF (Register A = the EOF low byte) onto the stack.
5F3E
INC DE 13
INCrement Register Pair DE to byte 4 of the source copy.
5F3F
LD A,(DE) 1A
Fetch the record length at Register Pair DE into Register A.
5F40
LD (HL),A 77
Store Register A (the record length) at Register Pair HL in the destination entry.
5F41
LD BC,0010H 01 10 00
Load Register Pair BC with 0010H, 16, the distance from byte 4 to byte 20.
5F44
ADD HL,BC 09
ADD Register Pair BC (16) to Register Pair HL: byte 20 of the destination entry.
5F45
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the destination entry's byte 20, Register Pair HL = the source copy's byte 4.
5F46
ADD HL,BC 09
ADD Register Pair BC (16) to Register Pair HL: byte 20 of the source copy.
5F47
LD A,(HL) 7E
Fetch the EOF middle byte at Register Pair HL (source copy) into Register A.
5F48
LD (DE),A 12
Store Register A (the EOF middle byte) at Register Pair DE in the destination entry.
5F49
INC DE 13
INCrement Register Pair DE to byte 21 of the destination entry.
5F4A
INC HL 23
INCrement Register Pair HL to byte 21 of the source copy.
5F4B
LD A,(HL) 7E
Fetch the EOF high byte at Register Pair HL into Register A.
5F4C
LD (DE),A 12
Store Register A (the EOF high byte) at Register Pair DE in the destination entry.
5F4D
DEC DE 1B
DECrement Register Pair DE back to byte 20 of the destination entry.
5F4E
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = byte 20 of the destination entry.
5F4F
POP AF F1
Restore Register Pair AF from the stack: Register A = the EOF low byte.
5F50
GOSUB to 6209H to adjust the EOF middle and high bytes at Register Pair HL when the EOF low byte is not 0 and only one of the two diskettes has TI flag M.
5F53
POP BC C1
Restore Register Pair BC from the stack: Register C = the destination DEC.
5F54
POP DE D1
Restore Register Pair DE from the stack: the destination entry.
5F55
POP HL E1
Restore Register Pair HL from the stack: the list entry.
5F56
SET 5,(HL) CB EE
Set bit 5 of the list entry's flags at Register Pair HL: the file has its destination entry.
5F58
INC HL 23
INCrement Register Pair HL to the list entry's second byte.
5F59
INC HL 23
INCrement Register Pair HL to the list entry's third byte.
5F5A
LD (HL),C 71
Store Register C (the destination DEC) at Register Pair HL, in place of the hash code.
5F5B
LD A,C 79
Copy Register C (the destination DEC) into Register A.
5F5C
LD (5B1EH),A 32 1E 5B
Store Register A (the destination DEC) at 5B1EH, the DEC of the destination FCB (FCB+7), which 60A9H uses.
5F5F
GOSUB to 5711H to write the directory sector in 4300H back now.
5F62
LD A,(4288H) 3A 88 42
Fetch the number of the overlay in 4D00H-51FFH from 4288H into Register A.
5F65
CP 05H FE 05
Compare Register A (the overlay) against 05H, SYS3/SYS, which 60A9H jumps into.
5F67
If the NZ FLAG is set (SYS3/SYS is not there), JUMP to 5608H for error 33H (DOS FATAL ERROR).
5F6A
INC DE 13
INCrement Register Pair DE to byte 1 of the destination entry, the second flag byte.
5F6B
LD A,(DE) 1A
Fetch byte 1 of the destination entry at Register Pair DE into Register A.
5F6C
BIT 6,A CB 77
Test bit 6 of Register A (entry byte 1): the file's excess space may not be freed (ASC=N).
5F6E
DEC DE 1B
DECrement Register Pair DE back to byte 0 of the entry. DEC DE does not change the flags.
5F6F
If the NZ FLAG is set (keep the space), JUMP to 5F89H.
5F71
LD HL,428BH 21 8B 42
Point Register Pair HL to 428BH, the SYS0/SYS temporary flags.
5F74
SET 2,(HL) CB D6
Set bit 2 of the byte at Register Pair HL (428BH) while the space is freed: SYS3/SYS then leaves the FCB alone at its end.
5F76
PUSH HL E5
Save Register Pair HL (428BH) onto the stack.
5F77
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the destination entry.
5F78
LD DE,5B17H 11 17 5B
Point Register Pair DE to 5B17H, the destination FCB, for SYS0/SYS 4925H.
5F7B
GOSUB to 60A9H to free the granules past the new EOF of the entry at Register Pair HL. It returns the Z FLAG, or the NZ FLAG with an error code in Register A.
5F7E
If the NZ FLAG is set (an error), JUMP to 521AH to end the command with it.
5F81
POP HL E1
Restore Register Pair HL from the stack: 428BH.
5F82
RES 2,(HL) CB 96
Clear bit 2 of the byte at Register Pair HL (428BH).
5F84
LD A,05H 3E 05
Load Register A with 05H, the number of SYS3/SYS.
5F86
LD (4288H),A 32 88 42
Store Register A (05H) at 4288H: SYS3/SYS cleared 4288H, but its code at 4E1AH onward is still in the overlay area and is used again.
5F89
LD HL,597DH 21 7D 59
Point Register Pair HL to 597DH, the destination's FDE sector count. 5F01H, 5F0DH and 5F6FH come here.
5F8C
GOSUB to 61BAH to step Register C to the next destination DEC. It returns the CARRY FLAG past the last one.
5F8F
If the NO CARRY FLAG is set (more entries), JUMP to 5EFEH.
5F92
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H into Register A. 5EF9H comes here.
5F95
BIT 3,A CB 5F
Test bit 3 of Register A (5995H): DFO, destination files only.
5F97
RET NZ C0
If the NZ FLAG is set (DFO: only files already on the destination are copied), RETurn.
5F98
GOSUB to 56F9H to read the destination GAT sector into 4300H.
5F9B
LD DE,6391H 11 91 63
Point Register Pair DE to 6391H, where the GAT copy is kept.
5F9E
GOSUB to 6172H to copy 256 bytes from Register Pair HL (4300H) to Register Pair DE (6391H).
5FA1
GOSUB to 6162H to read the destination HIT again into 4300H and copy it to 6291H.
5FA4
GOSUB to 6190H to start the 24-byte spaces again and set Register Pair HL to three bytes before the list's start.

Group Loop: each file of the group gets its flag bit 4 cleared; system files kept in place get their entry and granules here.

5FA7
GOSUB to 5699H to step Register Pair HL to the next list entry. It returns the Z FLAG at the end. 5FAFH and 608FH come here.
5FAA
If the Z FLAG is set (the end of the list), JUMP to 6092H to write the HIT and GAT.
5FAD
BIT 4,(HL) CB 66
Test bit 4 of the list entry's flags at Register Pair HL: in the current group.
5FAF
If the Z FLAG is set (not in this group), LOOP BACK to 5FA7H.
5FB1
RES 4,(HL) CB A6
Clear bit 4 of the list entry's flags at Register Pair HL: the file leaves the group.
5FB3
PUSH HL E5
Save Register Pair HL (the list entry) onto the stack.
5FB4
BIT 5,(HL) CB 6E
Test bit 5 of the list entry's flags at Register Pair HL: the file already has its destination entry.
5FB6
INC HL 23
INCrement Register Pair HL to the list entry's source DEC. INC HL does not change the flags.
5FB7
If the NZ FLAG is set (it has an entry), JUMP to 6083H.
5FBA
GOSUB to 61EAH: the NZ FLAG when the source or destination has TI flag M.
5FBD
If the NZ FLAG is set (TI flag M: no entry is kept in place), JUMP to 6083H; 60BFH gives the file an entry later.
5FC0
LD A,(HL) 7E
Fetch the source DEC at Register Pair HL into Register A.
5FC1
LD C,A 4F
Copy Register A (the source DEC) into Register C.
5FC2
LD B,00H 06 00
Load Register B with 00H: Register Pair BC = the DEC.
5FC4
AND 1FH E6 1F
AND Register A (the DEC) with 1FH, keeping bits 0-4, its FDE sector.
5FC6
LD HL,597DH 21 7D 59
Point Register Pair HL to 597DH, the destination's FDE sector count.
5FC9
CP (HL) BE
Compare Register A (the FDE sector) against the count at Register Pair HL.
5FCA
If the NO CARRY FLAG is set (the destination directory has no such sector), JUMP to 6083H.
5FCD
LD HL,6291H 21 91 62
Point Register Pair HL to 6291H, the destination HIT copy.
5FD0
ADD HL,BC 09
ADD Register Pair BC (the DEC) to Register Pair HL: the DEC's byte in the HIT copy.
5FD1
LD A,(HL) 7E
Fetch the HIT byte at Register Pair HL into Register A.
5FD2
OR A B7
OR Register A (the HIT byte) with itself: the Z FLAG when the destination entry is free.
5FD3
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the HIT byte. EX does not change the flags.
5FD4
If the NZ FLAG is set (the entry is taken), JUMP to 6083H.
5FD7
POP HL E1
Restore Register Pair HL from the stack: the list entry.
5FD8
SET 5,(HL) CB EE
Set bit 5 of the list entry's flags at Register Pair HL: the file has its destination entry.
5FDA
PUSH HL E5
Save Register Pair HL (the list entry) onto the stack again.
5FDB
INC HL 23
INCrement Register Pair HL to the list entry's second byte.
5FDC
INC HL 23
INCrement Register Pair HL to the list entry's third byte, the hash code.
5FDD
LD A,(HL) 7E
Fetch the hash code at Register Pair HL into Register A.
5FDE
LD (DE),A 12
Store Register A (the hash code) at Register Pair DE in the HIT copy: the entry is now in use.
5FDF
LD A,C 79
Copy Register C (the DEC, the same on both diskettes) into Register A.
5FE0
LD (HL),A 77
Store Register A (the destination DEC) at Register Pair HL, in place of the hash code.
5FE1
LD (6028H),A 32 28 60
Store Register A (the DEC) at 6028H, the operand of the CP nn at 6027H.
5FE4
GOSUB to 56E2H to point Register Pair HL to the destination entry of DEC Register A, reading its sector (and writing back a changed one) first.
5FE7
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the destination entry.
5FE8
LD HL,(61D8H) 2A D8 61
Load Register Pair HL from 61D8H, the operand of 61D7H: the next 24-byte space, which 6083H takes for this file.
5FEB
LD BC,0016H 01 16 00
Load Register Pair BC with 0016H: 22 bytes, the entry up to its extent elements.
5FEE
LDIR ED B0
Copy Register Pair BC (22) bytes from Register Pair HL (the source copy) to Register Pair DE (the destination entry).
5FF0
LD C,(HL) 4E
Load Register C with the first byte of the source's first extent element at Register Pair HL: the lump.
5FF1
INC HL 23
INCrement Register Pair HL to the second byte of the element.
5FF2
LD B,(HL) 46
Load Register B with the second byte at Register Pair HL: Register Pair BC = the first extent element (Register B = granule offset and count).
5FF3
PUSH BC C5
Save Register Pair BC (the source's first extent element) onto the stack.
5FF4
LD B,0AH 06 0A
Load Register B with 0AH: the 10 bytes of the destination entry's extent area.
5FF6
LD (6078H),DE ED 53 78 60
Store Register Pair DE (the destination entry's byte 22) at 6078H, the operand of the LD (nnnn),HL at 6077H.
5FFA
LD A,FFH 3E FF
Load Register A with FFH, the empty extent mark. 5FFEH comes here.
5FFC
LD (DE),A 12
Store Register A (FFH) at Register Pair DE in the destination entry.
5FFD
INC DE 13
INCrement Register Pair DE to the next byte of the destination entry's extent area.
5FFE
DECrement Register B and LOOP BACK to 5FFAH until all 10 extent bytes are FFH.
6000
POP BC C1
Restore Register Pair BC from the stack: the source's first extent element.
6001
GOSUB to 5706H to mark the directory sector in 4300H as changed.
6004
POP HL E1
Restore Register Pair HL from the stack: the list entry.
6005
BIT 6,(HL) CB 76
Test bit 6 of the list entry's flags at Register Pair HL: a system file that keeps its place.
6007
PUSH HL E5
Save Register Pair HL (the list entry) onto the stack again. PUSH does not change the flags.
6008
If the Z FLAG is set (not one), JUMP to 6083H: its space is allocated when it is written.
600B
LD A,C 79
Copy Register C (the extent's lump byte) into Register A.
600C
CP FEH FE FE
Compare Register A against FEH: the NO CARRY FLAG for FEH or FFH.
600E
If the NO CARRY FLAG is set (the source file has no space), JUMP to 6083H.
6010
LD L,A 6F
Copy Register A (the extent's lump number) into Register L for the multiply.
6011
LD A,(59BCH) 3A BC 59
Fetch the source's granules per lump from 59BCH into Register A.
6014
GOSUB to 4C37H (SYS0/SYS) to multiply Register L (the lump) by Register A (granules per lump): Register Pair HL = the lump's first granule on the source.
6017
LD A,B 78
Copy Register B (the extent's second byte) into Register A.
6018
AND 1FH E6 1F
AND Register A with 1FH, keeping bits 0-4: the granule count minus 1.
601A
LD C,A 4F
Copy Register A (the count minus 1) into Register C.
601B
LD A,B 78
Copy Register B (the extent's second byte) into Register A.
601C
RLCA 07
Rotate Register A (the extent's second byte) left, the first of three.
601D
RLCA 07
Rotate Register A (the extent's second byte) left, the second of three.
601E
RLCA 07
Rotate Register A left, the third: bits 5-7 are now bits 0-2.
601F
AND 07H E6 07
AND Register A with 07H, keeping the granule offset within the lump.
6021
LD E,A 5F
Copy Register A (the granule offset) into Register E.
6022
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the granule offset.
6024
ADD HL,DE 19
ADD Register Pair DE to Register Pair HL: the file's first granule on the source.
6025
LD A,02H 3E 02
Load Register A with 02H, DEC 2, for the comparison with the file's DEC.
6027
CP 00H FE 00
Compare Register A (02H) against the file's DEC. Self-Modifying Code
The operand at 6028H is 00H in the file; 5FE1H stores the DEC there.
6029
If the NZ FLAG is set (not DEC 2), JUMP to 6030H.
602B
LD HL,0001H 21 01 00
DEC 2, the first file after BOOT/SYS and DIR/SYS (SYS0/SYS on a system diskette): load Register Pair HL with 0001H, granule 1, where BOOT reads it.
602E
JUMP to 6064H to make the extent element from Register Pair HL (granule 1).
6030
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the file's first granule on the source. 6029H comes here.
6031
LD A,(59B7H) 3A B7 59
Fetch the source's directory starting lump from 59B7H into Register A.
6034
LD L,A 6F
Copy Register A (the source directory's lump) into Register L for the multiply.
6035
LD A,(59BCH) 3A BC 59
Fetch the source's granules per lump from 59BCH into Register A.
6038
GOSUB to 4C37H (SYS0/SYS) to multiply: Register Pair HL = the source directory's first granule.
603B
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the file's first granule, Register Pair DE = the directory's.
603C
LD A,(59C0H) 3A C0 59
Fetch the source's directory granule count from 59C0H into Register A.
603F
LD B,A 47
Copy Register A (the directory granules) into Register B.
6040
PUSH DE D5
Save Register Pair DE (the directory's first granule) onto the stack.
6041
INC DE 13
INCrement Register Pair DE. 6042H comes here.
6042
DECrement Register B and LOOP BACK to 6041H: Register Pair DE = the first granule after the source directory.
6044
OR A B7
OR Register A with itself, which clears the CARRY FLAG.
6045
SBC HL,DE ED 52
SUBtract Register Pair DE (the granule after the directory) from Register Pair HL (the file's first granule).
6047
If the CARRY FLAG is set (the file starts before the end of the directory), JUMP to 6053H.
6049
POP DE D1
The file is after the directory: discard the saved directory start from the stack into Register Pair DE.
604A
LD A,(59CEH) 3A CE 59
Fetch the destination's directory granule count from 59CEH into Register A.
604D
LD E,A 5F
Copy Register A (the destination directory's granules) into Register E.
604E
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the destination directory's granules.
6050
ADD HL,DE 19
ADD Register Pair DE to Register Pair HL: the file's distance from the start of the destination directory.
6051
JUMP to 6058H with Register Pair HL = the distance from the directory start.
6053
ADD HL,DE 19
ADD Register Pair DE back to Register Pair HL: the file's first granule again. 6047H comes here.
6054
POP DE D1
Restore Register Pair DE from the stack: the source directory's first granule.
6055
OR A B7
OR Register A with itself, which clears the CARRY FLAG.
6056
SBC HL,DE ED 52
SUBtract Register Pair DE from Register Pair HL: the file's distance from the directory start (negative before it).
6058
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the distance. 6051H comes here.
6059
LD A,(59C5H) 3A C5 59
Fetch the destination's directory starting lump from 59C5H into Register A.
605C
LD L,A 6F
Copy Register A (the destination directory's lump) into Register L for the multiply.
605D
LD A,(59CAH) 3A CA 59
Fetch the destination's granules per lump from 59CAH into Register A.
6060
GOSUB to 4C37H (SYS0/SYS) to multiply: Register Pair HL = the destination directory's first granule.
6063
ADD HL,DE 19
ADD Register Pair DE (the distance) to Register Pair HL: the file's first granule on the destination.
6064
LD D,C 51
Copy Register C (the granule count minus 1) into Register D. 602EH comes here.
6065
LD A,(59CAH) 3A CA 59
Fetch the destination's granules per lump from 59CAH into Register A.
6068
GOSUB to 4C59H (SYS0/SYS) to divide Register Pair HL by Register A: Register Pair HL = the lump, Register A = the granule within it.
606B
INC H 24
INCrement Register H (the high byte of the lump).
606C
DEC H 25
DECrement Register H back: the Z FLAG when the lump is below 256.
606D
If the NZ FLAG is set (no such lump), GOSUB to 5240H to report DISKETTE/GAT OVERFLOW and end the command.
6070
LD B,A 47
Copy Register A (the granule within the lump) into Register B.
6071
RRCA 0F
Rotate Register A (the granule) right, the first of three.
6072
RRCA 0F
Rotate Register A right, the second of three.
6073
RRCA 0F
Rotate Register A right, the third: the granule offset is now in bits 5-7.
6074
PUSH HL E5
Save Register Pair HL (Register L = the lump) onto the stack.
6075
OR D B2
OR Register D (the granule count minus 1) into Register A: the extent element's second byte.
6076
LD H,A 67
Copy Register A into Register H: Register Pair HL = the extent element (Register L = the lump).
6077
LD (0000H),HL 22 00 00
Store Register Pair HL as the destination entry's first extent element. Self-Modifying Code
The operand at 6078H-6079H is 0000H in the file; 5FF6H stores the address of the entry's byte 22 there.
607A
LD HL,6391H 21 91 63
Point Register Pair HL to 6391H, the GAT copy.
607D
LD C,D 4A
Copy Register D (the granule count minus 1) into Register C.
607E
POP DE D1
Restore Register Pair DE from the stack: Register E = the lump.
607F
INC C 0C
INCrement Register C: the number of granules.
6080
GOSUB to 621CH to mark Register C granules allocated in the GAT copy, from granule Register B of lump Register E.
6083
GOSUB to 61D6H to step past this file's 24-byte space. 5FB7H, 5FBDH, 5FCAH, 5FD4H, 6008H and 600EH come here.
6086
POP HL E1
Restore Register Pair HL from the stack: the list entry.
6087
BIT 5,(HL) CB 6E
Test bit 5 of the list entry's flags at Register Pair HL: the file has its destination entry now.
6089
If the NZ FLAG is set (it has), JUMP to 608FH.
608B
LD A,H 7C
Copy Register H (the high byte of the list entry's address, never 0) into Register A.
608C
LD (60C3H),A 32 C3 60
Store Register A (not 0) at 60C3H, the operand of the LD A,nn at 60C2H: some files still need a destination entry.
608F
JUMP to 5FA7H for the next list entry. 6089H comes here.
6092
GOSUB to 570DH to write the changed directory sector back, if there is one. 5FAAH comes here.
6095
LD HL,6291H 21 91 62
Point Register Pair HL to 6291H, the destination HIT copy.
6098
GOSUB to 616FH to copy 256 bytes from Register Pair HL (6291H) to 4300H. Register Pair HL returns 6391H.
609B
PUSH HL E5
Save Register Pair HL (6391H, the GAT copy) onto the stack.
609C
LD A,01H 3E 01
Load Register A with 01H, directory sector 1, the HIT.
609E
GOSUB to 5701H to write 4300H as directory sector Register A (the HIT).
60A1
POP HL E1
Restore Register Pair HL from the stack: 6391H, the GAT copy.
60A2
GOSUB to 616FH to copy 256 bytes from Register Pair HL (6391H) to 4300H.
60A5
XOR A AF
Set Register A to 00H, directory sector 0, the GAT.
60A6
JUMP to 5701H to write 4300H as the GAT; its RET goes back to the caller of 5EE4H (5EC5H, or 60BFH).

60A9H - Free the Space Past a File's New EOF

Called from 5F7BH with Register Pair HL pointing to the destination directory entry and Register Pair DE to the destination FCB. SYS0/SYS's routine at 4925H saves the registers and runs the code after the CALL (60ACH) as a DOS function with Index Register IX = the FCB. That code hands the entry's EOF to SYS3/SYS, whose CLOSE code (still in the overlay area) works out the granules the EOF needs and releases the rest.

60A9
GOSUB to 4925H (SYS0/SYS), which checks that the FCB at Register Pair DE is open, sets Index Register IX to it and Index Register IY to 4280H, and runs 60ACH-60BCH as a DOS function; it returns here with the result. 5F7BH calls here.
60AC
XOR A AF
Set Register A to 00H (XOR A), SYS3/SYS's mode value for CLOSE.
60AD
LD (4FB8H),A 32 B8 4F
Store Register A (00H) at 4FB8H, the operand of SYS3/SYS's LD A,nn at 4FB7H: SYS3/SYS works in its CLOSE mode (01H would be KILL).
60B0
PUSH HL E5
Save Register Pair HL (the directory entry) onto the stack, where SYS3/SYS expects the FPDE's address.
60B1
INC L 2C
INCrement Register L (the entry pointer) to byte 1 of the entry.
60B2
INC L 2C
INCrement Register L (the entry pointer) to byte 2 of the entry.
60B3
INC L 2C
INCrement Register L to byte 3, the EOF low byte.
60B4
LD A,(HL) 7E
Fetch the EOF low byte at Register Pair HL into Register A.
60B5
LD DE,0011H 11 11 00
Load Register Pair DE with 0011H, 17, the distance from byte 3 to byte 20.
60B8
ADD HL,DE 19
ADD Register Pair DE (17) to Register Pair HL: byte 20, the EOF middle byte.
60B9
LD E,(HL) 5E
Load Register E with the EOF middle byte at Register Pair HL.
60BA
INC HL 23
INCrement Register Pair HL to byte 21 of the entry, the EOF high byte.
60BB
LD D,(HL) 56
Load Register D with the EOF high byte at Register Pair HL: Register Pair DE = the EOF middle and high bytes.
60BC
JUMP to 4E1AH in SYS3/SYS with Register A = the EOF low byte, Register Pair DE = the EOF middle and high bytes and the FPDE address on the stack: SYS3/SYS works out the granules the EOF needs (its 4E1FH), frees the granules past them and returns through 4925H.

60BFH - COPY by File: Give the Remaining Files New Entries

Reached when 5EE4H returns for the last group (5EE0H pushed 60BFH as its return address). Files that did not get a destination entry at 5EE4H get a new one from SYS2/SYS (50CFH), in groups as memory allows: their bytes 0-21 are collected from the source directory (60C8H) and copied into the new entries (60F5H). When only one of the two diskettes has TI flag M, the entry's bytes 1-2 and both password codes are set for the destination's kind and the EOF is adjusted. Then the copying starts (6157H).

60BF
GOSUB to 568BH to switch to the system diskette and load SYS2/SYS into the overlay area for its free entry search at 50CFH. 5EE4H returns here.
60C2
LD A,00H 3E 00
Load Register A with the flag for files without a destination entry. Self-Modifying Code
The operand at 60C3H is 00H in the file; 608CH stores a value that is not 0 there when a file still needs an entry.
60C4
OR A B7
OR Register A (the flag) with itself: the Z FLAG when every file has its entry.
60C5
If the Z FLAG is set (all done), JUMP to 6157H to start copying.
60C8
GOSUB to 5578H to switch to the source diskette. 60DFH comes here.
60CB
GOSUB to 6190H to start the 24-byte spaces again and set Register Pair HL to three bytes before the list's start.

Collect Loop: Register Pair HL is the list entry; bytes 0-21 of each file without an entry are collected.

60CE
GOSUB to 5699H to step Register Pair HL to the next list entry. It returns the Z FLAG at the end. 60D5H and 60EFH come here.
60D1
If the Z FLAG is set (the end of the list), JUMP to 60F1H for the last group.
60D3
BIT 5,(HL) CB 6E
Test bit 5 of the list entry's flags at Register Pair HL: the file has a destination entry.
60D5
If the NZ FLAG is set (it has), LOOP BACK to 60CEH.
60D7
GOSUB to 61D6H to take the next 24-byte space into Register Pair DE. It returns the CARRY FLAG if there is room.
60DA
If the CARRY FLAG is set (room), JUMP to 60E1H.
60DC
Memory is full: GOSUB to 60F5H to give the files collected so far their entries.
60DF
JUMP to 60C8H to collect the rest of the files without an entry.
60E1
PUSH HL E5
Save Register Pair HL (the list entry) onto the stack. 60DAH comes here.
60E2
SET 4,(HL) CB E6
Set bit 4 of the list entry's flags at Register Pair HL: the file is in the current group.
60E4
INC HL 23
INCrement Register Pair HL to the list entry's source DEC.
60E5
LD A,(HL) 7E
Fetch the source DEC at Register Pair HL into Register A.
60E6
GOSUB to 56EFH to point Register Pair HL to the source directory entry of DEC Register A, reading its sector if needed.
60E9
LD BC,0016H 01 16 00
Load Register Pair BC with 0016H: 22 bytes, the entry up to its extent elements.
60EC
LDIR ED B0
Copy Register Pair BC (22) bytes from Register Pair HL (the source entry) to Register Pair DE (the 24-byte space).
60EE
POP HL E1
Restore Register Pair HL from the stack: the list entry.
60EF
LOOP BACK to 60CEH for the next list entry at Register Pair HL.
60F1
LD HL,6157H 21 57 61
Point Register Pair HL to 6157H, where the copying starts after the last group. 60D1H comes here.
60F4
PUSH HL E5
Save Register Pair HL (6157H) onto the stack as the return address, and fall into 60F5H for the last group.
60F5
GOSUB to 557DH to switch to the destination diskette. 60DCH calls here.
60F8
GOSUB to 6190H to start the 24-byte spaces again and set Register Pair HL to three bytes before the list's start.

Entry Loop: each file of the group gets a new destination entry.

60FB
GOSUB to 5699H to step Register Pair HL to the next list entry. It returns the Z FLAG at the end. 6101H and 6155H come here.
60FE
RET Z C8
If the Z FLAG is set (the end of the list), RETurn to 60DFH or 6157H.
60FF
BIT 4,(HL) CB 66
Test bit 4 of the list entry's flags at Register Pair HL: in the current group.
6101
If the Z FLAG is set (not in it), LOOP BACK to 60FBH.
6103
PUSH HL E5
Save Register Pair HL (the list entry) onto the stack.
6104
RES 4,(HL) CB A6
Clear bit 4 of the list entry's flags at Register Pair HL.
6106
GOSUB to 61D6H to take this file's 24-byte space into Register Pair DE.
6109
INC HL 23
INCrement Register Pair HL to the list entry's source DEC.
610A
LD B,(HL) 46
Load Register B with the source DEC at Register Pair HL: SYS2/SYS starts its free entry search in the same FDE sector.
610B
INC HL 23
INCrement Register Pair HL to the list entry's hash code.
610C
PUSH DE D5
Save Register Pair DE (the 24-byte copy) onto the stack.
610D
PUSH HL E5
Save Register Pair HL (the pointer to the hash code) onto the stack.
610E
GOSUB to 50CFH in SYS2/SYS, which finds a free destination entry (starting in FDE sector Register B AND 1FH), enters the hash code at Register Pair HL into the HIT, and returns Register Pair HL = the new entry and Register A = its DEC, or the NZ FLAG with an error code.
6111
If the NZ FLAG is set (no free entry), JUMP to 521AH to end the command with the error code in Register A.
6114
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the new destination entry.
6115
POP HL E1
Restore Register Pair HL from the stack: the pointer to the hash code in the list entry.
6116
LD (HL),A 77
Store Register A (the destination DEC) at Register Pair HL, in place of the hash code.
6117
POP HL E1
Restore Register Pair HL from the stack: the 24-byte copy of the source entry.
6118
PUSH DE D5
Save Register Pair DE (the new entry) onto the stack.
6119
LD BC,0016H 01 16 00
Load Register Pair BC with 0016H: 22 bytes, the entry up to its extents.
611C
LDIR ED B0
Copy Register Pair BC (22) bytes from Register Pair HL (the source copy) to Register Pair DE (the new entry). Its extent elements were left FFH by SYS2/SYS.
611E
POP DE D1
Restore Register Pair DE from the stack: the new entry.
611F
GOSUB to 61FCH: the NZ FLAG when only one of the two diskettes has TI flag M, with Register A = the destination's flags (59C7H).
6122
If the Z FLAG is set (both or neither have TI flag M), JUMP to 614FH and keep the source's bytes.
6124
BIT 5,A CB 6F
Test bit 5 of Register A (the destination's flags): TI flag M.
6126
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the new entry. EX does not change the flags.
6127
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, the value for entry bytes 1 and 2 on a destination without TI flag M.
612A
LD BC,4296H 01 96 42
Load Register Pair BC with 4296H, the code of a blank password.
612D
If the Z FLAG is set (the destination has no TI flag M), JUMP to 613AH.
612F
LD A,(421AH) 3A 1A 42
Fetch the system date's year from 421AH (SYS0/SYS) into Register A.
6132
LD D,A 57
Copy Register A (the year) into Register D, the value for entry byte 2.
6133
LD A,(421CH) 3A 1C 42
Fetch the system date's month from 421CH (SYS0/SYS) into Register A.
6136
LD E,A 5F
Copy Register A (the month) into Register E, the value for entry byte 1.
6137
LD BC,5CEFH 01 EF 5C
Load Register Pair BC with 5CEFH, the password code that SYS2/SYS's encoder gives while the TI flag M patches are in (5BD1H).
613A
INC HL 23
INCrement Register Pair HL to byte 1 of the new entry. 612DH comes here.
613B
LD (HL),E 73
Store Register E at Register Pair HL (entry byte 1).
613C
INC HL 23
INCrement Register Pair HL to byte 2 of the new entry.
613D
LD (HL),D 72
Store Register D at Register Pair HL (entry byte 2).
613E
INC HL 23
INCrement Register Pair HL to byte 3, the EOF low byte.
613F
LD A,(HL) 7E
Fetch the EOF low byte at Register Pair HL into Register A, for 6209H.
6140
LD DE,000DH 11 0D 00
Load Register Pair DE with 000DH, 13, the distance from byte 3 to byte 16.
6143
ADD HL,DE 19
ADD Register Pair DE (13) to Register Pair HL: byte 16, the update password code.
6144
LD (HL),C 71
Store Register C (the low byte of the password code) at Register Pair HL.
6145
INC HL 23
INCrement Register Pair HL to byte 17, the high byte of the update password code.
6146
LD (HL),B 70
Store Register B (the high byte of the password code) at Register Pair HL.
6147
INC HL 23
INCrement Register Pair HL to byte 18, the access password code.
6148
LD (HL),C 71
Store Register C (the low byte of the password code) at Register Pair HL.
6149
INC HL 23
INCrement Register Pair HL to byte 19, the high byte of the access password code.
614A
LD (HL),B 70
Store Register B (the high byte of the password code) at Register Pair HL.
614B
INC HL 23
INCrement Register Pair HL to byte 20, the EOF middle byte.
614C
GOSUB to 6209H to adjust the EOF middle and high bytes at Register Pair HL for the destination's kind, when the EOF low byte in Register A is not 0.
614F
GOSUB to 5711H to write the directory sector in 4300H. 6122H comes here.
6152
POP HL E1
Restore Register Pair HL from the stack: the list entry.
6153
SET 5,(HL) CB EE
Set bit 5 of the list entry's flags at Register Pair HL: the file has its destination entry.
6155
LOOP BACK to 60FBH for the next list entry of the group.
6157
LD A,FFH 3E FF
Load Register A with FFH. 60C5H jumps here and 60F1H pushes it as a return address.
6159
LD (5B1EH),A 32 1E 5B
Store Register A (FFH) at 5B1EH, the destination FCB's DEC: no destination file is open yet, so the first sector's marker byte always differs (534CH).
615C
LD (586AH),A 32 6A 58
Store Register A (FFH) at 586AH, the operand of the OR nn at 5869H, so that errors name the file being copied.
615F
JUMP to 524EH to compact the file list and start copying.

6162H - COPY by File Helpers

6162H reads the HIT sector of the current diskette and copies it to 6291H (Register Pair HL = 4300H on return). 616FH copies 256 bytes from Register Pair HL to 4300H, 6172H from Register Pair HL to Register Pair DE. 6178H returns Register A = the number of FDE sectors in the directory and Register C = the directory's granules. 6190H prepares a walk through the file list and the 24-byte spaces.

6162
LD A,01H 3E 01
Load Register A with 01H, directory sector 1, the HIT. 5D89H, 5EE7H and 5FA1H call here.
6164
GOSUB to 56FAH to read directory sector Register A into 4300H.
6167
LD DE,6291H 11 91 62
Point Register Pair DE to 6291H, where the HIT copy is kept (over the code of 6291H, which has run).
616A
GOSUB to 6172H to copy 256 bytes from Register Pair HL (4300H) to Register Pair DE (6291H).
616D
DEC H 25
DECrement Register H (43H after the copy): Register Pair HL = 4300H again.
616E
RET C9
RETurn with Register Pair HL = 4300H, the HIT sector.
616F
LD DE,4300H 11 00 43
Point Register Pair DE to 4300H, the sector buffer. 6098H and 60A2H call here.
6172
LD BC,0100H 01 00 01
Load Register Pair BC with 0100H: 256 bytes, one sector. 5F9EH and 616AH call here.
6175
LDIR ED B0
Copy Register Pair BC (256) bytes from Register Pair HL to Register Pair DE.
6177
RET C9
RETurn with Register Pair HL and Register Pair DE 256 bytes further on.
6178
GOSUB to 61F6H: the NZ FLAG when the current drive has TI flag M. 5D8CH and 5EEAH call here.
617B
LD A,10H 3E 10
Load Register A with 10H: 16 FDE sectors, the directory size used for a TI flag M diskette. LD does not change the flags.
617D
LD C,06H 0E 06
Load Register C with 06H: 6 directory granules for a TI flag M diskette.
617F
RET NZ C0
If the NZ FLAG is set (TI flag M), RETurn with Register A = 16 and Register C = 6.
6180
LD E,05H 1E 05
Load Register E with 05H, the sectors in a granule.
6182
LD A,(431FH) 3A 1F 43
Fetch HIT byte 1FH from 431FH (the HIT sector in 4300H) into Register A: the extra FDE sectors, 0, 5, 10, 15 or 20.
6185
ADD A,08H C6 08
ADD 08H to Register A: the standard 8 FDE sectors are added.
6187
LD B,A 47
Copy Register A (the FDE sector count) into Register B.
6188
LD C,00H 0E 00
Load Register C with 00H, the granule count before the loop.
618A
INC C 0C
INCrement Register C, the granule count. 618CH comes here.
618B
SUB E 93
SUBtract Register E (5 sectors) from Register A (the sectors left).
618C
If the NO CARRY FLAG is set (no borrow yet), LOOP BACK to 618AH: Register C = (FDE sectors / 5) + 1, the granules including the GAT and HIT sectors.
618E
LD A,B 78
Copy Register B (the FDE sector count) into Register A.
618F
RET C9
RETurn with Register A = the FDE sectors and Register C = the directory granules.
6190
LD HL,(5D14H) 2A 14 5D
Fetch the end of the file list from 5D14H into Register Pair HL. 5EB3H, 5EC8H, 5F07H, 5FA4H, 60CBH and 60F8H call here.
6193
LD (61D8H),HL 22 D8 61
Store Register Pair HL (the end of the list) at 61D8H, the operand of the LD HL,nnnn at 61D7H: the first 24-byte space.
6196
LD HL,(5D12H) 2A 12 5D
Fetch the start of the file list from 5D12H into Register Pair HL.
6199
DEC HL 2B
DECrement Register Pair HL, the first of three steps back.
619A
DEC HL 2B
DECrement Register Pair HL, the second step back.
619B
DEC HL 2B
DECrement Register Pair HL, the third: three bytes before the first entry, so that 5699H steps onto it.
619C
RET C9
RETurn with Register Pair HL three bytes before the list.

619DH - Look at a Directory Entry

Entered with Register C = a DEC. The HIT copy at 6291H is checked first: a free entry returns the CARRY FLAG and the NZ FLAG, and on a diskette without TI flag M so do DECs 0 and 1 (BOOT/SYS and DIR/SYS). Otherwise the entry is read and the Z FLAG returned if it is a primary entry in use (bit 4 set, bit 7 clear), with Register Pair HL pointing to it and Register B holding its HIT byte.

619D
LD B,00H 06 00
Load Register B with 00H: Register Pair BC = the DEC. 5E1AH and 5EFEH call here.
619F
LD HL,6291H 21 91 62
Point Register Pair HL to 6291H, the HIT copy.
61A2
ADD HL,BC 09
ADD Register Pair BC (the DEC) to Register Pair HL: the DEC's byte in the HIT copy.
61A3
LD A,(HL) 7E
Fetch the HIT byte at Register Pair HL into Register A.
61A4
CP 01H FE 01
Compare Register A (the HIT byte) against 01H: the CARRY FLAG for 00H (free), and the NZ FLAG with it.
61A6
LD B,A 47
Copy Register A (the HIT byte, the hash code) into Register B.
61A7
RET C D8
If the CARRY FLAG is set (free), RETurn with the NZ FLAG.
61A8
GOSUB to 61F6H: the NZ FLAG when the current drive has TI flag M.
61AB
LD A,C 79
Copy Register C (the DEC) into Register A. LD does not change the flags.
61AC
If the NZ FLAG is set (TI flag M), JUMP to 61B1H.
61AE
CP 02H FE 02
Compare Register A (the DEC) against 02H: the CARRY FLAG for DEC 0 or 1.
61B0
RET C D8
If the CARRY FLAG is set (BOOT/SYS or DIR/SYS), RETurn with the NZ FLAG.
61B1
GOSUB to 56E2H to point Register Pair HL to the entry of DEC Register A, reading its sector if needed. 61ACH comes here.
61B4
LD A,(HL) 7E
Fetch the entry's flag byte at Register Pair HL into Register A.
61B5
AND 90H E6 90
AND Register A (the flags) with 90H, keeping bit 7 (an extension entry) and bit 4 (in use).
61B7
CP 10H FE 10
Compare Register A against 10H: the Z FLAG for a primary entry in use.
61B9
RET C9
RETurn with the Z FLAG for a file's primary entry.

61BAH - Step to the Next DEC

Entered with Register C = the DEC and Register Pair HL pointing to the directory's FDE sector count. Steps through the entries in DEC order (the next entry position in the sector, then the next sector) and returns the CARRY FLAG after the last one. On a diskette with TI flag M the DECs are numbered 0-4FH one after another.

61BA
GOSUB to 61F6H: the NZ FLAG when the current drive has TI flag M. 5EADH and 5F8CH call here.
61BD
LD A,50H 3E 50
Load Register A with 50H, 80 entries for a TI flag M diskette. LD does not change the flags.
61BF
If the NZ FLAG is set (TI flag M), JUMP to 61C7H.
61C1
LD A,C 79
Copy Register C (the DEC) into Register A for the addition.
61C2
ADD A,20H C6 20
ADD 20H to Register A: the same FDE sector, one entry further on (DEC bits 5-7).
61C4
LD C,A 4F
Copy Register A (the new DEC) into Register C.
61C5
RET NC D0
If the NO CARRY FLAG is set (still within the sector), RETurn with the NO CARRY FLAG.
61C6
LD A,(HL) 7E
Past the last entry of the sector: fetch the FDE sector count at Register Pair HL into Register A.
61C7
DEC A 3D
DECrement Register A: the last FDE sector number (or 4FH, the last DEC). 61BFH comes here.
61C8
INC C 0C
INCrement Register C: the first entry of the next FDE sector (or the next DEC).
61C9
CP C B9
Compare Register A (the last one) against Register C: the CARRY FLAG when Register C is past it.
61CA
RET C9
RETurn with the CARRY FLAG after the last DEC.

61CBH - Store a Decimal Digit

Entered with Register A = a number, Register B = 100 or 10 and Register Pair HL pointing to where the digit goes. Nothing is stored if the number is below Register B. Returns Register A = the remainder.

61CB
CP B B8
Compare Register A (the number) against Register B (100 or 10). 5DD1H and 5DD6H call here.
61CC
RET C D8
If the CARRY FLAG is set (the number is smaller), RETurn with Register A unchanged and no digit stored.
61CD
LD (HL),2FH 36 2F
Store 2FH, one less than the character 0, at Register Pair HL.
61CF
INC (HL) 34
INCrement the digit at Register Pair HL. 61D1H comes here.
61D0
SUB B 90
SUBtract Register B (100 or 10) from Register A (the number).
61D1
If the NO CARRY FLAG is set (no borrow), LOOP BACK to 61CFH.
61D3
ADD A,B 80
ADD Register B back to Register A: the remainder.
61D4
INC HL 23
INCrement Register Pair HL past the digit just stored.
61D5
RET C9
RETurn with Register A = the remainder and Register Pair HL past the digit.

61D6H - Take the Next 24-Byte Space

Returns Register Pair DE = the next 24-byte space after the file list and the CARRY FLAG if it is still below the limit at 61DBH (the top of memory less 24). The pointer at 61D8H moves on by 24 either way. Register Pair HL is kept.

61D6
PUSH HL E5
Save Register Pair HL (the caller's value) onto the stack. 5EBDH, 5F13H, 6083H, 60D7H and 6106H call here.
61D7
LD HL,0000H 21 00 00
Load Register Pair HL with the next 24-byte space. Self-Modifying Code
The operand at 61D8H-61D9H is 0000H in the file; 6190H stores the end of the file list there and 61E4H advances it.
61DA
LD DE,0000H 11 00 00
Load Register Pair DE with the limit. Self-Modifying Code
The operand at 61DBH-61DCH is 0000H in the file; 5D9DH stores the top of memory less 24 there.
61DD
RST 18H DF
RST 18H, the ROM routine that compares Register Pair HL (the space) with Register Pair DE (the limit): the CARRY FLAG when the space is below the limit.
61DE
PUSH AF F5
Save Register Pair AF (the result of the comparison) onto the stack.
61DF
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the space.
61E0
LD HL,0018H 21 18 00
Load Register Pair HL with 0018H, 24, the size of one space.
61E3
ADD HL,DE 19
ADD Register Pair DE (the space) to Register Pair HL (24): the space after it.
61E4
LD (61D8H),HL 22 D8 61
Store Register Pair HL (the next space) at 61D8H.
61E7
POP AF F1
Restore Register Pair AF from the stack: the CARRY FLAG from the comparison.
61E8
POP HL E1
Restore Register Pair HL from the stack: the caller's value.
61E9
RET C9
RETurn with Register Pair DE = the space and the CARRY FLAG if there was room.

61EAH - TI Flag M Tests

61EAH returns the NZ FLAG if either diskette has TI flag M (bit 5 of the flags at 59B9H or 59C7H), 61F6H if the current drive has (4282H), and 61FCH if exactly one of the two has, with Register A = the destination's flags. 6209H adjusts the EOF middle and high bytes at Register Pair HL when a file with a partly used last sector moves between a diskette with TI flag M and one without.

61EA
PUSH HL E5
Save Register Pair HL (the caller's value) onto the stack. 5E5EH, 5FBAH and 674DH call here.
61EB
LD HL,59C7H 21 C7 59
Point Register Pair HL to 59C7H, the destination's flags (+2 of its working record).
61EE
LD A,(59B9H) 3A B9 59
Fetch the source's flags from 59B9H into Register A.
61F1
OR (HL) B6
OR the destination's flags at Register Pair HL into Register A.
61F2
POP HL E1
Restore Register Pair HL from the stack: the caller's value.
61F3
AND 20H E6 20
AND Register A with 20H, keeping bit 5 (TI flag M): the NZ FLAG if either has it.
61F5
RET C9
RETurn with the NZ FLAG when the source or destination has TI flag M.
61F6
LD A,(4282H) 3A 82 42
Fetch the current drive's PDRIVE flags from 4282H (SYS0/SYS) into Register A. 5E20H, 6178H, 61A8H and 61BAH call here.
61F9
AND 20H E6 20
AND Register A with 20H, keeping bit 5 (TI flag M).
61FB
RET C9
RETurn with the NZ FLAG and Register A = 20H when the current drive has TI flag M.
61FC
PUSH HL E5
Save Register Pair HL (the caller's value) onto the stack. 611FH and 620AH call here.
61FD
LD HL,59C7H 21 C7 59
Point Register Pair HL to 59C7H, the destination's flags.
6200
LD A,(59B9H) 3A B9 59
Fetch the source's flags from 59B9H into Register A.
6203
XOR (HL) AE
XOR the destination's flags at Register Pair HL into Register A: the bits that differ.
6204
AND 20H E6 20
AND Register A with 20H, keeping bit 5: the NZ FLAG when only one has TI flag M.
6206
LD A,(HL) 7E
Fetch the destination's flags at Register Pair HL into Register A. LD does not change the flags.
6207
POP HL E1
Restore Register Pair HL from the stack: the caller's value.
6208
RET C9
RETurn with Register A = the destination's flags and the NZ FLAG when only one diskette has TI flag M.
6209
OR A B7
OR Register A (the EOF low byte) with itself: the Z FLAG for 0. 5F50H and 614CH call here.
620A
If the NZ FLAG is set (the last sector is partly used), GOSUB to 61FCH, which returns the NZ FLAG when only one diskette has TI flag M and Register A = the destination's flags.
620D
RET Z C8
If the Z FLAG is set (nothing to adjust), RETurn.
620E
LD E,(HL) 5E
Fetch the EOF middle byte at Register Pair HL (entry byte 20) into Register E.
620F
INC HL 23
INCrement Register Pair HL to entry byte 21, the EOF high byte.
6210
LD D,(HL) 56
Fetch the EOF high byte at Register Pair HL into Register D: Register Pair DE = the EOF middle and high bytes.
6211
INC DE 13
INCrement Register Pair DE: one higher, the NEWDOS/80 form for a partly used last sector.
6212
BIT 5,A CB 6F
Test bit 5 of Register A (the destination's flags): TI flag M.
6214
If the Z FLAG is set (the destination has no TI flag M), JUMP to 6218H with the value one higher.
6216
DEC DE 1B
The destination has TI flag M: DECrement Register Pair DE.
6217
DEC DE 1B
DECrement Register Pair DE again: one lower than it was, the form without the extra 1.
6218
LD (HL),D 72
Store Register D (the high byte) at Register Pair HL (entry byte 21). 6214H comes here.
6219
DEC HL 2B
DECrement Register Pair HL back to entry byte 20, the EOF middle byte.
621A
LD (HL),E 73
Store Register E (the middle byte) at Register Pair HL (entry byte 20).
621B
RET C9
RETurn with the EOF middle and high bytes adjusted in the entry.

621CH - Allocate Granules in a GAT Copy

Entered with Register Pair HL = the GAT sector (or its copy), Register E = the lump, Register B = the first granule in it and Register C = the number of granules. Each granule's bit is set. A granule past the destination's last lump, or one already allocated, ends the command with DISKETTE/GAT OVERFLOW (5240H). Used by 6080H and by FORMAT (669FH).

621C
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the lump. 6080H and 669FH call here.
621E
ADD HL,DE 19
ADD Register Pair DE (the lump) to Register Pair HL (the GAT): the lump's byte.
621F
LD D,80H 16 80
Load Register D with 80H, the bit mask before the rotations.
6221
LD A,B 78
Copy Register B (the first granule) into Register A.
6222
INC B 04
INCrement Register B: the granule number plus 1, the rotation count.
6223
RLC D CB 02
Rotate Register D (the mask) left. 6225H comes here.
6225
DECrement Register B and LOOP BACK to 6223H: Register D now has the first granule's bit.
6227
LD B,A 47
Copy Register A (the first granule) into Register B.

Lump Loop: Register Pair HL is the lump's byte, Register D the granule's bit, Register B the granules left in the lump, Register C the granules left to allocate.

6228
LD A,(59CAH) 3A CA 59
Fetch the destination's granules per lump from 59CAH into Register A. 6247H comes here.
622B
SUB B 90
SUBtract Register B (the first granule) from Register A.
622C
LD B,A 47
Copy Register A into Register B: the granules left in this lump.
622D
PUSH HL E5
Save Register Pair HL (the lump's byte) onto the stack. 6241H comes here.
622E
LD HL,59C6H 21 C6 59
Point Register Pair HL to 59C6H, the destination's lump count.
6231
LD A,E 7B
Copy Register E (the lump number) into Register A for the comparison.
6232
CP (HL) BE
Compare Register A (the lump) against the lump count at Register Pair HL.
6233
POP HL E1
Restore Register Pair HL from the stack: the lump's byte.
6234
If the NO CARRY FLAG is set (past the last lump), JUMP to 6249H.
6236
LD A,(HL) 7E
Fetch the lump's byte at Register Pair HL into Register A.
6237
AND D A2
AND Register D (the granule's bit) into Register A.
6238
If the NZ FLAG is set (already allocated), JUMP to 6249H.
623A
LD A,(HL) 7E
Fetch the lump's byte at Register Pair HL into Register A again.
623B
OR D B2
OR Register D (the granule's bit) into Register A.
623C
LD (HL),A 77
Store Register A at Register Pair HL: the granule is allocated.
623D
DEC C 0D
DECrement Register C, the granules left to allocate.
623E
RET Z C8
If the Z FLAG is set (all the granules are allocated), RETurn.
623F
RLC D CB 02
Rotate Register D left: the next granule's bit.
6241
DECrement Register B (the granules left in the lump) and LOOP BACK to 622DH.
6243
LD D,01H 16 01
Load Register D with 01H, the bit of granule 0.
6245
INC HL 23
INCrement Register Pair HL to the next lump's byte.
6246
INC E 1C
INCrement Register E, the lump number, for the next lump's byte.
6247
JUMP to 6228H with Register B = 0, a whole lump.
6249
GOSUB to 5240H to report DISKETTE/GAT OVERFLOW and end the command. 6234H and 6238H come here.
624C-624E
DEFM " " 20 20 20
The extension to copy, from /ext (stored by 500DH). Three spaces in the file; compared with each file's extension at 5E49H.

624FH - Compare a Diskette Name

624FH compares the 8 characters at Register Pair HL with the diskette name in the GAT sector at 43D0H; 6254H compares Register B characters at Register Pair HL and Register Pair DE. The Z FLAG is set if they are the same.

624F
LD DE,43D0H 11 D0 43
Point Register Pair DE to 43D0H, the name field (GAT bytes D0H-D7H) of the GAT sector in 4300H. 6301H and 686BH call here.
6252
LD B,08H 06 08
Load Register B with 08H, the length of a diskette name.
6254
LD A,(DE) 1A
Fetch a character at Register Pair DE into Register A. 5F28H calls here; 6259H comes here.
6255
CP (HL) BE
Compare Register A against the character at Register Pair HL.
6256
RET NZ C0
If the NZ FLAG is set (different), RETurn with the NZ FLAG.
6257
INC DE 13
INCrement Register Pair DE to the next character.
6258
INC HL 23
INCrement Register Pair HL to the next character.
6259
DECrement Register B and LOOP BACK to 6254H for all the characters.
625B
RET C9
RETurn with the Z FLAG: the names are the same.
625C-6260
DEFM "RQNY", 00H 52 51 4E 59 00
The replies to the CFWO question (58E4H from 5E72H): R (0) start the questions again, Q (1) no more files, N (2) do not copy, Y (3) copy.
6261-627A
DEFM " Copy It? (Y/N/R/Q) ", 03H 20 20 20 20 43 6F 70 79 20 49 74 3F 20 20 28 59 2F 4E 2F 52 2F 51 29 20 20 03
The CFWO question that 58E4H displays after the file's name.
627B-6282
DEFM "Copying", 03H 43 6F 70 79 69 6E 67 03
Displayed by 5273H (through 587EH) when the copying of the sectors starts.
6283-6290
DEFM "ILF/XLF File ", 03H 49 4C 46 2F 58 4C 46 20 46 69 6C 65 20 03
Displayed by 5D68H before an error in the include or exclude list file.

6291H - Diskette COPY (Formats 5 and 6): Check the Diskettes

Reached from 4D88H. This code runs once; afterwards 6291H-6390H and 6391H-6490H are reused as copies of the destination's HIT and GAT sectors and 6491H onward for the file list. The list file of ILF or XLF is opened, the overlay needed at the end is loaded (SYS17/SYS for a sector by sector COPY, SYS3/SYS for a COPY by file), the source diskette's GAT is read for its name, date and password (SN, SPW, USD), and the two diskettes are checked against each other before the COPY engine starts.

6291
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A. 4D88H comes here.
6294
AND 30H E6 30
AND Register A (the 5997H flags) with 30H, keeping bit 4 (ILF) and bit 5 (XLF).
6296
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the buffer for the list file. LD does not change the flags.
6299
LD DE,4480H 11 80 44
Point Register Pair DE to 4480H, the DOS FCB that holds the list file's filespec (stored by 4FACH).
629C
If the NZ FLAG is set (ILF or XLF given), GOSUB to 4424H (SYS0/SYS) to open the list file through the FCB at Register Pair DE with the buffer at Register Pair HL. It returns the NZ FLAG with an error code if the file cannot be opened.
629F
If the NZ FLAG is set (the open failed), JUMP to 5D67H to report ILF/XLF FILE and the error. Without a list file the Z FLAG from the AND stays set.
62A2
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
62A5
AND 08H E6 08
AND Register A (the 5996H flags) with 08H, keeping bit 3 (CBF).
62A7
LD A,F3H 3E F3
Load Register A with F3H, the RST 28H code of SYS17/SYS function 7, which ends a sector by sector COPY. LD does not change the flags.
62A9
If the Z FLAG is set (a sector by sector COPY), JUMP to 62ADH to load SYS17/SYS, which 54D4H jumps into.
62AB
LD A,E5H 3E E5
COPY by file: load Register A with E5H, the RST 28H code of SYS3/SYS function 7, whose code 60BCH jumps into.
62AD
GOSUB to 568DH to switch to the system diskette and load the overlay of Register A into 4D00H-51FFH. 62A9H comes here.
62B0
GOSUB to 5578H to switch to the source diskette.
62B3
LD A,(428CH) 3A 8C 42
Fetch the system options from 428CH (SYS0/SYS, a copy of system data byte F0H) into Register A.
62B6
AND 82H E6 82
AND Register A (428CH) with 82H, keeping bit 7 (option AA, passwords are checked) and bit 1 (option AR).
62B8
CP 80H FE 80
Compare Register A against 80H: the Z FLAG when AA = Y and AR = N, so the source diskette's password must be checked.
62BA
If the Z FLAG is set (the password is checked), JUMP to 62C3H.
62BC
LD A,(5994H) 3A 94 59
Fetch the option flags from 5994H into Register A.
62BF
AND 02H E6 02
AND Register A (the 5994H flags) with 02H, keeping bit 1 (BDU).
62C1
If the NZ FLAG is set (BDU: the source's directory is not looked at), JUMP to 632CH.
62C3
GOSUB to 56F9H to read the source diskette's GAT sector into 4300H. 62BAH and 6312H come here.
62C6
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H into Register A.
62C9
BIT 5,A CB 6F
Test bit 5 of Register A (5995H): NDPW, a new destination password.
62CB
If the NZ FLAG is set (NDPW given), JUMP to 62D3H and keep the code at 5981H.
62CD
LD HL,(43CEH) 2A CE 43
Fetch the source diskette's password code from 43CEH (GAT bytes CEH-CFH) into Register Pair HL.
62D0
LD (5981H),HL 22 81 59
Store Register Pair HL (the source's password code) at 5981H: the destination gets it.
62D3
LD A,(5994H) 3A 94 59
Fetch the option flags from 5994H into Register A. 62CBH comes here.
62D6
BIT 2,A CB 57
Test bit 2 of Register A (5994H): NDN, a new destination name.
62D8
If the NZ FLAG is set (NDN given), JUMP to 62E5H and keep the name at 5983H.
62DA
LD HL,43D0H 21 D0 43
Point Register Pair HL to 43D0H, the source diskette's name (GAT bytes D0H-D7H).
62DD
LD DE,5983H 11 83 59
Point Register Pair DE to 5983H, the name for the destination's GAT.
62E0
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H: 8 characters.
62E3
LDIR ED B0
Copy Register Pair BC (8) bytes from Register Pair HL (43D0H) to Register Pair DE (5983H): the destination gets the source's name.
62E5
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H into Register A. 62D8H comes here.
62E8
BIT 4,A CB 67
Test bit 4 of Register A (5995H): USD, use the source's date.
62EA
If the Z FLAG is set (no USD), JUMP to 62F7H and keep the date at 598BH.
62EC
LD HL,43D8H 21 D8 43
Point Register Pair HL to 43D8H, the source diskette's date (GAT bytes D8H-DFH).
62EF
LD DE,598BH 11 8B 59
Point Register Pair DE to 598BH, the date for the destination's GAT.
62F2
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H: 8 characters.
62F5
LDIR ED B0
Copy Register Pair BC (8) bytes from Register Pair HL (43D8H) to Register Pair DE (598BH): the destination gets the source's date.
62F7
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A. 62EAH comes here.
62FA
BIT 7,A CB 7F
Test bit 7 of Register A (5996H): SN, the source diskette's name was given.
62FC
If the Z FLAG is set (no SN given), JUMP to 6314H to the password check.
62FE
LD HL,5968H 21 68 59
Point Register Pair HL to 5968H, the name given with SN=.
6301
GOSUB to 624FH to compare the 8 characters at Register Pair HL with the source's name in the GAT at 43D0H. It returns the Z FLAG when they are the same.
6304
If the Z FLAG is set (the names match), JUMP to 632CH.
6306
LD HL,5A3CH 21 3C 5A
Point Register Pair HL to 5A3CH, the word SOURCE.
6309
GOSUB to 6930H to display the word at Register Pair HL followed by DISKETTE NAME MISMATCH.
630C
GOSUB to 693CH to display the diskette's name and date from its GAT.
630F
GOSUB to 58C8H to ask C, R or P. C ends the command; P returns the Z FLAG, R the NZ FLAG.
6312
If the NZ FLAG is set (R), JUMP to 62C3H to read the GAT again, from the diskette now in the drive.
6314
LD A,(428CH) 3A 8C 42
P, or no SN: fetch the system options from 428CH into Register A. 62FCH comes here.
6317
AND 82H E6 82
AND Register A (428CH) with 82H, keeping bit 7 (AA) and bit 1 (AR).
6319
CP 80H FE 80
Compare Register A against 80H: the Z FLAG when AA = Y and AR = N.
631B
If the NZ FLAG is set (no password check), JUMP to 632CH.
631D
LD HL,(43CEH) 2A CE 43
Fetch the source diskette's password code from 43CEH into Register Pair HL.
6320
LD DE,(5978H) ED 5B 78 59
Fetch the code of the password given with SPW= from 5978H into Register Pair DE (0000H if SPW was not given).
6324
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
6325
SBC HL,DE ED 52
SUBtract Register Pair DE (the SPW code) from Register Pair HL (the diskette's code): the Z FLAG when they are the same.
6327
LD A,37H 3E 37
Load Register A with error code 37H (DISKETTE ACCESS DENIED). LD does not change the flags.
6329
If the NZ FLAG is set (the wrong password), JUMP to 521AH to end the command with error 37H.
632C
LD HL,5996H 21 96 59
Point Register Pair HL to 5996H, the option flags. 62C1H, 6304H and 631BH come here.
632F
RES 7,(HL) CB BE
Clear bit 7 of the byte at Register Pair HL (5996H): SN has been dealt with; the shared bit means RWF to the formatting code that follows.
6331
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
6334
BIT 3,A CB 5F
Test bit 3 of Register A (the 5996H flags): CBF, a COPY by file.
6336
If the NZ FLAG is set (a COPY by file), JUMP to 5D16H.

Sector by sector COPY (format 5). The source FCB's EOF is set to the number of sectors to copy.

6339
LD HL,(59D1H) 2A D1 59
Fetch the destination's total granules from 59D1H into Register Pair HL.
633C
LD DE,(59C3H) ED 5B C3 59
Fetch the source's total granules from 59C3H into Register Pair DE.
6340
RST 18H DF
RST 18H, the ROM routine that compares Register Pair HL (destination granules) with Register Pair DE (source granules): the CARRY FLAG when the destination is smaller.
6341
LD A,(5994H) 3A 94 59
Fetch the option flags from 5994H into Register A. LD does not change the flags.
6344
LD C,A 4F
Copy Register A (the 5994H flags) into Register C.
6345
LD HL,(59C1H) 2A C1 59
Fetch the source's total sectors from 59C1H into Register Pair HL: the sectors to copy.
6348
If the NO CARRY FLAG is set (the destination is big enough), JUMP to 6352H.
634A
BIT 1,C CB 49
Test bit 1 of Register C (the 5994H flags): BDU.
634C
If the Z FLAG is set (no BDU: the destination may not be smaller), JUMP to 5204H for error 3CH (INCOMPATIBLE DRIVES OR DISKETTES).
634F
LD HL,(59CFH) 2A CF 59
With BDU only as many sectors as the destination holds are copied: fetch the destination's total sectors from 59CFH into Register Pair HL.
6352
LD (5AF1H),HL 22 F1 5A
Store Register Pair HL (the sectors to copy) at 5AF1H, the source FCB's EOF. 6348H comes here.
6355
NOP 00
No operation, the first of two NOPs (00H 00H).
6356
NOP 00
No operation, the second of the two NOPs at 6355H-6356H.
6357
BIT 1,C CB 49
Test bit 1 of Register C (the 5994H flags): BDU.
6359
If the NZ FLAG is set (BDU), JUMP to 6365H without the granule size check.
635B
LD HL,59CAH 21 CA 59
Point Register Pair HL to 59CAH, the destination's granules per lump.
635E
LD A,(59BCH) 3A BC 59
Fetch the source's granules per lump from 59BCH into Register A.
6361
CP (HL) BE
Compare Register A (the source's granules per lump) against the destination's at Register Pair HL.
6362
If the NZ FLAG is set (different), JUMP to 5204H for error 3CH: the GAT of a sector copy would not fit the destination.
6365
GOSUB to 674DH, which ends the command unless BDU was given when either diskette has TI flag M. 6359H comes here.
6368
GOSUB to 67C5H to check the destination diskette and format it if required.
636B
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, sector 0, where both diskettes start.
636E
LD (5AEFH),HL 22 EF 5A
Store Register Pair HL (0) at 5AEFH, the source FCB's NEXT.
6371
LD (5B21H),HL 22 21 5B
Store Register Pair HL (0) at 5B21H, the destination FCB's NEXT.
6374
JUMP to 5273H to display COPYING and start the COPY engine.

6377H - Single File COPY (Formats 1 to 4): Find the Drives

Reached from 4DF0H. The drive of each filespec is found (6437H), the drive data and TI flag M patches are set up, SYS2/SYS is loaded for the opens, and the COPY engine is entered.

6377
LD BC,594CH 01 4C 59
Point Register Pair BC to 594CH, the source diskette's control block. 4DF0H comes here.
637A
LD DE,5AE5H 11 E5 5A
Point Register Pair DE to 5AE5H, the source FCB holding the first filespec.
637D
GOSUB to 6437H to find the drive of the filespec at Register Pair DE for the control block at Register Pair BC.
6380
LD BC,5956H 01 56 59
Point Register Pair BC to 5956H, the destination diskette's control block.
6383
LD DE,5B17H 11 17 5B
Point Register Pair DE to 5B17H, the destination FCB holding the second filespec.
6386
GOSUB to 6437H to find the drive of the filespec at Register Pair DE for the control block at Register Pair BC.
6389
GOSUB to 63B3H to save and load the drive data and prepare the TI flag M patches.
638C
GOSUB to 568BH to switch to the system diskette and load SYS2/SYS for the opens.
638F
JUMP to 5279H to start the COPY engine (without the COPYING message).

6392H - Parse the Destination Drive Number

Returns the CARRY FLAG and the drive number in Register A if the parameter at Register Pair HL is a drive number. The number is stored as the destination FCB's drive, the destination drive and at 4DFAH.

6392
GOSUB to 6ECAH to parse an optional colon and a drive number at Register Pair HL. It returns the CARRY FLAG with the drive in Register A, or the NO CARRY FLAG. 4D4DH and 65FAH call here.
6395
RET NC D0
If the NO CARRY FLAG is set (not a drive number), RETurn with the NO CARRY FLAG.
6396
LD (5B1DH),A 32 1D 5B
Store Register A (the drive) at 5B1DH, the destination FCB's drive (FCB+6).
6399
LD (5956H),A 32 56 59
Store Register A (the drive) at 5956H, the destination control block's drive.
639C
LD (4DFAH),A 32 FA 4D
Store Register A (the drive) at 4DFAH, the operand of the LD A,nn at 4DF9H, so that 4DF3H uses that drive's PDRIVE record.
639F
RET C9
RETurn with the CARRY FLAG and Register A = the drive.

63A0H - Parse an Optional Track Count

63A0H stores the destination track count at 64A9H; 63A3H stores it where Register Pair DE points (64A6H for the source). Nothing happens unless the character at Register Pair HL is =. A count of 0 gives error 2FH.

63A0
LD DE,64A9H 11 A9 64
Point Register Pair DE to 64A9H, the value byte of the destination track count entry in the override table. 4D53H and 6600H call here.
63A3
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A. 4D47H calls here with Register Pair DE = 64A6H.
63A4
CP 3DH FE 3D
Compare Register A (the character) against 3DH, the = before a track count.
63A6
RET NZ C0
If the NZ FLAG is set (no track count), RETurn.
63A7
PUSH DE D5
Save Register Pair DE (where the count goes) onto the stack.
63A8
INC HL 23
INCrement Register Pair HL past the = to the track count's digits.
63A9
GOSUB to 6EE6H to parse a decimal number of 0-255 at Register Pair HL into Register A.
63AC
POP DE D1
Restore Register Pair DE from the stack: where the count goes.
63AD
OR A B7
OR Register A (the track count) with itself: the Z FLAG for 0.
63AE
LD (DE),A 12
Store Register A (the track count) at Register Pair DE in the override table. LD does not change the flags.
63AF
RET NZ C0
If the NZ FLAG is set (a track count that is not 0), RETurn.
63B0
JUMP to 5218H for error 2FH: a track count of 0.

63B3H - Save and Load the Drive Data

Called from 4D79H, 6389H and 6630H. The PDRIVE entries of the drives used by the system, source and destination diskettes are saved as the originals (63B5H) and copied into each diskette's working record (63BFH). A source or destination given a PDRIVE number with SPDN= or DPDN= takes that record from the system diskette instead (63ECH), and the values typed in the command are put into the working records from the override table (63DAH). From now on each switch installs the diskette's working record.

63B3
LD B,03H 06 03
Load Register B with 03H, the mode for 5658H: bit 0 = the saved original (+6), bit 1 = copy the drive's PDRIVE entry into it, bit 2 clear = stop on an error. 4D79H, 6389H and 6630H call here.
63B5
GOSUB to 5646H to save the PDRIVE entry of each diskette's drive as its original.
63B8
LD B,02H 06 02
Load Register B with 02H, the mode for 5658H: bit 0 clear = the working record (+4), bit 1 = copy the drive's entry into it.
63BA
LD HL,593BH 21 3B 59
Point Register Pair HL to 593BH, the SYS6/SYS flags.
63BD
SET 7,(HL) CB FE
Set bit 7 of the byte at Register Pair HL (593BH): from now on each switch installs the diskette's working record and the exit puts the originals back.
63BF
GOSUB to 5646H to copy the PDRIVE entry of each diskette's drive into its working record.
63C2
LD BC,(594CH) ED 4B 4C 59
Load Register Pair BC from 594CH: Register C = the source drive, Register B = the source's role bit (02H).
63C6
LD HL,59B7H 21 B7 59
Point Register Pair HL to 59B7H, the source's working record.
63C9
LD A,FFH 3E FF
Load Register A with the PDRIVE number given with SPDN=. Self-Modifying Code
The operand at 63CAH is FFH in the file (none); 500BH stores the number there.
63CB
GOSUB to 63ECH to take the source's working record from that PDRIVE record of the system diskette, if one was given.
63CE
LD BC,(5956H) ED 4B 56 59
Load Register Pair BC from 5956H: Register C = the destination drive, Register B = the destination's role bit (04H).
63D2
LD HL,59C5H 21 C5 59
Point Register Pair HL to 59C5H, the destination's working record.
63D5
LD A,FFH 3E FF
Load Register A with the PDRIVE number given with DPDN=. Self-Modifying Code
The operand at 63D6H is FFH in the file (none); 500BH stores the number there.
63D7
GOSUB to 63ECH to take the destination's working record from that PDRIVE record, if one was given.
63DA
LD HL,64A3H 21 A3 64
Point Register Pair HL to 64A3H, the override table.
63DD
LD C,(HL) 4E
Load Register C with the number of entries at Register Pair HL (4).

Override Loop: each entry is the address of a byte in a working record and the value typed in the command (00H = not given).

63DE
INC HL 23
INCrement Register Pair HL to the next entry's address. 63E9H comes here.
63DF
LD E,(HL) 5E
Load Register E with the low byte of the address at Register Pair HL.
63E0
INC HL 23
INCrement Register Pair HL to the high byte of the entry's address.
63E1
LD D,(HL) 56
Load Register D with the high byte at Register Pair HL: Register Pair DE = the byte in the working record.
63E2
INC HL 23
INCrement Register Pair HL to the entry's value.
63E3
LD A,(HL) 7E
Fetch the value at Register Pair HL into Register A.
63E4
OR A B7
OR Register A (the value) with itself: the Z FLAG for 00H, not given.
63E5
If the Z FLAG is set (not given), JUMP to 63E8H.
63E7
LD (DE),A 12
Store Register A (the value) at Register Pair DE in the working record.
63E8
DEC C 0D
DECrement Register C, the entries left. 63E5H comes here.
63E9
If the NZ FLAG is set (more entries), LOOP BACK to 63DEH.
63EB
RET C9
RETurn to 4D7CH, 638CH or 6633H with the working records ready.

63ECH - Take a Working Record from the System Diskette's PDRIVE Data

Entered with Register A = a PDRIVE number (FFH = none), Register C = the diskette's drive, Register B = its role bit and Register Pair HL pointing to its working record. The ten bytes of that PDRIVE number's record are copied from the system diskette's PDRIVE sector. A diskette on drive 0 with other PDRIVE data cannot be the system diskette, so it is made a swapped diskette; and when the source and destination share a drive both are swapped.

63EC
CP FFH FE FF
Compare Register A (the PDRIVE number) against FFH. 63CBH and 63D7H call here.
63EE
RET Z C8
If the Z FLAG is set (no PDRIVE number given), RETurn unchanged.
63EF
RLCA 07
Rotate Register A (the PDRIVE number) left, the first of four.
63F0
RLCA 07
Rotate Register A (the PDRIVE number) left, the second of four.
63F1
RLCA 07
Rotate Register A (the PDRIVE number) left, the third of four.
63F2
RLCA 07
Rotate Register A left, the fourth: the number times 16, the offset of its record in the PDRIVE sector.
63F3
PUSH HL E5
Save Register Pair HL (the working record) onto the stack.
63F4
LD HL,5940H 21 40 59
Point Register Pair HL to 5940H, the swap set.
63F7
PUSH AF F5
Save Register Pair AF (Register A = the record's offset) onto the stack.
63F8
LD A,C 79
Copy Register C (the diskette's drive) into Register A.
63F9
OR A B7
OR Register A with itself: the Z FLAG for drive 0.
63FA
If the NZ FLAG is set (not drive 0), JUMP to 6406H.
63FC
DEC A 3D
DECrement Register A (00H, the drive) to FFH, a mask with every bit set.
63FD
XOR B A8
XOR Register B (the role bit) into Register A: every bit except this diskette's.
63FE
INC HL 23
INCrement Register Pair HL to 5941H, the mounted set.
63FF
AND (HL) A6
AND Register A with the mounted set at Register Pair HL: this diskette is taken out of it.
6400
LD (HL),A 77
Store Register A (the mounted set) back at Register Pair HL (5941H): it will be asked for.
6401
DEC HL 2B
DECrement Register Pair HL back to 5940H, the swap set.
6402
INC B 04
INCrement Register B (the role bit 02H or 04H): bit 0, the system diskette, is added (03H or 05H).
6403
LD A,(HL) 7E
Fetch the swap set at Register Pair HL into Register A.
6404
OR B B0
OR Register B into Register A: the system diskette and this one share drive 0.
6405
LD (HL),A 77
Store Register A (the swap set) back at Register Pair HL (5940H).
6406
LD A,(5956H) 3A 56 59
Fetch the destination drive from 5956H into Register A. 63FAH comes here.
6409
LD B,A 47
Copy Register A (the destination drive) into Register B.
640A
LD A,(594CH) 3A 4C 59
Fetch the source drive from 594CH into Register A.
640D
CP B B8
Compare Register A (the source drive) against Register B (the destination drive).
640E
If the NZ FLAG is set (different drives), JUMP to 6417H.
6410
LD A,(HL) 7E
Fetch the swap set at Register Pair HL (5940H) into Register A.
6411
OR 06H F6 06
OR Register A with 06H: the source and destination share the drive and are swapped.
6413
LD (HL),A 77
Store Register A (the swap set) back at Register Pair HL.
6414
INC HL 23
INCrement Register Pair HL to 5941H, the mounted set.
6415
LD (HL),01H 36 01
Store 01H at Register Pair HL (5941H): only the system diskette is mounted.
6417
GOSUB to 6424H to read the system diskette's PDRIVE sector into 4300H. Register Pair HL returns 4300H. 640EH comes here.
641A
POP AF F1
Restore Register Pair AF from the stack: Register A = the record's offset.
641B
ADD A,L 85
ADD Register L (00H, from 4300H) to Register A (the record's offset).
641C
LD L,A 6F
Copy Register A into Register L: Register Pair HL points to the PDRIVE record in 4300H.
641D
POP DE D1
Restore Register Pair DE from the stack: the working record.
641E
LD BC,000AH 01 0A 00
Load Register Pair BC with 000AH: 10 bytes, the in-memory part of a PDRIVE record.
6421
LDIR ED B0
Copy Register Pair BC (10) bytes from Register Pair HL (the PDRIVE record) to Register Pair DE (the working record).
6423
RET C9
RETurn with the working record filled from the PDRIVE sector.

6424H - Read the System Diskette's PDRIVE Sector

Reads sector 2 of the diskette in drive 0 (the third sector of BOOT/SYS, which holds the PDRIVE records and the SYSTEM options) into 4300H through the FCB at 5B49H, whose drive byte is 00H.

6424
LD HL,0002H 21 02 00
Load Register Pair HL with 0002H, sector 2 of the diskette. 4DF3H and 6417H call here.
6427
LD (5B53H),HL 22 53 5B
Store Register Pair HL (2) at 5B53H, the NEXT of the FCB at 5B49H.
642A
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the sector buffer.
642D
LD DE,5B49H 11 49 5B
Point Register Pair DE to 5B49H, the FCB for drive 0 sectors.
6430
GOSUB to 4436H (SYS0/SYS) to read the sector at the FCB's NEXT into its buffer (4300H). Register Pair HL is kept.
6433
RET Z C8
If the Z FLAG is set (read without error), RETurn with Register Pair HL = 4300H.
6434
JUMP to 521AH to end the command with the error code in Register A.

6437H - Find the Drive of a Filespec

Entered with Register Pair DE pointing to a filespec in an FCB and Register Pair BC to its diskette control block. A drive number in the filespec (:d) becomes the control block's drive. In formats 3 and 4 the filespec may not have one, and the drive from the command is added to it instead. In formats 1 and 2 a filespec without a drive number is opened at once (5538H), which finds its drive; that is not allowed with $, SPDN or DPDN.

6437
LD HL,5940H 21 40 59
Point Register Pair HL to 5940H, the swap set. 637DH and 6386H call here.

Scan Loop: look for a colon or the 03H that ends the filespec.

643A
LD A,(DE) 1A
Fetch a character of the filespec at Register Pair DE into Register A. 645AH comes here.
643B
CP 3AH FE 3A
Compare Register A (the character) against 3AH, a colon.
643D
INC DE 13
INCrement Register Pair DE to the next character. INC DE does not change the flags.
643E
If the NZ FLAG is set (not a colon), JUMP to 6458H.
6440
LD A,(HL) 7E
Fetch the swap set at Register Pair HL into Register A.
6441
CP 06H FE 06
Compare Register A (the swap set) against 06H: the NO CARRY FLAG for formats 3 and 4 (source and destination swapped in one drive).
6443
If the NO CARRY FLAG is set (a drive number is not allowed here), JUMP to 6482H for error 20H.
6445
PUSH HL E5
Save Register Pair HL (5940H) onto the stack.
6446
PUSH BC C5
Save Register Pair BC (the control block) onto the stack.
6447
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the drive digit after the colon.
6448
GOSUB to 6ED6H to parse the drive number at Register Pair HL and check that the drive exists. It returns the number in Register A.
644B
POP BC C1
Restore Register Pair BC from the stack: the control block.
644C
POP HL E1
Restore Register Pair HL from the stack: 5940H.
644D
OR A B7
OR Register A (the drive) with itself: the Z FLAG for drive 0.
644E
LD (BC),A 02
Store Register A (the drive) at Register Pair BC, the control block's drive. LD does not change the flags.
644F
RET NZ C0
If the NZ FLAG is set (not drive 0), RETurn with the drive stored.
6450
INC BC 03
INCrement Register Pair BC to the control block's role bit.
6451
LD A,(BC) 0A
Fetch the role bit at Register Pair BC into Register A.
6452
BIT 0,(HL) CB 46
Test bit 0 of the swap set at Register Pair HL: a $ was given (formats 2 and 4).
6454
RET Z C8
If the Z FLAG is set (no $: the diskette on drive 0 is the system diskette), RETurn.
6455
OR (HL) B6
OR the swap set at Register Pair HL into Register A (the role bit): this diskette is swapped with the system diskette.
6456
LD (HL),A 77
Store Register A (the swap set) back at Register Pair HL.
6457
RET C9
RETurn with this diskette added to the swap set at 5940H.
6458
CP 03H FE 03
Compare Register A (the character) against 03H, the end of the filespec. 643EH comes here.
645A
If the NZ FLAG is set (not the end), LOOP BACK to 643AH. Register Pair DE is now just past the 03H.
645C
LD A,(HL) 7E
No drive in the filespec. Fetch the swap set at Register Pair HL into Register A.
645D
CP 06H FE 06
Compare Register A (the swap set) against 06H: the CARRY FLAG for formats 1 and 2.
645F
If the CARRY FLAG is set (formats 1 and 2), JUMP to 6474H.
6461
LD A,(BC) 0A
Formats 3 and 4: fetch the drive from the command, at Register Pair BC (the control block), into Register A.
6462
OR A B7
OR Register A (the drive) with itself: the Z FLAG for drive 0.
6463
INC BC 03
INCrement Register Pair BC to the role bit. INC BC does not change the flags.
6464
If the NZ FLAG is set (not drive 0), JUMP to 6468H.
6466
SET 0,(HL) CB C6
Set bit 0 of the swap set at Register Pair HL: drive 0 is shared with the system diskette as well.
6468
ADD A,30H C6 30
ADD 30H to Register A (the drive): its ASCII digit. 6464H comes here.
646A
LD (DE),A 12
Store Register A (the digit) at Register Pair DE, the byte after the 03H.
646B
DEC DE 1B
DECrement Register Pair DE back to the 03H that ended the filespec.
646C
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the 03H.
646D
LD (HL),3AH 36 3A
Store 3AH, a colon, at Register Pair HL over the 03H.
646F
INC HL 23
INCrement Register Pair HL from the colon to the drive digit.
6470
INC HL 23
INCrement Register Pair HL past the drive digit to the next byte.
6471
LD (HL),03H 36 03
Store 03H at Register Pair HL: the filespec now ends with :d.
6473
RET C9
RETurn with the drive added to the filespec in the FCB.
6474
BIT 0,A CB 47
Test bit 0 of Register A (the swap set): a $ was given. 645FH comes here.
6476
If the NZ FLAG is set ($ without a drive number), JUMP to 6482H for error 20H.
6478
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A.
647B
AND C0H E6 C0
AND Register A (the 5997H flags) with C0H, keeping bit 7 (SPDN) and bit 6 (DPDN).
647D
LD H,B 60
Copy Register B (the high byte of the control block) into Register H. LD does not change the flags.
647E
LD L,C 69
Copy Register C (the low byte) into Register L: Register Pair HL = the control block.
647F
If the Z FLAG is set (no PDRIVE number given), JUMP to 5538H to switch in and open the file now, which finds its drive and stores it in the control block (5576H).
6482
JUMP to 5200H for error 20H (ILLEGAL OR MISSING DRIVE #). 6443H and 6476H come here.

6485H - Not in the File

The second load block ends at 6484H. 6485H-64A2H is the interleave table of the track format code (6A14H, 6A29H, 6A61H, 6AD3H, 6BEAH, 6C56H). From 6491H on, memory is also used for the include/exclude names and the COPY by file list.

6485-64A2
DEFS 30
Not in the file: the 30 bytes 6485H-64A2H, filled by the track format code at run time (the sector numbers of a track in the order they are formatted).

64A3H - Override Table (Data)

Used by 63DAH after the PDRIVE data has been loaded: a count, then for each entry the address of a byte in a working PDRIVE record and the value typed in the command (00H = not given).

64A3
DEFB 04H 04
The number of entries in the override table, read by 63DDH: four.
64A4-64A6
DEFW 59BAH / DEFB 00H BA 59 00
The source's track count (59BAH, byte +3 of its working record), from =tc1 (4D47H stores it at 64A6H).
64A7-64A9
DEFW 59C8H / DEFB 00H C8 59 00
The destination's track count (59C8H), from =tc2 or the FORMAT drive parameter (63A0H stores it at 64A9H).
64AA-64AC
DEFW 59CDH / DEFB 00H CD 59 00
The destination's directory starting lump (59CDH, DDSL), from DDSL= (4FC6H stores it at 64ACH).
64AD-64AF
DEFW 59CEH / DEFB 00H CE 59 00
The destination's directory granules (59CEH, DDGA), from DDGA= (4FA8H stores it at 64AFH).

64B0H - Fill the Sector Buffer

Fills 4300H-43FFH with the byte in Register A. Called from 6675H (FFH, a new GAT sector) and 66C1H (00H, the other directory sectors).

64B0
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the sector buffer. 6675H and 66C1H call here.
64B3
LD B,00H 06 00
Load Register B with 00H: 256 bytes for the DJNZ.
64B5
LD (HL),A 77
Store Register A (the fill byte) at Register Pair HL. 64B7H comes here.
64B6
INC HL 23
INCrement Register Pair HL to the next byte of the buffer.
64B7
DECrement Register B and LOOP BACK to 64B5H until all 256 bytes are filled.
64B9
RET C9
RETurn with Register Pair HL = 4300H and Register B = 0.

64BAH - Boot Sector Image

These bytes (64BAH-65B9H) are the boot sector. 67ACH-67B3H write them as sectors 0 and 1 of every diskette FORMAT makes, and a diskette COPY puts them in place of the source's boot sectors (52F6H). The ROM reads the boot sector into 4300H and jumps to 4300H, so each comment starts with the address the byte has there. FORMAT fills in the drive's values first (6759H): the directory lump (64BCH), the double density bit of the two select bytes (6506H, 6510H), the first track and sector of SYS0/SYS (64BFH-64C0H), the sectors per side (650BH) and per track (6571H), the first sector number of a track (6576H) and the PDRIVE bytes (65B7H-65B9H). The loader reads SYS0/SYS from track 0 sector 5 record by record and enters it at the byte after the A5H at its transfer address (4D01H). 65B3H-65B6H are not in the file.

64BA
NOP 00
4300H: No operation. Byte 0 of the boot sector is 00H. 52F6H and 67B3H point to this byte.
64BB
CP 11H FE 11
4301H: Compare Register A (whatever the ROM left in it) against 11H. The result is not used: the instruction steps over byte 4302H, the data byte 11H, which is the lump where the directory starts (SYS0/SYS reads it at its 4898H; FORMAT stores it through 6799H, a COPY through 5C88H).
64BD
DI F3
4303H: Disable interrupts. The loader runs with interrupts off; the end of each sector read comes as an NMI (4382H-4384H).
64BE
LD DE,0005H 11 05 00
4304H: Load Register Pair DE with 0005H: Register D = track 0 and Register E = sector 5, where SYS0/SYS starts. FORMAT adds 1 to the track (64C0H, 676CH) when the tracks are numbered from 1 and to the sector (64BFH, 6774H) when the sectors are numbered from 1.
64C1
EXX D9
4307H: Exchange Register Pairs BC, DE and HL with the alternate set. Register Pair DE' now keeps the track and sector; the sector read at 4348H works in the alternate set, and the main set is free for the loader.
64C2
LD SP,41E0H 31 E0 41
4308H: Load the Stack Pointer with 41E0H: the stack is below 41E0H, clear of the loader and of SYS0/SYS's records.
64C5
LD HL,51FFH 21 FF 51
430BH: Point Register Pair HL to 51FFH, the last byte of the sector buffer at 5100H-51FFH. The first INC L at 4345H wraps Register L to 00H, which makes 4345H read the first sector.
64C8
CALL 4345H CD 45 43
430EH: Record loop. GOSUB to 4345H to fetch the next byte of SYS0/SYS into Register A: the type of the record. 4331H comes here.
64CB
CP 20H FE 20
4311H: Compare Register A (the record type) against 20H. The NO CARRY FLAG is set for 20H and above, which is not a load file.
64CD
LD B,A 47
4313H: Copy Register A (the record type) into Register B for the two DJNZ tests. LD does not change the flags.
64CE
4314H: If the NO CARRY FLAG is set (type 20H or more), JUMP to 433FH (64F9H in this file) to display NO SYS.
64D0
LD D,A 57
4316H: Copy Register A (the type) into Register D. For a record that is passed over, Register Pair DE then points into the ROM (0000H-1FFFH), where the stores at 432CH have no effect.
64D1
CALL 4345H CD 45 43
4317H: GOSUB to 4345H to fetch the record's length byte into Register A.
64D4
LD C,A 4F
431AH: Copy Register A (the length) into Register C.
64D5
CALL 4345H CD 45 43
431BH: GOSUB to 4345H to fetch the next byte into Register A: the low byte of the load address, or the first byte of a record that is passed over.
64D8
LD E,A 5F
431EH: Copy Register A (the byte just fetched) into Register E.
64D9
431FH: DECrement Register B (the type) and, if it is not 0 (the type is not 01H), JUMP to 4333H (64EDH in this file).
64DB
CALL 4345H CD 45 43
4321H: Type 01H, a load block: GOSUB to 4345H to fetch the high byte of the load address into Register A.
64DE
LD D,A 57
4324H: Copy Register A into Register D: Register Pair DE = the load address.
64DF
DEC C 0D
4325H: DECrement Register C (the length byte), the first of two.
64E0
DEC C 0D
4326H: DECrement Register C again: Register C = the number of data bytes, the length less the two address bytes (00H gives 254, 01H 255, 02H 256).
64E1
INC L 2C
4327H: Data loop. INCrement Register L, the position in the sector buffer at 5100H. 432FH comes here.
64E2
CALL Z,4348H CC 48 43
4328H: If the Z FLAG is set (Register L wrapped to 00H: the buffer is used up), GOSUB to 4348H to read the next sector into 5100H.
64E5
LD A,(HL) 7E
432BH: Fetch the data byte at Register Pair HL into Register A.
64E6
LD (DE),A 12
432CH: Store Register A at Register Pair DE, the load address (or the ROM for a record that is passed over).
64E7
INC DE 13
432DH: INCrement Register Pair DE to the next load address.
64E8
DEC C 0D
432EH: DECrement Register C, the bytes left. 4333H comes here for a record that is passed over.
64E9
432FH: If the NZ FLAG is set (bytes left), LOOP BACK to 4327H (64E1H in this file).
64EB
4331H: JUMP to 430EH (64C8H in this file) for the next record.
64ED
4333H: DECrement Register B and, if it is not 0 (the type is not 02H), JUMP to 432EH (64E8H in this file) to pass over the rest of the record: its first byte is already in Register E, Register C - 1 bytes follow. 431FH comes here.
64EF
CALL 4345H CD 45 43
4335H: Type 02H, the transfer address: GOSUB to 4345H to fetch its high byte into Register A (the low byte is in Register E).
64F2
LD D,A 57
4338H: Copy Register A into Register D: Register Pair DE = the transfer address.
64F3
LD A,(DE) 1A
4339H: Fetch the byte at the transfer address (Register Pair DE) into Register A.
64F4
CP A5H FE A5
433AH: Compare Register A against A5H, the byte SYS0/SYS has at its transfer address 4D00H.
64F6
INC DE 13
433CH: INCrement Register Pair DE to the byte after it. INC DE does not change the flags.
64F7
PUSH DE D5
433DH: Save Register Pair DE (the transfer address + 1) onto the stack as the address for the RET.
64F8
RET Z C8
433EH: If the Z FLAG is set (A5H found), RETurn to the transfer address + 1: SYS0/SYS starts at 4D01H.
64F9
LD HL,43F0H 21 F0 43
433FH: Point Register Pair HL to 43F0H, the message NO SYS. 4314H comes here.
64FC
JP 43CCH C3 CC 43
4342H: JUMP to 43CCH to display the message and stop.
64FF
INC L 2C
4345H: Fetch the next byte. INCrement Register L, the position in the sector buffer; the Z FLAG is set when it wraps to 00H. 430EH, 4317H, 431BH, 4321H and 4335H call here.
6500
LD A,(HL) 7E
4346H: Fetch the byte at Register Pair HL into Register A. LD does not change the flags.
6501
RET NZ C0
4347H: If the NZ FLAG is set (the byte is in the buffer), RETurn with it in Register A. Otherwise the buffer is used up and the code goes on into 4348H.
6502
EXX D9
4348H: Read the next sector. Exchange Register Pairs BC, DE and HL with the alternate set: Register Pair DE = the track and sector. 4328H calls here.
6503
LD B,0AH 06 0A
4349H: Load Register B with 0AH, 10 tries to read the sector.
6505
LD L,01H 2E 01
434BH: Load Register L with 01H, the select byte for side 0: drive 0. FORMAT sets bit 7 of the operand at 434CH (6506H, 6781H) for a double density diskette. 43C7H comes here for another try.
6507
PUSH DE D5
434DH: Save Register Pair DE (the track and sector) onto the stack.
6508
PUSH BC C5
434EH: Save Register Pair BC (Register B = the tries left) onto the stack.
6509
LD A,E 7B
434FH: Copy Register E (the sector) into Register A.
650A
SUB 12H D6 12
4350H: SUBtract 12H, the sectors on one side, from Register A. FORMAT stores the drive's value in the operand at 4351H (650BH, 6793H).
650C
4352H: If the CARRY FLAG is set (the sector is on side 0), JUMP to 4357H (6511H in this file).
650E
LD E,A 5F
4354H: Copy Register A (the sector on side 1) into Register E.
650F
LD L,11H 2E 11
4355H: Load Register L with 11H, the select byte for side 1: drive 0 with bit 4. FORMAT sets bit 7 of the operand at 4356H (6510H, 6786H) for a double density diskette.
6511
CALL 43D7H CD D7 43
4357H: GOSUB to 43D7H to wait until the controller is not busy. 4352H comes here.
6514
LD A,L 7D
435AH: Copy Register L (the select byte) into Register A.
6515
OUT (F4H),A D3 F4
435BH: Send Register A to port F4H: drive 0, the side and the density are selected.
6517
LD A,D 7A
435DH: Copy Register D (the track) into Register A.
6518
OUT (F3H),A D3 F3
435EH: Send Register A (the track) to the controller's data register, port F3H, the destination of the Seek.
651A
LD A,E 7B
4360H: Copy Register E (the sector) into Register A.
651B
OUT (F2H),A D3 F2
4361H: Send Register A (the sector) to the controller's sector register, port F2H.
651D
LD A,1BH 3E 1B
4363H: Load Register A with 1BH, the Seek command with head load and the slowest stepping rate (bits 0-1 = 11).
651F
OUT (F0H),A D3 F0
4365H: Send Register A (1BH) to the controller's command register, port F0H.
6521
CALL 43D7H CD D7 43
4367H: GOSUB to 43D7H to wait until the Seek is done.
6524
LD A,L 7D
436AH: Copy Register L (the select byte) into Register A.
6525
OR 40H F6 40
436BH: OR Register A with 40H, setting bit 6: wait states, so that an INI from port F3H holds the CPU until the controller has the byte.
6527
LD E,A 5F
436DH: Copy Register A (the select byte with wait states) into Register E for the transfer loop.
6528
LD D,02H 16 02
436EH: Load Register D with 02H, the data request bit of the status.
652A
IN A,(F0H) DB F0
4370H: Read the controller's status from port F0H into Register A, which clears the interrupt request left by the Seek.
652C
LD (43A6H),SP ED 73 A6 43
4372H: Store the Stack Pointer at 43A6H, the operand of the LD SP,nnnn at 43A5H, so that the NMI routine returns to this level.
6530
LD HL,43A2H 21 A2 43
4376H: Point Register Pair HL to 43A2H, the routine for the NMI at the end of the read.
6533
LD (404AH),HL 22 4A 40
4379H: Store Register Pair HL (43A2H) at 404AH, the address part of the NMI vector at 4049H.
6536
LD A,C3H 3E C3
437CH: Load Register A with C3H, the opcode of JP.
6538
LD (4049H),A 32 49 40
437EH: Store Register A (C3H) at 4049H: the NMI vector is now JP 43A2H.
653B
LD A,C0H 3E C0
4381H: Load Register A with C0H, the NMI mask: bit 7 the controller's interrupt request, bit 6 the drive motor time-out.
653D
OUT (E4H),A D3 E4
4383H: Send Register A (C0H) to the NMI mask, port E4H.
653F
LD A,88H 3E 88
4385H: Load Register A with 88H, the Read Sector command.
6541
OUT (F0H),A D3 F0
4387H: Send Register A (88H) to the controller's command register, port F0H: the read starts.
6543
LD HL,5100H 21 00 51
4389H: Point Register Pair HL to 5100H, the sector buffer.
6546
LD BC,00F3H 01 F3 00
438CH: Load Register Pair BC with 00F3H: Register B = 00H (256 bytes for INI), Register C = F3H, the data port.
6549
CALL 43E2H CD E2 43
438FH: GOSUB to 43E2H for a short delay, so that the controller's status is valid.
654C
IN A,(F0H) DB F0
4392H: Read the controller's status from port F0H into Register A. 4395H comes here.
654E
AND D A2
4394H: AND Register A with Register D (02H), keeping the data request bit.
654F
4395H: If the Z FLAG is set (no data request yet), LOOP BACK to 4392H (654CH in this file).
6551
INI ED A2
4397H: INI: read the first byte from port F3H (Register C) into the buffer at Register Pair HL; Register Pair HL goes up by 1 and Register B down by 1 (FFH left).
6553
LD A,E 7B
4399H: Copy Register E (the select byte with wait states) into Register A.
6554
OUT (F4H),A D3 F4
439AH: Send Register A to port F4H: the drive is selected again with wait states before each byte. 439EH comes here.
6556
INI ED A2
439CH: INI: read the next byte from port F3H into the buffer at Register Pair HL; the CPU waits on the port until the controller has it. Register B counts down; the Z FLAG is set at 0.
6558
439EH: If the NZ FLAG is set (bytes left), LOOP BACK to 439AH (6554H in this file).
655A
43A0H: All 256 bytes are in: wait here (JUMP to 43A0H, 655AH in this file) until the controller ends the command, whose interrupt request causes the NMI.
655C
XOR A AF
43A2H: The NMI (through the vector at 4049H) comes here. Set Register A to 00H, the value that masks every NMI.
655D
OUT (E4H),A D3 E4
43A3H: Send Register A (00H) to the NMI mask, port E4H.
655F
LD SP,0000H 31 00 00
43A5H: Load the Stack Pointer with the value saved at 4372H (0000H in the file), which drops the NMI's return address. Self-Modifying Code
The operand at 43A6H (6560H) is stored by 4372H.
6562
IN A,(F0H) DB F0
43A8H: Read the controller's status from port F0H into Register A: the result of the read.
6564
AND FCH E6 FC
43AAH: AND Register A with FCH, keeping the error bits 2-7. The Z FLAG is set for a good read.
6566
LD A,D0H 3E D0
43ACH: Load Register A with D0H, the Force Interrupt command. LD does not change the flags.
6568
OUT (F0H),A D3 F0
43AEH: Send Register A (D0H) to port F0H, which ends any command still running. OUT does not change the flags.
656A
POP BC C1
43B0H: Restore Register Pair BC from the stack: Register B = the tries left.
656B
POP DE D1
43B1H: Restore Register Pair DE from the stack: the track and sector.
656C
43B2H: If the NZ FLAG is set (a read error), JUMP to 43C0H (657AH in this file) to try again.
656E
INC E 1C
43B4H: INCrement Register E to the next sector.
656F
LD A,E 7B
43B5H: Copy Register E (the next sector) into Register A.
6570
SUB 12H D6 12
43B6H: SUBtract 12H, the sectors per track, from Register A: the Z FLAG past the last sector of the track. FORMAT stores the drive's value in the operand at 43B7H (6571H, 678DH).
6572
43B8H: If the NZ FLAG is set (still on this track), JUMP to 43BDH (6577H in this file).
6574
INC D 14
43BAH: INCrement Register D to the next track.
6575
LD E,00H 1E 00
43BBH: Load Register E with 00H, the first sector of the track. FORMAT stores 01H in the operand at 43BCH (6576H, 6778H) when the sectors are numbered from 1.
6577
EXX D9
43BDH: Exchange Register Pairs BC, DE and HL with the alternate set: Register Pair HL = the buffer pointer again (5100H). 43B8H comes here.
6578
LD A,(HL) 7E
43BEH: Fetch the first byte of the new sector at Register Pair HL into Register A.
6579
RET C9
43BFH: RETurn with the byte in Register A to the caller of 4345H (or to 432BH for the CALL Z at 4328H).
657A
CALL 43E2H CD E2 43
43C0H: GOSUB to 43E2H for a short delay. 43B2H comes here.
657D
LD A,0BH 3E 0B
43C3H: Load Register A with 0BH, the Restore command with the slowest stepping rate: the head goes back to track 0.
657F
OUT (F0H),A D3 F0
43C5H: Send Register A (0BH) to the controller's command register, port F0H.
6581
43C7H: DECrement Register B (the tries left) and, if it is not 0, LOOP BACK to 434BH (6505H in this file) to try the sector again.
6583
LD HL,43E8H 21 E8 43
43C9H: Ten tries failed. Point Register Pair HL to 43E8H, the message ERROR.
6586
LD A,(HL) 7E
43CCH: Fetch the character at Register Pair HL into Register A. 4342H, 43CFH and 43D5H come here.
6587
CP 03H FE 03
43CDH: Compare Register A against 03H, the end of the message.
6589
43CFH: If the Z FLAG is set (the end), LOOP BACK to 43CCH (6586H in this file): the loader stops here for good.
658B
INC HL 23
43D1H: INCrement Register Pair HL to the next character.
658C
43D2H: GOSUB to 0033H (ROM) to display the character in Register A.
658F
43D5H: JUMP to 43CCH (6586H in this file) for the next character of the message.
6591
CALL 43E2H CD E2 43
43D7H: GOSUB to 43E2H for a short delay, so that the controller's status is valid. 4357H and 4367H call here.
6594
IN A,(F0H) DB F0
43DAH: Read the controller's status from port F0H into Register A. 43DDH comes here.
6596
RRCA 0F
43DCH: Rotate Register A right: bit 0 (busy) goes into the CARRY FLAG.
6597
43DDH: If the CARRY FLAG is set (busy), LOOP BACK to 43DAH (6594H in this file).
6599
IN A,(F0H) DB F0
43DFH: Read the controller's status from port F0H into Register A again.
659B
RET C9
43E1H: RETurn with the controller's status (port F0H) in Register A.
659C
LD A,08H 3E 08
43E2H: Load Register A with 08H, the count of a short delay. 438FH, 43C0H and 43D7H call here.
659E
DEC A 3D
43E4H: DECrement Register A. 43E5H comes here.
659F
43E5H: If the NZ FLAG is set, LOOP BACK to 43E4H (659EH in this file).
65A1
RET C9
43E7H: RETurn after the delay of 8 passes, with Register A = 00H.
65A2-65A9
DEFB 1CH, 1FH / DEFM "ERROR", 03H 1C 1F 45 52 52 4F 52 03
43E8H: the disk error message (43C9H): 1CH homes the cursor and 1FH clears to the end of the screen, the text ERROR and the end byte 03H that 43CDH tests for.
65AA-65B2
DEFB 1CH, 1FH / DEFM "NO SYS", 03H 1C 1F 4E 4F 20 53 59 53 03
43F0H: the message for a file that is not SYS0/SYS (433FH): the screen is cleared, then the text NO SYS and the end byte 03H.
65B3-65B6
DEFS 4
43F9H-43FCH: not in the file, and not used by the boot code. The boot sector is written with whatever these 4 bytes of memory hold at the time.
65B7
DEFB 00H 00
43FDH: byte FDH of the boot sector, byte +6 of the destination drive's PDRIVE record, stored by 675CH. SYS0/SYS reads it at reset (its 4D41H).
65B8
DEFB 00H 00
43FEH: byte FEH of the boot sector, byte +2 of the destination drive's PDRIVE record (the flags), stored by 67A8H. SYS0/SYS reads it at reset (its 4D37H).
65B9
DEFB 00H 00
43FFH: byte FFH of the boot sector, byte +7 of the destination drive's PDRIVE record (the disk I/O flags), stored by 6762H. SYS0/SYS reads it at reset (its 4D37H).

65BAH - Directory Entries for BOOT/SYS and DIR/SYS (Data)

The first two directory entries of a new diskette. 66E6H copies them into the first places of directory sectors 2 and 3 (DEC 0 and DEC 1).

65BA-65D9
DEFB 5EH, 00H, 00H, 00H, 00H / DEFM "BOOT SYS" / DEFW 7F60H, B21FH / DEFB 05H, 00H, 00H, 00H, FFH x 8 5E 00 00 00 00 42 4F 4F 54 20 20 20 20 53 59 53 60 7F 1F B2 05 00 00 00 FF FF FF FF FF FF FF FF
BOOT/SYS (DEC 0): flags 5EH (system file, in use, invisible, access level 6), EOF low byte 00H and record length 00H, the name and extension, update password code 7F60H, access password code B21FH, EOF middle and high bytes 0005H (five whole sectors), one extent element 00H 00H (lump 0, granule 0, one granule) and FFH in the rest.
65DA-65F9
DEFB 5DH, 00H, 00H, 00H, 00H / DEFM "DIR SYS" / DEFW 1DA7H, E5F9H / DEFB 0AH, 00H, 11H, 01H, FFH x 8 5D 00 00 00 00 44 49 52 20 20 20 20 20 53 59 53 A7 1D F9 E5 0A 00 11 01 FF FF FF FF FF FF FF FF
DIR/SYS (DEC 1): flags 5DH (system file, in use, invisible, access level 5), the name and extension, password codes 1DA7H and E5F9H, EOF 0AH whole sectors (66DEH stores the real number of directory sectors at 65EEH), one extent element at 65F0H-65F1H: lump 11H (the directory lump, stored by 67A2H) and 01H (granule 0, two granules; 67A2H stores the directory granules less one).

65FAH - FORMAT Command

Entered from 4D13H with Register Pair HL pointing to dn2[=tc2],name2,mm/dd/yy,password3[,options]. Null name, date and password parameters give NOTNAMED, the system date and PASSWORD. N is the default when none of N, Y, DDND, ODN, KDN or KDD is given. FORMAT shares the formatting code with COPY formats 5 and 6 (6643H) and ends by displaying DONE (552DH).

65FA
GOSUB to 6392H to parse the drive number at Register Pair HL; it becomes the destination drive (5956H, 5B1DH, 4DFAH) and returns the CARRY FLAG. 4D13H comes here.
65FD
If the NO CARRY FLAG is set (no drive number), JUMP to 5218H for error 2FH.
6600
GOSUB to 63A0H to parse an optional =tc2 at Register Pair HL into 64A9H, the destination track count override.
6603
PUSH HL E5
Save Register Pair HL (the command line pointer) onto the stack.
6604
LD HL,5997H 21 97 59
Point Register Pair HL to 5997H, the option flags.
6607
SET 2,(HL) CB D6
Set bit 2 (FMT) of the byte at Register Pair HL (5997H): FORMAT always formats.
6609
POP HL E1
Restore Register Pair HL from the stack: the command line pointer.
660A
GOSUB to 6EB4H to step to the name parameter. It returns the CARRY FLAG if a parameter follows, the NO CARRY FLAG if it is null or missing.
660D
If the CARRY FLAG is set, GOSUB to 4F95H to copy the name at Register Pair HL to 5983H (otherwise NOTNAMED stays).
6610
GOSUB to 6FB7H to parse the date at Register Pair HL into 598BH, or put the system date there.
6613
GOSUB to 6EB4H to step to the password parameter. It returns the CARRY FLAG if one follows.
6616
If the NO CARRY FLAG is set (no password), JUMP to 661FH: the code of PASSWORD (42E0H) stays at 5981H.
6618
GOSUB to 5025H to encode the password at Register Pair HL into Register Pair DE.
661B
LD (5981H),DE ED 53 81 59
Store Register Pair DE (the password code) at 5981H, for GAT bytes CEH-CFH.
661F
LD B,40H 06 40
Load Register B with 40H, the option table bit for FORMAT. 6616H comes here.
6621
GOSUB to 4EA7H to parse the options at Register Pair HL and check their combinations.
6624
LD HL,5994H 21 94 59
Point Register Pair HL to 5994H, the option flags.
6627
LD A,(HL) 7E
Fetch the option flags at Register Pair HL (5994H) into Register A.
6628
AND F9H E6 F9
AND Register A (the 5994H flags) with F9H, keeping bits 7 (N), 6 (Y), 5 (DDND), 4 (ODN), 3 (KDN) and 0 (KDD).
662A
If the NZ FLAG is set (one of them was given), JUMP to 6630H.
662C
LD A,(HL) 7E
Fetch the option flags at Register Pair HL (5994H) into Register A again.
662D
OR 80H F6 80
OR Register A with 80H, setting bit 7: N is the default for FORMAT.
662F
LD (HL),A 77
Store Register A (the flags with N) back at Register Pair HL (5994H).
6630
GOSUB to 63B3H to save the drives' PDRIVE data and fill in the destination's working record, with the overrides. 662AH comes here.
6633
LD HL,6DF2H 21 F2 6D
Point Register Pair HL to 6DF2H, the message STARTING DISKETTE FORMAT.
6636
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
6639
GOSUB to 6710H to work out the destination diskette's sector, granule and lump counts.
663C
GOSUB to 4DF3H to build the new PDRIVE sector at 6EB4H and work out the diskette swaps.
663F
LD HL,552DH 21 2D 55
Point Register Pair HL to 552DH, which displays DONE and ends the command.
6642
PUSH HL E5
Save Register Pair HL (552DH) onto the stack as the return address, and fall into 6643H.

6643H - Format the Destination and Write Its System Data

Called from 5D16H (COPY by file) and entered from 6642H (FORMAT). After 67C5H has checked (and with FMT formatted) the diskette, the whole diskette is read back (5784H). Unless BDU was given the system data is then written: the boot sector as sectors 0 and 1, the PDRIVE sector as sector 2, and the directory: a GAT with every granule of the diskette free except BOOT/SYS's and the directory's, a HIT with the hash codes of BOOT/SYS and DIR/SYS, and the FDE sectors with their two entries. Nothing is written after an NFMT or an RWF.

6643
GOSUB to 67C5H to check the destination diskette and, with FMT, format it. 5D16H calls here; 6642H falls in.
6646
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A.
6649
BIT 3,A CB 5F
Test bit 3 of Register A (the 5997H flags): NFMT, the diskette is not formatted.
664B
RET NZ C0
If the NZ FLAG is set (the diskette was not formatted), RETurn.
664C
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
664F
BIT 7,A CB 7F
Test bit 7 of Register A (5996H): RWF (in COPY, SN has been cleared at 632FH).
6651
RET NZ C0
If the NZ FLAG is set (RWF: a format only to wipe the diskette), RETurn.
6652
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, the first sector of the diskette.
6655
GOSUB to 5784H to read every sector of the new diskette from sector 0 (Register Pair DE).
6658
LD A,(5994H) 3A 94 59
Fetch the option flags from 5994H into Register A.
665B
BIT 1,A CB 4F
Test bit 1 of Register A (the 5994H flags): BDU, bypass the system data.
665D
RET NZ C0
If the NZ FLAG is set (BDU: no system data is written), RETurn.
665E
LD HL,6DD9H 21 D9 6D
Point Register Pair HL to 6DD9H, the message INITIALIZING SYSTEM DATA.
6661
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
6664
GOSUB to 67ACH to write the boot sector image as sectors 0 and 1. It returns the Z FLAG if they were written.
6667
LD DE,6EB4H 11 B4 6E
Point Register Pair DE to 6EB4H, the new PDRIVE sector built by 4DF3H. LD does not change the flags.
666A
LD BC,0002H 01 02 00
Load Register Pair BC with 0002H, sector 2, the system data sector.
666D
If the Z FLAG is set (the boot sectors were written), GOSUB to 67B6H to write the 256 bytes at Register Pair DE as sector Register Pair BC (2).
6670
If the NZ FLAG is set (a write error), JUMP to 521AH to end the command with the error code in Register A.
6673
LD A,FFH 3E FF
Load Register A with FFH, the GAT byte of a lump whose granules are all allocated.
6675
GOSUB to 64B0H to fill the buffer 4300H-43FFH with Register A (FFH).
6678
LD DE,(59D1H) ED 5B D1 59
Fetch the diskette's total granules from 59D1H into Register Pair DE.
667C
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the new GAT.
667F
LD (5B1AH),HL 22 1A 5B
Store Register Pair HL (4300H) at 5B1AH, the destination FCB's buffer.
6682
LD C,L 4D
Copy Register L (00H) into Register C: granule 0 of lump 0.
6683
PUSH HL E5
Save Register Pair HL (4300H) onto the stack.
6684
GOSUB to 5762H to free Register Pair DE granules in the GAT at Register Pair HL from granule Register C on: every granule of the diskette (and the same bits in the lockout table if there are no more than 96 lumps).
6687
POP HL E1
Restore Register Pair HL from the stack: 4300H, lump 0's byte.
6688
SET 0,(HL) CB C6
Set bit 0 of the byte at Register Pair HL (4300H): granule 0 of lump 0 belongs to BOOT/SYS.
668A
LD A,(59CDH) 3A CD 59
Fetch the directory starting lump (DDSL) from 59CDH into Register A.
668D
LD (59C5H),A 32 C5 59
Store Register A (the directory lump) at 59C5H, byte +0 of the destination's working record, the current directory lump.
6690
LD HL,(42B9H) 2A B9 42
Fetch the address of the drive's PDRIVE entry from 42B9H (SYS0/SYS) into Register Pair HL.
6693
LD (HL),A 77
Store Register A (the directory lump) at Register Pair HL, byte +0 of the PDRIVE entry, so that SYS0/SYS finds the new directory.
6694
LD B,00H 06 00
Load Register B with 00H, granule 0 of the lump.
6696
LD E,A 5F
Copy Register A (the directory lump) into Register E.
6697
LD A,(59CEH) 3A CE 59
Fetch the directory granule count (DDGA) from 59CEH into Register A.
669A
LD C,A 4F
Copy Register A (the directory granules) into Register C.
669B
PUSH DE D5
Save Register Pair DE (Register E = the directory lump) onto the stack.
669C
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the new GAT.
669F
GOSUB to 621CH to allocate Register C granules in the GAT at Register Pair HL from granule Register B of lump Register E: the directory's granules.
66A2
LD HL,597EH 21 7E 59
Point Register Pair HL to 597EH, the 22 bytes of system data for the GAT.
66A5
LD DE,43CBH 11 CB 43
Point Register Pair DE to 43CBH, byte CBH of the GAT.
66A8
LD BC,0016H 01 16 00
Load Register Pair BC with 0016H: 22 bytes, 597EH-5993H.
66AB
LDIR ED B0
Copy Register Pair BC (22) bytes from Register Pair HL (597EH) to Register Pair DE (43CBH): GAT bytes CBH-CDH, the password code (CEH-CFH), the name (D0H-D7H), the date (D8H-DFH) and the AUTO byte E0H.
66AD
POP HL E1
Restore Register Pair HL from the stack: Register L = the directory lump.
66AE
LD A,(59CAH) 3A CA 59
Fetch the granules per lump from 59CAH into Register A.
66B1
LD H,A 67
Copy Register A (the granules per lump) into Register H.
66B2
RLCA 07
Rotate Register A (the granules per lump) left: times 2.
66B3
RLCA 07
Rotate Register A (the granules per lump) left again: times 4.
66B4
ADD A,H 84
ADD Register H (the granules per lump) to Register A: times 5, the sectors in a lump.
66B5
GOSUB to 4C37H (SYS0/SYS) to multiply Register L (the directory lump) by Register A (the sectors per lump): Register Pair HL = the directory's first sector.
66B8
LD (5B21H),HL 22 21 5B
Store Register Pair HL (the directory's first sector) at 5B21H, the destination FCB's NEXT.
66BB
LD C,00H 0E 00
Load Register C with 00H, directory sector 0 (the GAT).
66BD
JUMP to 66FBH to write the GAT, which is already in 4300H.

Directory Sector Loop: Register C is the directory sector being written.

66BF
PUSH BC C5
Save Register Pair BC (Register C = the directory sector) onto the stack. 670DH comes here.
66C0
XOR A AF
Set Register A to 00H (XOR A), the fill byte for an empty sector.
66C1
GOSUB to 64B0H to fill the buffer 4300H-43FFH with Register A (00H).
66C4
LD A,C 79
Copy Register C (the directory sector) into Register A.
66C5
DEC A 3D
DECrement Register A: 0 for sector 1, the HIT.
66C6
If the NZ FLAG is set (not the HIT), JUMP to 66E6H.
66C8
LD HL,4300H 21 00 43
The HIT sector: point Register Pair HL to 4300H, its byte for DEC 0.
66CB
LD (HL),A2H 36 A2
Store A2H at Register Pair HL: the hash code of BOOT/SYS (DEC 0).
66CD
INC HL 23
INCrement Register Pair HL to the byte for DEC 1.
66CE
LD (HL),C4H 36 C4
Store C4H at Register Pair HL: the hash code of DIR/SYS (DEC 1).
66D0
LD A,(59CEH) 3A CE 59
Fetch the directory granule count from 59CEH into Register A.
66D3
SUB 02H D6 02
SUBtract 02H from Register A: the granules beyond the standard two.
66D5
LD C,A 4F
Copy Register A (the extra granules) into Register C.
66D6
RLCA 07
Rotate Register A (the extra granules) left: times 2.
66D7
RLCA 07
Rotate Register A (the extra granules) left again: times 4.
66D8
ADD A,C 81
ADD Register C to Register A: times 5, the extra FDE sectors (0, 5, 10, 15 or 20).
66D9
LD (431FH),A 32 1F 43
Store Register A (the extra FDE sectors) at 431FH, HIT byte 1FH.
66DC
ADD A,0AH C6 0A
ADD 0AH to Register A: the total number of directory sectors (GAT, HIT and FDE sectors).
66DE
LD (65EEH),A 32 EE 65
Store Register A (the directory sectors) at 65EEH, byte 20 of DIR/SYS's entry: its EOF in whole sectors.
66E1
LD (670CH),A 32 0C 67
Store Register A (the directory sectors) at 670CH, the operand of the CP nn at 670BH that ends the loop.
66E4
JUMP to 66FAH to write the HIT sector that is now in 4300H.
66E6
LD HL,65BAH 21 BA 65
Point Register Pair HL to 65BAH, BOOT/SYS's directory entry. 66C6H comes here with Register A = the sector number less 1.
66E9
CP 02H FE 02
Compare Register A (the sector number less 1) against 02H: the CARRY FLAG for sector 2, the Z FLAG for sector 3.
66EB
If the CARRY FLAG is set (sector 2, which holds DEC 0), JUMP to 66F2H with Register Pair HL = BOOT/SYS's entry.
66ED
If the NZ FLAG is set (sector 4 or later, an empty FDE sector), JUMP to 66FAH.
66EF
LD HL,65DAH 21 DA 65
Sector 3 (DEC 1): point Register Pair HL to 65DAH, DIR/SYS's directory entry.
66F2
LD DE,4300H 11 00 43
Point Register Pair DE to 4300H, the first entry of the sector. 66EBH comes here.
66F5
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H: 32 bytes, one directory entry.
66F8
LDIR ED B0
Copy Register Pair BC (32) bytes from Register Pair HL (the entry) to Register Pair DE (4300H).
66FA
POP BC C1
Restore Register Pair BC from the stack: Register C = the directory sector. 66E4H and 66EDH come here.
66FB
SET 0,(IX+00H) DD CB 00 C6
Set bit 0 of (IX+00H), the first byte of the destination FCB (Index Register IX = 5B17H): the sector is written with the directory mark. 66BDH comes here.
66FF
GOSUB to 57D4H to write 4300H at the destination FCB's NEXT and read it back (SYS0/SYS 443CH). NEXT moves on to the next sector.
6702
RES 0,(IX+00H) DD CB 00 86
Clear bit 0 of (IX+00H), the first byte of the destination FCB (Index Register IX), again. RES does not change the flags.
6706
If the NZ FLAG is set (a write error), JUMP to 521AH to end the command with the error code in Register A.
6709
INC C 0C
INCrement Register C, the next directory sector.
670A
LD A,C 79
Copy Register C (the directory sector) into Register A.
670B
CP 0AH FE 0A
Compare Register A (the directory sector) against the number of directory sectors. Self-Modifying Code
The operand at 670CH is 0AH in the file; 66E1H stores the real number there when the HIT is made.
670D
If the CARRY FLAG is set (more sectors), LOOP BACK to 66BFH.
670F
RET C9
RETurn to the caller (5D19H, or 552DH through the address pushed at 6642H).

6710H - Work Out a Diskette's Size

6710H does the destination (working record at 59C5H), 6713H the record at Register Pair HL (4D7CH passes the source's at 59B7H). The total sectors (tracks times sectors per track) are stored at +10, the total granules at +12, and the number of lumps at +1. More than 192 lumps gives the PDRIVE conflict message.

6710
LD HL,59C5H 21 C5 59
Point Register Pair HL to 59C5H, the destination's working record. 4D82H and 6639H call here.
6713
PUSH IX DD E5
Save Index Register IX (the caller's value) onto the stack. 4D7FH calls here with Register Pair HL = 59B7H.
6715
PUSH HL E5
Save Register Pair HL (the working record) onto the stack.
6716
POP IX DD E1
Restore the working record's address from the stack into Index Register IX.
6718
LD A,(IX+04H) DD 7E 04
Fetch the sectors per track from (IX+04H), byte +4 of the working record at Index Register IX, into Register A.
671B
LD L,(IX+03H) DD 6E 03
Fetch the track count from (IX+03H), byte +3 of the working record at Index Register IX, into Register L.
671E
GOSUB to 4C37H (SYS0/SYS) to multiply Register L (the tracks) by Register A (the sectors per track): Register Pair HL = the total sectors.
6721
LD (IX+0AH),L DD 75 0A
Store Register L (the low byte of the total sectors) at (IX+0AH), byte +10 after the working record at Index Register IX (59C1H or 59CFH).
6724
LD (IX+0BH),H DD 74 0B
Store Register H (the high byte of the total sectors) at (IX+0BH), byte +11 at Index Register IX.
6727
GOSUB to 5CFBH to divide Register Pair HL by the granule size of the record at Index Register IX (3 or 5 sectors): Register Pair HL = the total granules.
672A
LD (IX+0CH),L DD 75 0C
Store Register L (the low byte of the total granules) at (IX+0CH), byte +12 at Index Register IX (59C3H or 59D1H).
672D
LD (IX+0DH),H DD 74 0D
Store Register H (the high byte of the total granules) at (IX+0DH), byte +13 at Index Register IX.
6730
LD A,(IX+05H) DD 7E 05
Fetch the granules per lump from (IX+05H), byte +5 of the working record at Index Register IX, into Register A.
6733
GOSUB to 4C59H (SYS0/SYS) to divide Register Pair HL (the granules) by Register A: Register Pair HL = whole lumps, Register A = granules left over.
6736
OR A B7
OR Register A (the granules left over) with itself: the Z FLAG when none are left over.
6737
If the Z FLAG is set (no granules left over), JUMP to 673AH.
6739
INC HL 23
INCrement Register Pair HL: a part lump counts as a lump.
673A
LD A,H 7C
Copy Register H (the high byte of the lump count) into Register A. 6737H comes here.
673B
OR A B7
OR Register A with itself: the Z FLAG when Register H is 0.
673C
If the NZ FLAG is set (256 lumps or more), JUMP to 6747H.
673E
LD A,L 7D
Copy Register L (the lump count) into Register A.
673F
CP C1H FE C1
Compare Register A (the lump count) against C1H: the CARRY FLAG for 192 lumps or fewer, all a GAT can describe.
6741
LD (IX+01H),A DD 77 01
Store Register A (the lump count) at (IX+01H), byte +1 of the working record at Index Register IX. LD does not change the flags.
6744
POP IX DD E1
Restore Index Register IX from the stack: the caller's value. POP does not change the flags.
6746
RET C D8
If the CARRY FLAG is set (not too many lumps), RETurn.
6747
LD HL,6E56H 21 56 6E
Point Register Pair HL to 6E56H, the message EITHER BAD PARAMETER OR CONFLICT WITH PDRIVE DATA. 673CH and 6756H come here.
674A
JUMP to 5243H to display the message at Register Pair HL on a new line and end the command.

674DH - A TI Flag M Diskette Needs BDU

674DH checks whether either diskette has TI flag M; 6751H goes straight to the test of BDU. Without BDU the command ends with the PDRIVE conflict message: SYS6/SYS does not write system data for such a diskette.

674D
GOSUB to 61EAH: the NZ FLAG when the source or destination has TI flag M. 6365H calls here.
6750
RET Z C8
If the Z FLAG is set (neither has it), RETurn.
6751
LD A,(5994H) 3A 94 59
Fetch the option flags from 5994H into Register A. 6893H calls here.
6754
BIT 1,A CB 4F
Test bit 1 of Register A (the 5994H flags): BDU, bypass the system data.
6756
If the Z FLAG is set (no BDU), JUMP to 6747H to report the PDRIVE conflict and end the command.
6758
RET C9
RETurn with BDU given: the diskette may be used without its system data.

6759H - Fill In the Boot Sector and DIR/SYS Entry for the Destination

Called from 67C5H. Puts the destination drive's values into the boot sector image (64BAH-65B9H) and into DIR/SYS's directory entry (65DAH).

6759
LD A,(59CBH) 3A CB 59
Fetch byte +6 of the destination's working record from 59CBH into Register A: the byte SYS0/SYS writes to the controller's sector register when it selects the drive. 67C5H calls here.
675C
LD (65B7H),A 32 B7 65
Store Register A (byte +6) at 65B7H, byte FDH of the boot sector.
675F
LD A,(59CCH) 3A CC 59
Fetch the destination's disk I/O flags from 59CCH (+7) into Register A.
6762
LD (65B9H),A 32 B9 65
Store Register A (the disk I/O flags) at 65B9H, byte FFH of the boot sector.
6765
BIT 1,A CB 4F
Test bit 1 of Register A (the disk I/O flags): tracks numbered from 1 (TI flags J or K).
6767
If the Z FLAG is set (from 0), JUMP to 676DH.
6769
LD HL,64C0H 21 C0 64
Point Register Pair HL to 64C0H, the track (Register D) in the boot code's LD DE,0005H at 64BEH.
676C
INC (HL) 34
INCrement the byte at Register Pair HL (64C0H): SYS0/SYS starts on track 1.
676D
BIT 4,A CB 67
Test bit 4 of Register A (the disk I/O flags): sectors numbered from 1 (TI flag I). 6767H comes here.
676F
If the Z FLAG is set (from 0), JUMP to 677AH.
6771
LD HL,64BFH 21 BF 64
Point Register Pair HL to 64BFH, the sector (Register E) in the boot code's LD DE,0005H.
6774
INC (HL) 34
INCrement the byte at Register Pair HL (64BFH): SYS0/SYS starts at sector 6.
6775
LD HL,6576H 21 76 65
Point Register Pair HL to 6576H, the operand of the boot code's LD E,nn at 6575H: the first sector number of a track.
6778
LD (HL),01H 36 01
Store 01H at Register Pair HL (6576H): each track's sectors start at 1.
677A
BIT 0,A CB 47
Test bit 0 of Register A (the disk I/O flags): double density. 676FH comes here.
677C
If the Z FLAG is set (single density), JUMP to 6788H.
677E
LD HL,6506H 21 06 65
Point Register Pair HL to 6506H, the operand of the boot code's LD L,01H at 6505H (434BH when it runs): the select byte for side 0.
6781
SET 7,(HL) CB FE
Set bit 7 of the byte at Register Pair HL (6506H): the boot code selects side 0 with bit 7, double density, in the byte it sends to port F4H.
6783
LD HL,6510H 21 10 65
Point Register Pair HL to 6510H, the operand of the boot code's LD L,11H at 650FH (4355H when it runs): the select byte for side 1.
6786
SET 7,(HL) CB FE
Set bit 7 of the byte at Register Pair HL (6510H): side 1 is also selected with double density.
6788
BIT 6,A CB 77
Test bit 6 of Register A (the disk I/O flags): double sided. 677CH comes here.
678A
LD A,(59C9H) 3A C9 59
Fetch the destination's sectors per track from 59C9H (+4) into Register A. LD does not change the flags.
678D
LD (6571H),A 32 71 65
Store Register A (the sectors per track) at 6571H, the operand of the boot code's SUB nn at 6570H (43B6H when it runs), its end of track test.
6790
If the Z FLAG is set (single sided), JUMP to 6793H with the full count.
6792
RRCA 0F
Rotate Register A (the sectors per track, which PDRIVE requires to be even for two sides) right: halved, the sectors on one side.
6793
LD (650BH),A 32 0B 65
Store Register A (the sectors on one side) at 650BH, the operand of the boot code's SUB nn at 650AH (4350H when it runs), its side test. 6790H comes here.
6796
LD A,(59CDH) 3A CD 59
Fetch the directory starting lump (DDSL) from 59CDH into Register A.
6799
LD (64BCH),A 32 BC 64
Store Register A (the directory lump) at 64BCH, byte 2 of the boot sector.
679C
LD L,A 6F
Copy Register A (the directory lump) into Register L.
679D
LD A,(59CEH) 3A CE 59
Fetch the directory granule count (DDGA) from 59CEH into Register A.
67A0
LD H,A 67
Copy Register A (the directory granules) into Register H.
67A1
DEC H 25
DECrement Register H: the granule count less 1, granule offset 0.
67A2
LD (65F0H),HL 22 F0 65
Store Register Pair HL at 65F0H: Register L (the lump) and Register H (the count less 1) become DIR/SYS's extent element.
67A5
LD A,(59C7H) 3A C7 59
Fetch the destination's flags from 59C7H (+2) into Register A.
67A8
LD (65B8H),A 32 B8 65
Store Register A (the flags) at 65B8H, byte FEH of the boot sector.
67AB
RET C9
RETurn to 67C8H with the boot sector image filled in.

67ACH - Write the Boot Sectors or Another Sector

67ACH writes the boot sector at 64BAH as sectors 0 and 1 of the destination. 67B3H writes it as sector Register Pair BC, 67B6H writes the 256 bytes at Register Pair DE as sector Register Pair BC. Each sector is read back (57D4H). The flags returned are those of the last write: the Z FLAG if it went well.

67AC
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H, sector 0. 6664H and 6903H call here.
67AF
GOSUB to 67B3H to write the boot sector as sector Register Pair BC (0).
67B2
INC BC 03
INCrement Register Pair BC to 0001H and fall into 67B3H to write sector 1. The result of the sector 0 write is not kept.
67B3
LD DE,64BAH 11 BA 64
Point Register Pair DE to 64BAH, the boot sector image. 67AFH calls here.
67B6
LD (5B1AH),DE ED 53 1A 5B
Store Register Pair DE (the data to write) at 5B1AH, the destination FCB's buffer. 666DH calls here with Register Pair DE = 6EB4H.
67BA
LD IX,5B17H DD 21 17 5B
Point Index Register IX to 5B17H, the destination FCB.
67BE
LD (5B21H),BC ED 43 21 5B
Store Register Pair BC (the sector number) at 5B21H, the destination FCB's NEXT.
67C2
JUMP to 57D4H to write the sector and read it back; its RETurn goes to the caller with the Z FLAG or the error code.

67C5H - Check the Destination Diskette and Format It

Called from 6368H (diskette COPY) and 6643H. Unless Y was given, the destination's first sector and GAT are read to see what is on it: N requires an unformatted diskette, ODN, ODPW and DDND look at its old name, date and password, and KDN/KDD keep them. Then, unless NFMT was given, the diskette is formatted: a partial format with PFST, or every track, with track 0 in the other density for TI flag K.

67C5
GOSUB to 6759H to fill in the boot sector image and DIR/SYS's entry for the destination drive. 6368H and 6643H call here.
67C8
LD IX,5B17H DD 21 17 5B
Point Index Register IX to 5B17H, the destination FCB.
67CC
GOSUB to 557DH to switch to the destination diskette, asking for it if needed. 6885H comes here.
67CF
LD A,(5994H) 3A 94 59
Fetch the option flags from 5994H into Register A.
67D2
LD C,A 4F
Copy Register A (the 5994H flags) into Register C, kept for the tests below.
67D3
BIT 6,C CB 71
Test bit 6 of Register C (5994H): Y, the operator does not care what is on the diskette.
67D5
If the NZ FLAG is set (Y), JUMP to 6888H without looking at the diskette.
67D8
GOSUB to 57C8H to read the sector at the destination FCB's NEXT (sector 0) into the buffer address it holds. Only the result matters: the Z FLAG, or the NZ FLAG with the error code in Register A.
67DB
If the Z FLAG is set (the diskette is readable), JUMP to 67F0H.
67DD
CP 05H FE 05
Compare Register A (the error code) against 05H (DATA RECORD NOT FOUND DURING READ): the diskette is not formatted.
67DF
If the NZ FLAG is set (any other error), JUMP to 521AH to end the command with it.
67E2
BIT 7,C CB 79
Test bit 7 of Register C (the 5994H flags): N, the diskette must be empty.
67E4
If the NZ FLAG is set (N wants an unformatted diskette, and this is one), JUMP to 6888H.
67E7
LD HL,6D93H 21 93 6D
Point Register Pair HL to 6D93H, the message UNREADABLE DISKETTE.
67EA
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
67ED
JUMP to 6882H to ask C, R or P about the unreadable diskette.
67F0
XOR A AF
Set Register A to 00H, directory sector 0, the GAT. 67DBH comes here.
67F1
GOSUB to 48AFH (SYS0/SYS) to read directory sector Register A (the GAT) into 4300H. It returns the NZ FLAG with error 11H or 31H if the sector cannot be read as a directory sector.
67F4
If the Z FLAG is set (the GAT was read), JUMP to 6808H.
67F6
LD L,A 6F
Copy Register A (the error code) into Register L.
67F7
LD A,C 79
Copy Register C (the 5994H flags) into Register A.
67F8
AND 19H E6 19
AND Register A with 19H, keeping bit 0 (KDD), bit 3 (KDN) and bit 4 (ODN), which need the old name or date.
67FA
LD A,L 7D
Copy Register L (the error code) back into Register A. LD does not change the flags.
67FB
If the NZ FLAG is set (the old name or date is needed), JUMP to 521AH to end the command with the error code.
67FE
LD HL,43D0H 21 D0 43
Point Register Pair HL to 43D0H, the name and date fields of the GAT buffer.
6801
LD B,10H 06 10
Load Register B with 10H: 16 bytes, the name and the date.
6803
LD (HL),3FH 36 3F
Store 3FH, a question mark, at Register Pair HL: the old name and date are unknown. 6806H comes here.
6805
INC HL 23
INCrement Register Pair HL to the next byte of the name and date fields.
6806
DECrement Register B and LOOP BACK to 6803H until all 16 bytes are question marks.
6808
BIT 7,C CB 79
Test bit 7 of Register C (5994H): N. 67F4H comes here.
680A
If the Z FLAG is set (no N given), JUMP to 6814H for the other checks.
680C
LD HL,6D81H 21 81 6D
Point Register Pair HL to 6D81H, the message DISKETTE HAS DATA.
680F
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
6812
JUMP to 687CH to show the old name and date and ask C, R or P.
6814
LD A,(428CH) 3A 8C 42
Fetch the system options from 428CH (SYS0/SYS) into Register A. 680AH comes here.
6817
AND 82H E6 82
AND Register A (428CH) with 82H, keeping bit 7 (option AA) and bit 1 (option AR).
6819
CP 80H FE 80
Compare Register A against 80H: the Z FLAG when AA = Y and AR = N, so the diskette password is checked.
681B
If the NZ FLAG is set (not checked), JUMP to 6842H.
681D
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
6820
BIT 3,A CB 5F
Test bit 3 of Register A (the 5996H flags): CBF, a COPY by file.
6822
If the Z FLAG is set (not a COPY by file), JUMP to 6842H.
6824
LD A,(5995H) 3A 95 59
Fetch the option flags from 5995H into Register A.
6827
BIT 0,A CB 47
Test bit 0 of Register A (the 5995H flags): ODPW, the old password was given.
6829
If the Z FLAG is set (no ODPW given), JUMP to 6837H for error 37H.
682B
LD HL,(43CEH) 2A CE 43
Fetch the destination diskette's password code from 43CEH (GAT bytes CEH-CFH) into Register Pair HL.
682E
LD DE,(597AH) ED 5B 7A 59
Fetch the code given with ODPW= from 597AH into Register Pair DE.
6832
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
6833
SBC HL,DE ED 52
SUBtract Register Pair DE (the ODPW code) from Register Pair HL (the diskette's code): the Z FLAG when they are the same.
6835
If the Z FLAG is set (the right password), JUMP to 6842H.
6837
LD HL,5A44H 21 44 5A
Point Register Pair HL to 5A44H, the word DESTINATION. 6829H comes here.
683A
GOSUB to 4467H (SYS0/SYS) to display the word at Register Pair HL.
683D
LD A,37H 3E 37
Load Register A with error code 37H (DISKETTE ACCESS DENIED).
683F
JUMP to 521AH to end the command with the error code in Register A (37H).
6842
BIT 3,C CB 59
Test bit 3 of Register C (5994H): KDN, keep the destination's name. 681BH, 6822H and 6835H come here.
6844
If the Z FLAG is set (no KDN), JUMP to 6853H.
6846
PUSH BC C5
Save Register Pair BC (Register C = the 5994H flags) onto the stack.
6847
LD HL,43D0H 21 D0 43
Point Register Pair HL to 43D0H, the diskette's old name in the GAT buffer.
684A
LD DE,5983H 11 83 59
Point Register Pair DE to 5983H, the name for the new GAT.
684D
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H: 8 characters.
6850
LDIR ED B0
Copy Register Pair BC (8) bytes from Register Pair HL (43D0H) to Register Pair DE (5983H): the diskette keeps its old name.
6852
POP BC C1
Restore Register Pair BC from the stack: Register C = the 5994H flags.
6853
BIT 0,C CB 41
Test bit 0 of Register C (5994H): KDD, keep the destination's date. 6844H comes here.
6855
If the Z FLAG is set (no KDD), JUMP to 6864H.
6857
PUSH BC C5
Save Register Pair BC (Register C = the 5994H flags) onto the stack.
6858
LD HL,43D8H 21 D8 43
Point Register Pair HL to 43D8H, the diskette's old date in the GAT buffer.
685B
LD DE,598BH 11 8B 59
Point Register Pair DE to 598BH, the date for the new GAT.
685E
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H: 8 characters.
6861
LDIR ED B0
Copy Register Pair BC (8) bytes from Register Pair HL (43D8H) to Register Pair DE (598BH): the diskette keeps its old date.
6863
POP BC C1
Restore Register Pair BC from the stack: Register C = the 5994H flags.
6864
BIT 4,C CB 61
Test bit 4 of Register C (5994H): ODN, the name the destination must have. 6855H comes here.
6866
If the Z FLAG is set (no ODN), JUMP to 6878H.
6868
LD HL,5970H 21 70 59
Point Register Pair HL to 5970H, the name given with ODN=.
686B
GOSUB to 624FH to compare the 8 characters at Register Pair HL with the old name in the GAT at 43D0H. It returns the Z FLAG when they are the same.
686E
If the Z FLAG is set (the names match), JUMP to 6878H.
6870
LD HL,5A44H 21 44 5A
Point Register Pair HL to 5A44H, the word DESTINATION.
6873
GOSUB to 6930H to display the word at Register Pair HL followed by DISKETTE NAME MISMATCH.
6876
JUMP to 687CH to show the old name and date and ask.
6878
BIT 5,C CB 69
Test bit 5 of Register C (5994H): DDND, display the destination's old name and date. 6866H and 686EH come here.
687A
If the Z FLAG is set (no DDND), JUMP to 6888H.
687C
LD HL,5A44H 21 44 5A
Point Register Pair HL to 5A44H, the word DESTINATION. 6812H and 6876H come here.
687F
GOSUB to 693CH to display the word at Register Pair HL with the diskette's old name and date from the GAT buffer.
6882
GOSUB to 58C8H to ask C, R or P. C ends the command; P returns the Z FLAG, R the NZ FLAG. 67EDH comes here.
6885
If the NZ FLAG is set (R), JUMP to 67CCH to look at the diskette again.
6888
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A. 67D5H, 67E4H and 687AH come here.
688B
BIT 3,A CB 5F
Test bit 3 of Register A (the 5997H flags): NFMT, do not format.
688D
RET NZ C0
If the NZ FLAG is set (NFMT: no format), RETurn to the caller.
688E
LD A,(59C7H) 3A C7 59
Fetch the destination's flags from 59C7H into Register A.
6891
BIT 5,A CB 6F
Test bit 5 of Register A (the 59C7H flags): TI flag M of the destination.
6893
If the NZ FLAG is set (TI flag M), GOSUB to 6751H: formatting such a diskette needs BDU, else the command ends with the PDRIVE conflict message.
6896
LD HL,6D60H 21 60 6D
Point Register Pair HL to 6D60H, the message FORMATTING.
6899
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
689C
GOSUB to 471BH (SYS0/SYS) to select the drive of the FCB at Index Register IX (5B17H). It returns the Z FLAG, or the NZ FLAG with an error code.
689F
If the Z FLAG is set (selected), GOSUB to 46F5H (SYS0/SYS) to send a Restore command with the drive's stepping rate and wait: the head goes to track 0.
68A2
If the NZ FLAG is set (an error), JUMP to 521AH to end the command with the error code in Register A.
68A5
LD A,(5997H) 3A 97 59
Fetch the option flags from 5997H into Register A.
68A8
AND 02H E6 02
AND Register A (the 5997H flags) with 02H, keeping bit 1 (PFST).
68AA
If the Z FLAG is set (a full format), JUMP to 68D1H.
68AC
LD DE,0001H 11 01 00
Load Register Pair DE: Register E = the number of tracks to format and Register D = the first track. Self-Modifying Code
The operand at 68ADH-68AEH is 0001H in the file (one track from track 0); 4FD1H stores PFTC= at 68ADH and 4FD9H stores PFST= at 68AEH.
68AF
LD A,D 7A
Copy Register D (the first track) into Register A.
68B0
ADD A,E 83
ADD Register E (the track count) to Register A: the track after the last one.
68B1
LD C,A 4F
Copy Register A (the end track) into Register C.
68B2
If the CARRY FLAG is set (past 255), JUMP to 68B8H for the error.
68B4
LD A,(59C8H) 3A C8 59
Fetch the diskette's track count from 59C8H into Register A.
68B7
CP C B9
Compare Register A (the track count) against Register C (the end track): the CARRY FLAG when the range goes past the last track.
68B8
If the CARRY FLAG is set, JUMP to 5218H for error 2FH. 68B2H comes here.
68BB
BIT 1,(IY+07H) FD CB 07 4E
Test bit 1 of (IY+07H), the byte at 4287H (Index Register IY = 4280H): the disk I/O flags of the current drive, bit 1 = the tracks are numbered from 1.
68BF
If the Z FLAG is set (from 0), JUMP to 68C2H.
68C1
INC D 14
INCrement Register D (the first track): its number on the diskette is one higher.
68C2
LD A,D 7A
Copy Register D (the first track) into Register A. 68BFH comes here.
68C3
LD (6B24H),A 32 24 6B
Store Register A (the track) at 6B24H, the track number the format code writes into the sector IDs.
68C6
OUT (F3H),A D3 F3
Send Register A (the track) to the controller's data register, port F3H: the destination of the Seek at 68CAH.
68C8
LD C,18H 0E 18
Load Register C with 18H, the FDC Seek command with head load.
68CA
GOSUB to 46F7H (SYS0/SYS) to send the command in Register C ORed with the drive's stepping rate, and wait until it is done.
68CD
LD A,D 7A
Copy Register D (the first track) into Register A.
68CE
ADD A,E 83
ADD Register E (the track count) to Register A: the track to stop at.
68CF
JUMP to 6923H to format the tracks up to Register A.
68D1
LD A,(59C8H) 3A C8 59
Fetch the track count from 59C8H into Register A: format up to the last track. 68AAH comes here.
68D4
LD HL,5996H 21 96 59
Point Register Pair HL to 5996H, the option flags. LD does not change Register A.
68D7
BIT 7,(HL) CB 7E
Test bit 7 of the byte at Register Pair HL (5996H): RWF.
68D9
If the NZ FLAG is set (RWF), JUMP to 6923H to format every track in the drive's own density.
68DB
BIT 6,(IY+02H) FD CB 02 76
Test bit 6 of (IY+02H), the byte at 4282H (Index Register IY = 4280H): the PDRIVE flags of the current drive, bit 6 = TI flag K.
68DF
If the Z FLAG is set (no TI flag K), JUMP to 6923H.

TI flag K: track 0 is formatted in the other density with 10 sectors, the boot sectors are written to it, and the other tracks follow in the drive's own density.

68E1
PUSH IX DD E5
Save Index Register IX (the destination FCB) onto the stack.
68E3
LD IX,(42B9H) DD 2A B9 42
Point Index Register IX to the drive's PDRIVE entry, whose address is fetched from 42B9H (SYS0/SYS).
68E7
LD A,01H 3E 01
Load Register A with 01H, the double density bit.
68E9
LD E,(IY+07H) FD 5E 07
Load Register E with (IY+07H), the byte at 4287H (Index Register IY = 4280H): the disk I/O flags of the current drive.
68EC
XOR E AB
XOR Register E (the disk I/O flags) into Register A (01H): the other density.
68ED
AND 41H E6 41
AND Register A with 41H, keeping bit 0 (double density, now the other way round) and bit 6 (two sides). The other bits (tracks from 1, double step, sectors from 1, 8 inch) are clear for track 0.
68EF
LD (IX+07H),A DD 77 07
Store Register A (the disk I/O flags for track 0) at (IX+07H), byte +7 of the PDRIVE entry at Index Register IX.
68F2
LD D,(IX+04H) DD 56 04
Load Register D with (IX+04H), byte +4 of the PDRIVE entry at Index Register IX: the sectors per track, to be put back at 690DH.
68F5
LD (IX+04H),0AH DD 36 04 0A
Store 0AH at (IX+04H): track 0 gets 10 sectors (byte +4 of the PDRIVE entry at Index Register IX).
68F9
EX (SP),IX DD E3
Exchange Index Register IX with the word on top of the stack (Stack Pointer): Index Register IX = the destination FCB again, the PDRIVE entry address on the stack.
68FB
PUSH DE D5
Save Register Pair DE (Register D = the sectors per track, Register E = the disk I/O flags) onto the stack.
68FC
LD A,01H 3E 01
Load Register A with 01H: format only track 0 (stop at track 1).
68FE
GOSUB to 695AH to format the tracks up to Register A (track 0). It returns the Z FLAG if all went well.
6901
If the NZ FLAG is set (track 0 failed), JUMP to 6906H without writing the boot sectors.
6903
GOSUB to 67ACH to write the boot sector at 64BAH as sectors 0 and 1 of track 0, while the PDRIVE entry still describes track 0. It returns the Z FLAG if the writes went well.
6906
POP DE D1
Restore Register Pair DE from the stack: Register D = the sectors per track, Register E = the disk I/O flags.
6907
EX (SP),IX DD E3
Exchange Index Register IX with the word on top of the stack (Stack Pointer): Index Register IX = the PDRIVE entry, the destination FCB on the stack.
6909
PUSH AF F5
Save Register Pair AF (the result of the format and the boot sector write) onto the stack.
690A
LD (IX+07H),E DD 73 07
Store Register E (the disk I/O flags fetched at 68E9H) back at (IX+07H) in the PDRIVE entry at Index Register IX.
690D
LD (IX+04H),D DD 72 04
Store Register D (the sectors per track) back at (IX+04H) in the PDRIVE entry at Index Register IX.
6910
GOSUB to 4720H (SYS0/SYS) to select the current drive again, which loads 4280H-4287H from the PDRIVE entry. It returns the Z FLAG, or the NZ FLAG with an error code.
6913
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': the select result is kept there.
6914
POP AF F1
Restore Register Pair AF from the stack: the result of the format of track 0.
6915
POP IX DD E1
Restore Index Register IX from the stack: the destination FCB.
6917
If the NZ FLAG is set (track 0 failed), JUMP to 6926H.
6919
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': the select result.
691A
If the NZ FLAG is set (the select failed), JUMP to 6926H.
691C
GOSUB to 6CAEH to step the head of the drive in to track 1.
691F
LD A,(59C8H) 3A C8 59
Fetch the track count from 59C8H into Register A.
6922
INC A 3C
INCrement Register A: the drive's tracks are numbered from 1 (TI flag K), so the track to stop at is one higher.
6923
GOSUB to 695AH to format the tracks up to Register A. It returns the Z FLAG if all went well. 68CFH, 68D9H and 68DFH come here.
6926
EI FB
Enable interrupts, which the format code disabled. 6917H and 691AH come here.
6927
RET Z C8
If the Z FLAG is set (every track was formatted), RETurn.
6928
CP FFH FE FF
Compare Register A (the result) against FFH: a message is to be shown instead of a DOS error.
692A
If the NZ FLAG is set (a DOS error), JUMP to 521AH to end the command with it.
692D
JUMP to 5243H to display the message at Register Pair HL (MOTOR FAST or MOTOR SLOW) and end the command.

6930H - Display the Old Diskette Name and Date

6930H displays the word at Register Pair HL (SOURCE or DESTINATION) followed by DISKETTE NAME MISMATCH. 693CH displays the word followed by DISKETTE OLD NAME/DATE = and the name and date from the GAT sector in 4300H.

6930
PUSH HL E5
Save Register Pair HL (the word) onto the stack. 6309H and 6873H call here.
6931
GOSUB to 4467H (SYS0/SYS) to display the word at Register Pair HL.
6934
LD HL,6DC1H 21 C1 6D
Point Register Pair HL to 6DC1H, the message DISKETTE NAME MISMATCH.
6937
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
693A
POP HL E1
Restore Register Pair HL from the stack: the word, for 693CH.
693B
RET C9
RETurn to 630CH or 6876H with Register Pair HL = the word.
693C
GOSUB to 4467H (SYS0/SYS) to display the word at Register Pair HL. 630CH and 687FH call here.
693F
LD HL,6DA7H 21 A7 6D
Point Register Pair HL to 6DA7H, the message DISKETTE OLD NAME/DATE = .
6942
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
6945
LD HL,43D0H 21 D0 43
Point Register Pair HL to 43D0H, the diskette's name in the GAT sector (bytes D0H-D7H).
6948
LD B,08H 06 08
Load Register B with 08H: 8 characters, the length of a diskette name.
694A
GOSUB to 5886H to display Register B characters from Register Pair HL; Register Pair HL returns pointing to 43D8H, the date.
694D
LD B,04H 06 04
Load Register B with 04H: 4 spaces between the name and the date.
694F
GOSUB to 5898H to display Register B (4) spaces after the name.
6952
LD B,08H 06 08
Load Register B with 08H: 8 characters, the length of the date.
6954
GOSUB to 5886H to display the date, Register B characters from Register Pair HL (43D8H).
6957
JUMP to 5881H to start a new line; its RETurn goes back to the caller.

695AH - Format Tracks

Entered with Register A = the track to stop at, Index Register IX pointing to the destination FCB and the head over the first track (its number at 6B24H). The drive's kind (the 8 inch and double density bits of 4287H) picks a line of the table at 6CC1H, whose values are stored into the code below. For every track (and each side of a double sided drive) the sector numbers are laid out with the line's interleave and skew (6A14H), the track is written with Write Track (6AA7H), the bytes that fit after the last sector tell whether the drive turns at the right speed (6BCAH), and every sector is read back (6BDCH). A track that fails is tried 10 times. Returns the Z FLAG, or the NZ FLAG with Register A = a DOS error code, or Register A = FFH and Register Pair HL = MOTOR FAST or MOTOR SLOW.

695A
LD (6C74H),A 32 74 6C
Store Register A (the track to stop at) at 6C74H, the operand of the CP nn at 6C73H. 68FEH and 6923H call here.
695D
GOSUB to 4720H (SYS0/SYS) to select the current drive (427EH), which loads its PDRIVE data into 4280H-4287H. It returns the Z FLAG, or the NZ FLAG with an error code.
6960
RET NZ C0
If the NZ FLAG is set (an error), RETurn with it.
6961
LD A,(4287H) 3A 87 42
Fetch the disk I/O flags of the drive from 4287H (SYS0/SYS) into Register A.
6964
RLCA 07
Rotate Register A (the disk I/O flags) left: bit 7 (8 inch) goes to bit 0 and bit 0 (double density) to bit 1.
6965
AND 03H E6 03
AND Register A with 03H: 0 = 5 inch single density, 1 = 8 inch single, 2 = 5 inch double, 3 = 8 inch double.
6967
LD L,1AH 2E 1A
Load Register L with 1AH, 26, the length of a line of the table.
6969
GOSUB to 4C37H (SYS0/SYS) to multiply Register L (26) by Register A (the kind): Register Pair HL = the line's offset.
696C
LD DE,6CC1H 11 C1 6C
Point Register Pair DE to 6CC1H, the track format table.
696F
ADD HL,DE 19
ADD Register Pair DE (6CC1H) to Register Pair HL (the offset): the line for this drive.
6970
LD A,(HL) 7E
Fetch byte 0 of the line at Register Pair HL into Register A: the gap byte (FFH single density, 4EH double density).
6971
LD (6B42H),A 32 42 6B
Store Register A (the gap byte) at 6B42H, the operand of the LD D,nn at 6B41H: the gap after an ID field.
6974
INC HL 23
INCrement Register Pair HL to byte 1 of the line.
6975
LD (6B90H),A 32 90 6B
Store Register A (the gap byte) at 6B90H, the operand of the LD D,nn at 6B8FH: the gap after a data field, which 6AB5H also reads for the gap before the first ID field.
6978
LD A,(HL) 7E
Fetch byte 1 at Register Pair HL into Register A: the address mark lead-in (00H, or F5H, which the FDC writes as A1H in double density).
6979
LD (6B10H),A 32 10 6B
Store Register A (the lead-in) at 6B10H, the operand of the LD D,nn at 6B0FH, written three times before the ID mark.
697C
INC HL 23
INCrement Register Pair HL to byte 2 of the line.
697D
LD (6B66H),A 32 66 6B
Store Register A (the lead-in) at 6B66H, the operand of the LD D,nn at 6B65H, written three times before the data mark.
6980
LD A,(HL) 7E
Fetch byte 2 at Register Pair HL into Register A: the first byte of the data pattern.
6981
LD (6B7CH),A 32 7C 6B
Store Register A (the first pattern byte) at 6B7CH, the operand of the LD D,nn at 6B7BH.
6984
INC HL 23
INCrement Register Pair HL to byte 3 of the line.
6985
LD A,(HL) 7E
Fetch byte 3 at Register Pair HL into Register A: the second byte of the data pattern.
6986
LD (6B82H),A 32 82 6B
Store Register A (the second pattern byte) at 6B82H, the operand of the LD D,nn at 6B81H.
6989
INC HL 23
INCrement Register Pair HL to byte 4 of the line.
698A
LD A,(HL) 7E
Fetch byte 4 at Register Pair HL into Register A: the length of the gap before each ID field.
698B
LD (6B96H),A 32 96 6B
Store Register A (the gap length) at 6B96H, the operand of the LD B,nn at 6B95H, which 6AB9H also reads.
698E
INC HL 23
INCrement Register Pair HL to byte 5 of the line.
698F
LD A,(HL) 7E
Fetch byte 5 at Register Pair HL into Register A: the further zero bytes before the ID field.
6990
LD (6B04H),A 32 04 6B
Store Register A (the count) at 6B04H, the operand of the LD B,nn at 6B03H.
6993
INC HL 23
INCrement Register Pair HL to byte 6 of the line.
6994
LD A,(HL) 7E
Fetch byte 6 at Register Pair HL into Register A: the length of the gap between the ID and data fields.
6995
LD (6B48H),A 32 48 6B
Store Register A (the gap length) at 6B48H, the operand of the LD B,nn at 6B47H.
6998
INC HL 23
INCrement Register Pair HL to byte 7 of the line.
6999
LD A,(HL) 7E
Fetch byte 7 at Register Pair HL into Register A: the further zero bytes before the data field.
699A
LD (6B5AH),A 32 5A 6B
Store Register A (the count) at 6B5AH, the operand of the LD B,nn at 6B59H.
699D
INC HL 23
INCrement Register Pair HL to byte 8 of the line.
699E
LD E,(HL) 5E
Load Register E with byte 8 at Register Pair HL: the low byte of the bytes one sector takes on the track.
699F
INC HL 23
INCrement Register Pair HL to byte 9 of the format table line.
69A0
LD D,(HL) 56
Load Register D with byte 9 at Register Pair HL: Register Pair DE = the bytes per sector, gaps included.
69A1
INC HL 23
INCrement Register Pair HL to byte 10 of the format table line.
69A2
LD C,(HL) 4E
Load Register C with byte 10 at Register Pair HL: the low byte of the bytes a track holds at the nominal speed.
69A3
INC HL 23
INCrement Register Pair HL to byte 11 of the format table line.
69A4
LD B,(HL) 46
Load Register B with byte 11 at Register Pair HL: Register Pair BC = the track size.
69A5
LD (69DBH),BC ED 43 DB 69
Store Register Pair BC (the track size) at 69DBH, the operand of the LD HL,nnnn at 69DAH.
69A9
INC HL 23
INCrement Register Pair HL to byte 12 of the format table line.
69AA
LD C,(HL) 4E
Load Register C with byte 12 at Register Pair HL: the low byte of the first tolerance.
69AB
INC HL 23
INCrement Register Pair HL to byte 13 of the format table line.
69AC
LD B,(HL) 46
Load Register B with byte 13 at Register Pair HL: Register Pair BC = the first tolerance.
69AD
LD (69F3H),BC ED 43 F3 69
Store Register Pair BC (the first tolerance) at 69F3H, the operand of the LD DE,nnnn at 69F2H.
69B1
INC HL 23
INCrement Register Pair HL to byte 14 of the format table line.
69B2
LD C,(HL) 4E
Load Register C with byte 14 at Register Pair HL: the low byte of the second tolerance.
69B3
INC HL 23
INCrement Register Pair HL to byte 15 of the format table line.
69B4
LD B,(HL) 46
Load Register B with byte 15 at Register Pair HL: Register Pair BC = the second tolerance.
69B5
LD (69D7H),BC ED 43 D7 69
Store Register Pair BC (the second tolerance) at 69D7H, the operand of the LD BC,nnnn at 69D6H.
69B9
INC HL 23
INCrement Register Pair HL to byte 16 of the format table line.
69BA
LD A,(HL) 7E
Fetch byte 16 at Register Pair HL into Register A: the sector skew from one track to the next.
69BB
LD (6A01H),A 32 01 6A
Store Register A (the skew) at 6A01H, the operand of the LD A,nn at 6A00H.
69BE
INC HL 23
INCrement Register Pair HL to byte 17 of the format table line.
69BF
LD A,(HL) 7E
Fetch byte 17 at Register Pair HL into Register A: the sector interleave.
69C0
LD (6A34H),A 32 34 6A
Store Register A (the interleave) at 6A34H, the operand of the ADD A,nn at 6A33H.
69C3
INC HL 23
INCrement Register Pair HL to byte 18, which is not used.
69C4
NOP 00
No operation, the first of three NOPs at 69C4H-69C6H.
69C5
NOP 00
No operation, the second of the three NOPs at 69C4H-69C6H.
69C6
NOP 00
No operation, the third of the three NOPs at 69C4H-69C6H.
69C7
XOR A AF
Set Register A to 00H (XOR A), the starting place and side.
69C8
LD (6A03H),A 32 03 6A
Store Register A (00H) at 6A03H, the operand of the ADD A,nn at 6A02H: the first track's sector layout starts at place 0.
69CB
LD (6C62H),A 32 62 6C
Store Register A (00H) at 6C62H, the operand of the LD A,nn at 6C61H: side 0.
69CE
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the bytes per sector.
69CF
GOSUB to 6CA3H: Register E = the sectors on one side of a track.
69D2
LD A,E 7B
Copy Register E (the sectors per side) into Register A.
69D3
GOSUB to 4C39H (SYS0/SYS) to multiply Register Pair HL (the bytes per sector) by Register A: Register Pair HL = the bytes the sectors of one side need.
69D6
LD BC,0000H 01 00 00
Load Register Pair BC with the second tolerance. Self-Modifying Code
The operand at 69D7H-69D8H is 0000H in the file; 69B5H stores bytes 14-15 of the table line there.
69D9
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the bytes needed.
69DA
LD HL,0000H 21 00 00
Load Register Pair HL with the track size. Self-Modifying Code
The operand at 69DBH-69DCH is 0000H in the file; 69A5H stores bytes 10-11 of the table line there.
69DD
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
69DE
SBC HL,DE ED 52
SUBtract Register Pair DE (the bytes needed) from Register Pair HL (the track size): the bytes to spare (negative if the sectors do not fit).
69E0
PUSH HL E5
Save Register Pair HL (the bytes to spare) onto the stack.
69E1
If the NO CARRY FLAG is set (the sectors fit), JUMP to 69F2H with Register Pair HL = the bytes to spare.
69E3
ADD HL,HL 29
ADD Register Pair HL (the shortfall, negative) to itself: times 2.
69E4
ADD HL,HL 29
ADD Register Pair HL to itself again: four times the shortfall.
69E5
ADD HL,BC 09
ADD Register Pair BC (the second tolerance) to Register Pair HL: the CARRY FLAG when the tolerance covers four times the shortfall.
69E6
If the CARRY FLAG is set (within the tolerance), JUMP to 69EFH.
69E8
POP HL E1
The sectors cannot fit: discard the spare count from the stack into Register Pair HL.
69E9
LD HL,6D6BH 21 6B 6D
Point Register Pair HL to 6D6BH, the message MOTOR FAST.
69EC
OR FFH F6 FF
OR Register A with FFH: Register A = FFH and the NZ FLAG, a message to display.
69EE
RET C9
RETurn with Register A = FFH and Register Pair HL = the message.
69EF
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H: no bytes to spare. 69E6H comes here.
69F2
LD DE,0000H 11 00 00
Load Register Pair DE with the first tolerance. Self-Modifying Code
The operand at 69F3H-69F4H is 0000H in the file; 69ADH stores bytes 12-13 of the table line there. 69E1H comes here.
69F5
ADD HL,DE 19
ADD Register Pair DE (the first tolerance) to Register Pair HL (the bytes to spare, or 0).
69F6
LD (6BCBH),HL 22 CB 6B
Store Register Pair HL at 6BCBH, the operand of the LD BC,nnnn at 6BCAH: the fewest gap bytes the end of a track may take.
69F9
POP HL E1
Restore Register Pair HL from the stack: the bytes to spare.
69FA
ADD HL,DE 19
ADD Register Pair DE (the first tolerance) to Register Pair HL.
69FB
ADD HL,BC 09
ADD Register Pair BC (the second tolerance) to Register Pair HL.
69FC
ADD HL,BC 09
ADD Register Pair BC (the second tolerance) to Register Pair HL again.
69FD
LD (6BD4H),HL 22 D4 6B
Store Register Pair HL at 6BD4H, the operand of the LD BC,nnnn at 6BD3H: the range of end gap counts above the fewest that is accepted.

Track Loop: each pass lays out the sector numbers of one side and formats it.

6A00
LD A,02H 3E 02
Load Register A with the sector skew from one track to the next. Self-Modifying Code
The operand at 6A01H is 02H in the file; 69BBH stores byte 16 of the table line there. 6C79H comes here.
6A02
ADD A,00H C6 00
ADD the place of the previous track's first sector to Register A. Self-Modifying Code
The operand at 6A03H is 00H in the file; 69C8H clears it and 6A0BH and 6A44H store into it. 6C6BH jumps here with Register A = 0 for the back side.
6A04
GOSUB to 6CA3H: Register E = the sectors on one side.
6A07
CP E BB
Compare Register A (the new place) against Register E (the sectors per side).
6A08
If the CARRY FLAG is set (below), JUMP to 6A0BH.
6A0A
SUB E 93
SUBtract Register E from Register A: round the track.
6A0B
LD (6A03H),A 32 03 6A
Store Register A (the place of this track's first sector) at 6A03H. 6A08H comes here.
6A0E
LD (6A03H),A 32 03 6A
Store Register A at 6A03H again (the same store twice).
6A11
INC A 3C
INCrement Register A: the number of times the finished table is turned, one more than the place.
6A12
LD D,A 57
Copy Register A (the turn count) into Register D.
6A13
PUSH DE D5
Save Register Pair DE (Register D = the turn count, Register E = the sectors per side) onto the stack.

Build the interleave table at 6485H: the sector numbers in the order they pass the head.

6A14
LD HL,6485H 21 85 64
Point Register Pair HL to 6485H, the interleave table.
6A17
LD B,E 43
Copy Register E (the sectors per side) into Register B, the places to clear.
6A18
LD (HL),FFH 36 FF
Store FFH at Register Pair HL: a free place. 6A1BH comes here.
6A1A
INC HL 23
INCrement Register Pair HL to the next place.
6A1B
DECrement Register B and LOOP BACK to 6A18H until every place is free.
6A1D
LD D,00H 16 00
Load Register D with 00H, the first sector number.
6A1F
LD B,D 42
Copy Register D (00H) into Register B: Register Pair BC = the place, Register B stays 0.
6A20
JUMP to 6A27H to start at place 0 of the table.
6A22
INC C 0C
INCrement Register C: the next place. 6A2FH comes here.
6A23
LD A,C 79
Copy Register C (the place to try) into Register A.
6A24
CP E BB
Compare Register A (the place) against Register E (the sectors per side).
6A25
If the CARRY FLAG is set (still on the track), JUMP to 6A29H.
6A27
LD C,00H 0E 00
Load Register C with 00H: back to place 0. 6A20H comes here.
6A29
LD HL,6485H 21 85 64
Point Register Pair HL to 6485H, the interleave table. 6A25H and 6A3DH come here.
6A2C
ADD HL,BC 09
ADD Register Pair BC (the place) to Register Pair HL.
6A2D
LD A,(HL) 7E
Fetch the place's value at Register Pair HL into Register A.
6A2E
INC A 3C
INCrement Register A: the Z FLAG when the place is free (FFH).
6A2F
If the NZ FLAG is set (taken), LOOP BACK to 6A22H to try the next place.
6A31
LD (HL),D 72
Store Register D (the sector number) at Register Pair HL, the free place.
6A32
LD A,C 79
Copy Register C (the place just filled) into Register A.
6A33
ADD A,02H C6 02
ADD the interleave to Register A: the place for the next sector. Self-Modifying Code
The operand at 6A34H is 02H in the file; 69C0H stores byte 17 of the table line there.
6A35
CP E BB
Compare Register A (the next place) against Register E (the sectors per side).
6A36
If the CARRY FLAG is set (on the track), JUMP to 6A39H.
6A38
SUB E 93
SUBtract Register E from Register A: round the track.
6A39
LD C,A 4F
Copy Register A (the next place) into Register C. 6A36H comes here.
6A3A
INC D 14
INCrement Register D, the next sector number.
6A3B
LD A,D 7A
Copy Register D (the sector number) into Register A.
6A3C
CP E BB
Compare Register A (the sector number) against Register E (the sectors per side).
6A3D
If the CARRY FLAG is set (more sectors), LOOP BACK to 6A29H.
6A3F
LD HL,6A03H 21 03 6A
Point Register Pair HL to 6A03H, the place of the first sector.
6A42
LD A,(HL) 7E
Fetch the place at Register Pair HL into Register A.
6A43
ADD A,C 81
ADD Register C (the place after the last sector) to Register A.
6A44
LD (HL),A 77
Store Register A back at Register Pair HL (6A03H) for the next track.

Turn Loop: the table is turned by one place, Register D - 1 times, so that each track starts at its skewed place.

6A45
POP DE D1
Restore Register Pair DE from the stack: Register D = the turns left, Register E = the sectors per side. 6A57H comes here.
6A46
DEC D 15
DECrement Register D, the turns of the table still to do.
6A47
If the Z FLAG is set (no more turns), JUMP to 6A59H.
6A49
LD C,E 4B
Copy Register E (the sectors per side) into Register C: Register Pair BC = the count (Register B is 0).
6A4A
PUSH DE D5
Save Register Pair DE (the turn count) onto the stack.
6A4B
LD HL,6484H 21 84 64
Point Register Pair HL to 6484H, one byte before the table.
6A4E
ADD HL,BC 09
ADD Register Pair BC (the sectors per side) to Register Pair HL: the table's last place.
6A4F
LD D,H 54
Copy Register H (the high byte of the last place) into Register D.
6A50
LD E,L 5D
Copy Register L into Register E: Register Pair DE = the last place too.
6A51
DEC BC 0B
DECrement Register Pair BC: one byte less to move.
6A52
LD A,(HL) 7E
Fetch the last sector number at Register Pair HL into Register A.
6A53
DEC HL 2B
DECrement Register Pair HL to the place before it.
6A54
LDDR ED B8
Copy Register Pair BC bytes downward from Register Pair HL to Register Pair DE: the table moves up one place.
6A56
LD (DE),A 12
Store Register A (the old last number) at Register Pair DE, the first place (6485H).
6A57
JUMP to 6A45H for the next turn of the table.
6A59
LD A,(4287H) 3A 87 42
Fetch the disk I/O flags from 4287H into Register A. 6A47H comes here.
6A5C
BIT 4,A CB 67
Test bit 4 of Register A (4287H): the sectors are numbered from 1.
6A5E
If the Z FLAG is set (from 0), JUMP to 6A68H.
6A60
LD B,E 43
Copy Register E (the sectors per side) into Register B.
6A61
LD HL,6485H 21 85 64
Point Register Pair HL to 6485H, the interleave table.
6A64
INC (HL) 34
INCrement the sector number at Register Pair HL. 6A66H comes here.
6A65
INC HL 23
INCrement Register Pair HL to the next place.
6A66
DECrement Register B and LOOP BACK to 6A64H until every number is one higher.
6A68
LD A,0AH 3E 0A
Load Register A with 0AH, 10 tries for the track. 6A5EH and 6C4BH come here.
6A6A
LD (6C94H),A 32 94 6C
Store Register A (10) at 6C94H, the operand of the LD A,nn at 6C93H.

Try Loop: write the track and read it back.

6A6D
GOSUB to 4720H (SYS0/SYS) to select the current drive again. 6C1EH and 6C99H come here.
6A70
RET NZ C0
If the NZ FLAG is set (an error), RETurn with it.
6A71
GOSUB to 5733H to check the pause and cancel keys.
6A74
LD HL,427FH 21 7F 42
Point Register Pair HL to 427FH (SYS0/SYS), the select byte that SYS0/SYS sends to port F4H. 4720H has just set it for the drive.
6A77
LD B,(IY+07H) FD 46 07
Load Register B with (IY+07H), the byte at 4287H (Index Register IY = 4280H): the disk I/O flags of the current drive.
6A7A
BIT 0,B CB 40
Test bit 0 of Register B (the disk I/O flags): double density.
6A7C
If the Z FLAG is set (single density), JUMP to 6A80H.
6A7E
SET 7,(HL) CB FE
Set bit 7 of the byte at Register Pair HL (427FH): the select byte asks for double density.
6A80
LD A,(6B24H) 3A 24 6B
Fetch the track being formatted from 6B24H (the operand of the LD D,nn at 6B23H) into Register A. 6A7CH comes here.
6A83
LD C,A 4F
Copy Register A (the track being formatted) into Register C for the compare.
6A84
GOSUB to 4CA4H (SYS0/SYS) to fetch the drive's track count from 4283H into Register A, halved.
6A87
NOP 00
No operation: a spare byte between the CALL and the CP.
6A88
CP C B9
Compare Register A (half the track count) against Register C (the track): the NO CARRY FLAG when the track is not past the half.
6A89
If the NO CARRY FLAG is set (an outer track), JUMP to 6A8DH.
6A8B
SET 5,(HL) CB EE
Set bit 5 of the byte at Register Pair HL (427FH): write precompensation, for the inner half of the tracks.
6A8D
LD A,B 78
Copy Register B (the disk I/O flags) into Register A.
6A8E
AND 40H E6 40
AND Register A with 40H, keeping bit 6, double sided.
6A90
If the Z FLAG is set (single sided), JUMP to 6A9BH with Register A = 00H, side 0.
6A92
LD A,(6C62H) 3A 62 6C
Fetch the side being formatted from 6C62H, the operand of the LD A,nn at 6C61H, into Register A.
6A95
AND 01H E6 01
AND Register A with 01H: the Z FLAG for the front.
6A97
If the Z FLAG is set (the front), JUMP to 6A9BH.
6A99
SET 4,(HL) CB E6
Set bit 4 of the byte at Register Pair HL (427FH): the select byte asks for side 1. Register A stays 01H.
6A9B
LD (6B2AH),A 32 2A 6B
Store Register A (the side, 00H or 01H) at 6B2AH, the operand of the LD D,nn at 6B29H, for the ID fields. 6A90H and 6A97H come here.
6A9E
GOSUB to 4715H (SYS0/SYS) to send the select byte at 427FH to port F4H: the drive, the density, write precompensation and the side are selected.
6AA1
GOSUB to 46FFH (SYS0/SYS) to wait until the controller is no longer busy.
6AA4
GOSUB to 6CA3H: Register E = the sectors on one side.
6AA7
LD A,E 7B
Copy Register E (the sectors on one side) into Register A.
6AA8
LD (6AF2H),A 32 F2 6A
Store Register A (the sectors on one side) at 6AF2H, the operand of the LD E,nn at 6AF1H: the sector counter of the track.
6AAB
LD A,(427FH) 3A 7F 42
Fetch the select byte from 427FH (SYS0/SYS) into Register A.
6AAE
OR 40H F6 40
OR Register A with 40H, setting bit 6: wait states, so that an OUT to port F3H holds the CPU until the controller asks for the byte.
6AB0
LD (6AF0H),A 32 F0 6A
Store Register A (the select byte with wait states) at 6AF0H, the operand of the LD A,nn at 6AEFH.
6AB3
LD E,02H 1E 02
Load Register E with 02H, the data request bit of the status, for the first two bytes.
6AB5
LD A,(6B90H) 3A 90 6B
Fetch the gap byte from 6B90H (table byte 0, stored by 6975H) into Register A.
6AB8
LD D,A 57
Copy Register A (the gap byte) into Register D, the byte to write.
6AB9
LD A,(6B96H) 3A 96 6B
Fetch the gap length from 6B96H (table byte 4, stored by 698BH) into Register A.
6ABC
LD B,A 47
Copy Register A (the gap length) into Register B.
6ABD
DEC B 05
DECrement Register B: with the two bytes written at 6AE6H and 6AEDH, the gap before the first ID field is as long as the one before each later ID field (6B93H, 6AF5H and the loop at 6AF7H).
6ABE
LD C,F3H 0E F3
Load Register C with F3H, the controller's data port, for OUT (C),D.
6AC0
DI F3
Disable interrupts: from here on only the NMI at the end of the track ends the writing.
6AC1
LD A,(00F0H) 3A F0 00
Fetch the byte at 00F0H (ROM) into Register A. The value is not used: 6ACEH loads Register A again.
6AC4
LD (6BA9H),SP ED 73 A9 6B
Store the Stack Pointer at 6BA9H, the operand of the LD SP,nnnn at 6BA8H, so that the NMI routine returns to this level.
6AC8
LD HL,6BA5H 21 A5 6B
Point Register Pair HL to 6BA5H, the routine for the NMI at the end of the track.
6ACB
LD (404AH),HL 22 4A 40
Store Register Pair HL (6BA5H) at 404AH, the address part of the NMI vector at 4049H.
6ACE
LD A,C3H 3E C3
Load Register A with C3H, the opcode of JP, for the NMI vector.
6AD0
LD (4049H),A 32 49 40
Store Register A (C3H) at 4049H: the NMI vector is now JP 6BA5H.
6AD3
LD HL,6485H 21 85 64
Point Register Pair HL to 6485H, the interleave table: the sector numbers in the order they are written.
6AD6
LD A,C0H 3E C0
Load Register A with C0H, the NMI mask: bit 7 the controller's interrupt request, bit 6 the drive motor time-out.
6AD8
OUT (E4H),A D3 E4
Send Register A (C0H) to the NMI mask, port E4H.
6ADA
LD A,F4H 3E F4
Load Register A with F4H, the Write Track command with the head settling delay (bit 2).
6ADC
OUT (F0H),A D3 F0
Send Register A (F4H) to the controller's command register, port F0H. The controller waits for the index hole and then asks for the bytes of the track.
6ADE
GOSUB to 4789H (SYS0/SYS) for a short delay, so that the controller's status is valid. Register A returns the status, which is not used here.
6AE1
IN A,(F0H) DB F0
Read the controller's status from port F0H into Register A. 6AE4H comes here.
6AE3
AND E A3
AND Register A with Register E (02H), keeping the data request bit.
6AE4
If the Z FLAG is set (no data request yet), LOOP BACK to 6AE1H.
6AE6
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C): the first byte of the track.
6AE8
IN A,(F0H) DB F0
Read the controller's status from port F0H into Register A. 6AEBH comes here.
6AEA
AND E A3
AND Register A with Register E (02H), keeping the data request bit.
6AEB
If the Z FLAG is set (no data request yet), LOOP BACK to 6AE8H.
6AED
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C): the second byte of the track.
6AEF
LD A,00H 3E 00
Load Register A with the select byte with wait states. Self-Modifying Code
The operand at 6AF0H is 00H in the file; 6AB0H stores it.
6AF1
LD E,00H 1E 00
Load Register E with the sectors on one side, the sector counter. Self-Modifying Code
The operand at 6AF2H is 00H in the file; 6AA8H stores it.
6AF3
OUT (F4H),A D3 F4
Sector loop. Send Register A (the select byte with wait states) to port F4H, as before every byte from here on. 6B98H comes here.
6AF5
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C). The CPU waits until the controller asks for the byte.
6AF7
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H. 6AFBH comes here.
6AF9
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C).
6AFB
DECrement Register B (the gap bytes left) and LOOP BACK to 6AF7H until it is 0.
6AFD
LD D,00H 16 00
Load Register D with 00H, the zero bytes before the ID mark.
6AFF
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B01
OUT (C),D ED 51
Send Register D (00H) to port F3H (Register C): the first zero byte.
6B03
LD B,01H 06 01
Load Register B with the further zero bytes before the ID mark. Self-Modifying Code
The operand at 6B04H is 01H in the file; 6990H stores table byte 5 there.
6B05
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H. 6B09H comes here.
6B07
OUT (C),D ED 51
Send Register D (00H) to port F3H (Register C).
6B09
DECrement Register B (the zero bytes left) and LOOP BACK to 6B05H until it is 0.
6B0B
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B0D
OUT (C),D ED 51
Send Register D (00H) to port F3H (Register C): the last zero byte.
6B0F
LD D,00H 16 00
Load Register D with the address mark lead-in. Self-Modifying Code
The operand at 6B10H is 00H in the file; 6979H stores table byte 1 there.
6B11
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B13
OUT (C),D ED 51
Send Register D (the lead-in) to port F3H (Register C), the first of three.
6B15
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B17
OUT (C),D ED 51
Send Register D (the lead-in) to port F3H (Register C), the second of three.
6B19
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B1B
OUT (C),D ED 51
Send Register D (the lead-in) to port F3H (Register C), the third of three.
6B1D
LD D,FEH 16 FE
Load Register D with FEH, the ID address mark.
6B1F
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B21
OUT (C),D ED 51
Send Register D (FEH) to port F3H (Register C): the ID field begins.
6B23
LD D,00H 16 00
Load Register D with the track number. Self-Modifying Code
The operand at 6B24H is 00H in the file; 68C3H stores the first track there and 6C71H counts it up.
6B25
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B27
OUT (C),D ED 51
Send Register D (the track) to port F3H (Register C): ID byte 1.
6B29
LD D,00H 16 00
Load Register D with the side. Self-Modifying Code
The operand at 6B2AH is 00H in the file; 6A9BH stores 00H or 01H there.
6B2B
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B2D
OUT (C),D ED 51
Send Register D (the side) to port F3H (Register C): ID byte 2.
6B2F
LD D,(HL) 56
Load Register D with the sector number at Register Pair HL in the interleave table.
6B30
INC HL 23
INCrement Register Pair HL to the next sector number.
6B31
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B33
OUT (C),D ED 51
Send Register D (the sector number) to port F3H (Register C): ID byte 3.
6B35
LD D,01H 16 01
Load Register D with 01H, the length code of a 256 byte sector.
6B37
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B39
OUT (C),D ED 51
Send Register D (01H) to port F3H (Register C): ID byte 4.
6B3B
LD D,F7H 16 F7
Load Register D with F7H, which makes the controller write the two CRC bytes of the field.
6B3D
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B3F
OUT (C),D ED 51
Send Register D (F7H) to port F3H (Register C): the ID field ends with its CRC.
6B41
LD D,FFH 16 FF
Load Register D with the gap byte. Self-Modifying Code
The operand at 6B42H is FFH in the file; 6971H stores table byte 0 there.
6B43
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B45
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C): the first byte of the gap after the ID field.
6B47
LD B,0AH 06 0A
Load Register B with the gap length between the ID and data fields. Self-Modifying Code
The operand at 6B48H is 0AH in the file; 6995H stores table byte 6 there.
6B49
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B4B
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C): the second byte of the gap after the ID field.
6B4D
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H. 6B51H comes here.
6B4F
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C): one more byte of the gap after the ID field.
6B51
DECrement Register B (the gap bytes left) and LOOP BACK to 6B4DH until it is 0.
6B53
LD D,00H 16 00
Load Register D with 00H, the zero bytes before the data mark.
6B55
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B57
OUT (C),D ED 51
Send Register D (00H) to port F3H (Register C): the first zero byte.
6B59
LD B,04H 06 04
Load Register B with the further zero bytes before the data mark. Self-Modifying Code
The operand at 6B5AH is 04H in the file; 699AH stores table byte 7 there.
6B5B
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H. 6B5FH comes here.
6B5D
OUT (C),D ED 51
Send Register D (00H) to port F3H (Register C): one more zero byte before the data mark.
6B5F
DECrement Register B (the zero bytes left) and LOOP BACK to 6B5BH until it is 0.
6B61
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B63
OUT (C),D ED 51
Send Register D (00H) to port F3H (Register C): the last zero byte.
6B65
LD D,00H 16 00
Load Register D with the address mark lead-in. Self-Modifying Code
The operand at 6B66H is 00H in the file; 697DH stores table byte 1 there.
6B67
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B69
OUT (C),D ED 51
Send Register D (the lead-in) to port F3H (Register C), the first of three.
6B6B
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B6D
OUT (C),D ED 51
Send Register D (the lead-in) to port F3H (Register C), the second of three.
6B6F
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B71
OUT (C),D ED 51
Send Register D (the lead-in) to port F3H (Register C), the third of three.
6B73
LD D,FBH 16 FB
Load Register D with FBH, the data address mark.
6B75
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B77
OUT (C),D ED 51
Send Register D (FBH) to port F3H (Register C): the data field begins.
6B79
LD B,80H 06 80
Load Register B with 80H: 128 pairs of pattern bytes, the 256 data bytes.
6B7B
LD D,E5H 16 E5
Load Register D with the first pattern byte. Self-Modifying Code
The operand at 6B7CH is E5H in the file; 6981H stores table byte 2 there. 6B87H comes here.
6B7D
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B7F
OUT (C),D ED 51
Send Register D (the first pattern byte) to port F3H (Register C).
6B81
LD D,E5H 16 E5
Load Register D with the second pattern byte. Self-Modifying Code
The operand at 6B82H is E5H in the file; 6986H stores table byte 3 there.
6B83
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B85
OUT (C),D ED 51
Send Register D (the second pattern byte) to port F3H (Register C).
6B87
DECrement Register B (the pairs left) and LOOP BACK to 6B7BH until it is 0.
6B89
LD D,F7H 16 F7
Load Register D with F7H, which makes the controller write the two CRC bytes of the field.
6B8B
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B8D
OUT (C),D ED 51
Send Register D (F7H) to port F3H (Register C): the data field ends with its CRC.
6B8F
LD D,FFH 16 FF
Load Register D with the gap byte. Self-Modifying Code
The operand at 6B90H is FFH in the file; 6975H stores table byte 0 there.
6B91
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H.
6B93
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C): the first byte of the gap after the data field.
6B95
LD B,0AH 06 0A
Load Register B with the gap length before the next ID field, for the loop at 6AF7H. Self-Modifying Code
The operand at 6B96H is 0AH in the file; 698BH stores table byte 4 there.
6B97
DEC E 1D
DECrement Register E, the sectors left on this side.
6B98
If the NZ FLAG is set (sectors left), JUMP to 6AF3H for the next sector.
6B9B
LD HL,0001H 21 01 00
Load Register Pair HL with 0001H: Register Pair HL now counts the gap bytes written after the last sector.
6B9E
OUT (F4H),A D3 F4
Send Register A (the select byte with wait states) to port F4H. 6BA3H comes here.
6BA0
OUT (C),D ED 51
Send Register D (the gap byte) to port F3H (Register C): one more byte of the gap at the end of the track.
6BA2
INC HL 23
INCrement Register Pair HL, the end gap count.
6BA3
LOOP BACK to 6B9EH until the index hole ends the Write Track: the controller's interrupt request then causes the NMI, which leaves this loop.
6BA5
XOR A AF
The NMI (through the vector at 4049H, set by 6ACBH and 6AD0H) comes here. Set Register A to 00H, the value that masks every NMI.
6BA6
OUT (E4H),A D3 E4
Send Register A (00H) to the NMI mask, port E4H.
6BA8
LD SP,0000H 31 00 00
Load the Stack Pointer with the value saved at 6AC4H, which drops the NMI's return address. Self-Modifying Code
The operand at 6BA9H-6BAAH is 0000H in the file; 6AC4H stores it.
6BAB
LD DE,45EDH 11 ED 45
Load Register Pair DE with 45EDH: stored at 4049H, its bytes EDH 45H are a RETN.
6BAE
LD (4049H),DE ED 53 49 40
Store Register Pair DE at 4049H-404AH: the NMI vector is a RETN again.
6BB2
IN A,(F0H) DB F0
Read the controller's status from port F0H into Register A: the result of the Write Track.
6BB4
LD B,A 47
Copy Register A (the status) into Register B.
6BB5
LD A,D0H 3E D0
Load Register A with D0H, the Force Interrupt command.
6BB7
OUT (F0H),A D3 F0
Send Register A (D0H) to the controller's command register, port F0H, which ends any command still running.
6BB9
GOSUB to 4715H (SYS0/SYS) to send the select byte at 427FH to port F4H again: the drive stays selected, without the wait states.
6BBC
LD A,(5996H) 3A 96 59
Fetch the option flags from 5996H into Register A.
6BBF
BIT 7,A CB 7F
Test bit 7 of Register A (5996H): RWF, every error is ignored and each track is formatted once.
6BC1
If the NZ FLAG is set (RWF), JUMP to 6C5BH for the next side or track.
6BC4
LD A,B 78
Copy Register B (the final status) into Register A.
6BC5
AND FCH E6 FC
AND Register A with FCH, keeping the error bits 2-7.
6BC7
If the NZ FLAG is set (an error), JUMP to 6C88H to turn it into an error code.
6BCA
LD BC,0000H 01 00 00
Load Register Pair BC with the fewest end gap bytes allowed. Self-Modifying Code
The operand at 6BCBH-6BCCH is 0000H in the file; 69F6H stores it.
6BCD
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
6BCE
SBC HL,BC ED 42
SUBtract Register Pair BC from Register Pair HL (the end gap count).
6BD0
If the CARRY FLAG is set (too few bytes fitted: the diskette turns too fast), JUMP to 6C7CH for MOTOR FAST.
6BD3
LD BC,007DH 01 7D 00
Load Register Pair BC with the range accepted above the fewest. Self-Modifying Code
The operand at 6BD4H-6BD5H is 007DH in the file; 69FDH stores it.
6BD6
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC.
6BD7
SBC HL,BC ED 42
SUBtract Register Pair BC from Register Pair HL (the count above the fewest).
6BD9
If the NO CARRY FLAG is set (too many bytes fitted: the diskette turns too slowly), JUMP to 6C81H for MOTOR SLOW.

Read back every sector of the side with SYS0/SYS's FDC routine, keeping only the status.

6BDC
LD A,88H 3E 88
Load Register A with 88H, the Read Sector command.
6BDE
LD (4687H),A 32 87 46
Store Register A (88H) at 4687H (SYS0/SYS), the operand of the LD A,nn at 4686H that SYS0/SYS's routine at 466FH sends to the controller.
6BE1
LD A,(45F5H) 3A F5 45
Fetch the byte at 45F5H (SYS0/SYS) into Register A: A2H, the high byte of the LD BC,A202H at 45F3H and the second byte of INI.
6BE4
LD (469EH),A 32 9E 46
Store Register A (A2H) at 469EH (SYS0/SYS), the second byte of the instruction at 469DH, which becomes INI: the first byte is read.
6BE7
GOSUB to 5C96H to store A2H at 46A6H and 02H at 468FH (SYS0/SYS): the rest of the transfer loop is set for a read.
6BEA
LD HL,6485H 21 85 64
Point Register Pair HL to 6485H, the interleave table.
6BED
GOSUB to 6CA3H: Register E = the sectors on one side.

Read Back Loop: Register Pair HL walks the table from its second place; the first place is read last.

6BF0
INC HL 23
INCrement Register Pair HL to the next place of the interleave table. 6C54H comes here.
6BF1
LD A,(HL) 7E
Fetch the sector number at Register Pair HL into Register A.
6BF2
OUT (F2H),A D3 F2
Send Register A (the sector number) to the controller's sector register, port F2H. 6C59H comes here.
6BF4
IN A,(F1H) DB F1
Read the controller's track register from port F1H into Register A, to be put back at 6C0FH.
6BF6
PUSH HL E5
Save Register Pair HL (the table pointer) onto the stack.
6BF7
LD HL,46C9H 21 C9 46
Point Register Pair HL to 46C9H (SYS0/SYS), the POP AF after the Force Interrupt in SYS0/SYS's NMI routine at 46B6H.
6BFA
LD D,(HL) 56
Load Register D with the byte at Register Pair HL (46C9H): F1H, to be put back.
6BFB
PUSH DE D5
Save Register Pair DE (Register D = the saved byte, Register E = the sectors left) onto the stack.
6BFC
PUSH HL E5
Save Register Pair HL (46C9H) onto the stack.
6BFD
LD (HL),C9H 36 C9
Store C9H, a RET, at Register Pair HL (46C9H): SYS0/SYS's NMI routine returns right after the Force Interrupt to 6C0BH, with the status in Register B, without the POPs and the OUT (F1H) that belong to its other callers.
6BFF
PUSH AF F5
Save Register Pair AF (Register A = the track register) onto the stack.
6C00
LD A,(6B24H) 3A 24 6B
Fetch the track number written into the ID fields from 6B24H into Register A.
6C03
OUT (F1H),A D3 F1
Send Register A (the track) to the controller's track register, port F1H: the Read Sector looks for this number in the ID fields.
6C05
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H: the bytes read go to 0000H-00FFH, the ROM, where they are not stored.
6C08
GOSUB to 466FH (SYS0/SYS) to send the command at 4687H (88H) to the controller and read the sector through port F3H. The NMI at the end of the command runs 46B6H, which returns here at 6C0BH (by the RET at 46C9H) with the final status in Register B.
6C0B
GOSUB to 4715H (SYS0/SYS) to send the select byte at 427FH to port F4H: the drive stays selected, without the wait states.
6C0E
POP AF F1
Restore Register Pair AF from the stack: Register A = the track register value from 6BF4H.
6C0F
OUT (F1H),A D3 F1
Send Register A to the controller's track register, port F1H: its old value is back.
6C11
POP HL E1
Restore Register Pair HL from the stack: 46C9H.
6C12
POP DE D1
Restore Register Pair DE from the stack: Register D = the saved byte, Register E = the sectors left.
6C13
LD (HL),D 72
Store Register D (F1H) back at Register Pair HL (46C9H): SYS0/SYS's routine is whole again.
6C14
POP HL E1
Restore Register Pair HL from the stack: the table pointer.
6C15
LD A,B 78
Copy Register B (the status) into Register A.
6C16
AND 9CH E6 9C
AND Register A with 9CH, keeping bit 7 (not ready), bit 4 (record not found), bit 3 (CRC error) and bit 2 (lost data).
6C18
If the Z FLAG is set (read correctly), JUMP to 6C50H.
6C1A
LD HL,6C94H 21 94 6C
Point Register Pair HL to 6C94H, the tries left (the operand of the LD A,nn at 6C93H).
6C1D
DEC (HL) 35
DECrement the tries left at Register Pair HL.
6C1E
If the NZ FLAG is set (tries left), JUMP to 6A6DH to write the track again.
6C21
EI FB
Enable interrupts before the question. 6C9FH comes here.
6C22
LD HL,6EAAH 21 AA 6E
Point Register Pair HL to 6EAAH, the word FRONT.
6C25
LD A,(6C62H) 3A 62 6C
Fetch the side from 6C62H, the operand of the LD A,nn at 6C61H, into Register A.
6C28
OR A B7
OR Register A (the side) with itself: the Z FLAG for the front.
6C29
If the Z FLAG is set (the front), JUMP to 6C2EH.
6C2B
LD HL,6EAFH 21 AF 6E
Point Register Pair HL to 6EAFH, the word BACK with a space in front.
6C2E
LD DE,6E95H 11 95 6E
Point Register Pair DE to 6E95H, the word in the message CAN'T FORMAT FRONT SIDE OF TRACK. 6C29H comes here.
6C31
LD BC,0005H 01 05 00
Load Register Pair BC with 0005H: 5 characters.
6C34
LDIR ED B0
Copy Register Pair BC (5) bytes from Register Pair HL (the word) to Register Pair DE (6E95H): the message names the side.
6C36
LD HL,6E88H 21 88 6E
Point Register Pair HL to 6E88H, the message CAN'T FORMAT ... SIDE OF TRACK .
6C39
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL.
6C3C
LD A,(6B24H) 3A 24 6B
Fetch the track number from 6B24H into Register A.
6C3F
LD E,A 5F
Copy Register A (the track number) into Register E.
6C40
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the track number.
6C42
GOSUB to 5909H to display Register Pair DE in decimal.
6C45
GOSUB to 5881H to start a new line after the track number.
6C48
GOSUB to 58C8H to ask C, R or P. C ends the command; P returns the Z FLAG, R the NZ FLAG.
6C4B
If the NZ FLAG is set (R), JUMP to 6A68H to try the track 10 more times.
6C4E
P: JUMP to 6C5BH to go on with the next side or track.
6C50
DEC E 1D
DECrement Register E, the sectors left to read back. 6C18H comes here.
6C51
LD A,01H 3E 01
Load Register A with 01H, for the comparison with the sectors left.
6C53
CP E BB
Compare Register A (1) against Register E (the sectors left): the CARRY FLAG for more than one, the Z FLAG for exactly one.
6C54
If the CARRY FLAG is set (more than one left), LOOP BACK to 6BF0H.
6C56
LD A,(6485H) 3A 85 64
Fetch the first sector number of the table from 6485H into Register A. LD does not change the flags.
6C59
If the Z FLAG is set (one left), LOOP BACK to 6BF2H to read that sector last.
6C5B
BIT 6,(IY+07H) FD CB 07 76
Test bit 6 of (IY+07H), the byte at 4287H (Index Register IY = 4280H): the disk I/O flags of the current drive, bit 6 = two sides. 6BC1H and 6C4EH come here.
6C5F
If the Z FLAG is set (single sided), JUMP to 6C6EH.
6C61
LD A,00H 3E 00
Load Register A with the side just formatted. Self-Modifying Code
The operand at 6C62H is 00H in the file; 69CBH clears it and 6C65H changes it.
6C63
XOR 01H EE 01
XOR Register A (the side) with 01H: the other side.
6C65
LD (6C62H),A 32 62 6C
Store Register A (the new side) at 6C62H, the operand of 6C61H.
6C68
If the Z FLAG is set (back to the front: both sides are done), JUMP to 6C6EH for the next track.
6C6A
XOR A AF
The back of the same track: set Register A to 00H, no skew between the two sides.
6C6B
JUMP to 6A02H to lay out and format the back side.
6C6E
LD HL,6B24H 21 24 6B
Point Register Pair HL to 6B24H, the track number. 6C5FH and 6C68H come here.
6C71
INC (HL) 34
INCrement the track number at Register Pair HL.
6C72
LD A,(HL) 7E
Fetch the track number at Register Pair HL into Register A.
6C73
CP 23H FE 23
Compare Register A (the next track) against the track to stop at. Self-Modifying Code
The operand at 6C74H is 23H in the file; 695AH stores the end track there.
6C75
RET Z C8
If the Z FLAG is set (all tracks done), RETurn with the Z FLAG.
6C76
GOSUB to 6CAEH to step the head to the next track.
6C79
JUMP to 6A00H to lay out and format the next track.
6C7C
LD HL,6D6BH 21 6B 6D
Point Register Pair HL to 6D6BH, the message MOTOR FAST. 6BD0H comes here.
6C7F
JUMP to 6C84H with Register Pair HL = the MOTOR FAST message.
6C81
LD HL,6D76H 21 76 6D
Point Register Pair HL to 6D76H, the message MOTOR SLOW. 6BD9H comes here.
6C84
LD B,FFH 06 FF
Load Register B with FFH, the code for a message instead of a DOS error. 6C7FH comes here.
6C86
JUMP to 6C93H to count the try with Register B = FFH.
6C88
LD B,11H 06 11
Load Register B with 11H, one more than the highest code. 6BC7H comes here with Register A = the error bits.
6C8A
DEC B 05
DECrement Register B, the error code being formed. 6C8CH comes here.
6C8B
RLCA 07
Rotate Register A (the status) left: the highest bit goes into the CARRY FLAG.
6C8C
If the NO CARRY FLAG is set, LOOP BACK to 6C8AH. Register B ends as 10H for bit 7 (not ready), 0FH bit 6 (write protected), 0EH bit 5 (write fault), 0DH bit 4 (not found), 0CH bit 3 (CRC error) or 0BH bit 2 (lost data), the DOS write error codes.
6C8E
LD A,B 78
Copy Register B (the error code) into Register A.
6C8F
CP 0FH FE 0F
Compare Register A (the error code) against 0FH (WRITE PROTECTED DISKETTE).
6C91
If the Z FLAG is set (write protected), JUMP to 6CA1H: there is no point trying again.
6C93
LD A,00H 3E 00
Load Register A with the tries left. Self-Modifying Code
The operand at 6C94H is 00H in the file; 6A6AH stores 10 there. 6C86H comes here.
6C95
DEC A 3D
DECrement Register A, the tries left for this track.
6C96
LD (6C94H),A 32 94 6C
Store Register A (the tries left) back at 6C94H.
6C99
If the NZ FLAG is set (tries left), JUMP to 6A6DH to write the track again.
6C9C
LD A,B 78
Copy Register B (the error code, or FFH) into Register A.
6C9D
CP 0BH FE 0B
Compare Register A (the error code) against 0BH (lost data).
6C9F
If the Z FLAG is set (lost data), JUMP to 6C21H to report the track and ask.
6CA1
OR A B7
OR Register A (the code) with itself: the NZ FLAG. 6C91H comes here.
6CA2
RET C9
RETurn with the NZ FLAG and Register A = the error code, or FFH with Register Pair HL = the message.
6CA3
LD E,(IY+04H) FD 5E 04
Load Register E with (IY+04H), the byte at 4284H (Index Register IY = 4280H): the sectors per track of the current drive. 69CFH, 6A04H, 6AA4H and 6BEDH call here.
6CA6
BIT 6,(IY+07H) FD CB 07 76
Test bit 6 of (IY+07H), the byte at 4287H (Index Register IY = 4280H): the disk I/O flags, bit 6 = two sides.
6CAA
RET Z C8
If the Z FLAG is set (single sided), RETurn with Register E = the sectors per track.
6CAB
SRL E CB 3B
Shift Register E right: halved, the sectors on one side.
6CAD
RET C9
RETurn with Register E = the sectors on one side.

6CAEH - Step to the Next Track

Steps the head in by one track, or by two for a drive with TI flag L (the double step bit, bit 2 of the disk I/O flags).

6CAE
LD A,(4287H) 3A 87 42
Fetch the disk I/O flags from 4287H (SYS0/SYS) into Register A. 691CH and 6C76H call here.
6CB1
BIT 2,A CB 57
Test bit 2 of Register A (4287H): double step.
6CB3
If the NZ FLAG is set (double step), GOSUB to 6CB6H for the first of the two steps.
6CB6
LD BC,0100H 01 00 01
Load Register Pair BC with 0100H, the count for the delay routine. 6CB3H calls here.
6CB9
GOSUB to 4C92H (SYS0/SYS), which calls the ROM delay at 0060H with Register Pair BC = 0100H: 256 passes.
6CBC
LD C,58H 0E 58
Load Register C with 58H, the FDC Step In command that updates the track register.
6CBE
JUMP to 46F7H (SYS0/SYS) to send the command in Register C with the drive's stepping rate and wait until it is done.

6CC1H - Track Format Table (Data)

One 26-byte line for each kind of drive, chosen by 6961H from the 8 inch and double density bits of the disk I/O flags (4287H). Bytes: 0 gap byte (6B41H, 6B8FH), 1 address mark lead-in (6B0FH, 6B65H; F5H writes A1H in double density), 2-3 data pattern (6B7BH, 6B81H), 4 gap length before each ID field (6AB9H, 6B95H; 2 more gap bytes are written), 5 further zero bytes before the ID mark (6B03H; 2 more are written), 6 gap length between the ID and data fields (6B47H; 2 more gap bytes are written), 7 further zero bytes before the data mark (6B59H; 2 more are written), 8-9 bytes one sector takes on the track, 10-11 bytes a track holds at the nominal speed, 12-13 and 14-15 the tolerances for the speed check (69A5H-69FDH), 16 the sector skew from track to track, 17 the interleave, 18-25 not used.

6CC1-6CDA
DEFB FFH, 00H, E5H, E5H, 09H, 01H, 09H, 01H / DEFW 012CH, 0BECH, 000BH, 003EH / DEFB 02H, 02H, 00H x 8 FF 00 E5 E5 09 01 09 01 2C 01 EC 0B 0B 00 3E 00 02 02 00 00 00 00 00 00 00 00
Line 0, 5 inch single density: gap FFH, lead-in 00H, pattern E5H E5H, gap lengths 9 and 9 bytes, 300 bytes per sector, 3052 bytes per track, tolerances 11 and 62, skew 2, interleave 2.
6CDB-6CF4
DEFB FFH, 00H, E5H, E5H, 08H, 01H, 09H, 01H / DEFW 012BH, 13E6H, 000AH, 0068H / DEFB 04H, 03H, 00H x 8 FF 00 E5 E5 08 01 09 01 2B 01 E6 13 0A 00 68 00 04 03 00 00 00 00 00 00 00 00
Line 1, 8 inch single density: gap FFH, lead-in 00H, pattern E5H E5H, gap lengths 8 and 9 bytes, 299 bytes per sector, 5094 bytes per track, tolerances 10 and 104, skew 4, interleave 3.
6CF5-6D0E
DEFB 4EH, F5H, 5BH, 5BH, 0EH, 06H, 14H, 0AH / DEFW 014AH, 17DDH, 0010H, 007DH / DEFB 04H, 03H, 00H x 8 4E F5 5B 5B 0E 06 14 0A 4A 01 DD 17 10 00 7D 00 04 03 00 00 00 00 00 00 00 00
Line 2, 5 inch double density: gap 4EH, lead-in F5H, pattern 5BH 5BH, gap lengths 14 and 20 bytes, 330 bytes per sector, 6109 bytes per track, tolerances 16 and 125, skew 4, interleave 3.
6D0F-6D28
DEFB 4EH, F5H, 5BH, 5BH, 34H, 0AH, 26H, 0AH / DEFW 0186H, 279CH, 0044H, 00D0H / DEFB 05H, 04H, 00H x 8 4E F5 5B 5B 34 0A 26 0A 86 01 9C 27 44 00 D0 00 05 04 00 00 00 00 00 00 00 00
Line 3, 8 inch double density: gap 4EH, lead-in F5H, pattern 5BH 5BH, gap lengths 52 and 38 bytes, 390 bytes per sector, 10140 bytes per track, tolerances 68 and 208, skew 5, interleave 4.
6D29-6D42
DEFB 00H x 26 00 x 26
Not used: 26 zero bytes after the table that no instruction reads (6961H only picks lines 0 to 3).
6D43-6D5C
DEFB 00H x 26 00 x 26
Not used: 26 more zero bytes that no instruction reads.
6D5D-6D5F
DEFB 1CH, 1FH, 03H 1C 1F 03
The codes that clear the screen, sent by 5E7CH: 1CH homes the cursor, 1FH clears to the end of the screen, 03H ends the message.

6D60H - FORMAT and COPY Messages (Data)

Displayed through the SYS0/SYS routine at 4467H: 0DH ends a line, 03H ends a message without a new line.

6D60-6D6A
DEFM "Formatting", 0DH 46 6F 72 6D 61 74 74 69 6E 67 0D
Displayed by 6896H before the tracks are formatted.
6D6B-6D75
DEFM "Motor Fast", 0DH 4D 6F 74 6F 72 20 46 61 73 74 0D
Displayed when a track took too few bytes (6C7CH) or the sectors cannot fit at all (69E9H).
6D76-6D80
DEFM "Motor Slow", 0DH 4D 6F 74 6F 72 20 53 6C 6F 77 0D
Displayed when a track took too many bytes (6C81H).
6D81-6D92
DEFM "Diskette Has Data", 0DH 44 69 73 6B 65 74 74 65 20 48 61 73 20 44 61 74 61 0D
Displayed by 680CH when N was given but the diskette can be read.
6D93-6DA6
DEFM "UnReadable Diskette", 0DH 55 6E 52 65 61 64 61 62 6C 65 20 44 69 73 6B 65 74 74 65 0D
Displayed by 67E7H when the destination cannot be read.
6DA7-6DC0
DEFM "Diskette Old Name/Date = ", 03H 44 69 73 6B 65 74 74 65 20 4F 6C 64 20 4E 61 6D 65 2F 44 61 74 65 20 3D 20 03
Displayed by 693FH before the name and date from the GAT.
6DC1-6DD8
DEFM "Diskette Name Mismatch", 0AH, 0DH 44 69 73 6B 65 74 74 65 20 4E 61 6D 65 20 4D 69 73 6D 61 74 63 68 0A 0D
Displayed by 6934H after SOURCE or DESTINATION.
6DD9-6DF1
DEFM "Initializing System Data", 0DH 49 6E 69 74 69 61 6C 69 7A 69 6E 67 20 53 79 73 74 65 6D 20 44 61 74 61 0D
Displayed by 665EH before the system data is written.
6DF2-6E0A
DEFM "Starting Diskette Format", 0DH 53 74 61 72 74 69 6E 67 20 44 69 73 6B 65 74 74 65 20 46 6F 72 6D 61 74 0D
The message that 6633H points Register Pair HL to and displays when the formatting of the destination diskette begins, ended by 0DH.
6E0B-6E21
DEFM "Starting Diskette Copy", 0DH 53 74 61 72 74 69 6E 67 20 44 69 73 6B 65 74 74 65 20 43 6F 70 79 0D
Displayed by 4D57H when a diskette COPY starts.
6E22-6E31
DEFM "Are System And ", 03H 41 72 65 20 53 79 73 74 65 6D 20 41 6E 64 20 03
Displayed by 4E71H, followed by SOURCE or DESTINATION.
6E32-6E44
DEFM "The Same Diskette?", 03H 54 68 65 20 53 61 6D 65 20 44 69 73 6B 65 74 74 65 3F 03
The question that 4E7BH points to after ARE SYSTEM AND SOURCE or DESTINATION; 58DEH displays it and waits for Y or N. Ended by 03H.
6E45-6E55
DEFM "Format Diskette?", 03H 46 6F 72 6D 61 74 20 44 69 73 6B 65 74 74 65 3F 03
The question that 4EBBH points to when neither FMT nor NFMT was given; 58DEH displays it unless NDMW was given. Ended by 03H.
6E56-6E87
DEFM "Either Bad Parameter or Conflict With Pdrive Data", 0DH 45 69 74 68 65 72 20 42 61 64 20 50 61 72 61 6D 65 74 65 72 20 6F 72 20 43 6F 6E 66 6C 69 63 74 20 57 69 74 68 20 50 64 72 69 76 65 20 44 61 74 61 0D
The message that 6747H points to when a parameter is bad or conflicts with the drive's PDRIVE entry (673CH and 6756H go there). Ended by 0DH.
6E88-6EA9
DEFM "Can't Format Front Side Of Track ", 03H 43 61 6E 27 74 20 46 6F 72 6D 61 74 20 46 72 6F 6E 74 20 53 69 64 65 20 4F 66 20 54 72 61 63 6B 20 03
Displayed by 6C36H, followed by the track number. 6C34H copies FRONT or BACK over the five characters at 6E95H first.
6EAA-6EB3
DEFM "Front Back" 46 72 6F 6E 74 20 42 61 63 6B
The two five-character words FRONT (6EAAH) and BACK with a space in front (6EAFH), copied by 6C34H.

6EB4H - Command Line Parsing Routines

Used only while the command line is parsed: 4DF3H copies the new PDRIVE sector over 6EB4H-6FB3H afterwards. 6EB4H steps to the next parameter: it returns the Z FLAG at the end of the line, the CARRY FLAG if a parameter follows, and the NO CARRY FLAG with the NZ FLAG if the parameter is null (two separators). 6EBFH returns the Z FLAG at the end of the line and otherwise steps over a separator; 6EC3H requires a separator (error 34H).

6EB4
GOSUB to 6EBFH to step over the separator at Register Pair HL, or return the Z FLAG at the end of the line. 660AH, 6613H and 6FBCH call here.
6EB7
RET Z C8
If the Z FLAG is set (the end of the line), RETurn with the Z FLAG.
6EB8
GOSUB to 4C7EH (SYS0/SYS) to step over another separator at Register Pair HL. It returns the CARRY FLAG when the character is not a separator.
6EBB
RET C D8
If the CARRY FLAG is set (a parameter follows), RETurn with the CARRY FLAG.
6EBC
RET Z C8
If the Z FLAG is set, RETurn. 4C7EH returns the NZ FLAG after a separator (Register A = 34H), so this is not taken.
6EBD
DEC HL 2B
A second separator: the parameter is null. DECrement Register Pair HL back onto it, for the next call.
6EBE
RET C9
RETurn with the NO CARRY FLAG and the NZ FLAG.
6EBF
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A. 4EA7H and 6EB4H call here.
6EC0
CP 0DH FE 0D
Compare Register A (the character) against 0DH, the end of the line.
6EC2
RET Z C8
If the Z FLAG is set (the end), RETurn with the Z FLAG.
6EC3
GOSUB to 4C7EH (SYS0/SYS) to step over a comma or spaces at Register Pair HL. It returns the NO CARRY FLAG after a separator, the CARRY FLAG if there is none; Register A = 34H either way. 4D94H and 6FE4H call here.
6EC6
RET NC D0
If the NO CARRY FLAG is set (stepped over), RETurn with the NZ FLAG and Register Pair HL on the next parameter.
6EC7
No separator: JUMP to 521AH to end the command with error 34H (ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR), which 4C7EH left in Register A. 6EDCH comes here with another error code.

6ECAH - Parse a Drive Number

Parses an optional colon and a drive number at Register Pair HL. Returns the CARRY FLAG with the number in Register A if the parameter starts with a digit, otherwise the NO CARRY FLAG. 6ED6H is entered with Register Pair HL on the digit (from 6448H). The drive must be available (SYS0/SYS 4723H), or the command ends with the error.

6ECA
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A. 4D33H and 6392H call here.
6ECB
CP 3AH FE 3A
Compare Register A (the character) against 3AH, a colon.
6ECD
If the NZ FLAG is set (no colon), JUMP to 6ED0H.
6ECF
INC HL 23
A colon: INCrement Register Pair HL past it, onto the character that should be the drive number.
6ED0
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A. 6ECDH comes here.
6ED1
SUB 30H D6 30
SUBtract 30H (the character 0) from Register A.
6ED3
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG for a digit.
6ED5
RET NC D0
If the NO CARRY FLAG is set (not a digit), RETurn with the NO CARRY FLAG.
6ED6
GOSUB to 6EE6H to parse a decimal number of 0-255 at Register Pair HL into Register A and Register Pair DE. 6448H calls here.
6ED9
GOSUB to 4723H (SYS0/SYS) to select the drive in Register A. It returns the NZ FLAG with error 20H if the drive is not available; Register E keeps the drive number.
6EDC
If the NZ FLAG is set (an error), JUMP to 6EC7H to end the command with the error code in Register A.
6EDE
LD A,E 7B
Copy Register E (the drive number) into Register A.
6EDF
SCF 37
Set the CARRY FLAG: a drive number was found.
6EE0
RET C9
RETurn with the CARRY FLAG and Register A = the drive number.

6EE1H - Parse a Number of 0-255

6EE1H accepts a decimal number or a hexadecimal one ending in H; 6EE6H a decimal number. Returns the value in Register A (and Register Pair DE) with Register Pair HL past the number. A missing number or one over 255 gives error 2FH. A number over 65535 is not detected (6F46H).

6EE1
GOSUB to 6EF0H to parse a decimal or hexadecimal number at Register Pair HL into Register Pair DE. 4FCEH and 4FD6H call here.
6EE4
JUMP to 6EE9H to check that the number in Register Pair DE is below 256 and return its low byte in Register A.
6EE6
GOSUB to 6F0EH to parse a decimal number at Register Pair HL into Register Pair DE. 4FC3H, 5003H, 63A9H and 6ED6H call here.
6EE9
LD A,D 7A
Copy Register D (the high byte of the number) into Register A. 6EE4H comes here.
6EEA
OR A B7
OR Register A with itself: the Z FLAG when the number is below 256.
6EEB
LD A,E 7B
Copy Register E (the low byte) into Register A. LD does not change the flags.
6EEC
RET Z C8
If the Z FLAG is set (0-255), RETurn with the number in Register A.
6EED
JUMP to 5218H to end the command with error 2FH (BAD PARAMETER(S)). 6F06H and 6F0CH come here.
6EF0
PUSH HL E5
Save Register Pair HL (the start of the number) onto the stack. 6EE1H calls here.
6EF1
GOSUB to 6F13H to parse the digits at Register Pair HL as decimal. Register Pair HL returns on the first character that is not a digit.
6EF4
LD A,(HL) 7E
Fetch the character that ended the digits at Register Pair HL into Register A.
6EF5
SUB 41H D6 41
SUBtract 41H (the letter A) from Register A, the character that ended the digits, so that A-H give 0-7.
6EF7
CP 08H FE 08
Compare Register A against 08H: the CARRY FLAG for a letter A-H.
6EF9
If the NO CARRY FLAG is set (not A-H: the number was decimal), JUMP to 6F08H.
6EFB
POP HL E1
A letter: restore Register Pair HL from the stack, the start of the number.
6EFC
LD B,01H 06 01
Load Register B with 01H: bit 0 = hexadecimal, bit 1 (a digit seen) clear.
6EFE
PUSH HL E5
Save Register Pair HL (the start) onto the stack again.
6EFF
GOSUB to 6F15H to parse the number at Register Pair HL as hexadecimal into Register Pair DE.
6F02
LD A,(HL) 7E
Fetch the character that ended it at Register Pair HL into Register A.
6F03
CP 48H FE 48
Compare Register A (the character) against 48H, the letter H.
6F05
INC HL 23
INCrement Register Pair HL past it. INC HL does not change the flags.
6F06
If the NZ FLAG is set (no H at the end), JUMP to 6EEDH for error 2FH.
6F08
BIT 1,B CB 48
Test bit 1 of Register B: set once a digit has been seen. 6EF9H comes here, and 6F0FH pushes this address as a return address.
6F0A
POP BC C1
Discard the saved start of the number from the stack into Register Pair BC. POP does not change the flags.
6F0B
RET NZ C0
If the NZ FLAG is set (a digit was seen), RETurn with the number in Register Pair DE.
6F0C
No digit was seen: JUMP to 6EEDH to end the command with error 2FH (BAD PARAMETER(S)).
6F0E
PUSH HL E5
Save Register Pair HL (the start of the number) onto the stack. 6EE6H calls here.
6F0F
LD DE,6F08H 11 08 6F
Point Register Pair DE to 6F08H, the check that a digit was seen, to be pushed as the return address of the digit loop.
6F12
PUSH DE D5
Save Register Pair DE (6F08H) onto the stack as the return address, so that the end of the number is checked there.
6F13
LD B,00H 06 00
Load Register B with 00H: decimal, no digit seen yet. 6EF1H calls here.
6F15
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, the number so far. 6EFFH calls here with Register B = 01H.

Digit Loop: Register Pair DE is the number, Register Pair HL the text, Register B the flags (bit 0 hexadecimal, bit 1 a digit seen).

6F18
LD A,(HL) 7E
Fetch a character at Register Pair HL into Register A. 6F48H comes here.
6F19
SUB 30H D6 30
SUBtract 30H (the character 0) from Register A.
6F1B
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG for a digit 0-9.
6F1D
If the CARRY FLAG is set (a digit), JUMP to 6F29H with its value in Register A.
6F1F
BIT 0,B CB 40
Not a digit 0-9: test bit 0 of Register B, the flag that the number is being parsed as hexadecimal.
6F21
RET Z C8
If the Z FLAG is set (decimal), RETurn: the number has ended.
6F22
SUB 11H D6 11
SUBtract 11H from Register A: the letter A now gives 0.
6F24
CP 06H FE 06
Compare Register A against 06H: the CARRY FLAG for A-F.
6F26
RET NC D0
If the NO CARRY FLAG is set (not A-F), RETurn: the number has ended.
6F27
ADD A,0AH C6 0A
ADD 0AH to Register A: the value of the hexadecimal digit, 10-15.
6F29
PUSH HL E5
Save Register Pair HL (the text pointer) onto the stack. 6F1DH comes here.
6F2A
LD H,D 62
Copy Register D (the high byte of the number) into Register H.
6F2B
LD L,E 6B
Copy Register E (the low byte) into Register L: Register Pair HL = the number.
6F2C
LD C,A 4F
Copy Register A (the digit's value) into Register C.
6F2D
XOR A AF
Set Register A to 00H: it collects the overflow.
6F2E
SET 1,B CB C8
Set bit 1 of Register B: a digit has been seen.
6F30
ADD HL,HL 29
ADD Register Pair HL to itself: the number times 2.
6F31
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG: the overflow collects in Register A.
6F32
ADD HL,HL 29
ADD Register Pair HL (the number times 2) to itself: Register Pair HL = the number times 4.
6F33
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG, collecting the overflow.
6F34
BIT 0,B CB 40
Test bit 0 of Register B, the hexadecimal flag, to choose between times 5 (decimal) and times 8 (hexadecimal).
6F36
If the Z FLAG is set (decimal), JUMP to 6F3BH.
6F38
ADD HL,HL 29
Hexadecimal: ADD Register Pair HL to itself, times 8.
6F39
JUMP to 6F3CH with Register Pair HL = the number times 8, skipping the decimal ADD at 6F3BH.
6F3B
ADD HL,DE 19
Decimal: ADD Register Pair DE (the number) to Register Pair HL (4 times it): times 5. 6F36H comes here.
6F3C
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG, collecting the overflow. 6F39H comes here.
6F3D
ADD HL,HL 29
ADD Register Pair HL to itself: times 10 (decimal) or 16 (hexadecimal).
6F3E
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG, collecting the overflow.
6F3F
LD E,C 59
Copy Register C (the digit's value) into Register E.
6F40
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the digit.
6F42
ADD HL,DE 19
ADD Register Pair DE (the digit) to Register Pair HL.
6F43
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG: Register A is not 0 if the number went past 65535.
6F44
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the new number.
6F45
POP HL E1
Restore Register Pair HL from the stack: the text pointer.
6F46
RET NZ C0
If the NZ FLAG is set (the number went past 65535), RETurn early with Register Pair HL on the digit. The callers only test that a digit was seen, so such a number is not rejected; its low 16 bits are used.
6F47
INC HL 23
INCrement Register Pair HL to the next character.
6F48
JUMP to 6F18H to fetch the next character at Register Pair HL and add it to the number in Register Pair DE if it is a digit.

6F4AH - APPEND Command

Entered from 4D0AH (function code 68H) with Register Pair HL pointing to filespec1[,TO],filespec2. filespec2 is opened and positioned to its end, then every byte of filespec1 is read and written to it. The file is closed, which also writes its new EOF. The command returns to SYS1/SYS through 4428H, so the SYS6/SYS exit at 521AH is used only for errors.

6F4A
LD DE,5AE5H 11 E5 5A
Point Register Pair DE to 5AE5H, the source FCB. 4D0AH comes here.
6F4D
GOSUB to 4E8DH to copy the first filespec at Register Pair HL into the FCB at Register Pair DE.
6F50
GOSUB to 6FE4H to step over the separator and an optional TO at Register Pair HL.
6F53
GOSUB to 4E8AH to copy the second filespec at Register Pair HL into the destination FCB at 5B17H; Register Pair DE returns 5B17H.
6F56
GOSUB to 5210H: nothing may follow at Register Pair HL (error 34H).
6F59
LD HL,65B0H 21 B0 65
Point Register Pair HL to 65B0H, the 256-byte buffer for the second file (over SYS6/SYS's boot image and FORMAT code, which APPEND does not use).
6F5C
LD B,00H 06 00
Load Register B with 00H, the record length: byte I/O.
6F5E
GOSUB to 4424H (SYS0/SYS) to open the existing second file in the FCB at Register Pair DE (5B17H) with the buffer at Register Pair HL.
6F61
RET NZ C0
If the NZ FLAG is set (it cannot be opened), RETurn with the error code in Register A.
6F62
GOSUB to 4448H (SYS0/SYS) to position the second file at its end (EOF).
6F65
RET NZ C0
If the NZ FLAG is set (an error), RETurn with the error code in Register A.
6F66
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set: the alternate Register Pair DE' keeps 5B17H, the second file's FCB.
6F67
LD HL,64B0H 21 B0 64
Point Register Pair HL to 64B0H, the 256-byte buffer for the first file.
6F6A
LD B,00H 06 00
Load Register B with 00H, the record length: byte I/O.
6F6C
LD DE,5AE5H 11 E5 5A
Point Register Pair DE to 5AE5H, the source FCB.
6F6F
GOSUB to 4424H (SYS0/SYS) to open the existing first file in the FCB at Register Pair DE with the buffer at Register Pair HL.
6F72
RET NZ C0
If the NZ FLAG is set (it cannot be opened), RETurn with the error code in Register A.

Byte Loop: each byte of the first file is read and written to the second.

6F73
GOSUB to 0013H, the ROM routine that reads a byte from the device or file at Register Pair DE (the first file's FCB) into Register A. 6F7DH comes here.
6F76
If the NZ FLAG is set (an error or the end of the file), JUMP to 6F82H.
6F78
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set: Register Pair DE = 5B17H, the second file's FCB.
6F79
GOSUB to 001BH, the ROM routine that writes the byte in Register A to the file at Register Pair DE.
6F7C
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set back: Register Pair DE = 5AE5H.
6F7D
If the Z FLAG is set (written), LOOP BACK to 6F73H for the next byte.
6F7F
JUMP to 521AH to end the command with the error code in Register A. 6F88H comes here.
6F82
CP 1CH FE 1C
Compare Register A (the error code) against 1CH (END OF FILE ENCOUNTERED). 6F76H comes here.
6F84
If the Z FLAG is set (the first file has been copied), JUMP to 6F8AH.
6F86
CP 1DH FE 1D
Compare Register A (the error code) against 1DH (PAST END OF FILE).
6F88
If the NZ FLAG is set (any other error), JUMP to 6F7FH.
6F8A
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set: Register Pair DE = 5B17H, the second file's FCB. 6F84H comes here.
6F8B
JUMP to 4428H (SYS0/SYS) to close the second file at Register Pair DE, which writes its new EOF; its RETurn goes back to SYS1/SYS with the result.

6F8EH - Copy a Name

Copies up to 8 letters and digits (the first must be a letter) from Register Pair HL to Register Pair DE and pads the rest of the 8 bytes with spaces. Returns Register A = Register C = the number of characters copied, with the Z FLAG if there were none. Register Pair HL points past the name.

6F8E
LD B,08H 06 08
Load Register B with 08H: 8 places. 4F98H and 5028H call here.
6F90
LD C,00H 0E 00
Load Register C with 00H, the count of characters copied.
6F92
JUMP to 6F9DH: the first character must be a letter.

Character Loop: Register Pair HL walks the text, Register Pair DE the name, Register B counts the places.

6F94
LD A,(HL) 7E
Fetch a character at Register Pair HL into Register A. 6FAAH comes here.
6F95
CP 3AH FE 3A
Compare Register A (the character) against 3AH, one past the digit 9.
6F97
If the NO CARRY FLAG is set (above the digits), JUMP to 6F9DH to test for a letter.
6F99
CP 30H FE 30
Compare Register A (the character, below 3AH) against 30H, the digit 0: the NO CARRY FLAG for a digit 0-9.
6F9B
If the NO CARRY FLAG is set (a digit), JUMP to 6FA6H to copy it.
6F9D
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A. 6F92H and 6F97H come here.
6F9E
CP 5BH FE 5B
Compare Register A against 5BH, one past the letter Z.
6FA0
If the NO CARRY FLAG is set (above Z), JUMP to 6FAEH to pad.
6FA2
CP 41H FE 41
Compare Register A against 41H, the letter A.
6FA4
If the CARRY FLAG is set (below A), JUMP to 6FAEH to pad.
6FA6
LD (DE),A 12
Store Register A (the letter or digit) at Register Pair DE. 6F9BH comes here.
6FA7
INC HL 23
INCrement Register Pair HL to the next character.
6FA8
INC DE 13
INCrement Register Pair DE to the next place.
6FA9
INC C 0C
INCrement Register C, the count of characters copied.
6FAA
DECrement Register B (the places left) and LOOP BACK to 6F94H.
6FAC
Register B reached 0, so all 8 places of the name are filled: JUMP to 6FB4H to return the count in Register C.
6FAE
LD A,20H 3E 20
Load Register A with 20H, a space. 6FA0H, 6FA4H and 6FB2H come here.
6FB0
LD (DE),A 12
Store Register A (a space) at Register Pair DE.
6FB1
INC DE 13
INCrement Register Pair DE to the next place.
6FB2
DECrement Register B (the places left) and LOOP BACK to 6FAEH.
6FB4
LD A,C 79
Copy Register C (the count) into Register A. 6FACH comes here.
6FB5
OR A B7
OR Register A with itself: the Z FLAG when no character was copied.
6FB6
RET C9
RETurn with Register A = Register C = the count.

6FB7H - Parse the Date

Parses mm/dd/yy into 598BH, checking each digit against the highest value stored there in the file (2:/4:/::: the month's first digit below 2, the day's below 4, the others below :). A null or missing date parameter takes the system date instead.

6FB7
LD DE,598BH 11 8B 59
Point Register Pair DE to 598BH, the date for the new GAT. 4D5EH and 6610H call here.
6FBA
LD C,03H 0E 03
Load Register C with 03H: three parts, month, day and year.
6FBC
GOSUB to 6EB4H to step to the date parameter at Register Pair HL. It returns the CARRY FLAG if one follows.
6FBF
If the NO CARRY FLAG is set (null or missing), JUMP to 6FDDH for the system date.

Part Loop: two digits, then a slash, three times.

6FC1
LD B,02H 06 02
Load Register B with 02H: two digits in a part. 6FD8H comes here.
6FC3
LD A,(HL) 7E
Fetch a character at Register Pair HL into Register A. 6FD0H comes here.
6FC4
CP 30H FE 30
Compare Register A (the character) against 30H, the digit 0.
6FC6
If the CARRY FLAG is set (below 0), JUMP to 6FDAH for error 2FH.
6FC8
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the place in the date at 598BH.
6FC9
CP (HL) BE
Compare Register A (the digit) against the highest value allowed, stored at Register Pair HL.
6FCA
If the NO CARRY FLAG is set (too high), JUMP to 6FDAH for error 2FH.
6FCC
LD (HL),A 77
Store Register A (the digit) at Register Pair HL in the date.
6FCD
EX DE,HL EB
Exchange Register Pairs DE and HL back: Register Pair HL = the command line.
6FCE
INC DE 13
INCrement Register Pair DE to the next place of the date.
6FCF
INC HL 23
INCrement Register Pair HL to the next character.
6FD0
DECrement Register B (the digits left) and LOOP BACK to 6FC3H.
6FD2
DEC C 0D
Both digits of this part are stored: DECrement Register C, the count of date parts left to parse.
6FD3
RET Z C8
If the Z FLAG is set (all three parts), RETurn.
6FD4
LD A,(DE) 1A
Fetch the separator from the date at Register Pair DE (a slash) into Register A.
6FD5
CP (HL) BE
Compare Register A (the slash) against the character typed at Register Pair HL.
6FD6
INC DE 13
INCrement Register Pair DE past the slash in the date. INC DE does not change the flags.
6FD7
INC HL 23
INCrement Register Pair HL past the character typed. INC HL does not change the flags.
6FD8
If the Z FLAG is set (a slash was typed), LOOP BACK to 6FC1H for the next part.
6FDA
JUMP to 5218H to end the command with error 2FH (BAD PARAMETER(S)). 6FC6H and 6FCAH come here.
6FDD
PUSH HL E5
Save Register Pair HL (the command line pointer) onto the stack. 6FBFH comes here.
6FDE
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = 598BH.
6FDF
GOSUB to 4470H (SYS0/SYS) to put the system date at Register Pair HL as MM/DD/YY.
6FE2
POP HL E1
Restore Register Pair HL from the stack: the command line pointer.
6FE3
RET C9
RETurn to the caller with the date at 598BH and Register Pair HL on the command line.

6FE4H - Step to the Next Parameter, Skipping TO

Requires a separator (error 34H), then steps over the keyword TO and the separator after it if they are there. A word that only starts with TO (such as a file named TOM) is left alone.

6FE4
GOSUB to 6EC3H to step over the separator at Register Pair HL (error 34H if there is none). 4D4AH, 4DB6H and 6F50H call here.
6FE7
LD D,H 54
Copy Register H (the high byte of the parameter's address in Register Pair HL) into Register D.
6FE8
LD E,L 5D
Copy Register L into Register E: Register Pair DE = the start of the parameter.
6FE9
LD BC,6FF6H 01 F6 6F
Point Register Pair BC to 6FF6H, the keyword TO ended by 00H.
6FEC
GOSUB to 4C6AH (SYS0/SYS) to compare the string at Register Pair BC with the text at Register Pair HL. It returns the Z FLAG with Register Pair HL past TO when they match, else the NZ FLAG with Register Pair HL unchanged.
6FEF
RET NZ C0
If the NZ FLAG is set (not TO), RETurn with Register Pair HL on the parameter.
6FF0
GOSUB to 4C7EH (SYS0/SYS) to step over a separator after TO at Register Pair HL. It returns the NO CARRY FLAG after one.
6FF3
RET NC D0
If the NO CARRY FLAG is set (TO was a keyword), RETurn with Register Pair HL on the next parameter.
6FF4
EX DE,HL EB
No separator: the TO starts a filespec. Exchange Register Pairs DE and HL: Register Pair HL = the start of the parameter again.
6FF5
RET C9
RETurn with Register Pair HL on the filespec.
6FF6-6FF8
DEFM "TO", 00H 54 4F 00
The keyword for 6FE4H (pointed to by 6FE9H), ended by 00H for the SYS0/SYS compare at 4C6AH.