TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - SYS8/SYS Disassembled

Page Customization

Introduction/Summary

NEWDOS/80 v2.0 SYS8/SYS Disassembly - DIR and FREE (Model I)

SYS8/SYS lists directories and free space. It loads into the overlay area at 4D00H-51E7H (1,256 bytes in five load records, transfer address 4D00H). SYS1 calls it for the DIR command with LD A,2AH / RST 28H (function 1) and for FREE with 4AH (function 2); the SYS0 dispatcher (4BC2H) loads SYS8 when 4317H does not already hold its number (0AH). Any other code returns error 2AH.

The page shows every byte of the file once, in address order. The listing that the rebuild started from decodes 4E0EH-4E10H (the extension filter) and the tables and texts from 5109H on as instructions; they are shown here as data.

DIR and FREE

DIR [:][$][d] [options] (4D50H). The drive defaults to option AN. The options, separated by commas or spaces, are:

OptionEffect
AOne file per line with its details: EOF (sectors/bytes), record length, records, granules, extent elements and attributes (4E8BH), under column headings (4FC7H).
SAlso list system files.
IAlso list invisible files.
UOnly files whose updated flag (FPDE byte 1 bit 5) is set.
/extOnly files with this extension.
PTo the printer instead of the screen (5058H).
$Before the listing ask for the diskette (MOUNT TARGET DISKETTE ON DRIVE d (ENTER)); for drive 0 also ask for the system diskette afterwards.

With U or /ext, system and invisible files are not left out. Without A the names are shown four to a line, each padded to 15 columns. The screen listing stops with ? after each page (13 lines, then 15) until ENTER is pressed; BREAK goes to DOS READY (506BH). There is no stop while a chain file runs or when printing.

FREE [P] (4D0DH) shows the drive line for every drive from 0 up to the last drive allowed by option AL that has a diskette.

Output Lines

The drive line (4FDBH, text at 514EH) starts both DIR and FREE: DRIVE d name date ttt TRKS fff FDES gggg GRANS. The name and date come from GAT bytes D0H-DFH, the tracks from the drive's PDRIVE values (430DH). Free granules are the clear bits of the GAT (granules per lump 430FH, lumps 430BH); free FDEs are the HIT bytes that are 00H in the positions of the 8 + extra FDE sectors (HIT byte 1FH).

The A line after each name (518CH): sssss/bbb lll rrrrrr gggg eee attributes, under the headings EOF LRL RECS GRANS EXTS SIUEC....UAL. The EOF is shown as whole sectors and the byte in the last sector (the FPDE's middle/high bytes are one too high when the low byte is not 0, so 1 is taken off). Records = EOF / LRL rounded up, with LRL 0 counted as 256. The attributes: S system, I invisible, U updated, E no extension (ASE=N), C no space release (ASC=N), four unused periods, U and A when the update and access passwords are not blank, and the access level digit.

Numbers are written into the texts by 50BFH with leading zeros shown as spaces. The first entry of its power-of-ten table (5109H) is +100000, not -100000, so the first of the six record positions always stays blank.

Variables and Self-Modifying Code

Locations inside SYS8 whose contents change while it runs:

Address RangePurpose
4D33H
1 byte
The DEC of the entry being listed, its FDE sector in bits 0-4 (operand of 4D32H; written at 4D34H).
4D47H
1 byte
The opcode of LD HL,4F96H at 4D47H: CDH (CALL 4F96H) after DIR $ for drive 0 (written at 4DE7H).
4E0EH-4E10H
3 bytes
The extension given with /ext (written at 4DCDH, compared at 4F67H).
4F35H
1 byte
The number of FDE sectors, 8 + HIT byte 1FH (operand of 4F34H; written at 5035H).
5090H
1 byte
6AH (JP 446AH, print) with P instead of 67H (operand of 508FH; written at 5064H).
50A8H
1 byte
3BH (CALL 003BH, printer) with P instead of 33H (operand of 50A7H; written at 505FH; tested at 4FB8H and 5070H).
5132H
1 byte
The drive digit in the MOUNT message (written at 4DEDH).
5154H-51BAH
various
The drive line and the DIR A detail line, filled in by 4FDBH and 4E8BH-4F1DH (see 514EH and 518CH).

Locations outside SYS8 that it reads or writes:

Address RangePurpose
3840H
1 byte
Keyboard row 6: ENTER (bit 0) and BREAK (bit 2), read at 507BH.
4200H-42FFH
256 bytes
The directory sector buffer: the GAT (name and date at 42D0H-42DFH), the HIT (421FH the extra FDE sectors), or an FDE sector.
4296H-4297H
2 bytes
The code of a blank password, compared at 4E73H and 4E7CH.
430BH
1 byte
The selected drive's number of lumps (IY-75H).
430DH
1 byte
The selected drive's number of tracks.
430FH
1 byte
The selected drive's granules per lump (IY-71H).
4369H
1 byte
System flags: bit 5 chaining on (IY-17H): no page stops.
43A0H
1 byte
Option AN, the default drive for DIR.

Register B holds the DIR options (bit 0 A, 1 S, 2 I, 3 P, 4 /ext, 5 U, 6 $), Register C the drive and later the names left on the line; the line count is kept on the stack.

Disassembly

4D00H - Function Dispatcher

SYS8 is entered by the SYS0 RST 28H dispatcher (4BC2H) with Register A = the RST 28H code and Register Pair HL pointing to the rest of the command line. Code 2AH (function 1) is DIR, 4AH (function 2) is FREE; any other code returns error 2AH.

4D00
LD IY,4380H FD 21 80 43
Load Index Register IY with 4380H, the base for the SYS0 variables (IY-75H = 430BH, IY-71H = 430FH, IY-17H = 4369H).
4D04
CP 2AH FE 2A
Compare Register A (the RST 28H code) against 2AH: function 1, DIR.
4D06
If the Z FLAG is set (DIR), JUMP to 4D50H with Register Pair HL = the command line.
4D08
CP 4AH FE 4A
Compare Register A (the RST 28H code) against 4AH: function 2, FREE.
4D0A
LD A,2AH 3E 2A
Load Register A with 2AH, error code ILLEGAL DOS FUNCTION. LD does not change the flags.
4D0C
RET NZ C0
If the NZ FLAG is set (neither code), RETURN with error 2AH in Register A; FREE falls into 4D0DH.

4D0DH - FREE Command

FREE [P] shows one line per drive, from drive 0 up to the last drive allowed by option AL: the drive number, the diskette name and date, the number of tracks, free FDEs and free granules (4FDBH). Drives without a diskette are skipped. After every 13 lines the listing waits (506BH). P sends the listing to the printer.

4D0D
GOSUB to 5058H to check the character at Register Pair HL for P (printer); Register A comes back with the next character.
4D10
CP 0DH FE 0D
Compare Register A against 0DH, the carriage return at the end of the line.
4D12
If the NZ FLAG is set (something else follows), JUMP to 4D3DH for error 34H.
4D14
LD C,00H 0E 00
Load Register C with 00H: FREE starts with drive 0.
4D16
GOSUB to 5086H to start a new output line before the first drive.

PAGE LOOP
Register B counts the 13 lines of a page, Register C = the drive.

4D19
LD B,0DH 06 0D
Load Register B with 0DH, the 13 lines of a page.
4D1B
GOSUB to 4FDBH to show the drive line for drive Register C: the Z FLAG if shown, else the error in Register A.
4D1E
If the Z FLAG is set (the drive line was shown), JUMP to 4D2AH.
4D20
CP 20H FE 20
Compare Register A (the error) against 20H, ILLEGAL OR MISSING DRIVE #: past option AL.
4D22
If the Z FLAG is set (no such drive), JUMP to 4FB8H to end the listing.
4D25
CP 08H FE 08
Compare Register A (the error) against 08H, no diskette in the drive.
4D27
If the NZ FLAG is set (any other error), JUMP to 4D43H to return it.
4D29
INC B 04
No diskette: increment Register B, since this drive takes no line.
4D2A
INC C 0C
Increment Register C to the next drive number.
4D2B
Decrement Register B (the lines left); if it is not 0, LOOP back to 4D1BH.
4D2D
GOSUB to 506BH to wait for ENTER (or BREAK) at the end of the page.
4D30
LOOP back to 4D19H for the next page of drives.

4D32H - Read the Directory Sector of an Entry

4D32H reads the sector of the entry being listed again (its DEC is kept in the operand at 4D33H). 4D34H stores the DEC in Register A first; 4D37H reads the sector of DEC A without storing it. Register Pair HL comes back pointing to the entry. A read error ends DIR.

4D32
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the DEC of the entry being listed, the operand 4D33H (00H in the file, stored at 4D34H).
4D34
LD (4D33H),A 32 33 4D
Self-Modifying Code
Store Register A (the DEC) at 4D33H, the operand of 4D32H.
4D37
GOSUB to SYS0 492FH, which points Register Pair HL to the entry of DEC Register A, reading its sector into 4200H if it is not there; Register A comes back with the entry's offset in the sector.
4D3A
RET Z C8
If the Z FLAG is set (read), RETURN with Register Pair HL = the entry.
4D3B
JUMP to 4D43H to end DIR with the read error in Register A.

4D3DH - Error 34H and the End of DIR and FREE

4D43H is the common exit of DIR and FREE, with Register A = 00H for no error. If DIR was given with $ for drive 0, the opcode at 4D47H has been made CALL (CDH, at 4DE7H), so the operator is asked to put the system diskette back first (MOUNT SYSTEM DISKETTE ON DRIVE 0).

4D3D
LD A,34H 3E 34
Load Register A with 34H, error code ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR.
4D3F
JUMP to 4D43H to return error 34H in Register A.

4D41H - Unreferenced Error Code

Nothing jumps to 4D41H, and 4D3FH jumps over it.

4D41
LD A,2FH 3E 2F
Load Register A with 2FH, error code BAD PARAMETER(S); unreferenced, it would fall into 4D43H.

4D43H - DIR and FREE Exit

Register A = the error code, 00H for none.

4D43
PUSH AF F5
Save Register Pair AF (Register A = the error code) on the stack.
4D44
LD HL,513DH 21 3D 51
Load Register Pair HL with 513DH, the word SYSTEM, for the MOUNT message.
4D47
LD HL,4F96H 21 96 4F
Self-Modifying Code
Load Register Pair HL with 4F96H. As loaded this does nothing useful; 4DE7H makes the opcode CDH, so it is CALL 4F96H with Register Pair HL = SYSTEM: MOUNT SYSTEM DISKETTE ON DRIVE 0 (ENTER).
4D4A
POP AF F1
Restore Register Pair AF from the stack: Register A = the error code.
4D4B
OR A B7
OR Register A with itself: the Z FLAG is set if there is no error.
4D4C
RET Z C8
If the Z FLAG is set (Register A = 00H), RETURN.
4D4D
JUMP to SYS0 4409H, the error exit, with the error code in Register A.

4D50H - DIR Command: Drive and Options

Form: DIR [:][$][d] [options], the options separated by commas or spaces: A (details, one file per line), S (system files too), I (invisible files too), U (only files with the updated flag), P (to the printer), /ext (only files with this extension). The drive defaults to option AN (43A0H). With $ the operator is asked to mount the diskette first. Register B collects the options: bit 0 A, bit 1 S, bit 2 I, bit 3 P, bit 4 /ext, bit 5 U, bit 6 $. Register C holds the drive.

4D50
LD A,(43A0H) 3A A0 43
Load Register A with the byte at 43A0H, option AN: the default drive.
4D53
LD C,A 4F
Load Register C with Register A: the drive, option AN until a number is given.
4D54
LD B,00H 06 00
Load Register B with 00H: no DIR options yet in Register B.
4D56
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the first character.
4D57
CP 3AH FE 3A
Compare Register A (the first character) against 3AH, a colon.
4D59
If the NZ FLAG is set (no colon), JUMP to 4D5CH.
4D5B
INC HL 23
Increment Register Pair HL past the colon to the next character.
4D5C
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character.
4D5D
CP 24H FE 24
Compare Register A (the character) against 24H, a $.
4D5F
If the NZ FLAG is set (no $), JUMP to 4D64H to look for a drive number.
4D61
SET 6,B CB F0
Set bit 6 of Register B, the $ option (ask for the diskette).
4D63
INC HL 23
Increment Register Pair HL past the $ to the next character.
4D64
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character.
4D65
SUB 30H D6 30
Subtract 30H from Register A: the digits 0-9 become 00H-09H.
4D67
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG is set for a digit.
4D69
If the NO CARRY FLAG is set (not a digit), JUMP to 4D89H: no drive number, Register C keeps option AN.

READ THE DRIVE NUMBER
Register C = the number so far, Register Pair HL steps through the digits.

4D6B
LD C,A 4F
Load Register C with Register A, the drive number so far.
4D6C
INC HL 23
Increment Register Pair HL to the next character.
4D6D
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character.
4D6E
SUB 30H D6 30
Subtract 30H from Register A: the digits 0-9 become 00H-09H.
4D70
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG is set for a digit.
4D72
If the NO CARRY FLAG is set (not a digit), JUMP to 4D85H: the number has ended.
4D74
LD E,A 5F
Load Register E with Register A, the new digit.
4D75
LD A,C 79
Load Register A with Register C, the number so far.
4D76
LD D,09H 16 09
Load Register D with 09H: the number is added 9 more times, making it times 10.
4D78
ADD A,C 81
Add Register C (the number so far) to Register A.
4D79
If the CARRY FLAG is set (over 255), JUMP to 4D81H for error 20H.
4D7B
DEC D 15
Decrement Register D, the additions left for the times 10.
4D7C
If the NZ FLAG is set (more additions), LOOP back to 4D78H.
4D7E
ADD A,E 83
Add Register E (the new digit) to Register A.
4D7F
If the NO CARRY FLAG is set (no overflow), LOOP back to 4D6BH with the new number in Register A.
4D81
LD A,20H 3E 20
Load Register A with 20H, error code ILLEGAL OR MISSING DRIVE #.
4D83
JUMP to 4D43H to return error 20H in Register A.

OPTION LOOP
Register Pair HL = the command line, Register B = the options so far.

4D85
GOSUB to SYS0 4CD5H with Register Pair HL = the command line: the Z FLAG at the end of the line, the NO CARRY FLAG after stepping over a comma or spaces.
4D88
RET C D8
If the CARRY FLAG is set (another character, no separator), RETURN with error 34H in Register A.
4D89
GOSUB to 5058H: P selects the printer. Register A = the character (or the next one after P), Register Pair HL is past it.
4D8C
If the Z FLAG is set (it was P), LOOP back to 4D85H.
4D8E
CP 0DH FE 0D
Compare Register A against 0DH, the carriage return at the end of the line.
4D90
If the Z FLAG is set (the end), JUMP to 4DD5H to list the directory.
4D92
CP 41H FE 41
Compare Register A against 41H, the letter A.
4D94
If the NZ FLAG is set (not A), JUMP to 4D9AH.
4D96
SET 0,B CB C0
Set bit 0 of Register B, option A (one file per line with details).
4D98
LOOP back to 4D85H for the next option at Register Pair HL.
4D9A
CP 53H FE 53
Compare Register A against 53H, the letter S.
4D9C
If the NZ FLAG is set (not S), JUMP to 4DA2H.
4D9E
SET 1,B CB C8
Set bit 1 of Register B, option S (list system files too).
4DA0
LOOP back to 4D85H for the next option at Register Pair HL.
4DA2
CP 49H FE 49
Compare Register A against 49H, the letter I.
4DA4
If the NZ FLAG is set (not I), JUMP to 4DAAH.
4DA6
SET 2,B CB D0
Set bit 2 of Register B, option I (list invisible files too).
4DA8
LOOP back to 4D85H for the next option at Register Pair HL.
4DAA
CP 55H FE 55
Compare Register A against 55H, the letter U.
4DAC
If the NZ FLAG is set (not U), JUMP to 4DB2H.
4DAE
SET 5,B CB E8
Set bit 5 of Register B, option U (only files with the updated flag).
4DB0
LOOP back to 4D85H for the next option at Register Pair HL.
4DB2
CP 2FH FE 2F
Compare Register A (the option's letter) against 2FH, a slash.
4DB4
If the NZ FLAG is set (anything else), JUMP to 4D3DH for error 34H.
4DB7
SET 4,B CB E0
Set bit 4 of Register B, option /ext (only files with this extension).
4DB9
PUSH BC C5
Save Register Pair BC (the options and the drive) on the stack.
4DBA
LD B,03H 06 03
Load Register B with 03H: up to three characters.
4DBC
LD DE,4E0EH 11 0E 4E
Load Register Pair DE with 4E0EH, the extension filter (three spaces as loaded).

COPY THE EXTENSION
Register Pair HL = the command line, Register Pair DE = the filter, Register B = the room left.

4DBF
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character.
4DC0
SUB 30H D6 30
Subtract 30H from Register A: the digits 0-9 become 00H-09H.
4DC2
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG is set for a digit.
4DC4
If the CARRY FLAG is set (a digit), JUMP to 4DCCH to copy it.
4DC6
SUB 11H D6 11
Subtract 11H from Register A: the letters A-Z become 00H-19H.
4DC8
CP 1AH FE 1A
Compare Register A against 1AH: the CARRY FLAG is set for a letter.
4DCA
If the NO CARRY FLAG is set (not a letter), JUMP to 4DD2H: the extension has ended.
4DCC
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the character again.
4DCD
LD (DE),A 12
Self-Modifying Code
Store Register A at Register Pair DE, in the extension filter at 4E0EH-4E10H.
4DCE
INC DE 13
Increment Register Pair DE to the filter's next position.
4DCF
INC HL 23
Increment Register Pair HL to the next character.
4DD0
Decrement Register B (the room left); if it is not 0, LOOP back to 4DBFH.
4DD2
POP BC C1
Restore Register Pair BC from the stack: the options and the drive.
4DD3
LOOP back to 4D85H for the next option at Register Pair HL.

4DD5H - DIR: Start the Listing

Clears the screen (not when printing), handles $ (the MOUNT prompts), shows the drive line (4FDBH), reads the first FDE sector and starts at its first entry (4F3BH) with 5 in Register C (names left on this line, counted down before each) and 13 lines left on the stack.

4DD5
BIT 3,B CB 58
Test bit 3 of Register B, option P (printing).
4DD7
LD HL,514BH 21 4B 51
Load Register Pair HL with 514BH, the bytes 1CH 1FH 03H (home the cursor, clear the screen). LD does not change the flags.
4DDA
If the Z FLAG is set (not printing), GOSUB to 508FH to send the bytes at Register Pair HL: the screen is cleared.
4DDD
BIT 6,B CB 70
Test bit 6 of Register B, the $ option (ask for the diskette).
4DDF
If the Z FLAG is set (no $), JUMP to 4DF6H to show the drive line.
4DE1
LD A,C 79
Load Register A with Register C, the drive number, to test it for 0.
4DE2
OR A B7
OR Register A with itself: the Z FLAG is set for drive 0.
4DE3
If the NZ FLAG is set (not drive 0), JUMP to 4DEAH.
4DE5
LD A,CDH 3E CD
Load Register A with CDH, the opcode of CALL.
4DE7
LD (4D47H),A 32 47 4D
Self-Modifying Code
Store Register A (CDH) at 4D47H: the LD HL,4F96H there becomes CALL 4F96H, so the system diskette is asked for again at the end.
4DEA
LD A,C 79
Load Register A with Register C, the drive number.
4DEB
ADD A,30H C6 30
Add 30H to Register A: the drive number as a digit (drives 0-9).
4DED
LD (5132H),A 32 32 51
Store Register A (the digit) at 5132H, the drive digit in the message DISKETTE ON DRIVE d.
4DF0
LD HL,5144H 21 44 51
Load Register Pair HL with 5144H, the word TARGET.
4DF3
GOSUB to 4F96H to show MOUNT TARGET DISKETTE ON DRIVE d (ENTER) and wait for ENTER.
4DF6
GOSUB to 4FDBH to select drive Register C and show its line: the Z FLAG if shown.
4DF9
If the NZ FLAG is set (an error), JUMP to 4D43H to return it in Register A.
4DFC
XOR A AF
Load Register A with 00H (XOR A with itself): DEC 00H, the first entry of the first FDE sector.
4DFD
GOSUB to 4D34H to store the DEC in Register A and read its sector: Register Pair HL = the entry.
4E00
GOSUB to 5086H to start a new output line after the drive line.
4E03
LD D,0DH 16 0D
Load Register D with 0DH, 13 lines left on the first page.
4E05
GOSUB to 4FC7H to show the column headings (only with option A), counting a line in Register D.
4E08
PUSH DE D5
Save Register Pair DE (Register D = the lines left) on the stack, where it stays between entries.
4E09
LD C,05H 0E 05
Load Register C with 05H: the first line takes 4 names, counted down before each.
4E0B
JUMP to 4F3BH to test the first entry at Register Pair HL.

4E0EH - DIR: Extension Filter

4E0E-4E10
DEFM " " 20 20 20
The extension given with /ext, stored by 4DCDH and compared by 4F62H; three spaces in the file.

4E11H - DIR: Show a File

Register Pair HL points to the FPDE, Register B = the options, Register C = the names left on the line, and the line count is on the stack. The attribute text at 51AFH-51BAH is prepared for the A option: the access level digit, S (system), I (invisible), U (updated flag, byte 1 bit 5), E (byte 1 bit 7, no extension), C (byte 1 bit 6, no space release), then U and A if the update and access passwords are not blank; other positions show a period. The name and /extension are shown without spaces and padded to 15 columns. Without the A option that is all; with it 4E8BH adds the details on the same line.

4E11
PUSH DE D5
Save Register Pair DE (Register D = the lines left on the page) on the stack.
4E12
PUSH BC C5
Save Register Pair BC (Register B = the options, Register C = the names left on the line) on the stack.
4E13
PUSH HL E5
Save Register Pair HL (the entry's address) on the stack.
4E14
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the entry.
4E15
LD HL,51AFH 21 AF 51
Load Register Pair HL with 51AFH, the attribute text.
4E18
LD B,0BH 06 0B
Load Register B with 0BH, the eleven positions 51AFH-51B9H.
4E1A
PUSH HL E5
Save Register Pair HL (51AFH, the start of the text) on the stack.

FILL WITH PERIODS
Register Pair HL steps through the text, Register B counts.

4E1B
LD (HL),2EH 36 2E
Store 2EH (a period) at Register Pair HL, in the attribute text.
4E1D
INC HL 23
Increment Register Pair HL to the next position.
4E1E
Decrement Register B (the positions left); if it is not 0, LOOP back to 4E1BH.
4E20
LD A,(DE) 1A
Load Register A with the byte at Register Pair DE, byte 0 of the entry (the attributes).
4E21
AND 07H E6 07
Mask Register A against 07H (0000 0111) to keep the access level.
4E23
ADD A,30H C6 30
Add 30H to Register A: the access level as a digit.
4E25
LD (HL),A 77
Store Register A (the digit) at Register Pair HL, 51BAH.
4E26
POP HL E1
Restore Register Pair HL from the stack: 51AFH, the start of the text.
4E27
LD A,(DE) 1A
Load Register A with the byte at Register Pair DE, byte 0 of the entry again.
4E28
BIT 6,A CB 77
Test bit 6 of Register A: set for a system file.
4E2A
If the Z FLAG is set (not a system file), JUMP to 4E2EH.
4E2C
LD (HL),53H 36 53
Store 53H (S) at Register Pair HL, 51AFH, for a system file.
4E2E
INC HL 23
Increment Register Pair HL to 51B0H, the I position.
4E2F
BIT 3,A CB 5F
Test bit 3 of Register A (byte 0): set for an invisible file.
4E31
If the Z FLAG is set (visible), JUMP to 4E35H.
4E33
LD (HL),49H 36 49
Store 49H (I) at Register Pair HL, 51B0H, for an invisible file.
4E35
INC HL 23
Increment Register Pair HL to 51B1H, the U position.
4E36
INC DE 13
Increment Register Pair DE to byte 1 of the entry.
4E37
LD A,(DE) 1A
Load Register A with the byte at Register Pair DE, byte 1 of the entry (the flags).
4E38
BIT 5,A CB 6F
Test bit 5 of Register A (byte 1 of the entry): the updated flag.
4E3A
If the Z FLAG is set (not updated), JUMP to 4E3EH.
4E3C
LD (HL),55H 36 55
Store 55H (U) at Register Pair HL, 51B1H, for an updated file.
4E3E
INC HL 23
Increment Register Pair HL to 51B2H, the E position.
4E3F
BIT 7,A CB 7F
Test bit 7 of Register A (byte 1): set for no extension (ASE=N).
4E41
If the Z FLAG is set (bit 7 of Register A clear), JUMP to 4E45H.
4E43
LD (HL),45H 36 45
Store 45H (E) at Register Pair HL, 51B2H: no extension (ASE=N).
4E45
INC HL 23
Increment Register Pair HL to 51B3H, the C position.
4E46
BIT 6,A CB 77
Test bit 6 of Register A (byte 1): set for no space release (ASC=N).
4E48
If the Z FLAG is set (bit 6 of Register A clear), JUMP to 4E4CH.
4E4A
LD (HL),43H 36 43
Store 43H (C) at Register Pair HL, 51B3H: no space release (ASC=N).
4E4C
LD HL,0004H 21 04 00
Load Register Pair HL with 0004H, the distance from byte 1 to the name.
4E4F
ADD HL,DE 19
Add Register Pair DE (byte 1) to Register Pair HL: HL = the entry's name (byte 5).
4E50
LD C,0FH 0E 0F
Load Register C with 0FH: Register C counts down the 15 columns of the name field.
4E52
LD B,08H 06 08
Load Register B with 08H, the eight characters of the name.
4E54
GOSUB to 509AH to show Register B characters from Register Pair HL without spaces, counting Register C down; Register Pair HL comes back at the extension (byte 13).
4E57
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the extension's first character.
4E58
CP 20H FE 20
Compare Register A against 20H: the Z FLAG is set if there is no extension.
4E5A
LD A,2FH 3E 2F
Load Register A with 2FH, a slash. LD does not change the flags.
4E5C
If the NZ FLAG is set (an extension), GOSUB to 50A4H to show the slash and count the column in Register C.
4E5F
LD B,03H 06 03
Load Register B with 03H, the three characters of the extension.
4E61
GOSUB to 509AH to show them without spaces; Register Pair HL comes back at byte 16.
4E64
LD B,C 41
Load Register B with Register C, the columns left in the name field.
4E65
GOSUB to 5092H to output Register B spaces: the name is padded to 15 columns.
4E68
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, byte 16: the update password code's low byte.
4E69
INC HL 23
Increment Register Pair HL to byte 17 of the entry, the code's high byte.
4E6A
LD D,(HL) 56
Load Register D with the byte at Register Pair HL. Register Pair DE = the update password code.
4E6B
PUSH DE D5
Save Register Pair DE (the update password code) on the stack.
4E6C
INC HL 23
Increment Register Pair HL to byte 18 of the entry, the access password code.
4E6D
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, the access password code's low byte.
4E6E
INC HL 23
Increment Register Pair HL to byte 19 of the entry, the code's high byte.
4E6F
LD D,(HL) 56
Load Register D with the byte at Register Pair HL. Register Pair DE = the access password code.
4E70
LD HL,4296H 21 96 42
Load Register Pair HL with 4296H, the code of a blank password.
4E73
RST 18H DF
RST 18H: compare Register Pair HL (4296H) with Register Pair DE (the access password code); the Z FLAG is set if they are equal.
4E74
If the Z FLAG is set (no access password), JUMP to 4E7BH.
4E76
LD A,41H 3E 41
Load Register A with 41H, the letter A (an access password is set).
4E78
LD (51B9H),A 32 B9 51
Store Register A (A) at 51B9H in the attribute text.
4E7B
POP DE D1
Restore Register Pair DE from the stack: the update password code.
4E7C
RST 18H DF
RST 18H: compare Register Pair HL (4296H) with Register Pair DE (the update password code); the Z FLAG is set if they are equal.
4E7D
If the Z FLAG is set (no update password), JUMP to 4E84H.
4E7F
LD A,55H 3E 55
Load Register A with 55H, the letter U (an update password is set).
4E81
LD (51B8H),A 32 B8 51
Store Register A (U) at 51B8H in the attribute text.
4E84
POP HL E1
Restore Register Pair HL from the stack: the entry's address.
4E85
POP BC C1
Restore Register Pair BC from the stack: Register B = the options, Register C = the names left.
4E86
BIT 0,B CB 40
Test bit 0 of Register B, option A (details on the line).
4E88
If the Z FLAG is set (no option A), JUMP to 4F28H for the next entry; the line count stays on the stack.

4E8BH - DIR A: Show the Details

Register Pair HL = the entry. The rest of the line (the text at 518CH): the end of file as sectors/bytes, the record length, the number of records, the granules, the extent elements, and the attribute text. Records = (EOF / LRL) rounded up; LRL 0 means 256. The EOF middle/high bytes of the FPDE are one higher when the low byte is not 0 (4EA1H corrects that).

4E8B
LD C,01H 0E 01
Load Register C with 01H: with option A there is one file per line.
4E8D
PUSH BC C5
Save Register Pair BC (Register B = the options, Register C = 1) on the stack.
4E8E
PUSH HL E5
Save Register Pair HL (the entry's address) on the stack.
4E8F
INC HL 23
Increment Register Pair HL to byte 1 of the entry.
4E90
INC HL 23
Increment Register Pair HL (the entry) to byte 2.
4E91
INC HL 23
Increment Register Pair HL to byte 3, the EOF low byte.
4E92
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, the EOF low byte.
4E93
LD D,00H 16 00
Load Register D with 00H. Register Pair DE = the EOF low byte.
4E95
INC HL 23
Increment Register Pair HL to byte 4, the record length.
4E96
LD B,D 42
Load Register B with Register D (00H), the record length's high byte.
4E97
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL. Register Pair BC = the record length.
4E98
SET 4,L CB E5
Set bit 4 of Register L: Register Pair HL = byte 20 (entry + 14H), the EOF middle byte.
4E9A
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the EOF middle byte.
4E9B
INC HL 23
Increment Register Pair HL to byte 21, the EOF high byte.
4E9C
PUSH HL E5
Save Register Pair HL (the address of byte 21) on the stack, for 4EE3H.
4E9D
LD H,(HL) 66
Load Register H with the byte at Register Pair HL, the EOF high byte.
4E9E
LD L,A 6F
Load Register L with Register A, the middle byte. Register Pair HL = the EOF's middle and high bytes.
4E9F
LD A,E 7B
Load Register A with Register E, the EOF low byte.
4EA0
OR A B7
OR Register A with itself: the Z FLAG is set if the low byte is 0.
4EA1
If the Z FLAG is set (the file ends on a sector boundary), JUMP to 4EA4H.
4EA3
DEC HL 2B
The low byte is not 0, so the stored value is one too high: decrement Register Pair HL, the number of whole sectors.
4EA4
INC C 0C
Increment Register C, the record length's low byte...
4EA5
DEC C 0D
Decrement Register C again: the Z FLAG is set if the record length is 0.
4EA6
If the NZ FLAG is set (not 0), JUMP to 4EAAH.
4EA8
LD B,01H 06 01
Load Register B with 01H: a record length of 0 means 256, Register Pair BC = 0100H.
4EAA
PUSH DE D5
Save Register Pair DE (the EOF low byte) on the stack.
4EAB
PUSH HL E5
Save Register Pair HL (the whole sectors) on the stack.
4EAC
PUSH BC C5
Save Register Pair BC (the record length) on the stack.
4EAD
If the NZ FLAG is set (the record length is not 256), JUMP to 4EB2H to divide.
4EAF
LD E,L 5D
256: the records are the sectors. Load Register E with Register L, the sectors' low byte.
4EB0
LD L,H 6C
Load Register L with Register H, the sectors' high byte.
4EB1
LD H,D 62
Load Register H with Register D (00H): Register H / L / E = the sectors; Register A is still the EOF low byte, the remainder.
4EB2
If the NZ FLAG is set, GOSUB to 50ADH to divide the bytes in Register H / L / E (sectors and EOF low byte) by the record length in Register C: the quotient in Register H / L / E, the remainder in Register A.
4EB5
OR A B7
OR Register A (the remainder) with itself: the Z FLAG is set if there is none.
4EB6
If the Z FLAG is set (no remainder), JUMP to 4EBCH.
4EB8
INC E 1C
Round up: increment Register E, the quotient's low byte.
4EB9
If the NZ FLAG is set (no carry), JUMP to 4EBCH.
4EBB
INC HL 23
Increment Register Pair HL, the quotient's high bytes: the carry.
4EBC
LD A,H 7C
Load Register A with Register H, the records' high byte.
4EBD
LD B,L 45
Load Register B with Register L, the records' middle byte.
4EBE
LD C,E 4B
Load Register C with Register E. Register A / B / C = the number of records.
4EBF
LD HL,519BH 21 9B 51
Load Register Pair HL with 519BH, the position before the records field (519CH-51A1H).
4EC2
LD DE,5109H 11 09 51
Load Register Pair DE with 5109H, the power-of-ten table from its first entry.
4EC5
GOSUB to 50C8H to write Register A / B / C in the 6 positions from 519CH.
4EC8
POP BC C1
Restore Register Pair BC from the stack: the record length.
4EC9
LD HL,5197H 21 97 51
Load Register Pair HL with 5197H, the position before the record length field.
4ECC
GOSUB to 50BFH to write Register Pair BC in the 3 positions from 5198H.
4ECF
POP BC C1
Restore Register Pair BC from the stack: the whole sectors.
4ED0
LD HL,518CH 21 8C 51
Load Register Pair HL with 518CH, the position before the sectors field.
4ED3
LD DE,510CH 11 0C 51
Load Register Pair DE with 510CH, the table from -10000.
4ED6
GOSUB to 50C7H to write Register Pair BC in the 5 positions from 518DH; Register Pair HL comes back at 5192H.
4ED9
LD (HL),30H 36 30
Store 30H (a 0) at Register Pair HL (5192H), so the byte count that follows keeps its leading zeros.
4EDB
POP BC C1
Restore Register Pair BC from the stack: the EOF low byte.
4EDC
PUSH HL E5
Save Register Pair HL (5192H, the slash position) on the stack.
4EDD
GOSUB to 50BFH to write Register Pair BC in the 3 positions from 5193H.
4EE0
POP HL E1
Restore Register Pair HL from the stack: 5192H.
4EE1
LD (HL),2FH 36 2F
Store 2FH (a slash) at Register Pair HL (5192H), between the sectors and the bytes.

4EE3H - DIR A: Count the Granules and Extent Elements

Walks the extent elements of the FPDE and its FXDEs (FEH, then the DEC of the next entry; FFH ends). Register Pair BC counts the granules (bits 0-4 of each element's second byte, plus 1) and Register Pair DE the elements. An entry with no end mark gives error 2CH.

4EE3
POP HL E1
Restore Register Pair HL from the stack: the address of byte 21, pushed at 4E9CH.
4EE4
INC HL 23
Increment Register Pair HL to byte 22, the first extent element.
4EE5
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H, the granule count.
4EE8
LD D,B 50
Load Register D with Register B (00H), the element count's high byte.
4EE9
LD E,C 59
Load Register E with Register C. Register Pair DE = 0000H, the element count.

ELEMENT LOOP
Register Pair HL = the element, Register Pair BC = the granules, Register Pair DE = the elements.

4EEA
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the element's first byte.
4EEB
CP FEH FE FE
Compare Register A against FEH: the NO CARRY FLAG is set for FEH (a link) or FFH (the end).
4EED
INC HL 23
Increment Register Pair HL to the element's second byte. INC HL does not change the flags.
4EEE
If the NO CARRY FLAG is set (FEH or FFH), JUMP to 4F04H.
4EF0
INC DE 13
Increment Register Pair DE, the element count.
4EF1
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the element's second byte.
4EF2
AND 1FH E6 1F
Mask Register A against 1FH (0001 1111) to keep bits 0-4: the granules minus 1.
4EF4
INC HL 23
Increment Register Pair HL to the next element.
4EF5
INC A 3C
Increment Register A: the number of granules in the element.
4EF6
ADD A,C 81
Add Register C (the count's low byte) to Register A.
4EF7
LD C,A 4F
Load Register C with Register A, the count's new low byte.
4EF8
If the NO CARRY FLAG is set, JUMP to 4EFBH: nothing to carry.
4EFA
INC B 04
Increment Register B, the granule count's high byte: the carry from Register C.
4EFB
BIT 4,L CB 65
Test bit 4 of Register L: bytes 16H-1FH of an entry have it set, so the NZ FLAG means still inside the entry.
4EFD
If the NZ FLAG is set (inside), LOOP back to 4EEAH.
4EFF
LD A,2CH 3E 2C
No end mark in the entry: load Register A with 2CH, error code BAD DIRECTORY DATA.
4F01
JUMP to 4D43H to return error 2CH in Register A.
4F04
If the NZ FLAG is set (FFH, the end), JUMP to 4F0FH.
4F06
LD A,(HL) 7E
FEH: load Register A with the byte at Register Pair HL, the DEC of the FXDE.
4F07
GOSUB to 4D37H to read the FXDE's sector: Register Pair HL = the entry, Register A = its offset in the sector.
4F0A
ADD A,16H C6 16
Add 16H to Register A: the offset of the FXDE's first extent element.
4F0C
LD L,A 6F
Load Register L with Register A: Register Pair HL = that element.
4F0D
LOOP back to 4EEAH for the FXDE's elements at Register Pair HL.
4F0F
GOSUB to 4D32H to read the listed entry's sector again.
4F12
PUSH DE D5
Save Register Pair DE (the element count) on the stack.
4F13
LD HL,51A3H 21 A3 51
Load Register Pair HL with 51A3H, the position before the granules field.
4F16
GOSUB to 50C4H to write Register Pair BC (the granules) in the 4 positions from 51A4H.
4F19
POP BC C1
Restore Register Pair BC from the stack: the element count.
4F1A
LD HL,51A9H 21 A9 51
Load Register Pair HL with 51A9H, the position before the elements field.
4F1D
GOSUB to 50BFH to write Register Pair BC in the 3 positions from 51AAH.
4F20
LD HL,518CH 21 8C 51
Load Register Pair HL with 518CH, the detail text, which runs on into the attribute text and its 03H end.
4F23
GOSUB to 508FH to show the text at Register Pair HL.
4F26
POP HL E1
Restore Register Pair HL from the stack: the entry's address.
4F27
POP BC C1
Restore Register Pair BC from the stack: Register B = the options, Register C = 1.

4F28H - DIR: Next Entry and the Filters

Register Pair HL = the entry. Steps through the 8 entries of each FDE sector and through all the FDE sectors (their number is at 4F35H). An entry is shown if it is an FPDE in use and passes the filters: system files only with S, invisible files only with I (neither test when /ext or U is given), the extension given with /ext, and the updated flag with U. Register C counts the names on a line (4 per line, 1 with A); Register D (on the stack) counts the lines of a page.

4F28
LD A,L 7D
Load Register A with Register L, the entry's offset in the sector.
4F29
ADD A,20H C6 20
Add 20H to Register A: the next entry's offset.
4F2B
LD L,A 6F
Load Register L with Register A: Register Pair HL = the next entry.
4F2C
If the NO CARRY FLAG is set (still in this sector), JUMP to 4F3BH.
4F2E
LD A,(4D33H) 3A 33 4D
Load Register A with the byte at 4D33H, the DEC being listed.
4F31
AND 1FH E6 1F
Mask Register A against 1FH (0001 1111) to keep the FDE sector number.
4F33
INC A 3C
Increment Register A: the next FDE sector number.
4F34
CP 00H FE 00
Self-Modifying Code
Compare Register A against the number of FDE sectors, the operand 4F35H (00H in the file, stored at 5035H: 8 plus HIT byte 1FH).
4F36
If the Z FLAG is set (all sectors done), JUMP to 4FAFH.
4F38
GOSUB to 4D34H to store DEC Register A (entry 0 of the next sector) and read it: Register Pair HL = the entry.
4F3B
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, byte 0 of the entry.
4F3C
AND 90H E6 90
Mask Register A against 90H (1001 0000) to keep bit 7 (an FXDE) and bit 4 (in use).
4F3E
CP 10H FE 10
Compare Register A against 10H: the Z FLAG is set for an FPDE in use.
4F40
If the NZ FLAG is set (free, or an FXDE), JUMP to 4F28H for the next entry.
4F42
LD A,B 78
Load Register A with Register B, the options.
4F43
AND 30H E6 30
Mask Register A against 30H (0011 0000) to keep bit 4 (/ext) and bit 5 (U).
4F45
If the NZ FLAG is set (/ext or U given), JUMP to 4F58H: system and invisible files are not left out.
4F47
BIT 6,(HL) CB 76
Test bit 6 of the byte at Register Pair HL (byte 0): set for a system file.
4F49
If the Z FLAG is set (not a system file), JUMP to 4F4FH.
4F4B
BIT 1,B CB 48
Test bit 1 of Register B, option S (list system files).
4F4D
JUMP to 4F55H with the Z FLAG set if option S is missing.
4F4F
BIT 3,(HL) CB 5E
Test bit 3 of the byte at Register Pair HL (byte 0): set for an invisible file.
4F51
If the Z FLAG is set (visible), JUMP to 4F58H.
4F53
BIT 2,B CB 50
Test bit 2 of Register B, option I (list invisible files).
4F55
If the Z FLAG is set (the option is missing), JUMP to 4F28H for the next entry.
4F58
BIT 4,B CB 60
Test bit 4 of Register B, option /ext (an extension filter).
4F5A
If the Z FLAG is set (no /ext), JUMP to 4F73H.
4F5C
PUSH HL E5
Save Register Pair HL (the entry's address) on the stack.
4F5D
PUSH BC C5
Save Register Pair BC (the options and the names left) on the stack.
4F5E
LD DE,000DH 11 0D 00
Load Register Pair DE with 000DH, the offset of the extension.
4F61
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: HL = the entry's extension (byte 13).
4F62
LD DE,4E0EH 11 0E 4E
Load Register Pair DE with 4E0EH, the extension given with /ext.
4F65
LD B,03H 06 03
Load Register B with 03H, the three characters of an extension.

COMPARE THE EXTENSION
Register Pair DE steps through the filter, Register Pair HL through the entry's extension.

4F67
LD A,(DE) 1A
Load Register A with the byte at Register Pair DE, a character of the filter.
4F68
CP (HL) BE
Compare Register A with the byte at Register Pair HL, the entry's character.
4F69
INC DE 13
Increment Register Pair DE to the filter's next character. INC DE does not change the flags.
4F6A
INC HL 23
Increment Register Pair HL to the entry's next character. INC HL does not change the flags.
4F6B
If the NZ FLAG is set (different), JUMP to 4F6FH.
4F6D
Decrement Register B (the characters left); if it is not 0, LOOP back to 4F67H.
4F6F
POP BC C1
Restore Register Pair BC from the stack: the options and the names left. POP does not change the flags.
4F70
POP HL E1
Restore Register Pair HL from the stack: the entry's address.
4F71
If the NZ FLAG is set (a different extension), JUMP to 4F28H for the next entry.
4F73
BIT 5,B CB 68
Test bit 5 of Register B, option U (updated files only).
4F75
If the Z FLAG is set (no option U), JUMP to 4F7DH to show the file.
4F77
INC HL 23
Increment Register Pair HL to byte 1 of the entry.
4F78
BIT 5,(HL) CB 6E
Test bit 5 of the byte at Register Pair HL (byte 1): the updated flag.
4F7A
DEC HL 2B
Decrement Register Pair HL back to byte 0. DEC HL does not change the flags.
4F7B
If the Z FLAG is set (not updated), JUMP to 4F28H for the next entry.
4F7D
POP DE D1
Restore Register Pair DE from the stack: Register D = the lines left on the page.
4F7E
DEC C 0D
Decrement Register C, the names left on this line.
4F7F
If the NZ FLAG is set (room on the line), JUMP to 4F93H.
4F81
LD C,04H 0E 04
The line is full: load Register C with 04H, the names on the next line.
4F83
GOSUB to 5086H to start a new output line for the next names.
4F86
DEC D 15
Decrement Register D, the lines left on the page.
4F87
If the NZ FLAG is set (room on the page), JUMP to 4F93H.
4F89
LD D,0FH 16 0F
New page: load Register D with 0FH, 15 lines.
4F8B
GOSUB to 506BH to wait for ENTER (or BREAK) at the end of the page.
4F8E
BIT 3,B CB 58
Test bit 3 of Register B, option P (printing).
4F90
If the Z FLAG is set (not printing), GOSUB to 4FC7H to show the column headings again (only with option A).
4F93
JUMP to 4E11H to show the file at Register Pair HL.

4F96H - Ask for a Diskette

Register Pair HL = the word SYSTEM or TARGET. Shows MOUNT, the word, and DISKETTE ON DRIVE d (ENTER) (the drive digit is at 5132H), then waits for ENTER.

4F96
PUSH HL E5
Save Register Pair HL (the word) on the stack.
4F97
LD HL,5118H 21 18 51
Load Register Pair HL with 5118H, the message MOUNT and a space.
4F9A
GOSUB to SYS0 4467H to display the message at Register Pair HL.
4F9D
POP HL E1
Restore Register Pair HL from the stack: the word.
4F9E
GOSUB to SYS0 4467H to display the word at Register Pair HL.
4FA1
LD HL,511FH 21 1F 51
Load Register Pair HL with 511FH, the rest of the message: DISKETTE ON DRIVE d (ENTER).
4FA4
GOSUB to SYS0 4467H to display the message at Register Pair HL.

WAIT FOR ENTER
Register A = each key read.

4FA7
GOSUB to ROM 0049H ($KEY), which waits for a key and returns it in Register A.
4FAA
CP 0DH FE 0D
Compare Register A (the key) against 0DH, ENTER.
4FAC
If the NZ FLAG is set (not ENTER), LOOP back to 4FA7H.
4FAE
RET C9
RETURN with Register A = 0DH, the ENTER key that was pressed.

4FAFH - DIR: End of the Listing

Also the end of FREE (4FB8H). On the screen the listing waits for ENTER unless at least 4 lines are left; on the printer two more lines are fed.

4FAF
GOSUB to 5086H to end the last output line of the listing.
4FB2
POP AF F1
Restore Register Pair AF from the stack: Register A = the lines left on the page (the Register D pushed as DE).
4FB3
CP 04H FE 04
Compare Register A against 04H: the CARRY FLAG is set if fewer than 4 lines are left.
4FB5
If the CARRY FLAG is set, GOSUB to 506BH to wait for ENTER (or BREAK).
4FB8
LD A,(50A8H) 3A A8 50
Load Register A with the byte at 50A8H, the operand of the CALL at 50A7H: 33H for the display, 3BH for the printer.
4FBB
CP 3BH FE 3B
Compare Register A against 3BH: the Z FLAG is set when printing.
4FBD
If the Z FLAG is set (printing), GOSUB to 5086H for an empty line; 5086H keeps the flags.
4FC0
If the Z FLAG is set (printing), GOSUB to 5086H for another.
4FC3
XOR A AF
Load Register A with 00H (XOR A with itself): no error.
4FC4
JUMP to 4D43H to end DIR or FREE with Register A = 00H.

4FC7H - DIR A: Column Headings

Only with the A option: 20 spaces and the headings at 51BCH. Counts one line in Register D.

4FC7
BIT 0,B CB 40
Test bit 0 of Register B, option A (the headings are only for it).
4FC9
RET Z C8
If the Z FLAG is set (no option A in Register B), RETURN.
4FCA
PUSH HL E5
Save Register Pair HL (the caller's entry address) on the stack.
4FCB
PUSH BC C5
Save Register Pair BC (the options and the names left) on the stack.
4FCC
DEC D 15
Decrement Register D, the lines left on the page: the headings take one.
4FCD
LD B,14H 06 14
Load Register B with 14H, twenty spaces before the headings.
4FCF
GOSUB to 5092H to output Register B (20) spaces before the headings.
4FD2
LD HL,51BCH 21 BC 51
Load Register Pair HL with 51BCH, the column headings.
4FD5
GOSUB to 508FH to show the text at Register Pair HL.
4FD8
POP BC C1
Restore Register Pair BC from the stack: the options and the names left.
4FD9
POP HL E1
Restore Register Pair HL from the stack: the caller's entry address.
4FDA
RET C9
RETURN with Register D one lower: the headings took a line.

4FDBH - Show the Drive Line

Used by DIR and FREE with Register C = the drive. Selects the drive (error 20H for a drive past option AL, 08H if there is no diskette) and shows: DRIVE d, the diskette name and date (GAT D0H-DFH), the number of tracks (430DH), the free FDEs (HIT bytes that are 00H, counted over the 8 plus extra FDE sectors of each of the 8 entry positions), and the free granules (clear bits in the GAT, granules per lump from 430FH, lumps from 430BH). Also stores the number of FDE sectors at 4F35H. Returns the Z FLAG, or the NZ FLAG with the error in Register A.

4FDB
LD A,C 79
Load Register A with Register C, the drive number to select.
4FDC
GOSUB to SYS0 47ECH to select drive Register A and check that a diskette is in it.
4FDF
RET NZ C0
If the NZ FLAG is set (an error), RETURN with the error in Register A.
4FE0
PUSH BC C5
Save Register Pair BC (the caller's options and drive) on the stack.
4FE1
LD B,00H 06 00
Load Register B with 00H: Register Pair BC = the drive.
4FE3
LD HL,5153H 21 53 51
Load Register Pair HL with 5153H, the position before the drive number field.
4FE6
GOSUB to 50BFH to write Register Pair BC in the 3 positions from 5154H.
4FE9
LD A,(430DH) 3A 0D 43
Load Register A with the byte at 430DH, the selected drive's number of tracks.
4FEC
LD C,A 4F
Load Register C with Register A, the selected drive's number of tracks.
4FED
LD B,00H 06 00
Load Register B with 00H. Register Pair BC = the tracks.
4FEF
LD HL,516CH 21 6C 51
Load Register Pair HL with 516CH, the position before the tracks field.
4FF2
GOSUB to 50BFH to write Register Pair BC in the 3 positions from 516DH.
4FF5
XOR A AF
Load Register A with 00H (XOR A with itself): directory sector 0, the GAT.
4FF6
GOSUB to SYS0 490AH to read directory sector Register A into 4200H; Register Pair HL = its first byte.
4FF9
If the NZ FLAG is set (a read error), JUMP to 5056H to return it.
4FFB
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H, the count of free granules.

LUMP LOOP
Register Pair HL = the lump's GAT byte, Register Pair BC = the free granules.

4FFE
LD E,(IY-71H) FD 5E 8F
Load Register E with the byte at Index Register IY-71H (430FH), the granules per lump.
5001
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the lump's GAT byte (a set bit is an allocated granule).
5002
INC HL 23
Increment Register Pair HL to the next lump's byte.

GRANULE LOOP
Register A shifts right, Register E counts the granules of the lump.

5003
RRCA 0F
Rotate Register A right: the next granule's bit goes into the CARRY FLAG.
5004
If the CARRY FLAG is set (allocated), JUMP to 5007H.
5006
INC BC 03
Free: increment Register Pair BC, the count of free granules.
5007
DEC E 1D
Decrement Register E, the granules left in the lump.
5008
If the NZ FLAG is set (more granules), LOOP back to 5003H.
500A
LD A,L 7D
Load Register A with Register L, the next lump's number (Register Pair HL = 4200H + lump).
500B
CP (IY-75H) FD BE 8B
Compare Register A with the byte at Index Register IY-75H (430BH), the number of lumps: the CARRY FLAG is set while lumps remain.
500E
If the CARRY FLAG is set, LOOP back to 4FFEH for the next lump.
5010
LD HL,5180H 21 80 51
Load Register Pair HL with 5180H, the position before the granules field.
5013
GOSUB to 50C4H to write Register Pair BC (the free granules) in the 4 positions from 5181H.
5016
LD HL,42D0H 21 D0 42
Load Register Pair HL with 42D0H, the diskette name in the GAT (bytes D0H-D7H).
5019
LD DE,5159H 11 59 51
Load Register Pair DE with 5159H, the name field of the drive line.
501C
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H, the eight characters of the name.
501F
LDIR ED B0
Copy Register Pair BC (8) bytes from Register Pair HL (42D0H) to Register Pair DE (5159H); Register Pair HL ends at 42D8H, the date.
5021
LD DE,5163H 11 63 51
Load Register Pair DE with 5163H, the date field of the drive line.
5024
LD C,08H 0E 08
Load Register C with 08H: Register Pair BC = 0008H, the eight characters of the date.
5026
LDIR ED B0
Copy Register Pair BC (8) bytes from Register Pair HL (42D8H, GAT D8H-DFH) to Register Pair DE (5163H); Register Pair BC ends at 0000H.
5028
LD A,01H 3E 01
Load Register A with 01H: directory sector 1, the HIT.
502A
GOSUB to SYS0 490AH to read directory sector Register A into 4200H; Register Pair HL = its first byte.
502D
If the NZ FLAG is set (a read error), JUMP to 5056H to return it.

ENTRY POSITION LOOP
Register Pair HL = the HIT byte, Register Pair BC = the free FDEs (0000H after the LDIR), Register E counts the FDE sectors.

502F
LD A,(421FH) 3A 1F 42
Load Register A with the byte at 421FH, HIT byte 1FH: the number of extra FDE sectors.
5032
ADD A,08H C6 08
Add 08H to Register A: the number of FDE sectors.
5034
LD E,A 5F
Load Register E with Register A, the FDE sectors to count.
5035
LD (4F35H),A 32 35 4F
Self-Modifying Code
Store Register A (the number of FDE sectors) at 4F35H, the operand of the CP at 4F34H.
5038
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, a HIT byte (00H = a free FDE).
5039
OR A B7
OR Register A with itself: the Z FLAG is set for a free FDE.
503A
INC HL 23
Increment Register Pair HL to the next HIT byte. INC HL does not change the flags.
503B
If the NZ FLAG is set (in use), JUMP to 503EH.
503D
INC BC 03
Free: increment Register Pair BC, the count of free FDEs.
503E
DEC E 1D
Decrement Register E, the FDE sectors left in this entry position.
503F
If the NZ FLAG is set (more), LOOP back to 5038H.
5041
LD A,L 7D
Load Register A with Register L, the HIT byte's offset.
5042
ADD A,1FH C6 1F
Add 1FH to Register A, to round up to the next 32-byte boundary.
5044
AND E0H E6 E0
Mask Register A against E0H (1110 0000): the next entry position's first HIT byte.
5046
LD L,A 6F
Load Register L with Register A: Register Pair HL = that byte.
5047
If the NZ FLAG is set (not past the last of the 8 positions), LOOP back to 502FH.
5049
LD HL,5176H 21 76 51
Load Register Pair HL with 5176H, the position before the FDEs field.
504C
GOSUB to 50BFH to write Register Pair BC (the free FDEs) in the 3 positions from 5177H.
504F
LD HL,514EH 21 4E 51
Load Register Pair HL with 514EH, the drive line.
5052
GOSUB to 508FH to show the text at Register Pair HL.
5055
XOR A AF
Load Register A with 00H (XOR A with itself), which also sets the Z FLAG: no error.
5056
POP BC C1
Restore Register Pair BC from the stack: the caller's options and drive.
5057
RET C9
RETURN with the Z FLAG, or the NZ FLAG and the error in Register A.

5058H - P Option: Output to the Printer

Tests the character at Register Pair HL for P and steps past it in any case. For P it makes 50A7H call the ROM printer routine (003BH) instead of the display routine (0033H), makes 508FH jump to the SYS0 print routine (446AH) instead of 4467H, sets bit 3 of Register B, and returns the Z FLAG with Register A = the next character. Otherwise the NZ FLAG with Register A = the character.

5058
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the character.
5059
CP 50H FE 50
Compare Register A against 50H, the letter P.
505B
INC HL 23
Increment Register Pair HL past the character. INC HL does not change the flags.
505C
RET NZ C0
If the NZ FLAG is set (not P), RETURN with the character in Register A.
505D
LD A,3BH 3E 3B
Load Register A with 3BH, the low byte of the ROM printer routine 003BH.
505F
LD (50A8H),A 32 A8 50
Self-Modifying Code
Store Register A (3BH) at 50A8H, the operand of the CALL at 50A7H: it becomes CALL 003BH, the printer.
5062
LD A,6AH 3E 6A
Load Register A with 6AH, the low byte of the SYS0 print routine 446AH.
5064
LD (5090H),A 32 90 50
Self-Modifying Code
Store Register A (6AH) at 5090H, the operand of the JP at 508FH: it becomes JP 446AH.
5067
SET 3,B CB D8
Set bit 3 of Register B, option P (the output goes to the printer).
5069
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character.
506A
RET C9
RETURN with the Z FLAG from the compare and the next character in Register A.

506BH - Wait at the End of a Page

Not while a chain file is running (bit 5 of 4369H) and not when printing. Shows ? and waits for ENTER (the listing goes on) or BREAK (DOS READY through 402DH).

506B
BIT 5,(IY-17H) FD CB E9 6E
Test bit 5 of the byte at Index Register IY-17H (4369H): set while chaining.
506F
RET NZ C0
If the NZ FLAG is set (chaining), RETURN: no stop.
5070
LD A,(50A8H) 3A A8 50
Load Register A with the byte at 50A8H, the operand of the CALL at 50A7H.
5073
CP 33H FE 33
Compare Register A against 33H: the Z FLAG is set when the output is the display (CALL 0033H).
5075
RET NZ C0
If the NZ FLAG is set (printing), RETURN: no stop.
5076
LD A,3FH 3E 3F
Load Register A with 3FH, a question mark: the page prompt.
5078
GOSUB to 50A5H to output the character in Register A.

WAIT FOR ENTER OR BREAK
Register A = keyboard row 6.

507B
LD A,(3840H) 3A 40 38
Load Register A with the byte at 3840H, keyboard row 6 (ENTER, CLEAR, BREAK and the arrows).
507E
AND 05H E6 05
Mask Register A against 05H (0000 0101) to keep ENTER (bit 0) and BREAK (bit 2).
5080
If the Z FLAG is set (neither is pressed), LOOP back to 507BH.
5082
RRCA 0F
Rotate Register A right: bit 0 (ENTER) goes into the CARRY FLAG.
5083
If the NO CARRY FLAG is set (BREAK), JUMP to SYS0 402DH: DOS READY. ENTER falls into 5086H to end the line.

5086H - Output Routines

5086H ends a line (a space, then a carriage return). 508FH shows the message at Register Pair HL. 5092H outputs Register B spaces. 509AH outputs Register B characters from Register Pair HL, leaving out spaces, and counts each one shown down in Register C. 50A4H counts a column and 50A5H outputs the character in Register A, through ROM 0033H (display) or 003BH (printer). All of them keep Register Pair AF's flags and Register Pair DE.

5086
LD A,20H 3E 20
Load Register A with 20H, a space, before the line ends.
5088
GOSUB to 50A5H to output the space in Register A.
508B
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return to end the line.
508D
JUMP to 50A5H to output the carriage return in Register A and return from there.
508F
Self-Modifying Code
JUMP to SYS0 4467H to display the message at Register Pair HL. With P the operand 5090H is 6AH (stored at 5064H): JP 446AH, which prints it.

SPACES
Register B counts the spaces.

5092
LD A,20H 3E 20
Load Register A with 20H, a space, to output.
5094
GOSUB to 50A5H to output the space in Register A.
5097
Decrement Register B (the spaces left); if it is not 0, LOOP back to 5092H.
5099
RET C9
RETURN with Register B = 00H after the spaces.

CHARACTERS WITHOUT SPACES
Register Pair HL steps through the text, Register B counts, Register C counts the columns used.

509A
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character.
509B
CP 20H FE 20
Compare Register A against 20H: the Z FLAG is set for a space.
509D
INC HL 23
Increment Register Pair HL to the next character. INC HL does not change the flags.
509E
If the NZ FLAG is set (not a space), GOSUB to 50A4H to output Register A and count the column in Register C.
50A1
Decrement Register B (the characters left); if it is not 0, LOOP back to 509AH.
50A3
RET C9
RETURN with Register Pair HL after the characters.
50A4
DEC C 0D
Decrement Register C, the columns left in the field.
50A5
PUSH DE D5
Save Register Pair DE on the stack; the ROM output routine may change it.
50A6
PUSH AF F5
Save Register Pair AF (the character and the flags) on the stack.
50A7
Self-Modifying Code
GOSUB to ROM 0033H ($DSP) to display the character in Register A. With P the operand 50A8H is 3BH (stored at 505FH): CALL 003BH, the printer.
50AA
POP AF F1
Restore Register Pair AF from the stack: the character and the caller's flags.
50AB
POP DE D1
Restore Register Pair DE from the stack: the caller's value.
50AC
RET C9
RETURN with Register Pair AF and Register Pair DE unchanged.

50ADH - Divide 24 Bits by 8 Bits

Register H / L / E divided by Register C: the quotient is left in Register H / L / E, the remainder in Register A.

50AD
LD B,18H 06 18
Load Register B with 18H, the 24 bits of the dividend.
50AF
XOR A AF
Load Register A with 00H (XOR A with itself): the remainder starts at 0.

DIVIDE LOOP
Register A / H / L / E shift left together, Register B counts the bits.

50B0
SLA E CB 23
Shift Register E left: bit 7 goes into the CARRY FLAG, bit 0 becomes 0 (the quotient bit).
50B2
ADC HL,HL ED 6A
Add Register Pair HL to itself with the CARRY FLAG: Register Pair HL shifts left, taking Register E's bit 7.
50B4
RLA 17
Rotate Register A left through the CARRY FLAG: Register H's bit 7 goes into the remainder.
50B5
If the CARRY FLAG is set (the remainder passed 255, so it is bigger than Register C), JUMP to 50BAH.
50B7
CP C B9
Compare Register A (the remainder) against Register C (the divisor): the CARRY FLAG is set if it is lower.
50B8
If the CARRY FLAG is set (below the divisor), JUMP to 50BCH.
50BA
SUB C 91
Subtract Register C (the divisor) from Register A, the remainder.
50BB
INC E 1C
Increment Register E: the new quotient bit in Register E's bit 0 is 1.
50BC
Decrement Register B (the bits left); if it is not 0, LOOP back to 50B0H.
50BE
RET C9
RETURN with the quotient in Register H / L / E and the remainder in Register A.

50BFH - Put a Number Into a Text

Writes a number as decimal digits after Register Pair HL, one position per table entry plus the units, and returns Register Pair HL after the last digit. 50BFH: Register Pair BC in 3 positions (table from 5112H, -100). 50C4H: Register Pair BC in 4 positions (from 510FH, -1000). 50C7H: Register A = 0, then 50C8H: the 24-bit value Register A / B / C with the table at Register Pair DE. Each digit is found by adding the negative power of ten until it goes below zero. A leading zero is shown as a space when the position before it is not a digit; the units digit is always shown. Returns Register Pair BC = the units.

50BF
LD DE,5112H 11 12 51
Load Register Pair DE with 5112H: three positions, starting with the -100 entry.
50C2
JUMP to 50C7H with Register Pair DE = 5112H, the -100 entry.
50C4
LD DE,510FH 11 0F 51
Load Register Pair DE with 510FH: four positions, starting with the -1000 entry.
50C7
XOR A AF
Load Register A with 00H (XOR A with itself): the value's high byte.

DIGIT LOOP
Register A / H / L = the value while a digit is found, Register B = the digit, Register Pair DE and Register C = the power of ten.

50C8
PUSH DE D5
Save Register Pair DE (the table entry) on the stack.
50C9
PUSH HL E5
Save Register Pair HL (the text position) on the stack.
50CA
PUSH BC C5
Save Register Pair BC (the value's low 16 bits) on the stack.
50CB
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = the table entry.
50CC
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, the power's low byte.
50CD
INC HL 23
Increment Register Pair HL to the middle byte.
50CE
LD D,(HL) 56
Load Register D with the byte at Register Pair HL, the middle byte. Register Pair DE = the power's low 16 bits.
50CF
INC HL 23
Increment Register Pair HL to the power's high byte in the table entry.
50D0
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the power's high byte.
50D1
LD B,2FH 06 2F
Load Register B with 2FH, one below the character 0: the digit is counted up from there.
50D3
POP HL E1
Restore Register Pair HL from the stack: the value's low 16 bits.
50D4
INC B 04
Increment Register B, the digit being counted.
50D5
ADD HL,DE 19
Add Register Pair DE (the power's low 16 bits) to Register Pair HL.
50D6
ADC A,C 89
Add Register C (the power's high byte) and the CARRY FLAG to Register A: the CARRY FLAG is set while the value is still 0 or more.
50D7
If the CARRY FLAG is set, LOOP back to 50D4H.
50D9
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
50DA
SBC HL,DE ED 52
Subtract Register Pair DE from Register Pair HL: undo the last addition.
50DC
SBC A,C 99
Subtract Register C and the CARRY FLAG from Register A: Register A / H / L = the value left.
50DD
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (at the Stack Pointer SP): HL = the text position, and the value's low 16 bits are saved.
50DE
PUSH AF F5
Save Register Pair AF (Register A = the value's high byte) on the stack.
50DF
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the character before this position.
50E0
SUB 30H D6 30
Subtract 30H from Register A: the digits 0-9 become 00H-09H.
50E2
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG is set if it is a digit.
50E4
INC HL 23
Increment Register Pair HL to this position. INC HL does not change the flags.
50E5
LD (HL),B 70
Store Register B (the digit) at Register Pair HL.
50E6
If the CARRY FLAG is set (after a digit), JUMP to 50EFH: the digit stays.
50E8
LD A,B 78
Load Register A with Register B, the digit, to test it for 0.
50E9
CP 30H FE 30
Compare Register A against 30H, the character 0.
50EB
If the NZ FLAG is set (not 0), JUMP to 50EFH.
50ED
LD (HL),20H 36 20
A leading 0: store 20H (a space) at Register Pair HL instead.
50EF
LD A,E 7B
Load Register A with Register E, the low byte of the power just used.
50F0
CP F6H FE F6
Compare Register A against F6H: the Z FLAG is set for -10, the last entry before the units.
50F2
If the Z FLAG is set (Register E = F6H, the -10 entry), JUMP to 50FCH.
50F4
POP AF F1
Restore Register Pair AF from the stack: Register A = the value's high byte.
50F5
POP BC C1
Restore Register Pair BC from the stack: the value's low 16 bits.
50F6
POP DE D1
Restore Register Pair DE from the stack: the table entry.
50F7
INC DE 13
Increment Register Pair DE past the entry's low byte.
50F8
INC DE 13
Increment Register Pair DE past the middle byte.
50F9
INC DE 13
Increment Register Pair DE past the high byte: the next entry.
50FA
LOOP back to 50C8H for the next digit with Register Pair DE = the next entry.
50FC
POP DE D1
Restore Register Pair DE from the stack, discarding the value's high byte (Register Pair AF).
50FD
POP BC C1
Restore Register Pair BC from the stack: the units, 0-9.
50FE
POP DE D1
Restore Register Pair DE from the stack, discarding the table entry.
50FF
INC HL 23
Increment Register Pair HL to the units position.
5100
LD A,C 79
Load Register A with Register C, the units value (0-9).
5101
ADD A,30H C6 30
Add 30H to Register A: the units as the characters 0-9.
5103
LD (HL),A 77
Store Register A (the digit) at Register Pair HL.
5104
INC HL 23
Increment Register Pair HL past the number, for the caller.
5105
RET C9
RETURN with Register Pair HL after the last digit and Register Pair BC = the units.

5106H - Unreferenced Code

Nothing reaches 5106H.

5106
POP AF F1
Restore Register Pair AF from the stack, discarding a word; unreferenced code.
5107
POP AF F1
Restore Register Pair AF from the stack, discarding another word; unreferenced code.
5108
RET C9
RETURN; unreferenced, like the two POPs before it.

5109H - Powers of Ten

Three bytes each (low, middle, high), used by 50C8H. All but the first are negative. The first entry is +100000 instead of -100000, so the first of the six record positions (4EC5H) is always blank: adding it never carries, the digit found is 0, and the position before it is a space.

5109-510B
DEFB A0H, 86H, 01H A0 86 01
A0H 86H 01H: +100000 (0186A0H), used only by 4EC5H for the first records position.
510C-510E
DEFB F0H, D8H, FFH F0 D8 FF
F0H D8H FFH: -10000, the first entry for the sectors (4ED3H).
510F-5111
DEFB 18H, FCH, FFH 18 FC FF
18H FCH FFH: -1000, the first entry for four positions (50C4H).
5112-5114
DEFB 9CH, FFH, FFH 9C FF FF
9CH FFH FFH: -100, the first entry for three positions (50BFH).
5115-5117
DEFB F6H, FFH, FFH F6 FF FF
F6H FFH FFH: -10. After this entry the units are stored directly (50EFH tests the F6H).

5118H - Messages

5118-511E
DEFM "MOUNT ", 03H 4D 4F 55 4E 54 20 03
The message MOUNT and a space, ended by 03H (no new line), shown by 4F97H.
511F-513C
DEFM " DISKETTE ON DRIVE 0 (ENTER)", 0DH 20 44 49 53 4B 45 54 54 45 20 4F 4E 20 44 52 49 56 45 20 30 20 20 28 45 4E 54 45 52 29 0D
The message DISKETTE ON DRIVE 0 (ENTER) and a carriage return, shown by 4FA1H; 4DEDH stores the drive digit at 5132H.
513D-5143
DEFM "SYSTEM", 03H 53 59 53 54 45 4D 03
The word SYSTEM, ended by 03H, put into the MOUNT message by 4D44H.
5144-514A
DEFM "TARGET", 03H 54 41 52 47 45 54 03
The word TARGET, ended by 03H, put into the MOUNT message by 4DF0H.
514B-514D
DEFB 1CH, 1FH, 03H 1C 1F 03
1CH 1FH 03H: home the cursor, clear to the end of the screen, end of text; sent by 4DD7H.

514EH - The Drive Line

Filled in and shown by 4FDBH.

514E-5158
DEFM "DRIVE 000 " 44 52 49 56 45 20 30 30 30 20 20
DRIVE 000 and two spaces: the drive number goes into 5154H-5156H (4FE6H).
5159-5162
DEFM "XXXXXXXX " 58 58 58 58 58 58 58 58 20 20
XXXXXXXX and two spaces: the diskette name (GAT D0H-D7H) goes into 5159H-5160H (501FH).
5163-516C
DEFM "MM/DD/YY " 4D 4D 2F 44 44 2F 59 59 20 20
MM/DD/YY and two spaces: the diskette date (GAT D8H-DFH) goes into 5163H-516AH (5026H).
516D-5176
DEFM "000 TRKS " 30 30 30 20 54 52 4B 53 20 20
000 TRKS and two spaces: the number of tracks goes into 516DH-516FH (4FF2H).
5177-5180
DEFM "000 FDES " 30 30 30 20 46 44 45 53 20 20
000 FDES and two spaces: the free FDEs go into 5177H-5179H (504CH).
5181-518B
DEFM "0000 GRANS", 0DH 30 30 30 30 20 47 52 41 4E 53 0D
0000 GRANS and a carriage return: the free granules go into 5181H-5184H (5013H).

518CH - The DIR A Detail Line

Filled in and shown by 4E8BH-4F23H after the name.

518C-5197
DEFM " 000000000 " 20 30 30 30 30 30 30 30 30 30 20 20
A space, 000000000 and two spaces: the EOF, sectors in 518DH-5191H, a slash at 5192H, bytes in 5193H-5195H.
5198-51A3
DEFM "000 000000 " 30 30 30 20 30 30 30 30 30 30 20 20
000 000000 and two spaces: the record length in 5198H-519AH, the records in 519CH-51A1H.
51A4-51A9
DEFM "0000 " 30 30 30 30 20 20
0000 and two spaces: the granules, written by 4F16H.
51AA-51AE
DEFM "000 " 30 30 30 20 20
000 and two spaces: the extent elements, written by 4F1DH.
51AF-51BB
DEFM "SIUEC....AUL", 03H 53 49 55 45 43 2E 2E 2E 2E 41 55 4C 03
The attributes SIUEC....AUL and 03H, rebuilt for every file by 4E11H: S, I, U, E, C, four periods, U and A for the passwords (51B8H, 51B9H), and the access level digit at 51BAH.

51BCH - The DIR A Headings

Shown by 4FC7H after 20 spaces.

51BC-51E6
DEFM "EOF LRL RECS GRANS EXTS SIUEC....UAL", 0DH 45 4F 46 20 20 20 20 4C 52 4C 20 20 20 52 45 43 53 20 47 52 41 4E 53 20 45 58 54 53 20 20 53 49 55 45 43 2E 2E 2E 2E 55 41 4C 0D
The column headings EOF LRL RECS GRANS EXTS SIUEC....UAL and a carriage return.
51E7
DEFB 00H 00
00H, the last byte of the file; nothing in SYS8 reads or writes it.