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

Page Customization

Introduction/Summary

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

SYS8/SYS is the overlay that carries out the library commands DIR and FREE. Its five load records fill 4D00H-51E7H of the overlay area (1,256 bytes) and its transfer address is 4D00H. SYS1/SYS runs it with RST 28H code 2AH (DIR, directory slot 0AH, function 1) or 4AH (FREE, function 2); the dispatcher at 4D00H gives error 2AH for any other code.

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

DIR and FREE

FREE (4D0DH), optionally with P for the printer, shows the drive line (4FDBH) of every drive from 0 up to the last one allowed by option AL, leaving out drives without a diskette, and waits after every 13 lines.

DIR (4D50H) takes [:][$][d] and the options A, S, I, U, P and /ext, separated by commas or spaces; the drive defaults to option AN (42C0H). Register B collects the options as bits: 0 A, 1 S, 2 I, 3 P, 4 /ext, 5 U, 6 $. With $ the operator is asked to mount the diskette (Mount TARGET Diskette In Drive d), and for drive 0 to put the system diskette back at the end (the opcode at 4D47H is made a CALL).

The listing (4DD5H) clears the screen, shows the drive line and walks every entry of every FDE sector (8 plus HIT byte 1FH sectors, the count stored at 4F35H). An FPDE in use is shown when it passes the filters (4F28H): system files only with S and invisible files only with I (these two tests are skipped when /ext or U is given), the extension given with /ext, and the updated flag with U. Without A four names go on a line, each padded to 15 columns; with A each file has a line of details (4E8BH) under column headings. The screen listing waits with a question mark after each page (506BH): ENTER goes on, BREAK goes to DOS READY; it does not wait while a chain file supplies the keys or when printing.

P (5058H) patches the output: the CALL at 50A7H becomes CALL 003BH (the ROM printer routine) and the JP at 508FH becomes JP 446AH (the SYS0/SYS print routine).

Output Lines

The numbers are written into the texts by 50BFH with a table of negative powers of ten (5109H); a leading zero becomes a space unless the position before it holds a digit. The first table entry is +100000, so the first of the six record positions always stays blank.

LineFields
Drive line 514EHDrive number 5154H-5156H, diskette name 5159H-5160H (GAT D0H-D7H), date 5163H-516AH (GAT D8H-DFH), tracks 516DH-516FH (4283H), free FDEs 5177H-5179H (HIT bytes 00H), free granules 5181H-5184H (clear GAT bits)
Detail line 518CHEOF as sectors 518DH-5191H / bytes 5193H-5195H, record length 5198H-519AH, records 519CH-51A1H, granules 51A4H-51A7H, extent elements 51AAH-51ACH, attributes 51AFH-51BAH
Headings 51BCHEof, Lrl, Recs, Grans, Exts and the attribute letters SIUEC....UAL, after 20 spaces

Attribute letters: S system file, I invisible, U updated, E may not be extended (ASE=N), C CLOSE keeps the space beyond EOF (ASC=N), then U update password set, A access password set, and the access level 0-7. A period stands for a letter not set.

Variables

Memory Outside SYS8/SYS

Address
Size
Contents
4281H
1 byte
Lumps on the Diskette
PDRIVE byte 1 of the selected drive, read as IY+01H by 500BH: the GAT bytes counted for the free granules.
4283H
1 byte
Tracks
PDRIVE byte 3 of the selected drive, shown in the drive line (4FE9H).
4285H
1 byte
Granules per Lump
PDRIVE byte 5 of the selected drive, read as IY+05H by 4FFEH: the bits tested in each GAT byte.
4289H
1 byte
System Flags
Bit 5 is set while a chain file supplies the keys; the page wait is skipped then (506BH, IY+09H).
42C0H
1 byte
Option AN
The default drive of DIR (4D50H).
4300H-43FFH
256 bytes
Sector Buffer
The GAT (4FF6H: lump bytes from 4300H, the diskette name 43D0H-43D7H and date 43D8H-43DFH), the HIT (502AH: HIT byte 1FH at 431FH) and the FDE sectors (4D37H).
48D5H
1 byte
Directory Sector Held
The number of the directory sector in 4300H, which SYS0/SYS 48D4H tests before reading (4D37H).

SYS8/SYS Variables

Address
Size
Contents
4E0EH-4E10H
3 bytes
Extension Filter
Three spaces as loaded; /ext stores up to three characters (4DCDH), compared with bytes 13-15 of each entry (4F67H).
5132H
1 byte
Drive Digit
The drive in the Mount message, stored by 4DEDH.
514EH-518BH
62 bytes
Drive Line
Filled in by 4FDBH-504CH and shown by 5052H.
518CH-51BBH
48 bytes
Detail Line
Filled in for DIR A by 4E15H-4F1DH and shown by 4F23H.

Operands Changed at Run Time

Address
Size
Contents
4D33H
1 byte
DEC Being Listed
The operand of the LD A at 4D32H, stored by 4D34H.
4D47H
1 byte
Exit Opcode
21H (LD HL) as loaded; 4DE7H stores CDH (CALL) for DIR $ on drive 0, so the system diskette is asked for at the end.
4F35H
1 byte
FDE Sector Count
The operand of the CP at 4F34H: 8 plus HIT byte 1FH, stored by 5035H.
5090H
1 byte
Message Routine Low Byte
The operand of the JP at 508FH: 67H (4467H, display) as loaded, 6AH (446AH, print) for P (5064H).
50A8H
1 byte
Character Routine Low Byte
The operand of the CALL at 50A7H: 33H (ROM 0033H, display) as loaded, 3BH (ROM 003BH, printer) for P (505FH). Read by 4FB8H and 5070H to tell which.

Outside Routines Called

AddressContents
0033H, 003BHROM: display or print the character in Register A (50A7H).
0049HROM: wait for a key (4FA7H, 507BH).
402DHDOS READY, reached with BREAK at a page wait (507FH).
4409HSYS0/SYS: the DOS error exit (4D4DH).
4467H, 446AHSYS0/SYS: display or print a message (4F9AH, 508FH).
4791HSYS0/SYS: select a drive and test for a diskette (4FDCH).
48AFH, 48D4HSYS0/SYS: read a directory sector, point to an entry by its DEC (4FF6H, 502AH, 4D37H).
4BC2H, 4BC5HSYS0/SYS: the dispatcher's CALL to 4D00H and its return address, through which DIR and FREE return to 4408H.
4C7AHSYS0/SYS: end of line or separator test (4D85H).

Disassembly

4D00H - Function Dispatcher

SYS8/SYS (directory slot 0AH) is loaded by the SYS0/SYS RST 28H dispatcher into 4D00H-51E7H and entered at 4D00H by the CALL at 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. Both commands return through the dispatcher's return address 4BC5H to SYS0/SYS 4408H.

4D00
LD IY,4280H FD 21 80 42
Load Index Register IY with 4280H, the base for the selected drive's PDRIVE values: IY+01H is 4281H (the lumps), IY+05H is 4285H (the granules per lump) and IY+09H is 4289H (the system flags).
4D04
CP 2AH FE 2A
Compare Register A, the RST 28H code passed by SYS1/SYS, against 2AH, the code of function 1 (DIR); the Z FLAG is set for DIR.
4D06
If the Z FLAG is set (Register A = 2AH, DIR), JUMP to 4D50H with Register Pair HL = the command line after DIR.
4D08
CP 4AH FE 4A
Compare Register A, the RST 28H code, against 4AH, the code of function 2 (FREE); the Z FLAG is set for FREE.
4D0A
LD A,2AH 3E 2A
Load Register A with 2AH, the error code ILLEGAL DOS FUNCTION, in case the code was neither; LD does not change the flags.
4D0C
RET NZ C0
If the NZ FLAG is set (Register A was neither 2AH nor 4AH), RETURN through 4BC5H to SYS0/SYS 4408H 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 (the command line after FREE) for P, the printer option; Register A comes back with the next character and Register Pair HL past the one tested.
4D10
CP 0DH FE 0D
Compare Register A, the character after FREE (or after its P), against 0DH, the carriage return that ends the command line.
4D12
If the NZ FLAG is set (Register A is something else), JUMP to 4D3DH for error 34H ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR.
4D14
LD C,00H 0E 00
Load Register C with 00H: Register C holds the drive number, and FREE starts with drive 0.
4D16
GOSUB to 5086H to output a space and a carriage return, starting a new output line before the first drive line.

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: Register B counts down the 13 drive lines that fit on a page before the listing waits.
4D1B
GOSUB to 4FDBH to select drive Register C and show its drive line; it returns the Z FLAG when the line was shown, or the NZ FLAG with the error code in Register A.
4D1E
If the Z FLAG is set (the drive line for drive Register C was shown), JUMP to 4D2AH to step Register C to the next drive.
4D20
CP 20H FE 20
Compare Register A, the error code from 4FDBH, against 20H, ILLEGAL OR MISSING DRIVE #: drive Register C is past option AL, the last drive.
4D22
If the Z FLAG is set (Register A = 20H, no such drive), JUMP to 4FB8H to end the listing without an error.
4D25
CP 08H FE 08
Compare Register A, the error code from 4FDBH, against 08H, DEVICE NOT AVAILABLE: drive Register C has no diskette turning in it.
4D27
If the NZ FLAG is set (Register A holds any other error), JUMP to 4D43H to end FREE with that error code in Register A.
4D29
INC B 04
No diskette in drive Register C: increment Register B, the lines left on the page, because this drive showed no line.
4D2A
INC C 0C
Increment Register C, the drive number, to the next drive.
4D2B
Decrement Register B, the lines left on the page; if Register B is not 0, LOOP back to 4D1BH for drive Register C.
4D2D
The page is full: GOSUB to 506BH to show a question mark and wait for ENTER (BREAK goes to DOS READY) before the next page.
4D30
LOOP back to 4D19H to start the next page of 13 lines with drive Register C.

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 at 4D33H (00H in the file, stored by 4D34H).
4D34
LD (4D33H),A 32 33 4D
Self-Modifying Code
Store Register A, the DEC (bits 0-4 the FDE sector, bits 5-7 the entry), at 4D33H, the operand of the LD A at 4D32H.
4D37
GOSUB to SYS0/SYS 48D4H, which points Register Pair HL to the entry of DEC Register A, reading its FDE sector into 4300H unless 48D5H says it is already there; Register A comes back with the entry's offset in the sector.
4D3A
RET Z C8
If the Z FLAG is set (the sector is in 4300H), RETURN with Register Pair HL = the entry and Register A = its offset in the sector.
4D3B
JUMP to 4D43H to end DIR with the read error code from 48D4H 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, stored at 4DE7H), so the operator is asked to put the system diskette back first (Mount SYSTEM Diskette In Drive 0 (ENTER)).

4D3D
LD A,34H 3E 34
Load Register A with 34H, the error code ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR, for a command line DIR or FREE cannot read.
4D3F
JUMP to 4D43H, the common exit, with 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, the error code BAD PARAMETER(S); no instruction in SYS8/SYS reaches this row, which 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, 00H for none) on the stack while the system diskette may be asked for.
4D44
LD HL,513DH 21 3D 51
Load Register Pair HL with 513DH, the word SYSTEM (ending in 03H), for the Mount message.
4D47
LD HL,4F96H 21 96 4F
Self-Modifying Code
Load Register Pair HL with 4F96H. As loaded this only changes Register Pair HL; 4DE7H makes the opcode CDH, so it is CALL 4F96H with Register Pair HL = 513DH: Mount SYSTEM Diskette In Drive 0 (ENTER).
4D4A
POP AF F1
Restore Register Pair AF from the stack: Register A = the error code saved at 4D43H.
4D4B
OR A B7
OR Register A, the error code, with itself: the Z FLAG is set if Register A is 00H (no error).
4D4C
RET Z C8
If the Z FLAG is set (Register A = 00H), RETURN through 4BC5H to SYS0/SYS 4408H: the command ended without an error.
4D4D
JUMP to SYS0/SYS 4409H, the DOS error exit, with the error code in Register A; 4409H passes it to SYS4/SYS, which displays the message and ends the command.

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 (42C0H). 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,(42C0H) 3A C0 42
Load Register A with the byte at 42C0H, option AN: the drive DIR lists when no drive number is given.
4D53
LD C,A 4F
Load Register C with Register A: Register C holds the drive, option AN from 42C0H until a number is read.
4D54
LD B,00H 06 00
Load Register B with 00H: Register B collects the DIR options as bits, none given yet.
4D56
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the first character after DIR.
4D57
CP 3AH FE 3A
Compare Register A, the first character, against 3AH, a colon that may come before the drive number.
4D59
If the NZ FLAG is set (Register A is not a colon), JUMP to 4D5CH with Register Pair HL still at the character.
4D5B
INC HL 23
Increment Register Pair HL past the colon to the next character of the command line.
4D5C
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character of the command line.
4D5D
CP 24H FE 24
Compare Register A, the character, against 24H, the $ that asks for the diskette to be mounted.
4D5F
If the NZ FLAG is set (Register A is not $), JUMP to 4D64H to look for a drive number.
4D61
SET 6,B CB F0
Set bit 6 of Register B, the options: $ was given, so the operator is asked to mount the diskette (4DDDH).
4D63
INC HL 23
Increment Register Pair HL past the $ to the next character of the command line.
4D64
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the character that may start the drive number.
4D65
SUB 30H D6 30
Subtract 30H from Register A, the character: the digits 0-9 become 00H-09H, anything else 0AH or more (or a borrow).
4D67
CP 0AH FE 0A
Compare Register A, the converted character, against 0AH: the CARRY FLAG is set only for a digit 0-9.
4D69
If the NO CARRY FLAG is set (Register A was not a digit), JUMP to 4D89H to read options: 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 (the first digit, or the value built at 4D7EH).
4D6C
INC HL 23
Increment Register Pair HL to the next character of the command line.
4D6D
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character of the drive number.
4D6E
SUB 30H D6 30
Subtract 30H from Register A, the character: the digits 0-9 become 00H-09H.
4D70
CP 0AH FE 0A
Compare Register A, the converted character, against 0AH: the CARRY FLAG is set only for a digit 0-9.
4D72
If the NO CARRY FLAG is set (Register A was not a digit), JUMP to 4D85H: the number in Register C has ended.
4D74
LD E,A 5F
Load Register E with Register A, the new digit (00H-09H), to add after the multiplication.
4D75
LD A,C 79
Load Register A with Register C, the drive number so far, to be multiplied by 10.
4D76
LD D,09H 16 09
Load Register D with 09H: Register C is added 9 more times to Register A, making it the number times 10.
4D78
ADD A,C 81
Add Register C, the number so far, to Register A, the running product.
4D79
If the CARRY FLAG is set (Register A passed 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 (Register D is not 0, more additions), LOOP back to 4D78H.
4D7E
ADD A,E 83
Add Register E, the new digit, to Register A, the number times 10: Register A = the new drive number.
4D7F
If the NO CARRY FLAG is set (Register A did not pass 255), LOOP back to 4D6BH to keep the new number in Register C.
4D81
LD A,20H 3E 20
Load Register A with 20H, the error code ILLEGAL OR MISSING DRIVE #, for a drive number above 255.
4D83
JUMP to 4D43H, the common exit, with error 20H in Register A.

Option Loop
Register Pair HL = the command line, Register B = the options so far.

4D85
GOSUB to SYS0/SYS 4C7AH with Register Pair HL = the command line: the Z FLAG at the carriage return, the NO CARRY FLAG with Register Pair HL past a comma or spaces, the CARRY FLAG and Register A = 34H before any other character.
4D88
RET C D8
If the CARRY FLAG is set (no separator before the character), RETURN through 4BC5H to SYS0/SYS 4408H with error 34H in Register A.
4D89
GOSUB to 5058H with Register Pair HL = the command line: P selects the printer. Register A comes back with the character (or the one after P) and Register Pair HL past the character tested.
4D8C
If the Z FLAG is set (the character was P), LOOP back to 4D85H for the separator before the next option.
4D8E
CP 0DH FE 0D
Compare Register A, the character, against 0DH, the carriage return that ends the command line.
4D90
If the Z FLAG is set (Register A = 0DH), JUMP to 4DD5H to start the listing with the options in Register B.
4D92
CP 41H FE 41
Compare Register A, the option letter, against 41H, the letter A.
4D94
If the NZ FLAG is set (Register A is not A), JUMP to 4D9AH to test for S.
4D96
SET 0,B CB C0
Set bit 0 of Register B, the options: A was given (one file per line with the details).
4D98
LOOP back to 4D85H for the separator and the next option at Register Pair HL.
4D9A
CP 53H FE 53
Compare Register A, the option letter, against 53H, the letter S.
4D9C
If the NZ FLAG is set (Register A is not S), JUMP to 4DA2H to test for I.
4D9E
SET 1,B CB C8
Set bit 1 of Register B, the options: S was given (system files are listed too).
4DA0
LOOP back to 4D85H for the separator and the next option at Register Pair HL.
4DA2
CP 49H FE 49
Compare Register A, the option letter, against 49H, the letter I.
4DA4
If the NZ FLAG is set (Register A is not I), JUMP to 4DAAH to test for U.
4DA6
SET 2,B CB D0
Set bit 2 of Register B, the options: I was given (invisible files are listed too).
4DA8
LOOP back to 4D85H for the separator and the next option at Register Pair HL.
4DAA
CP 55H FE 55
Compare Register A, the option letter, against 55H, the letter U.
4DAC
If the NZ FLAG is set (Register A is not U), JUMP to 4DB2H to test for a slash.
4DAE
SET 5,B CB E8
Set bit 5 of Register B, the options: U was given (only files whose updated flag is set).
4DB0
LOOP back to 4D85H for the separator and the next option at Register Pair HL.
4DB2
CP 2FH FE 2F
Compare Register A, the option character, against 2FH, the slash that starts /ext.
4DB4
If the NZ FLAG is set (Register A is anything else), JUMP to 4D3DH for error 34H.
4DB7
SET 4,B CB E0
Set bit 4 of Register B, the options: /ext was given (only files with this extension).
4DB9
PUSH BC C5
Save Register Pair BC (Register B = the options, Register C = the drive) on the stack, because Register B counts the characters.
4DBA
LD B,03H 06 03
Load Register B with 03H: an extension has 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 of the extension.
4DC0
SUB 30H D6 30
Subtract 30H from Register A, the character: the digits 0-9 become 00H-09H.
4DC2
CP 0AH FE 0A
Compare Register A, the converted character, against 0AH: the CARRY FLAG is set for a digit 0-9.
4DC4
If the CARRY FLAG is set (a digit), JUMP to 4DCCH to copy the character at Register Pair HL.
4DC6
SUB 11H D6 11
Subtract 11H from Register A (the character minus 30H): the letters A-Z become 00H-19H.
4DC8
CP 1AH FE 1A
Compare Register A, the converted character, against 1AH: the CARRY FLAG is set for a letter A-Z.
4DCA
If the NO CARRY FLAG is set (Register A was not a letter), JUMP to 4DD2H: the extension has ended at Register Pair HL.
4DCC
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the letter or digit itself.
4DCD
LD (DE),A 12
Self-Modifying Code
Store Register A (the character) at Register Pair DE, in the extension filter at 4E0EH-4E10H.
4DCE
INC DE 13
Increment Register Pair DE to the next position of the extension filter.
4DCF
INC HL 23
Increment Register Pair HL to the next character of the command line.
4DD0
Decrement Register B, the room left in the filter; if Register B is not 0, LOOP back to 4DBFH.
4DD2
POP BC C1
Restore Register Pair BC from the stack: Register B = the options, Register C = the drive.
4DD3
LOOP back to 4D85H for the separator and the next option at Register Pair HL.

4DD5H - DIR: Start the Listing

Clears the screen (not when printing), handles $ (the Mount requests), 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, the options: bit 3 is set when P sends the listing to the printer.
4DD7
LD HL,514BH 21 4B 51
Load Register Pair HL with 514BH, the bytes 1CH 1FH 03H (home the cursor, clear to the end of the screen). LD does not change the flags.
4DDA
If the Z FLAG is set (bit 3 of Register B clear, 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 options: bit 6 is set when $ asks for the diskette.
4DDF
If the Z FLAG is set (no $), JUMP to 4DF6H to show the drive line of drive Register C.
4DE1
LD A,C 79
Load Register A with Register C, the drive number, to test it for drive 0.
4DE2
OR A B7
OR Register A, the drive number, with itself: the Z FLAG is set for drive 0.
4DE3
If the NZ FLAG is set (Register A is not drive 0), JUMP to 4DEAH: the system diskette need not be asked for again.
4DE5
LD A,CDH 3E CD
Load Register A with CDH, the opcode of CALL, to patch the exit at 4D47H.
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 (0-9 for one digit).
4DEB
ADD A,30H C6 30
Add 30H to Register A, the drive number: Register A = the drive as the character 0-9.
4DED
LD (5132H),A 32 32 51
Store Register A (the digit) at 5132H, the drive digit in the message at 511FH ( Diskette In Drive d (ENTER)).
4DF0
LD HL,5144H 21 44 51
Load Register Pair HL with 5144H, the word TARGET (ending in 03H), for the Mount message.
4DF3
GOSUB to 4F96H to show Mount TARGET Diskette In Drive d (ENTER) and wait for ENTER; Register Pair HL = 5144H, the word TARGET.
4DF6
GOSUB to 4FDBH to select drive Register C and show its line; it returns the Z FLAG when shown, else the NZ FLAG with the error code in Register A.
4DF9
If the NZ FLAG is set (an error), JUMP to 4D43H to end DIR with the error code 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 DEC Register A (00H) at 4D33H and read its FDE sector: Register Pair HL = the first entry (4300H).
4E00
GOSUB to 5086H to output a space and a carriage return, ending the drive line before the file names.
4E03
LD D,0DH 16 0D
Load Register D with 0DH: Register D counts down the 13 lines left on the first page.
4E05
GOSUB to 4FC7H to show the column headings (only with option A, bit 0 of Register B), counting one line in Register D.
4E08
PUSH DE D5
Save Register Pair DE (Register D = the lines left on the page) on the stack, where it stays between entries.
4E09
LD C,05H 0E 05
Load Register C with 05H: Register C counts down the names on a line before each one, so the first line takes 4 names.
4E0B
JUMP to 4F3BH to test the first entry at Register Pair HL.
4E0E-4E10
DEFM " " 20 20 20
The extension filter for /ext: three spaces as loaded, overwritten by 4DCDH with up to three letters or digits and compared with bytes 13-15 of each entry at 4F67H. Never executed: 4E0BH jumps over it.

4E11H - DIR: Show One File

Register Pair HL = the entry, Register B = the options, Register C = the names left on the line. The name and extension are shown padded to 15 columns. The attribute text at 51AFH-51BAH is always built (S system, I invisible, U updated, E no extension, C no space release, U update password, A access password, the access level digit), but only option A shows it, with the details (4E8BH).

4E11
PUSH DE D5
Save Register Pair DE on the stack: Register D = the lines left on the page, taken off the stack at 4F7DH and kept there while the entry is shown. 4F93H jumps here for every file listed.
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 address of the entry in the sector buffer at 4300H, on the stack.
4E14
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the entry (byte 0), Register Pair HL is free for the text.
4E15
LD HL,51AFH 21 AF 51
Load Register Pair HL with 51AFH, the first position of the attribute text (51AFH-51BAH).
4E18
LD B,0BH 06 0B
Load Register B with 0BH, the eleven positions 51AFH-51B9H to fill with periods.
4E1A
PUSH HL E5
Save Register Pair HL (51AFH, the start of the attribute text) on the stack for 4E26H.

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, the next position of the attribute text.
4E1D
INC HL 23
Increment Register Pair HL to the next position of the attribute text.
4E1E
Decrement Register B, the positions left; if Register B 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: bit 6 system, bit 3 invisible, bits 0-2 the access level.
4E21
AND 07H E6 07
Mask Register A, byte 0 of the entry, against 07H (0000 0111) to keep bits 0-2, the access level 0-7.
4E23
ADD A,30H C6 30
Add 30H to Register A, the access level: Register A = the level as the character 0-7.
4E25
LD (HL),A 77
Store Register A (the level digit) at Register Pair HL, 51BAH, the L position of the attribute text.
4E26
POP HL E1
Restore Register Pair HL from the stack: 51AFH, the start of the attribute text, the S position.
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, byte 0 of the entry: bit 6 is set for a system file.
4E2A
If the Z FLAG is set (bit 6 clear, not a system file), JUMP to 4E2EH, leaving the period at 51AFH.
4E2C
LD (HL),53H 36 53
Store 53H (S) at Register Pair HL, 51AFH, the S position: a system file.
4E2E
INC HL 23
Increment Register Pair HL to 51B0H, the I position of the attribute text.
4E2F
BIT 3,A CB 5F
Test bit 3 of Register A, byte 0 of the entry: bit 3 is set for an invisible file.
4E31
If the Z FLAG is set (bit 3 clear, a visible file), JUMP to 4E35H, leaving the period at 51B0H.
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, the second flag byte.
4E37
LD A,(DE) 1A
Load Register A with the byte at Register Pair DE, byte 1 of the entry: bit 7 ASE=N, bit 6 ASC=N, bit 5 updated.
4E38
BIT 5,A CB 6F
Test bit 5 of Register A, byte 1 of the entry: bit 5 is set when the file has been updated.
4E3A
If the Z FLAG is set (bit 5 clear, not updated), JUMP to 4E3EH, leaving the period at 51B1H.
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 of the entry: bit 7 is set when the file may not be extended (ASE=N).
4E41
If the Z FLAG is set (bit 7 of Register A clear), JUMP to 4E45H, leaving the period at 51B2H.
4E43
LD (HL),45H 36 45
Store 45H (E) at Register Pair HL, 51B2H: the file may not be extended (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 of the entry: bit 6 is set when CLOSE keeps the space beyond EOF (ASC=N).
4E48
If the Z FLAG is set (bit 6 of Register A clear), JUMP to 4E4CH, leaving the period at 51B3H.
4E4A
LD (HL),43H 36 43
Store 43H (C) at Register Pair HL, 51B3H: CLOSE keeps the space beyond EOF (ASC=N).
4E4C
LD HL,0004H 21 04 00
Load Register Pair HL with 0004H, the distance from byte 1 of the entry to its name at byte 5.
4E4F
ADD HL,DE 19
Add Register Pair DE (byte 1 of the entry) to Register Pair HL: Register Pair 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 as characters are shown.
4E52
LD B,08H 06 08
Load Register B with 08H, the eight characters of the name (bytes 5-12 of the entry).
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 first character of the extension (byte 13 of the entry).
4E58
CP 20H FE 20
Compare Register A, the extension's first character, against 20H: the Z FLAG is set if the file has no extension.
4E5A
LD A,2FH 3E 2F
Load Register A with 2FH, the slash shown before an extension. LD does not change the flags.
4E5C
If the NZ FLAG is set (an extension), GOSUB to 50A4H to show the slash in Register A and count the column in Register C.
4E5F
LD B,03H 06 03
Load Register B with 03H, the three characters of the extension (bytes 13-15 of the entry).
4E61
GOSUB to 509AH to show the extension at Register Pair HL without spaces, counting Register C down; Register Pair HL comes back at byte 16.
4E64
LD B,C 41
Load Register B with Register C, the columns left in the 15-column name field (3 or more).
4E65
GOSUB to 5092H to output Register B spaces: the name and extension are padded to 15 columns.
4E68
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, byte 16 of the entry: the low byte of the update password code.
4E69
INC HL 23
Increment Register Pair HL to byte 17 of the entry, the high byte of the update password code.
4E6A
LD D,(HL) 56
Load Register D with the byte at Register Pair HL, byte 17: Register Pair DE = the update password code.
4E6B
PUSH DE D5
Save Register Pair DE, the update password code, on the stack for 4E7BH.
4E6C
INC HL 23
Increment Register Pair HL to byte 18 of the entry, the low byte of the access password code.
4E6D
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, byte 18: the access password code's low byte.
4E6E
INC HL 23
Increment Register Pair HL to byte 19 of the entry, the high byte of the access password code.
4E6F
LD D,(HL) 56
Load Register D with the byte at Register Pair HL, byte 19: 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 (no password set).
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 (the access password is blank), JUMP to 4E7BH, leaving the period at 51B9H.
4E76
LD A,41H 3E 41
Load Register A with 41H, the letter A: the file has an access password.
4E78
LD (51B9H),A 32 B9 51
Store Register A (the letter A) at 51B9H, the A position of the attribute text.
4E7B
POP DE D1
Restore Register Pair DE from the stack: the update password code saved at 4E6BH.
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 (the update password is blank), JUMP to 4E84H, leaving the period at 51B8H.
4E7F
LD A,55H 3E 55
Load Register A with 55H, the letter U: the file has an update password.
4E81
LD (51B8H),A 32 B8 51
Store Register A (the letter U) at 51B8H, the U position of the attribute text.
4E84
POP HL E1
Restore Register Pair HL from the stack: the address of the entry in 4300H, saved at 4E13H.
4E85
POP BC C1
Restore Register Pair BC from the stack: Register B = the options, Register C = the names left on the line.
4E86
BIT 0,B CB 40
Test bit 0 of Register B, the options: bit 0 is set for option A (the details on the line).
4E88
If the Z FLAG is set (no option A), JUMP to 4F28H for the next entry; the lines left on the page stay on the stack.

4E8BH - DIR A: Show the Details

Register Pair HL = the entry. The rest of the line is the text at 518CH: the end of file as sectors/bytes (518DH-5195H), the record length (5198H-519AH), the number of records (519CH-51A1H), the granules (51A4H-51A7H), the extent elements (51AAH-51ACH) and the attribute text (51AFH-51BAH). 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 every file takes a line, so the names-left count in Register C runs out after each file.
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 address of the entry in 4300H, on the stack.
4E8F
INC HL 23
Increment Register Pair HL, the entry pointer, to byte 1 of the entry.
4E90
INC HL 23
Increment Register Pair HL, the entry pointer, to byte 2 of the entry.
4E91
INC HL 23
Increment Register Pair HL, the entry pointer, to byte 3, the EOF low byte (the byte offset in the last sector).
4E92
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, byte 3: the EOF low byte.
4E93
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the EOF low byte, 0-255.
4E95
INC HL 23
Increment Register Pair HL, the entry pointer, to byte 4, the record length (LRL).
4E96
LD B,D 42
Load Register B with Register D (00H), the high byte of the record length.
4E97
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, byte 4: Register Pair BC = the record length (0 stands for 256).
4E98
SET 4,L CB E5
Set bit 4 of Register L: Register Pair HL (entry + 4) becomes entry + 14H, byte 20, the EOF middle byte.
4E9A
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, byte 20: the EOF middle byte.
4E9B
INC HL 23
Increment Register Pair HL, the entry pointer, 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, byte 21: the EOF high byte.
4E9E
LD L,A 6F
Load Register L with Register A, the EOF middle byte: Register Pair HL = the EOF's middle and high bytes, a sector count.
4E9F
LD A,E 7B
Load Register A with Register E, the EOF low byte.
4EA0
OR A B7
OR Register A, the EOF low byte, with itself: the Z FLAG is set if it is 0.
4EA1
If the Z FLAG is set (the file ends on a sector boundary), JUMP to 4EA4H with Register Pair HL = the whole sectors.
4EA3
DEC HL 2B
The low byte is not 0, so the stored sector count includes the last, partly used sector: decrement Register Pair HL to the whole sectors.
4EA4
INC C 0C
Increment Register C, the record length's low byte, as the first half of a test for 0.
4EA5
DEC C 0D
Decrement Register C again, back to the record length: the Z FLAG is set if Register C is 0 (a record length of 256).
4EA6
If the NZ FLAG is set (Register C is not 0), JUMP to 4EAAH with Register Pair BC = the record length.
4EA8
LD B,01H 06 01
Load Register B with 01H: a record length of 0 means 256, so Register Pair BC = 0100H.
4EAA
PUSH DE D5
Save Register Pair DE (the EOF low byte) on the stack for 4EDBH.
4EAB
PUSH HL E5
Save Register Pair HL (the whole sectors) on the stack for 4ECFH.
4EAC
PUSH BC C5
Save Register Pair BC (the record length, 0100H for 256) on the stack for 4EC8H.
4EAD
If the NZ FLAG is set (the record length is not 256), JUMP to 4EB2H to divide.
4EAF
LD E,L 5D
Record length 256, one record per sector: load Register E with Register L, the low byte of the whole sectors.
4EB0
LD L,H 6C
Load Register L with Register H, the high byte of the whole sectors.
4EB1
LD H,D 62
Load Register H with Register D (00H): Register H / L / E = the whole sectors; Register A, the EOF low byte, is the remainder.
4EB2
If the NZ FLAG is set, GOSUB to 50ADH to divide the bytes in Register H / L / E (whole 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 the bytes divide evenly into records.
4EB6
If the Z FLAG is set (no remainder in Register A), JUMP to 4EBCH with the record count in Register H / L / E.
4EB8
INC E 1C
Round up for the partial record: increment Register E, the low byte of the record count.
4EB9
If the NZ FLAG is set (Register E did not wrap to 00H), JUMP to 4EBCH.
4EBB
INC HL 23
Increment Register Pair HL, the two high bytes of the record count: the carry out of Register E.
4EBC
LD A,H 7C
Load Register A with Register H, the high byte of the record count.
4EBD
LD B,L 45
Load Register B with Register L, the middle byte of the record count.
4EBE
LD C,E 4B
Load Register C with Register E, the low byte: 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 (six positions).
4EC5
GOSUB to 50C8H to write Register A / B / C (the records) in the 6 positions 519CH-51A1H.
4EC8
POP BC C1
Restore Register Pair BC from the stack: the record length saved at 4EACH (0100H for 256).
4EC9
LD HL,5197H 21 97 51
Load Register Pair HL with 5197H, the position before the record length field (5198H-519AH).
4ECC
GOSUB to 50BFH to write Register Pair BC (the record length) in the 3 positions 5198H-519AH.
4ECF
POP BC C1
Restore Register Pair BC from the stack: the whole sectors saved at 4EABH.
4ED0
LD HL,518CH 21 8C 51
Load Register Pair HL with 518CH, the position before the sectors field (518DH-5191H).
4ED3
LD DE,510CH 11 0C 51
Load Register Pair DE with 510CH, the power-of-ten table from its -10000 entry (five positions).
4ED6
GOSUB to 50C7H to write Register Pair BC (the whole sectors) in the 5 positions 518DH-5191H; Register Pair HL comes back at 5192H.
4ED9
LD (HL),30H 36 30
Store 30H (a 0) at Register Pair HL (5192H), so that the byte count written after it keeps its leading zeros.
4EDB
POP BC C1
Restore Register Pair BC from the stack: the EOF low byte saved at 4EAAH as Register Pair DE.
4EDC
PUSH HL E5
Save Register Pair HL (5192H, the slash position) on the stack.
4EDD
GOSUB to 50BFH to write Register Pair BC (the EOF low byte) in the 3 positions 5193H-5195H.
4EE0
POP HL E1
Restore Register Pair HL from the stack: 5192H, the position between the sectors and the bytes.
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 of the entry, pushed at 4E9CH.
4EE4
INC HL 23
Increment Register Pair HL, the entry pointer, to byte 22, the first extent element.
4EE5
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H: Register Pair BC counts the granules of the file.
4EE8
LD D,B 50
Load Register D with Register B (00H), the high byte of the element count.
4EE9
LD E,C 59
Load Register E with Register C (00H): Register Pair DE = 0000H, the count of extent elements.

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 (the lump, or FEH link, or FFH end).
4EEB
CP FEH FE FE
Compare Register A, the element's first byte, 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 (Register A is FEH or FFH), JUMP to 4F04H with the Z FLAG set for FEH.
4EF0
INC DE 13
Increment Register Pair DE, the count of extent elements.
4EF1
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the element's second byte: bits 5-7 the first granule, bits 0-4 the granules minus 1.
4EF2
AND 1FH E6 1F
Mask Register A, the element's second byte, against 1FH (0001 1111) to keep bits 0-4: the granules in the element minus 1.
4EF4
INC HL 23
Increment Register Pair HL to the next element (its first byte).
4EF5
INC A 3C
Increment Register A: the number of granules in the element.
4EF6
ADD A,C 81
Add Register C, the low byte of the granule count, to Register A, the element's granules.
4EF7
LD C,A 4F
Load Register C with Register A, the new low byte of the granule count in Register Pair BC.
4EF8
If the NO CARRY FLAG is set (the addition did not pass 255), JUMP to 4EFBH: nothing to carry into Register B.
4EFA
INC B 04
Increment Register B, the high byte of the granule count: the carry from Register C.
4EFB
BIT 4,L CB 65
Test bit 4 of Register L, the low byte of the element pointer: offsets 16H-1FH of an entry have it set, so the NZ FLAG means still inside the entry.
4EFD
If the NZ FLAG is set (Register Pair HL is still inside the entry), LOOP back to 4EEAH for the next element.
4EFF
LD A,2CH 3E 2C
No end mark in the entry: load Register A with 2CH, the error code BAD DIRECTORY DATA.
4F01
JUMP to 4D43H, the common exit, with error 2CH in Register A.
4F04
If the NZ FLAG is set (Register A was FFH, the end of the elements), JUMP to 4F0FH to show the counts.
4F06
LD A,(HL) 7E
FEH: load Register A with the byte at Register Pair HL, the DEC of the FXDE that continues the elements.
4F07
GOSUB to 4D37H to read the FXDE's FDE sector into 4300H: Register Pair HL = the FXDE, Register A = its offset in the sector.
4F0A
ADD A,16H C6 16
Add 16H to Register A, the FXDE's offset: Register A = the offset of its first extent element (byte 22).
4F0C
LD L,A 6F
Load Register L with Register A: Register Pair HL = the FXDE's first extent element.
4F0D
LOOP back to 4EEAH for the FXDE's elements at Register Pair HL, with the counts in Register Pairs BC and DE.
4F0F
GOSUB to 4D32H to read the FDE sector of the listed entry again (DEC at 4D33H), as an FXDE may have replaced it in 4300H.
4F12
PUSH DE D5
Save Register Pair DE, the count of extent elements, on the stack.
4F13
LD HL,51A3H 21 A3 51
Load Register Pair HL with 51A3H, the position before the granules field (51A4H-51A7H).
4F16
GOSUB to 50C4H to write Register Pair BC (the granules) in the 4 positions 51A4H-51A7H.
4F19
POP BC C1
Restore Register Pair BC from the stack: the count of extent elements saved at 4F12H as Register Pair DE.
4F1A
LD HL,51A9H 21 A9 51
Load Register Pair HL with 51A9H, the position before the extent elements field (51AAH-51ACH).
4F1D
GOSUB to 50BFH to write Register Pair BC (the extent elements) in the 3 positions 51AAH-51ACH.
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 (518CH), the details after the name.
4F26
POP HL E1
Restore Register Pair HL from the stack: the address of the entry in 4300H, saved at 4E8EH.
4F27
POP BC C1
Restore Register Pair BC from the stack: Register B = the options, Register C = 1, saved at 4E8DH.

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

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 at 4E0EH-4E10H.
4F68
CP (HL) BE
Compare Register A, the filter's character, with the byte at Register Pair HL, the entry's character; the Z FLAG is set if they match.
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 (the characters differ), JUMP to 4F6FH with the NZ FLAG.
4F6D
Decrement Register B, the characters left; if Register B is not 0, LOOP back to 4F67H (when it is, the Z FLAG from 4F68H says all three matched).
4F6F
POP BC C1
Restore Register Pair BC from the stack: Register B = the options, Register C = the names left. POP does not change the flags.
4F70
POP HL E1
Restore Register Pair HL from the stack: the address of the entry in 4300H. POP does not change the flags.
4F71
If the NZ FLAG is set (the extension differs from the filter), JUMP to 4F28H for the next entry.
4F73
BIT 5,B CB 68
Test bit 5 of Register B, the options: bit 5 is set for option U (only updated files).
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, the entry pointer, to byte 1 of the entry.
4F78
BIT 5,(HL) CB 6E
Test bit 5 of the byte at Register Pair HL, byte 1 of the entry: bit 5 is the updated flag.
4F7A
DEC HL 2B
Decrement Register Pair HL back to byte 0 of the entry. DEC HL does not change the flags.
4F7B
If the Z FLAG is set (the file is not marked 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 (pushed at 4E08H or 4E11H).
4F7E
DEC C 0D
Decrement Register C, the names left on this line.
4F7F
If the NZ FLAG is set (Register C is not 0, room on the line), JUMP to 4F93H to show the file.
4F81
LD C,04H 0E 04
The line is full: load Register C with 04H, the names on the next line (counted down before each).
4F83
GOSUB to 5086H to output a space and a carriage return, starting 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 (Register D is not 0, room on the page), JUMP to 4F93H to show the file.
4F89
The page is full: GOSUB to 506BH to show a question mark and wait for ENTER (BREAK goes to DOS READY).
4F8C
LD D,0FH 16 0F
Load Register D with 0FH: every later page holds 15 lines, counted down in Register D.
4F8E
BIT 3,B CB 58
Test bit 3 of Register B, the options: bit 3 is set when P sends the listing to the printer.
4F90
If the Z FLAG is set (not printing), GOSUB to 4FC7H to show the column headings again (only with option A), counting a line in Register D.
4F93
JUMP to 4E11H to show the file at Register Pair HL, with Register D = the lines left and Register C = the names left.

4F96H - Ask for a Diskette

Register Pair HL = the word SYSTEM or TARGET (ending in 03H). Shows Mount, the word, and Diskette In Drive d (ENTER) (the drive digit is at 5132H), then waits for ENTER.

4F96
PUSH HL E5
Save Register Pair HL, the word SYSTEM (513DH) or TARGET (5144H), on the stack.
4F97
LD HL,5118H 21 18 51
Load Register Pair HL with 5118H, the text Mount and a space, ending in 03H.
4F9A
GOSUB to SYS0/SYS 4467H to display the text at Register Pair HL (5118H) up to its 03H.
4F9D
POP HL E1
Restore Register Pair HL from the stack: the word SYSTEM or TARGET.
4F9E
GOSUB to SYS0/SYS 4467H to display the word at Register Pair HL up to its 03H, on the same line.
4FA1
LD HL,511FH 21 1F 51
Load Register Pair HL with 511FH, the rest of the message: Diskette In Drive d (ENTER) and a carriage return.
4FA4
GOSUB to SYS0/SYS 4467H to display the text at Register Pair HL (511FH) up to and including its carriage return.

Wait for ENTER
Register A = each key read.

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

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 output a space and a carriage return, ending the last 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 part of Register Pair DE).
4FB3
CP 04H FE 04
Compare Register A, the lines left, against 04H: the CARRY FLAG is set if fewer than 4 lines are left.
4FB5
If the CARRY FLAG is set (Register A below 4), GOSUB to 506BH to show a question mark and wait for ENTER.
4FB8
LD A,(50A8H) 3A A8 50
Load Register A with the byte at 50A8H, the operand of the CALL at 50A7H: 33H when the output goes to the display, 3BH for the printer. FREE comes here at its end (4D22H).
4FBB
CP 3BH FE 3B
Compare Register A, the operand from 50A8H, against 3BH: the Z FLAG is set when printing.
4FBD
If the Z FLAG is set (printing), GOSUB to 5086H to feed an empty line; 5086H keeps the flags.
4FC0
If the Z FLAG is still set (printing), GOSUB to 5086H to feed another empty line.
4FC3
XOR A AF
Load Register A with 00H (XOR A with itself): no error.
4FC4
JUMP to 4D43H, the common exit, 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, the options: bit 0 is set for option A, the only listing with headings.
4FC9
RET Z C8
If the Z FLAG is set (bit 0 of Register B clear, no option A), RETURN with Register D unchanged.
4FCA
PUSH HL E5
Save Register Pair HL, the caller's entry address in 4300H, on the stack.
4FCB
PUSH BC C5
Save Register Pair BC (Register B = the options, Register C = the names left) on the stack, because Register B counts the spaces.
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, the twenty spaces before the headings (under the name field).
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 text ending in a carriage return.
4FD5
GOSUB to 508FH to show the text at Register Pair HL (51BCH).
4FD8
POP BC C1
Restore Register Pair BC from the stack: Register B = the options, Register C = the names left.
4FD9
POP HL E1
Restore Register Pair HL from the stack: the caller's entry address in 4300H.
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 fills in the text at 514EH: the drive number, the diskette name and date (GAT D0H-DFH), the number of tracks (4283H), the free FDEs (HIT bytes that are 00H, counted over the FDE sectors of each of the 8 entry positions), and the free granules (clear bits in the GAT, granules per lump from 4285H, lumps from 4281H). 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 number of the drive to select.
4FDC
GOSUB to SYS0/SYS 4791H to select drive Register A and wait for the index hole to show that a diskette turns; it returns the NZ FLAG with error 20H or 08H in Register A.
4FDF
RET NZ C0
If the NZ FLAG is set (no such drive, or no diskette), RETURN with the error code in Register A.
4FE0
PUSH BC C5
Save Register Pair BC (Register B = the caller's options, Register C = the drive) on the stack.
4FE1
LD B,00H 06 00
Load Register B with 00H: Register Pair BC = the drive number, for the number writer.
4FE3
LD HL,5153H 21 53 51
Load Register Pair HL with 5153H, the position before the drive number field (5154H-5156H).
4FE6
GOSUB to 50BFH to write Register Pair BC (the drive) in the 3 positions 5154H-5156H.
4FE9
LD A,(4283H) 3A 83 42
Load Register A with the byte at 4283H, PDRIVE byte 3 of the selected drive: its 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 number of tracks.
4FEF
LD HL,516CH 21 6C 51
Load Register Pair HL with 516CH, the position before the tracks field (516DH-516FH).
4FF2
GOSUB to 50BFH to write Register Pair BC (the tracks) in the 3 positions 516DH-516FH.
4FF5
XOR A AF
Load Register A with 00H (XOR A with itself): directory sector 0, the GAT.
4FF6
GOSUB to SYS0/SYS 48AFH to read directory sector Register A (0, the GAT) into 4300H; Register Pair HL = 4300H, the GAT byte of lump 0.
4FF9
If the NZ FLAG is set (the GAT could not be read), JUMP to 5056H to return the error code in Register A.
4FFB
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H: Register Pair BC counts the free granules.

Lump Loop
Register Pair HL = the GAT byte of the lump, Register Pair BC = the free granules so far.

4FFE
LD E,(IY+05H) FD 5E 05
Load Register E with the byte at Index Register IY+05H, 4285H: the granules per lump of the selected drive (PDRIVE byte 5), the bits to test in this lump's GAT byte.
5001
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the lump's GAT byte: bit n set means granule n is allocated.
5002
INC HL 23
Increment Register Pair HL to the next lump's GAT byte.

Granule Loop
Register A shifts right, Register E counts the granules of the lump.

5003
RRCA 0F
Rotate Register A, the GAT byte, right: the next granule's bit goes into the CARRY FLAG.
5004
If the CARRY FLAG is set (the granule is allocated), JUMP to 5007H without counting it.
5006
INC BC 03
The granule is free: increment Register Pair BC, the count of free granules.
5007
DEC E 1D
Decrement Register E, the granules left to test in this lump.
5008
If the NZ FLAG is set (Register E is not 0, 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 = 4300H + the lump).
500B
CP (IY+01H) FD BE 01
Compare Register A (the next lump number) with the byte at Index Register IY+01H, 4281H: the number of lumps on the diskette (PDRIVE byte 1); the CARRY FLAG is set while lumps remain.
500E
If the CARRY FLAG is set (Register A is below the number of lumps), 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 (5181H-5184H).
5013
GOSUB to 50C4H to write Register Pair BC (the free granules) in the 4 positions 5181H-5184H.
5016
LD HL,43D0H 21 D0 43
Load Register Pair HL with 43D0H, GAT bytes D0H-D7H in the sector buffer: the diskette name.
5019
LD DE,5159H 11 59 51
Load Register Pair DE with 5159H, the name field of the drive line (5159H-5160H).
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 (43D0H) to Register Pair DE (5159H-5160H); Register Pair HL ends at 43D8H, the date, and Register Pair BC at 0000H.
5021
LD DE,5163H 11 63 51
Load Register Pair DE with 5163H, the date field of the drive line (5163H-516AH).
5024
LD C,08H 0E 08
Load Register C with 08H: Register Pair BC = 0008H (Register B is 00H after the LDIR), the eight characters of the date.
5026
LDIR ED B0
Copy Register Pair BC (8) bytes from Register Pair HL (43D8H, GAT D8H-DFH) to Register Pair DE (5163H-516AH); Register Pair BC ends at 0000H, the count of free FDEs.
5028
LD A,01H 3E 01
Load Register A with 01H: directory sector 1, the HIT.
502A
GOSUB to SYS0/SYS 48AFH to read directory sector Register A (1, the HIT) into 4300H; Register Pair HL = 4300H, the first HIT byte.
502D
If the NZ FLAG is set (the HIT could not be read), JUMP to 5056H to return the error code in Register A.

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,(431FH) 3A 1F 43
Load Register A with the byte at 431FH, HIT byte 1FH: the number of FDE sectors beyond the first 8.
5032
ADD A,08H C6 08
Add 08H to Register A: Register A = the number of FDE sectors in the directory.
5034
LD E,A 5F
Load Register E with Register A, the FDE sectors to count in this row of the HIT.
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 that ends DIR's sector loop.
5038
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, a HIT byte: 00H means its FDE (DEC = the HIT offset) is free.
5039
OR A B7
OR Register A, the HIT byte, 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 (the FDE is in use), JUMP to 503EH without counting it.
503D
INC BC 03
The FDE is 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 (row of the HIT).
503F
If the NZ FLAG is set (Register E is not 0, more FDE sectors), LOOP back to 5038H.
5041
LD A,L 7D
Load Register A with Register L, the offset of the next HIT byte.
5042
ADD A,1FH C6 1F
Add 1FH to Register A, the offset, to round it up to the next 32-byte boundary.
5044
AND E0H E6 E0
Mask Register A against E0H (1110 0000): the first HIT byte of the next entry position (row).
5046
LD L,A 6F
Load Register L with Register A: Register Pair HL = the first HIT byte of the next row.
5047
If the NZ FLAG is set (Register A is not 00H, so not past the eighth row), LOOP back to 502FH.
5049
LD HL,5176H 21 76 51
Load Register Pair HL with 5176H, the position before the FDEs field (5177H-5179H).
504C
GOSUB to 50BFH to write Register Pair BC (the free FDEs) in the 3 positions 5177H-5179H.
504F
LD HL,514EH 21 4E 51
Load Register Pair HL with 514EH, the drive line: Drive, the number, the name, the date, the tracks, the free FDEs and the free granules.
5052
GOSUB to 508FH to show the drive line at Register Pair HL (514EH), ending in a carriage return.
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: Register B = the caller's options, Register C = the drive (saved at 4FE0H).
5057
RET C9
RETURN with the Z FLAG and Register A = 00H, or the NZ FLAG and the error code 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/SYS 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 of the command line to test.
5059
CP 50H FE 50
Compare Register A, the character, against 50H, the letter P; the Z FLAG is set for 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 (Register A is not P), RETURN with the character in Register A and the NZ FLAG.
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/SYS 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, the options: P was given (the output goes to the printer).
5069
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the character after the P.
506A
RET C9
RETURN with the Z FLAG from the compare at 5059H and the character after the P in Register A.

506BH - Wait at the End of a Page

Only for the display, and not while a chain file supplies the keys: shows a question mark and waits for a key. BREAK (01H) goes to DOS READY (402DH); ENTER (0DH) ends the line and returns; other keys are ignored.

506B
BIT 5,(IY+09H) FD CB 09 6E
Test bit 5 of the byte at Index Register IY+09H, 4289H, the system flags: bit 5 is set while a chain file supplies the keys.
506F
RET NZ C0
If the NZ FLAG is set (a chain file is running), RETURN without stopping.
5070
LD A,(50A8H) 3A A8 50
Load Register A with the byte at 50A8H, the operand of the CALL at 50A7H (33H display, 3BH printer).
5073
CP 33H FE 33
Compare Register A, the operand from 50A8H, 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 without stopping.
5076
LD A,3FH 3E 3F
Load Register A with 3FH, a question mark: the prompt at the end of a page.
5078
GOSUB to 50A5H to output the question mark in Register A.

Key Loop
Register A = the key read.

507B
GOSUB to ROM 0049H, which waits for a key and returns it in Register A.
507E
DEC A 3D
Decrement Register A, the key: the Z FLAG is set for 01H, the BREAK key, and ENTER (0DH) becomes 0CH.
507F
If the Z FLAG is set (BREAK), JUMP to 402DH, DOS READY: the listing is abandoned.
5082
CP 0CH FE 0C
Compare Register A (the key minus 1) against 0CH: the Z FLAG is set for ENTER.
5084
If the NZ FLAG is set (another key), LOOP back to 507BH to wait for the next key; ENTER falls into 5086H, which ends 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). 50A5H keeps Register Pairs AF and DE.

5086
LD A,20H 3E 20
Load Register A with 20H, a space, sent before the carriage return that ends the line.
5088
GOSUB to 50A5H to output the space in Register A to the display or printer.
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 with the caller's flags.
508F
Self-Modifying Code
JUMP to SYS0/SYS 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 to the display or printer.
5097
Decrement Register B, the spaces left; if Register B 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 of the name or extension.
509B
CP 20H FE 20
Compare Register A, the character, against 20H: the Z FLAG is set for a space, which is not shown.
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 (Register A is 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 Register B is not 0, LOOP back to 509AH.
50A3
RET C9
RETURN with Register Pair HL after the characters and Register C = the columns left.
50A4
DEC C 0D
Decrement Register C, the columns left in the name field, for the character about to be shown.
50A5
PUSH DE D5
Save Register Pair DE on the stack; the ROM output routine loads Register Pair DE with its control block.
50A6
PUSH AF F5
Save Register Pair AF (Register A = the character, and the caller's flags) on the stack.
50A7
Self-Modifying Code
GOSUB to ROM 0033H 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: Register A = the character and the caller's flags.
50AB
POP DE D1
Restore Register Pair DE from the stack: the caller's value of Register Pair DE.
50AC
RET C9
RETURN with Register Pairs AF and DE as the caller had them.

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: Register B counts the 24 bits of the dividend in Register H / L / E.
50AF
XOR A AF
Load Register A with 00H (XOR A with itself): Register A holds the remainder, which 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, the dividend's low byte, left: bit 7 goes into the CARRY FLAG and bit 0 becomes 0, the place for the next quotient bit.
50B2
ADC HL,HL ED 6A
Add Register Pair HL to itself with the CARRY FLAG: Register Pair HL, the dividend's high bytes, shifts left and takes Register E's bit 7.
50B4
RLA 17
Rotate Register A, the remainder, 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 to subtract.
50B7
CP C B9
Compare Register A, the remainder, against Register C, the divisor: the CARRY FLAG is set if the remainder is lower.
50B8
If the CARRY FLAG is set (Register A below the divisor in Register C), JUMP to 50BCH: this quotient bit is 0.
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 bit 0 of Register E is 1.
50BC
Decrement Register B, the bits left; if Register B 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, the table entry for -100: three positions (hundreds, tens, units).
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, the table entry for -1000: four positions (thousands to units).
50C7
XOR A AF
Load Register A with 00H (XOR A with itself): the high byte of the value is 0 for a 16-bit number in Register Pair BC.

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

5106H - Unreferenced Code

No branch, call or stored address in SYS8/SYS reaches 5106H.

5106
POP AF F1
Restore Register Pair AF from the stack, discarding a word; no instruction in SYS8/SYS reaches this row.
5107
POP AF F1
Restore Register Pair AF from the stack, discarding another word; not reached, like 5106H.
5108
RET C9
RETURN; not reached by anything in SYS8/SYS, like the two POP AF rows 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 (FFD8F0H), the first entry for the sectors (4ED3H).
510F-5111
DEFB 18H, FCH, FFH 18 FC FF
18H FCH FFH: -1000 (FFFC18H), the first entry for four positions (50C4H).
5112-5114
DEFB 9CH, FFH, FFH 9C FF FF
9CH FFH FFH: -100 (FFFF9CH), the first entry for three positions (50BFH).
5115-5117
DEFB F6H, FFH, FFH F6 FF FF
F6H FFH FFH: -10 (FFFFF6H), the last entry: 50F0H finds F6H in Register E and writes the units next.

5118H - Messages and Texts

The texts that 4467H (or 446AH with P) shows end in 0DH, which is sent, or 03H, which is not. The fields of the drive line and the detail line are filled in by 50BFH-5105H with leading zeros shown as spaces.

5118-511E
DEFM "Mount " / DEFB 03H 4D 6F 75 6E 74 20 03
The first part of the diskette request (4F97H), ending in 03H so that the word follows on the same line.
511F-513C
DEFM " Diskette In Drive 0 (ENTER)" / DEFB 0DH 20 44 69 73 6B 65 74 74 65 20 49 6E 20 44 72 69 76 65 20 30 20 20 28 45 4E 54 45 52 29 0D
The end of the diskette request (4FA1H). 5132H, the 0, is replaced by the drive digit at 4DEDH.
513D-5143
DEFM "SYSTEM" / DEFB 03H 53 59 53 54 45 4D 03
The word for the system diskette, shown by 4F96H when 4D47H has been made a CALL (Register Pair HL = 513DH from 4D44H).
5144-514A
DEFM "TARGET" / DEFB 03H 54 41 52 47 45 54 03
The word for the diskette to be listed (4DF0H).
514B-514D
DEFB 1CH, 1FH, 03H 1C 1F 03
Home the cursor (1CH) and clear to the end of the screen (1FH), ending in 03H: the screen is cleared before DIR lists to the display (4DD7H).
514E-518B
DEFM "Drive 000 XXXXXXXX MM/DD/YY 000 Trks 000 Fdes 0000 Grans" / DEFB 0DH 44 72 69 76 65 20 30 30 30 20 20 58 58 58 58 58 58 58 58 20 20 4D 4D 2F 44 44 2F 59 59 20 20 30 30 30 20 54 72 6B 73 20 20 30 30 30 20 46 64 65 73 20 20 30 30 30 30 20 47 72 61 6E 73 0D
The drive line (504FH): drive number 5154H-5156H, diskette name 5159H-5160H, date 5163H-516AH, tracks 516DH-516FH, free FDEs 5177H-5179H, free granules 5181H-5184H.
518C-51BB
DEFM " 000000000 000 000000 0000 000 SIUEC....AUL" / DEFB 03H 20 30 30 30 30 30 30 30 30 30 20 20 30 30 30 20 30 30 30 30 30 30 20 20 30 30 30 30 20 20 30 30 30 20 20 53 49 55 45 43 2E 2E 2E 2E 41 55 4C 03
The detail line of DIR A (4F20H): sectors 518DH-5191H, a slash at 5192H, bytes 5193H-5195H, record length 5198H-519AH, records 519CH-51A1H, granules 51A4H-51A7H, extent elements 51AAH-51ACH, attributes 51AFH-51BAH (filled with periods and letters by 4E15H-4E81H), ending in 03H.
51BC-51E6
DEFM "Eof Lrl Recs Grans Exts SIUEC....UAL" / DEFB 0DH 45 6F 66 20 20 20 20 4C 72 6C 20 20 20 52 65 63 73 20 47 72 61 6E 73 20 45 78 74 73 20 20 53 49 55 45 43 2E 2E 2E 2E 55 41 4C 0D
The column headings of DIR A (4FD2H), shown after 20 spaces. UAL heads the update password, access password and level positions 51B8H-51BAH.
51E7
DEFB 00H 00
The last byte of the file, 00H after the headings; nothing reads it.
51E8-51FF
DEFS 24
Not in the file: the rest of the overlay area. SYS8/SYS neither reads nor writes these bytes.