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

Page Customization

SYS7/SYS - ATTRIB Command Handler

SYS7/SYS is the ATTRIB (file attribute) command handler for NEWDOS/80 v2.0. This overlay module manages file attributes and directory entry modifications for the TRS-80 Model I disk operating system.

The ATTRIB command allows users to view and modify various file attributes including:

  • Visibility - INV/VIS (invisible/visible in directory listings)
  • Protection Levels - PROT= and XPROT= (execute protection)
  • Access Control - ACC= (access level 0-7)
  • File Flags - UPD= (update protection), ASE= (auto-start enable), ASC= (ASCII mode)
  • User Defined - UDF= (user-defined flag)
  • Logical Record Length - LRL= (record size for random access)
  • File Operations - LOCK/UNLOCK, KILL, RENAME, NAME
  • Password - PW= (file password protection)
  • Date - NDATE= (new date assignment)

The module uses a dispatcher pattern, decoding function codes in Register C to route to appropriate handler routines. It heavily interfaces with SYS0 for directory operations, FCB management, and disk I/O.

Entry Point: 4D00H - Called via RST 28H with A=E9H (ATTRIB SVC code)

Size: 1256 bytes (4D00H-51E7H)

Variables:

AddressBytesPurpose
4D4FH1Self-modifying: Dispatch RST number (modified by command setup)
4DD2H1Self-modifying: Maximum value for parameter validation
4F1AH1Self-modifying: Flag accumulator for file attribute updates
4F6DH1Self-modifying: Maximum granule count for directory scan
51BEH2Self-modifying: Stored end address for DUMP command
51C5H2Self-modifying: Stored start address for DUMP command
51CCH2Self-modifying: Stored HL value for DUMP calculations
51E8H-51EFH8Filename buffer for file specification parsing

Command String Table:

AddressLengthString / Purpose
5054H4"INV" + 00H - Invisible attribute toggle
5058H6"INVIS" + 00H - Invisible attribute (alternate)
505EH8"XPROT=" + 00H - Execute protection level
5066H6"ACC=" + 00H - Access level (0-7)
506DH6"UPD=" + 00H - Update protection flag
5074H6"ASE=" + 00H - Auto-start enable flag
507BH6"ASC=" + 00H - ASCII mode flag
5082H6"UDF=" + 00H - User-defined flag
5089H6"LRL=" + 00H - Logical record length
5090H2Dispatch byte + "N" (name prefix)
5093H5"LOCK" + 00H - Lock file
5098H6"EXEC" + 00H - Execute protection
509EH6"READ" + 00H - Read-only attribute
50A4H7"WRITE" + 00H - Write protection
50ABH8"RENAME" + 00H - Rename protection
50B3H6"NAME" + 00H - Name display/change
50B9H6"KILL" + 00H - Kill protection
50BFH6"FULL" + 00H - Full attribute display
50C5H2Padding bytes
50C7H4"PW=" + 00H - Password specification
50CBH9"OUNLOCK" + 00H - Owner unlock
50D4H7"NLOCK" + 00H - New lock
50DBH8"NNAME=" + 00H - New name specification
50E3H8"NDATE=" + 00H - New date specification
50EBH3"NR" + data - Additional parameters

Command Keyword Summary Tables

Table 1 (5054H) - Attribute Commands: Uses 2-byte handler addresses

AddressKeywordHandlerDescription
5054HINV4E54HSet file invisible in directory listings
505AHVIS4E58HClear invisible attribute
5060HPROT=4E6AHSet protection level (uses Table 2)
5068HACC=4E78HSet access password
506FHUPD=4E7CHSet update password
5076HASE=4E31HAuto-space-extend flag (Y/N)
507DHASC=4E35HAuto-space-compress flag (Y/N)
5084HUDF=4E2AHUser-defined/updated flag (Y/N)
508BHLRL=4E17HLogical record length (0-255)

Table 2 (5093H) - Protection Levels: Uses 1-byte protection level values

AddressKeywordLevelDescription
5093HLOCK7No access (except overlay loader)
5099HEXEC6Execute only
509FHREAD5Execute or read
50A5HWRITE4Execute, read or write
50ACHRENAME2Execute, read, write or rename
50B4HNAME2Same as RENAME (alias)
50BAHKILL1Execute, read, write, rename or kill
50C0HFULL0All operations allowed

Table 3 (50C7H) - Password/File Operations: Uses 2-byte handler addresses

AddressKeywordHandlerDescription
50C7HPW=4F09HPassword specification
50CDHUNLOCK4EFAHRemove lock from file
50D6HLOCK4EFEHApply lock to file
50DDHNNAME=4EDDHRename file to new name
50E6HNDATE=4EF6HSet new date for file
50EFHNRUF-No random update flag

Disassembly:

4D00H - SYS7 Entry Point and Command Dispatcher

This is the main entry point for SYS7. The DOS loader jumps here with Register A containing the SVC function code (E9H for ATTRIB) and Register C containing the sub-function number. IY is set to point to the DOS system area at 4280H which contains drive parameters and system state.

4D00
LD IY,4280H FD 21 80 42
Point Index Register IY to 4280H, the DOS system parameter block base address. This provides quick access to drive parameters and system state through indexed addressing throughout the ATTRIB command handler.
4D04
CP E9H FE E9
Compare Register A against E9H (the ATTRIB SVC function code). If Register A equals E9H, the Z FLAG is set indicating this is an ATTRIB command; otherwise NZ FLAG is set for a different function.
4D06
If the NZ FLAG is set (Register A is not E9H - not ATTRIB command), JUMP to 4D34H to handle alternative entry (likely PROT command or parameter display functions).

[COMMAND DISPATCH TABLE] The following code decrements Register C to dispatch to the appropriate ATTRIB sub-function. Each DEC C tests for a specific function number (0, 1, 2, etc.) and branches to the corresponding handler.

4D08
DEC C 0D
DECrement Register C by 1. If C was 1 (sub-function 1), C becomes 0 and Z FLAG is set.
4D09
If Z FLAG is set (C was 1 = PROT function), JUMP to 4D68H to handle protection level display/modification.
4D0B
DEC C 0D
DECrement Register C by 1. If C was 2, C becomes 0 and Z FLAG is set.
4D0C
If Z FLAG is set (C was 2 = file specification parse), JUMP to 4D7DH to parse filespec and set memory limit.
4D0F
DEC C 0D
DECrement Register C by 1. If C was 3, C becomes 0 and Z FLAG is set.
4D10
If Z FLAG is set (C was 3 = ACC function), JUMP to 4D6CH to handle access level display/modification.
4D12
DEC C 0D
DECrement Register C by 1. If C was 4, C becomes 0 and Z FLAG is set.
4D13
If Z FLAG is set (C was 4 = directory entry update), JUMP to 4DDBH to modify directory entry attributes.
4D16
DEC C 0D
DECrement Register C by 1. If C was 5, C becomes 0 and Z FLAG is set.
4D17
If Z FLAG is set (C was 5 = file open/validate), JUMP to 4DFAH to open file and validate attributes.
4D1A
DEC C 0D
DECrement Register C by 1. If C was 6, C becomes 0 and Z FLAG is set.
4D1B
If Z FLAG is set (C was 6 = password handler), JUMP to 4ECCH to process password-related operations.
4D1E
DEC C 0D
DECrement Register C by 1. If C was 7, C becomes 0 and Z FLAG is set.
4D1F
If Z FLAG is set (C was 7 = DUMP command), JUMP to 50F4H to display memory dump.
4D22
DEC C 0D
DECrement Register C by 1. If C was 8, C becomes 0 and Z FLAG is set.
4D23
If Z FLAG is set (C was 8 = DUMP continuation), JUMP to 5149H to continue memory dump processing.
4D26
DEC C 0D
DECrement Register C by 1. If C was 9, C becomes 0 and Z FLAG is set.
4D27
If Z FLAG is set (C was 9 = FULL attribute display), JUMP to 4D70H to display all file attributes.

If we reach here, C was 10 or higher. Set up for LRL (Logical Record Length) parameter handling with dispatch byte 36H and max value 3AH (58 decimal, corresponding to ':')

4D29
LD DE,4219H 11 19 42
Load Register Pair DE with 4219H, pointing to the DOS parameter area for LRL storage location.
4D2C
LD B,3AH 06 3A
Load Register B with 3AH (58 decimal, ASCII :). This is the maximum valid character for LRL parameter validation.
4D2E
LD A,36H 3E 36
Load Register A with 36H (54 decimal). This is the dispatch RST code for the LRL handler routine.
4D30
DEC C 0D
DECrement Register C by 1. If C was 10, C becomes 0 and Z FLAG is set.
4D31
If Z FLAG is set (C was 10 = LRL function), JUMP to 4D3EH to store parameters and process LRL command.
4D33
DEC C 0D
DECrement Register C by 1. If C was 11, C becomes 0 and Z FLAG is set.

4D34H - Alternative Entry / Error Return Setup

This section handles alternative entry points when Register A was not E9H, or when C has been decremented beyond valid function numbers. It sets up error code 2AH (general error) and jumps to error handler if no match found.

4D34
LD A,2AH 3E 2A
Load Register A with error code 2AH (42 decimal = "General error"). This is used when no valid sub-function matches.
4D36
If NZ FLAG is set (no matching function found), JUMP to 4D65H to invoke the DOS error handler with error code 2AH.

If Z FLAG was set from the DEC C at 4D33H (C was 11), this is the NDATE= function. Set up E=1CH (date offset in directory entry), B=2FH (max value '/'), A=33H (dispatch code).

4D38
LD E,1CH 1E 1C
Load Register E with 1CH (28 decimal). This is the offset within the directory entry for the date field.
4D3A
LD B,2FH 06 2F
Load Register B with 2FH (47 decimal, ASCII /). This is the maximum valid character for date parameter parsing.
4D3C
LD A,33H 3E 33
Load Register A with 33H (51 decimal). This is the dispatch RST code for the NDATE handler.

4D3EH - Parameter Storage and Command Processing

This section stores the dispatch code and maximum value into self-modifying code locations, then checks if command line has additional parameters. If no parameters (CR found), it displays current value; otherwise processes the new value.

4D3E
LD (4D4FH),A 32 4F 4D
Store the dispatch code from Register A into memory location 4D4FH. This is self-modifying code that will be executed later as an RST instruction operand.
4D41
LD A,B 78
Load Register A with the maximum value from Register B (3AH for LRL or 2FH for NDATE).
4D42
LD (4DD2H),A 32 D2 4D
Store the maximum value from Register A into memory location 4DD2H. This is self-modifying code used for parameter validation.
4D45
LD A,(HL) 7E
Load Register A with the character at memory address pointed to by HL (current position in command line buffer).
4D46
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If A equals 0DH, Z FLAG is set indicating end of command line (no parameter specified).
4D48
If NZ FLAG is set (more parameters exist on command line), JUMP to 4DAEH to parse and process the new parameter value.

No parameter was specified - display current value. Set up to call the display routine at 51E8H (filename buffer) and then use RST to invoke the handler.

4D4A
LD HL,51E8H 21 E8 51
Load Register Pair HL with 51E8H, pointing to the filename buffer area used for building output strings.
4D4D
PUSH HL E5
Save HL (filename buffer pointer) onto the stack for later use after the CALL returns.
4D4E
GOSUB to ROM routine at 3036H - This is a variant display routine that outputs a string or value. The following byte (at 4D51H) is used as the RST function code.
4D51
JUMP to 4D8DH to complete processing and return. (Note: The byte 3AH at 4D51H may also be used as data by the preceding CALL routine.)

4D53H - Error Return Points

These are various entry points that set specific error codes and jump to the common error handler at 4D65H.

4D53
LD A,2CH 3E 2C
Load Register A with error code 2CH (44 decimal = "Directory full" error).
4D55
JUMP to 4D65H to invoke the DOS error handler with error code 2CH.
4D57
LD A,20H 3E 20
Load Register A with error code 20H (32 decimal = "Invalid parameter" error).
4D59
JUMP to 4D65H to invoke the DOS error handler with error code 20H.

4D5BH - Skip Whitespace and Check End of Line

This utility routine skips whitespace in the command buffer and checks if end-of-line has been reached. Returns with Carry set and A=34H (parse error) if unexpected characters found.

4D5B
GOSUB to SYS0 routine at 4C7AH to skip whitespace in the command line buffer. HL is advanced past any spaces.
4D5E
RET NC D0
If NO CARRY FLAG is set (end of buffer not reached, valid data present), RETURN to caller with success.
4D5F
LD A,(HL) 7E
Load Register A with the character at current buffer position (pointed to by HL).
4D60
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If A equals 0DH, Z FLAG is set indicating end of command line.
4D62
RET Z C8
If Z FLAG is set (carriage return found = end of line), RETURN to caller with Z flag indicating success/end.
4D63
LD A,34H 3E 34
Load Register A with error code 34H (52 decimal = "Parse error" - unexpected characters in command).

4D65H - DOS Error Handler Jump

This is the common error exit point. It jumps to the SYS0 error handler at 4409H which will display the error message corresponding to the code in Register A.

4D65
JUMP to SYS0 error handler at 4409H. Register A contains the error code to be displayed. The error handler will output the corresponding message and return to DOS READY.

4D68H - PROT Function Handler Setup

Sets up for protection level function (sub-function 1). B=33H is the RST dispatch code for PROT handler.

4D68
LD B,33H 06 33
Load Register B with 33H (51 decimal). This is the RST dispatch code for the PROT (protection level) handler.
4D6A
JUMP to 4D73H to continue with common attribute handler processing.

4D6CH - ACC Function Handler Setup

Sets up for access level function (sub-function 3). B=32H is the RST dispatch code for ACC handler.

4D6C
LD B,32H 06 32
Load Register B with 32H (50 decimal). This is the RST dispatch code for the ACC (access level) handler.
4D6E
JUMP to 4D73H to continue with common attribute handler processing.

4D70H - FULL Attribute Display Setup

Sets up for FULL attribute display (sub-function 9). BC=E506H loads both B (E5H = PUSH HL opcode) and C (06H = counter).

4D70
LD BC,E506H 01 06 E5
Load Register Pair BC with E506H. B=E5H (PUSH HL opcode used as dispatch marker), C=06H (counter for attribute types to display).

4D73H - Common Attribute Handler

Common processing for PROT, ACC, and FULL functions. Calls the directory lookup routine and then dispatches via RST 28H.

4D73
PUSH BC C5
Save BC (dispatch code in B, counter in C) onto the stack for use after directory lookup.
4D74
GOSUB to 4E90H to parse filespec and perform directory lookup. Returns with directory entry information.
4D77
POP BC C1
Restore BC from the stack (dispatch code in B, counter in C).
4D78
LD A,B 78
Load Register A with the dispatch code from Register B.
4D79
LD B,(IY+FEH) FD 46 FE
Load Register B with the value at IY+FEH (offset -2 from 4280H = 427EH). This retrieves a system parameter for the RST handler.
4D7C
RST 28H EF
Execute RST 28H - DOS Supervisor Call. Register A contains the function code (32H, 33H, or E5H) to dispatch to the appropriate handler routine.

4D7DH - File Specification Parse and Memory Limit Handler

This handler (sub-function 2) parses a file specification from the command line and sets the high memory limit. If no filespec is provided, it displays the current memory limit.

4D7D
LD A,(HL) 7E
Load Register A with the character at current command buffer position (pointed to by HL).
4D7E
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If A equals 0DH, Z FLAG is set indicating no filespec provided.
4D80
If NZ FLAG is set (filespec parameter provided), JUMP to 4D93H to parse and validate the new memory limit value.

No parameter specified - display current high memory limit. Load current value from 4411H and format it for display.

4D82
LD DE,(4411H) ED 5B 11 44
Load Register Pair DE with the 16-bit value stored at 4411H - the current high memory limit address.
4D86
LD HL,51E8H 21 E8 51
Load Register Pair HL with 51E8H, pointing to the filename/output buffer for building the display string.
4D89
PUSH HL E5
Save HL (buffer pointer) onto the stack for use after conversion routine returns.
4D8A
GOSUB to SYS0 routine at 44D2H to convert the 16-bit value in DE to ASCII hexadecimal string at (HL).

4D8DH - Display String and Return

Appends carriage return to buffer, retrieves buffer pointer, and calls DOS display routine to output the result.

4D8D
LD (HL),0DH 36 0D
Store 0DH (carriage return) at the memory location pointed to by HL, terminating the output string.
4D8F
POP HL E1
Restore HL from the stack - now points to the start of the output buffer (51E8H).
4D90
JUMP to SYS0 routine at 4467H to display the string at (HL) and return to DOS READY. This outputs the formatted memory limit value.

4D93H - Parse New Memory Limit Value

Parse the hexadecimal memory limit value from the command line, validate it's within acceptable range (must be >= 7000H), and update the system high memory pointer.

4D93
GOSUB to 4FA5H to parse a hexadecimal number from the command line. Returns value in DE.
4D96
GOSUB to 4D5FH to check for end of line. Ensures no extra characters after the hex value.
4D99
LD A,D 7A
Load Register A with the high byte of the parsed value from Register D.
4D9A
CP 70H FE 70
Compare Register A against 70H. If A < 70H (value < 7000H), CARRY FLAG is set indicating value is too low.
4D9C
If CARRY FLAG is set (memory limit < 7000H - too low), JUMP to 4DD7H to return error code 2FH (parameter out of range).

Validate that specified address doesn't exceed actual available RAM. Load current high memory (42C9H) and compare.

4D9F
LD HL,(42C9H) 2A C9 42
Load Register Pair HL with the 16-bit value at 42C9H - the actual top of available RAM detected at boot.
4DA2
OR A B7
Clear the CARRY FLAG by ORing A with itself (preparation for 16-bit subtraction).
4DA3
SBC HL,DE ED 52
Subtract DE (requested limit) from HL (actual RAM top) with borrow. If DE > HL, CARRY is set.
4DA5
ADD HL,DE 19
ADD DE back to HL to restore the original RAM top value (since SBC modified it).
4DA6
If CARRY FLAG is set (requested limit > actual RAM), JUMP to 4DA9H to use the actual RAM top instead.
4DA8
EX DE,HL EB
Exchange DE and HL. Now HL contains the validated memory limit (either requested or actual RAM top).
4DA9
LD (4411H),HL 22 11 44
Store the validated high memory limit from HL into 4411H - the system high memory pointer.
4DAC
XOR A AF
Set Register A to ZERO (XOR A with itself) and clear all flags. A=0 indicates success.
4DAD
RET C9
RETURN to caller with A=0 indicating successful memory limit update.

4DAEH - Parse Numeric Date/LRL Parameter

This routine parses a numeric parameter (either date in MM/DD/YY format or LRL value) from the command line. It disables interrupts during parsing to prevent timing issues, then validates each digit pair.

4DAE
DI F3
Disable Interrupts to prevent timer interrupts from corrupting the parsing state during critical section.
4DAF
LD B,03H 06 03
Load Register B with 03H (3 decimal). This is the counter for parsing 3 pairs of digits (e.g., MM/DD/YY for date).

[LOOP START] Parse each digit pair from command line.

4DB1
LD A,(HL) 7E
[LOOP] Load Register A with the character at current buffer position (first digit of pair).
4DB2
SUB 30H D6 30
Subtract 30H (ASCII '0') from A to convert ASCII digit to binary value (0-9).
4DB4
CP 0AH FE 0A
Compare A against 0AH (10). If A >= 10, NO CARRY and character was not a valid digit.
4DB6
INC HL 23
INCrement HL to point to the next character in the buffer.
4DB7
If NO CARRY FLAG is set (character was not 0-9), JUMP to 4DD6H to re-enable interrupts and return error.

Valid first digit. Multiply by 10 (A*10 = A*8 + A*2) to prepare for adding second digit.

4DB9
LD C,A 4F
Save the first digit value in Register C for the multiplication.
4DBA
RLCA 07
Rotate A left (multiply by 2). A now contains digit * 2.
4DBB
RLCA 07
Rotate A left again (multiply by 2). A now contains digit * 4.
4DBC
ADD A,C 81
ADD original digit (C) to A. A now contains digit * 4 + digit = digit * 5.
4DBD
ADD A,A 87
ADD A to itself (multiply by 2). A now contains digit * 10.
4DBE
LD C,A 4F
Save the tens value (first digit * 10) in Register C.

Parse the second digit and add to tens value.

4DBF
LD A,(HL) 7E
Load Register A with the next character (second digit of pair).
4DC0
SUB 30H D6 30
Subtract 30H (ASCII '0') to convert to binary.
4DC2
CP 0AH FE 0A
Compare A against 0AH. If A >= 10, not a valid digit.
4DC4
INC HL 23
INCrement HL to point to the next character.
4DC5
If NO CARRY FLAG is set (not a digit), JUMP to 4DD6H to handle error.
4DC7
ADD A,C 81
ADD the tens value (C) to the units value (A). A now contains the complete 2-digit decimal number.
4DC8
LD (DE),A 12
Store the parsed 2-digit value at the memory location pointed to by DE (date/LRL storage area).
4DC9
DEC DE 1B
DECrement DE to point to the next storage position (date fields stored in reverse order: YY, DD, MM).
4DCA
DECrement B and Jump if Not Zero. If more pairs to parse, JUMP to 4DD0H to check for separator.

All 3 pairs parsed successfully. Re-enable interrupts and continue parsing.

4DCC
EI FB
Enable Interrupts - parsing complete, safe to allow timer interrupts again.
4DCD
JUMP to SYS0 routine at 4C7AH to skip whitespace and continue command line parsing.

4DD0H - Check Date/Parameter Separator

After parsing a digit pair, check for the separator character (/ or :). The expected separator was stored at 4DD2H during setup.

4DD0
LD A,(HL) 7E
Load Register A with the current character (should be separator like '/' or ':').
4DD1
CP 00H FE 00
Compare A against 00H. (Note: This address 4DD2H is modified by code at 4D42H to contain the expected separator character.)
4DD3
INC HL 23
INCrement HL to point past the separator.
4DD4
If Z FLAG is set (separator matches expected), LOOP BACK to 4DB1H to parse the next digit pair.
4DD6
EI FB
Enable Interrupts before returning with error.

4DD7H - Parameter Error Return

Return error code 2FH (47 decimal = "Parameter out of range" error) via the common error handler.

4DD7
LD A,2FH 3E 2F
Load Register A with error code 2FH (47 decimal = "Parameter out of range" error).
4DD9
JUMP to 4D65H to invoke the DOS error handler with error code 2FH.

4DDBH - Directory Entry Update Handler

This handler (sub-function 4) updates a directory entry. It expects HL pointing to the source data and DE pointing to the directory entry. It validates the file, then copies up to 32 bytes of attribute data to the directory sector buffer.

4DDB
EX DE,HL EB
Exchange DE and HL. Now HL points to the directory entry area, DE points to the source data.
4DDC
XOR A AF
Set Register A to ZERO. This will be used as the "open for read" mode parameter.
4DDD
GOSUB to SYS0 routine at 4723H to validate/open the file. A=0 specifies read mode validation.
4DE0
RET NZ C0
If NZ FLAG is set (validation failed), RETURN immediately with error code in A.
4DE1
XOR A AF
Set Register A to ZERO again for the sector read call.
4DE2
GOSUB to SYS0 routine at 48AFH to read the directory sector containing this file's entry into the buffer.
4DE5
RET NZ C0
If NZ FLAG is set (read failed), RETURN immediately with error code.

Directory sector is now in buffer. Set up to copy the new attribute data from (DE) to the directory entry at buffer offset E0H.

4DE6
LD B,20H 06 20
Load Register B with 20H (32 decimal) - the size of a directory entry to copy.
4DE8
LD L,E0H 2E E0
Load Register L with E0H. Combined with H (which contains the buffer page), this points to the directory entry location within the sector buffer.

[LOOP START] Copy bytes from source (DE) to directory entry (HL) until carriage return or 32 bytes copied.

4DEA
LD A,(DE) 1A
[LOOP] Load Register A with the byte at source address (DE).
4DEB
CP 0DH FE 0D
Compare A against 0DH (carriage return). If A equals 0DH, Z FLAG is set indicating end of source data.
4DED
LD (HL),A 77
Store the byte from A into the directory entry buffer at (HL).
4DEE
INC DE 13
INCrement DE to point to the next source byte.
4DEF
INC HL 23
INCrement HL to point to the next destination byte.
4DF0
If Z FLAG is set (carriage return found = end of data), JUMP to 4DF7H to write the updated directory sector.
4DF2
DECrement B and Jump if Not Zero. LOOP BACK to 4DEAH until all 32 bytes copied.

32 bytes copied but no carriage return found - source data too long. Return error.

4DF4
JUMP to 4DD7H to return error code 2FH (parameter out of range - data too long).
4DF7
JUMP to SYS0 routine at 48C4H to write the modified directory sector back to disk and return.

4DFAH - File Open and Validate Handler

This handler (sub-function 5) opens a file and validates its attributes. It pops the return addresses pushed by the SVC caller to adjust stack state, then performs file operations.

4DFA
POP AF F1
Restore AF from the stack (discard SVC caller's saved AF).
4DFB
POP HL E1
Restore HL from the stack (pointer to command line buffer).
4DFC
GOSUB to 4F72H to parse the filespec from (HL) and look up the file in the directory. Returns DE = directory entry address.
4DFF
PUSH DE D5
Save DE (directory entry address) onto the stack.
4E00
POP IX DD E1
Restore IX from the stack (IX now points to the directory entry - same value as DE).
4E02
INC DE 13
INCrement DE to point to offset +1 in the directory entry (file flags byte).
4E03
LD A,(DE) 1A
Load Register A with the file flags byte from directory entry offset +1.
4E04
AND 07HAND 00000111 E6 07
Mask A with 07H to isolate bits 0-2 (protection level - 0=none through 7=maximum).
4E06
LD A,19H 3E 19
Load Register A with error code 19H (25 decimal = "Access denied").
4E08
RET NZ C0
If NZ FLAG is set (protection level is non-zero = file is protected), RETURN with error code 19H.

File has no protection. Continue with file processing.

4E09
PUSH HL E5
Save HL (command line pointer) onto the stack.
4E0A
GOSUB to SYS0 routine at 48F0H to perform additional file validation and setup.
4E0D
If NZ FLAG is set (validation failed), JUMP to 4D65H to invoke error handler.
4E10
EX (SP),HL E3
Exchange HL with the value on top of stack. HL gets previous HL value, stack gets current HL.
4E11
LD BC,5054H 01 54 50
Load Register Pair BC with 5054H - pointer to the command string table starting with "INV".
4E14
JUMP to 4F78H to search the command string table for a matching keyword and dispatch to appropriate handler.

4E17H - Update Directory Entry Offset Handler

This code handles updating a specific byte offset within a directory entry, typically for single-byte attributes.

4E17
GOSUB to 4FA5H to parse a hexadecimal/decimal value from the command line into DE.
4E1A
DEC DE 1B
DECrement DE by 1 (adjust parsed value).
4E1B
LD A,D 7A
Load Register A with the high byte of DE.
4E1C
OR A B7
OR A with itself to test if D is zero (value must be single byte, i.e., < 256).
4E1D
If NZ FLAG is set (D > 0 = value too large), JUMP to 4DD7H to return parameter error.

Value is valid (fits in single byte). Update the directory entry at the specified offset.

4E1F
EX (SP),HL E3
Exchange HL with value on stack. Gets directory entry pointer from stack.
4E20
PUSH HL E5
Save the directory entry pointer onto the stack.
4E21
INC HL 23
INCrement HL to point to offset +1.
4E22
INC HL 23
INCrement HL to point to offset +2.
4E23
INC HL 23
INCrement HL to point to offset +3.
4E24
INC HL 23
INCrement HL to point to offset +4 (file attribute byte).
4E25
INC E 1C
INCrement E (the parsed value) by 1 to adjust for storage.
4E26
LD (HL),E 73
Store the adjusted value from E into the directory entry at offset +4.
4E27
POP HL E1
Restore the directory entry pointer from the stack.
4E28
JUMP to 4E51H to continue processing additional parameters or complete.

4E2AH - Y/N Boolean Parameter Handlers

These routines handle Y/N (Yes/No) boolean parameters for various attributes. Each entry point sets up specific mask bits before the common processing code.

4E2A
LD C,20H 0E 20
Load Register C with 20H (bit 5 mask) - ASE (Auto-Start Enable) attribute bit.
4E2C
LD DE,FF00H 11 00 FF
Load DE with FF00H: D=FFH (all bits for "Y"), E=00H (no bits for "N").
4E2F
JUMP to 4E3AH for common Y/N parsing.
4E31
LD C,80H 0E 80
Load Register C with 80H (bit 7 mask) - INV (Invisible) attribute bit.
4E33
JUMP to 4E37H to set default DE and continue.
4E35
LD C,40H 0E 40
Load Register C with 40H (bit 6 mask) - UPD (Update protection) attribute bit.
4E37
LD DE,00FFH 11 FF 00
Load DE with 00FFH: D=00H (no bits for "Y"), E=FFH (all bits for "N"). This is inverted logic.

4E3AH - Parse Y/N Response

Parse the Y or N character from command line and update the appropriate attribute bit in the directory entry.

4E3A
LD A,(HL) 7E
Load Register A with the current character from command line (should be 'Y' or 'N').
4E3B
CP 59H FE 59
Compare A against 59H (ASCII Y). If A equals 'Y', Z FLAG is set.
4E3D
INC HL 23
INCrement HL to point past the Y/N character.
4E3E
If Z FLAG is set (character was 'Y'), JUMP to 4E45H to apply the "Yes" setting.
4E40
LD D,E 53
Copy E to D. D now contains the "No" value (00H or FFH depending on attribute).
4E41
CP 4EH FE 4E
Compare A against 4EH (ASCII N). If A equals 'N', Z FLAG is set.
4E43
If NZ FLAG is set (character was neither 'Y' nor 'N'), JUMP to 4DD7H for parameter error.
4E45
EX (SP),HL E3
Exchange HL with top of stack to get directory entry pointer.
4E46
INC HL 23
INCrement HL to point to the flags byte in directory entry (offset +1).
4E47
LD A,C 79
Load Register A with the bit mask from C.
4E48
AND D A2
AND A with D (the Y/N value). A now contains the bit to set (if Y) or 00H (if N).
4E49
LD B,A 47
Save the result in B (the new bit value).
4E4A
LD A,FFH 3E FF
Load A with FFH (all bits set) in preparation for creating the complement mask.
4E4C
XOR C A9
XOR A with C to create complement mask (all bits except the target bit are set).
4E4D
AND (HL) A6
AND with current directory byte to clear the target bit position.
4E4E
OR B B0
OR with B to set the target bit if appropriate (based on Y/N input).
4E4F
LD (HL),A 77
Store the updated flags byte back into the directory entry.
4E50
DEC HL 2B
DECrement HL to point back to the start of the directory entry.

4E51H - Continue Parameter Processing

After processing one parameter, swap the command line pointer back and check for more parameters or end of command.

4E51
EX (SP),HL E3
Exchange HL with stack. HL now contains command line pointer again.
4E52
JUMP to 4E62H to check for more parameters or complete processing.

4E54H - Protection Level Update Handlers

These entry points set specific protection level bits in the directory entry's second byte.

4E54
LD C,08H 0E 08
Load Register C with 08H (bit 3 mask) - EXEC protection bit.
4E56
JUMP to 4E5AH for common protection processing.
4E58
LD C,00H 0E 00
Load Register C with 00H - clear all protection bits (full access).
4E5A
LD B,F7H 06 F7
Load Register B with F7H (complement of 08H) - mask to clear bit 3 while preserving others.
4E5C
POP DE D1
Restore DE from the stack (directory entry pointer).
4E5D
LD A,(DE) 1A
Load Register A with the byte at directory entry (flags byte).
4E5E
AND B A0
AND A with B to clear the target protection bit.
4E5F
OR C B1
OR with C to set the new protection bit if specified.
4E60
LD (DE),A 12
Store the updated flags byte back to the directory entry.
4E61
PUSH DE D5
Save DE (directory entry pointer) back onto the stack.

4E62H - Check For More Parameters

Check if there are more parameters on the command line. If not, write the directory sector; if yes, continue parsing.

4E62
GOSUB to 4D5BH to skip whitespace and check for end of line.
4E65
If NZ FLAG is set (more parameters exist), JUMP BACK to 4E11H to parse the next keyword.

End of parameters reached. Write updated directory sector to disk.

4E67
POP AF F1
Restore AF from the stack (discard saved directory pointer).
4E68
JUMP to 4DF7H to write the updated directory sector and return.

4E6AH - LOCK Keyword Handler

Handles the LOCK keyword to set file lock status. References the command table at 5093H for "LOCK" string.

4E6A
LD BC,5093H 01 93 50
Load Register Pair BC with 5093H - pointer to "LOCK" string in the command table.
4E6D
LD D,01H 16 01
Load Register D with 01H - search parameter indicating one string to match.
4E6F
GOSUB to 4F84H to search for keyword in command table and return entry address.
4E72
LD A,(BC) 0A
Load Register A with the byte at (BC) - the dispatch code associated with the matched keyword.
4E73
LD C,A 4F
Copy the dispatch code from A to C.
4E74
LD B,F8H 06 F8
Load Register B with F8H - mask to clear bits 0-2 (protection level bits) while preserving others.
4E76
JUMP to 4E5CH to apply the protection mask and update directory entry.

4E78H - Protection Level Numeric Handlers

These routines handle setting specific numeric protection levels (0-7) on a file.

4E78
LD A,12H 3E 12
Load Register A with 12H (18 decimal) - offset for protection level 2 handler.
4E7A
JUMP to 4E7EH to apply protection level.
4E7C
LD A,10H 3E 10
Load Register A with 10H (16 decimal) - offset for protection level 0 handler.
4E7E
PUSH AF F5
Save AF (protection offset) onto the stack.
4E7F
GOSUB to 5005H to parse filename and build hash for directory lookup.
4E82
PUSH HL E5
Save HL onto the stack.
4E83
POP BC C1
Restore BC from the stack (BC now contains HL value - filename hash).
4E84
POP AF F1
Restore AF from the stack (protection offset in A).
4E85
POP HL E1
Restore HL from the stack (directory entry pointer).
4E86
PUSH HL E5
Save HL (directory entry pointer) back onto the stack.
4E87
ADD A,L 85
ADD L to A to calculate offset within directory entry for storing protection data.
4E88
LD L,A 6F
Copy the calculated offset from A to L.
4E89
LD (HL),E 73
Store the low byte (E) of the filename hash/protection value at (HL).
4E8A
INC HL 23
INCrement HL to point to the next byte.
4E8B
LD (HL),D 72
Store the high byte (D) of the filename hash/protection value at (HL).
4E8C
LD H,B 60
Copy B to H (restoring original HL high byte from BC).
4E8D
LD L,C 69
Copy C to L (restoring original HL low byte from BC).
4E8E
JUMP to 4E62H to continue processing or complete.

4E90H - Parse Filespec and Drive Lookup

This routine parses a file specification from the command line, validates the drive number, and performs directory lookup. It's used by multiple ATTRIB sub-functions.

4E90
GOSUB to 5005H to parse the filename from command line and compute hash.
4E93
LD A,(HL) 7E
Load Register A with the character after the filename (should be ':' if drive specified).
4E94
CP 3AH FE 3A
Compare A against 3AH (ASCII :). If A equals ':', Z FLAG is set indicating drive specification follows.
4E96
INC HL 23
INCrement HL to point past the ':' or to the next character.
4E97
If Z FLAG is set (':' found), JUMP to 4EA3H to continue with explicit drive number.

No explicit drive - use default drive from system area.

4E99
PUSH HL E5
Save HL (command line pointer) onto the stack.
4E9A
LD HL,4296H 21 96 42
Load HL with 4296H - address of default drive number in system area.
4E9D
RST 18H DF
Execute RST 18H - Compare routine to validate default drive.
4E9E
POP HL E1
Restore HL (command line pointer) from the stack.
4E9F
DEC HL 2B
DECrement HL to back up one position (no ':' was consumed).
4EA0
If NZ FLAG is set (drive validation failed), JUMP to 4DD7H for parameter error.
4EA3
PUSH DE D5
Save DE (filename hash or pointer) onto the stack.
4EA4
GOSUB to 4FA5H to parse the drive number from command line into DE.
4EA7
LD A,D 7A
Load Register A with the high byte of parsed value.
4EA8
OR A B7
OR A with itself to test if high byte is zero (drive number must be < 256).
4EA9
If NZ FLAG is set (high byte non-zero = invalid drive number), JUMP to 4D57H for error 20H.
4EAC
LD A,E 7B
Load Register A with the low byte of parsed value (drive number 0-7).
4EAD
POP DE D1
Restore DE from the stack.
4EAE
GOSUB to SYS0 routine at 4791H to validate drive number and select the drive.
4EB1
If NZ FLAG is set (drive select failed), JUMP to 4EC9H to handle error.

Drive selected successfully. Read directory to find the file.

4EB3
PUSH HL E5
Save HL (command line pointer) onto the stack.
4EB4
XOR A AF
Set Register A to ZERO for directory read mode.
4EB5
GOSUB to SYS0 routine at 48AFH to read the directory sector.
4EB8
If NZ FLAG is set (read failed), JUMP to 4EC9H to handle error.
4EBA
LD HL,(43CEH) 2A CE 43
Load HL with the value at 43CEH - current directory entry address.
4EBD
OR A B7
Clear CARRY FLAG for comparison.
4EBE
SBC HL,DE ED 52
Subtract DE (filename hash) from HL to compare directory entry.
4EC0
POP HL E1
Restore HL (command line pointer) from the stack.
4EC1
RET Z C8
If Z FLAG is set (file found - hashes match), RETURN with success.

File not found. Check system flags to determine error response.

4EC2
LD A,(428CH) 3A 8C 42
Load Register A with the system flags byte from 428CH.
4EC5
RLCA 07
Rotate A left - move bit 7 to bit 0 and into CARRY.
4EC6
RET NC D0
If NO CARRY (bit 7 was 0 - silent mode), RETURN without error.
4EC7
LD A,37H 3E 37
Load Register A with error code 37H (55 decimal = "File not found").
4EC9
JUMP to 4D65H to invoke error handler with code in A.

4ECCH - Password Command Handler

This handler (sub-function 6) processes password-related ATTRIB commands like PW= (set password).

4ECC
GOSUB to 4E90H to parse filespec and lookup file in directory.
4ECF
GOSUB to 4F72H to validate file access and get directory entry.
4ED2
LD BC,50C7H 01 C7 50
Load Register Pair BC with 50C7H - pointer to "PW=" string in command table.
4ED5
JUMP to 4F78H to search for password keyword and dispatch to handler.

4ED8H - Name Copy Routines

These routines copy filename data to specific directory entry offsets for NAME and NNAME operations.

4ED8
LD DE,43D8H 11 D8 43
Load Register Pair DE with 43D8H - destination address for name data (secondary location).
4EDB
JUMP to 4EE0H for common copy code.
4EDD
LD DE,43D0H 11 D0 43
Load Register Pair DE with 43D0H - destination address for name data (primary location).
4EE0
LD B,08H 06 08
Load Register B with 08H (8 decimal) - filename length to copy.

[LOOP START] Copy up to 8 characters of filename, padding with spaces if needed.

4EE2
[LOOP] GOSUB to SYS0 routine at 4C7AH to skip whitespace and check for valid character.
4EE5
If NO CARRY (end of data or delimiter), JUMP to 4EEBH to pad with spaces.
4EE7
LD A,(HL) 7E
Load Register A with the character at (HL).
4EE8
INC HL 23
INCrement HL to point to the next character.
4EE9
JUMP to 4EF0H to store the character.
4EEB
If Z FLAG is set (at end of buffer), JUMP to 4EEEH to use space padding.
4EED
DEC HL 2B
DECrement HL (back up past delimiter).
4EEE
LD A,20H 3E 20
Load Register A with 20H (ASCII space) for padding.
4EF0
LD (DE),A 12
Store the character (or space) at destination (DE).
4EF1
INC DE 13
INCrement DE to point to next destination position.
4EF2
DECrement B and Jump if Not Zero. LOOP BACK to 4EE2H until 8 characters copied.
4EF4
JUMP to 4F10H to continue processing.

4EF6H - Flag Accumulator Handlers

These entry points set specific flag bits that accumulate in the self-modifying location at 4F1AH.

4EF6
LD A,04H 3E 04
Load Register A with 04H (bit 2) - flag for one type of attribute operation.
4EF8
JUMP to 4F00H to OR with accumulated flags.
4EFA
LD A,01H 3E 01
Load Register A with 01H (bit 0) - flag for another attribute operation.
4EFC
JUMP to 4F00H to OR with accumulated flags.
4EFE
LD A,02H 3E 02
Load Register A with 02H (bit 1) - flag for another attribute operation.

4F00H - Accumulate Flag Bits

This routine ORs the flag value in Register A with the accumulated flags stored at 4F1AH. This allows multiple attribute flags to be combined before the final directory update.

4F00
PUSH HL E5
Save HL (command line pointer) onto the stack.
4F01
LD HL,4F1AH 21 1A 4F
Load HL with 4F1AH - address of the flag accumulator byte (self-modifying code location).
4F04
OR (HL) B6
OR Register A with the current value at (HL). This combines the new flag with previously accumulated flags.
4F05
LD (HL),A 77
Store the combined flags back to 4F1AH.
4F06
POP HL E1
Restore HL (command line pointer) from the stack.
4F07
JUMP to 4F10H to continue parameter processing.

4F09H - Store Directory Entry Pointer

Store the current directory entry address for later use in attribute updates.

4F09
GOSUB to 5005H to parse filename and compute hash.
4F0C
LD (43CEH),DE ED 53 CE 43
Store DE (filename hash/directory entry pointer) at 43CEH - the directory entry pointer variable.

4F10H - Continue Processing or Complete

Check for more parameters on the command line. If none, proceed to write updates to the directory sector.

4F10
GOSUB to 4D5BH to skip whitespace and check for end of line.
4F13
If NZ FLAG is set (more parameters), JUMP BACK to 4ED2H to process next keyword.

No more parameters. Write the directory sector with accumulated changes.

4F15
GOSUB to SYS0 routine at 48C4H to write the modified directory sector to disk.
4F18
RET NZ C0
If NZ FLAG is set (write failed), RETURN with error code in A.

Directory written successfully. Check if any flags were accumulated that require additional processing.

4F19
LD A,00H 3E 00
Load Register A with 00H. (Note: This byte at 4F1AH is modified by code at 4F05H to contain accumulated flags.)
4F1B
OR A B7
OR A with itself to test if any flags were accumulated.
4F1C
LD B,A 47
Copy flags to B for later testing.
4F1D
RET Z C8
If Z FLAG is set (no flags accumulated), RETURN - simple attribute update complete.

Flags were accumulated. Process the additional operations (like copying names or updating allocation).

4F1E
LD DE,(43CEH) ED 5B CE 43
Load DE with the directory entry pointer from 43CEH.
4F22
RRCA 0F
Rotate A right - move bit 0 to CARRY for testing.
4F23
If NO CARRY (bit 0 was clear), JUMP to 4F28H to skip name update.
4F25
LD DE,4296H 11 96 42
Load DE with 4296H - address of default drive/name area.
4F28
LD A,01H 3E 01
Load Register A with 01H - write mode parameter for directory update.
4F2A
GOSUB to SYS0 routine at 48AFH to read directory sector for modification.
4F2D
RET NZ C0
If NZ FLAG is set (read failed), RETURN with error code.
4F2E
LD A,(431FH) 3A 1F 43
Load Register A with the value at 431FH - number of granules per file or system parameter.
4F31
ADD 08H C6 08
ADD 08H to A (adjust for granule table offset).
4F33
LD (4F6DH),A 32 6D 4F
Store adjusted granule count at 4F6DH - self-modifying code for loop limit.
4F36
XOR A AF
Set Register A to ZERO.
4F37
LD C,A 4F
Initialize Register C to zero (granule counter).

4F38H - Directory Entry Scan Loop

[LOOP START] Scan through directory entries looking for matching files or empty slots.

4F38
[LOOP] GOSUB to SYS0 routine at 48DBH to read next directory entry. Returns with HL pointing to entry.
4F3B
RET NZ C0
If NZ FLAG is set (read error), RETURN with error code.
4F3C
LD A,(HL) 7E
Load Register A with the first byte of directory entry (status/flags byte).
4F3D
AND 90H E6 90
Mask A with 90H to isolate bits 7 (active) and 4 (extent flag).
4F3F
CP 10H FE 10
Compare A against 10H. If A equals 10H (extent entry, not deleted), Z FLAG is set.
4F41
If NZ FLAG is set (not a valid extent), JUMP to 4F5EH to skip to next entry.

Valid extent entry found. Check if update flags indicate we should modify it.

4F43
BIT 2,B CB 50
Test bit 2 of B (accumulated flags). If set, need to clear write-protect flag.
4F45
If Z FLAG is set (bit 2 clear), JUMP to 4F4BH to skip write-protect clear.
4F47
INC HL 23
INCrement HL to point to flags byte (offset +1).
4F48
RES 5,(HL) CB AE
Reset (clear) bit 5 of the byte at (HL) - clear write-protect flag.
4F4A
DEC HL 2B
DECrement HL to point back to start of directory entry.
4F4B
LD A,B 78
Load Register A with accumulated flags from B.
4F4C
AND 03H E6 03
Mask A with 03H to isolate bits 0-1 (name copy flags).
4F4E
If Z FLAG is set (no name copy needed), JUMP to 4F5EH to skip to next entry.
4F50
LD A,(HL) 7E
Load Register A with the directory entry status byte.
4F51
AND 48HAND 01001000 E6 48
Mask A with 48H to check bits 6 and 3 (locked/protected flags).
4F53
If NZ FLAG is set (entry is locked/protected), JUMP to 4F5EH to skip modification.

Entry can be modified. Update the name/extent data at offset 10H-13H.

4F55
SET 4,L CB E5
Set bit 4 of L, changing HL from entry+0 to entry+10H (name area offset).
4F57
LD (HL),E 73
Store E (low byte of name hash) at entry+10H.
4F58
INC HL 23
INCrement HL to entry+11H.
4F59
LD (HL),D 72
Store D (high byte of name hash) at entry+11H.
4F5A
INC HL 23
INCrement HL to entry+12H.
4F5B
LD (HL),E 73
Store E again at entry+12H (duplicated for extent tracking).
4F5C
INC HL 23
INCrement HL to entry+13H.
4F5D
LD (HL),D 72
Store D at entry+13H.

4F5EH - Advance to Next Directory Entry

Calculate address of next directory entry (each is 32 bytes) and continue loop if more entries remain.

4F5E
LD A,L 7D
Load Register A with the low byte of HL (current position in directory sector).
4F5F
AND 0E0HAND 11100000 E6 E0
Mask A with E0H to align to 32-byte boundary (clear bits 0-4).
4F61
ADD 20H C6 20
ADD 20H (32) to advance to next directory entry.
4F63
LD L,A 6F
Store the new low byte back to L.
4F64
If NO CARRY (didn't wrap past sector boundary), LOOP BACK to 4F3CH to process next entry.

Finished this sector. Write it and continue with next directory sector.

4F66
GOSUB to SYS0 routine at 48C4H to write the current directory sector.
4F69
RET NZ C0
If NZ FLAG is set (write failed), RETURN with error code.
4F6A
INC C 0C
INCrement C (directory sector counter).
4F6B
LD A,C 79
Load Register A with the sector counter.
4F6C
CP 00H FE 00
Compare A against 00H. (Note: This byte at 4F6DH is modified at 4F33H with max sector count.)
4F6E
If CARRY (more sectors to process), LOOP BACK to 4F37H to read next directory sector.

All directory sectors processed. Return success.

4F70
XOR A AF
Set Register A to ZERO indicating success.
4F71
RET C9
RETURN with A=0 (success).

4F72H - File Specification Validation

Validate that a file specification was provided on the command line. If no filespec, return parse error.

4F72
GOSUB to SYS0 routine at 4C7EH to check for valid filespec character at (HL).
4F75
RET NC D0
If NO CARRY (valid character found = filespec present), RETURN normally to continue processing.
4F76
JUMP to 4F97H to return parse error (no filespec provided).

4F78H - Keyword Table Search and Dispatch

Search through a null-terminated keyword table pointed to by BC. Each entry has format: dispatch_byte, string, 00H. On match, push dispatch address and return to execute it.

4F78
LD D,02H 16 02
Load Register D with 02H - number of bytes to read for dispatch address (low+high).
4F7A
GOSUB to 4F84H to search for matching keyword in table at (BC).

Match found. BC points past the matched string. Read the 2-byte dispatch address.

4F7D
LD A,(BC) 0A
Load Register A with the low byte of dispatch address from (BC).
4F7E
LD E,A 5F
Copy low byte to E.
4F7F
INC BC 03
INCrement BC to point to high byte of dispatch address.
4F80
LD A,(BC) 0A
Load Register A with the high byte of dispatch address from (BC).
4F81
LD D,A 57
Copy high byte to D. DE now contains the dispatch address.
4F82
PUSH DE D5
Push the dispatch address onto the stack.
4F83
RET C9
RETURN - this pops the dispatch address and jumps to it (trampoline pattern).

4F84H - Keyword String Match

Compare command line at (HL) against keyword table entries at (BC). Each table entry is: byte, null-terminated_string. D contains number of entries to skip on mismatch.

4F84
[LOOP] GOSUB to SYS0 routine at 4C6AH to compare command line (HL) against table entry (BC).
4F87
RET Z C8
If Z FLAG is set (strings match), RETURN with BC pointing past the matched string.

No match. Skip to null terminator then advance past the associated data bytes.

4F88
LD A,(BC) 0A
[INNER LOOP] Load byte from table at (BC).
4F89
CP 00H FE 00
Compare A against 00H (null terminator).
4F8B
INC BC 03
INCrement BC to next byte.
4F8C
If NZ (not null yet), LOOP BACK to 4F88H to continue scanning for null.

Found null terminator. Now skip D bytes of data associated with this entry.

4F8E
LD E,D 5A
Copy D (skip count) to E for countdown.
4F8F
INC BC 03
[SKIP LOOP] INCrement BC past data byte.
4F90
DEC E 1D
DECrement E (remaining bytes to skip).
4F91
If NZ (more to skip), LOOP BACK to 4F8FH.

Check if there are more entries in table (next byte non-zero).

4F93
LD A,(BC) 0A
Load next byte from table.
4F94
OR A B7
OR A with itself to test if zero (end of table).
4F95
If NZ (more entries), LOOP BACK to 4F84H to try next keyword.

End of table - no match found. Return parse error.

4F97
JUMP to 4D63H to return error code 34H (parse error).

4F9AH - Parse Parameter with Whitespace Check

Skip whitespace, then verify a valid parameter character exists before parsing.

4F9A
GOSUB to SYS0 routine at 4C7AH to skip whitespace in command buffer.
4F9D
If NZ FLAG is set (valid character found), JUMP to 4FA3H to check for parameter.
4F9F
RET C9
RETURN - no parameter present (end of line).

4FA0H - Parse Filespec Character Check

Check for valid filespec character and return error if invalid.

4FA0
GOSUB to SYS0 routine at 4C7EH to check for valid filespec character.
4FA3
If CARRY (invalid character), JUMP to 4F97H for parse error.

4FA5H - Parse Hexadecimal/Decimal Number

Parse a numeric value from command line. If value ends with 'H', treat as hexadecimal; otherwise decimal. Returns value in DE.

4FA5
PUSH HL E5
Save HL (command line pointer) onto the stack.
4FA6
LD B,00H 06 00
Load Register B with 00H - flags: bit 0=hex mode, bit 1=digit found.
4FA8
GOSUB to 4FC6H to parse digits from command line into DE.

Check if value should be interpreted as hex (followed by 'H').

4FAB
LD A,(HL) 7E
Load Register A with character after the number.
4FAC
SUB 41H D6 41
Subtract 41H (ASCII 'A'). If result is 0-7, it's a valid drive letter.
4FAE
CP 08H FE 08
Compare against 08H. If < 8, it's a valid drive letter (A-H).
4FB0
If NO CARRY (not a drive letter), JUMP to 4FBFH to check flags.

Letter A-H follows. This triggers hex mode. Re-parse from beginning.

4FB2
POP HL E1
Restore original HL (start of number).
4FB3
LD B,01H 06 01
Load B with 01H - set bit 0 to enable hex digit parsing.
4FB5
PUSH HL E5
Save HL again for potential error recovery.
4FB6
GOSUB to 4FC6H to re-parse as hexadecimal.
4FB9
LD A,(HL) 7E
Load character after hex number.
4FBA
CP 48H FE 48
Compare against 48H (ASCII H). If equal, valid hex suffix.
4FBC
INC HL 23
INCrement HL past the 'H' suffix.
4FBD
If NZ (not 'H'), JUMP to 4FC3H for error.
4FBF
BIT 1,B CB 48
Test bit 1 of B (was at least one digit found?).
4FC1
POP BC C1
Restore BC (discard saved HL).
4FC2
RET NZ C0
If NZ (digit was found = valid number), RETURN with value in DE.
4FC3
JUMP to 4DD7H for parameter error (no valid digits found).

4FC6H - Parse Digit String

Parse consecutive digits from (HL) into DE. B bit 0 controls hex/decimal mode. Sets B bit 1 when digit found.

4FC6
LD DE,0000H 11 00 00
Initialize DE to 0000H - accumulator for parsed value.
4FC9
LD A,(HL) 7E
[LOOP] Load character from command line at (HL).
4FCA
SUB 30H D6 30
Subtract 30H (ASCII '0'). If 0-9, valid decimal digit.
4FCC
CP 0AH FE 0A
Compare against 0AH. If < 10, valid decimal digit.
4FCE
If CARRY (digit 0-9), JUMP to 4FDAH to process it.

Not 0-9. Check if hex mode and if character is A-F.

4FD0
BIT 0,B CB 40
Test bit 0 of B (hex mode flag).
4FD2
RET Z C8
If Z (decimal mode only), RETURN - non-digit ends parsing.
4FD3
SUB 11H D6 11
Subtract 11H to convert 'A'-'F' to 0-5 range (after '0' subtraction).
4FD5
CP 06H FE 06
Compare against 06H. If < 6, valid hex letter A-F.
4FD7
RET NC D0
If NO CARRY (not A-F), RETURN - parsing complete.
4FD8
ADD 0AH C6 0A
ADD 0AH to convert to value 10-15.
4FDA
PUSH HL E5
Save HL (command line pointer).
4FDB
LD H,D 62
Copy D to H (prepare for multiplication).
4FDC
LD L,E 6B
Copy E to L. HL now contains current accumulated value.
4FDD
LD C,A 4F
Save new digit value in C.
4FDE
XOR A AF
Clear A (overflow accumulator for 24-bit multiplication).
4FDF
SET 1,B CB C8
Set bit 1 of B to indicate at least one digit was found.

Multiply accumulated value by base (10 or 16) and add new digit.

4FE1
ADD HL,HL 29
HL = HL * 2 (shift left).
4FE2
ADC A,A 8F
A = A * 2 + carry (track overflow).
4FE3
ADD HL,HL 29
HL = HL * 2 (total: * 4).
4FE4
ADC A,A 8F
Track overflow.
4FE5
BIT 0,B CB 40
Test bit 0 of B (hex mode?).
4FE7
If Z (decimal mode), JUMP to 4FECH to add original value.

Hex mode: multiply by 16 total (need * 4 more).

4FE9
ADD HL,HL 29
HL = HL * 2 (total: * 8).
4FEA
JUMP to 4FEDH to continue multiply by 2.

Decimal mode: multiply by 10 total (need +original value then *2).

4FEC
ADD HL,DE 19
ADD original value: HL = HL + DE (was *4, now *5).
4FED
ADC A,A 8F
Track overflow.
4FEE
ADD HL,HL 29
HL = HL * 2 (decimal: *10 total, hex: *16 total).
4FEF
ADC A,A 8F
Track overflow.

Add new digit value to accumulated result.

4FF0
LD E,C 59
Load E with digit value from C.
4FF1
LD D,00H 16 00
Clear D (DE now contains digit value as 16-bit).
4FF3
ADD HL,DE 19
ADD digit value: HL = HL + digit.
4FF4
ADC A,A 8F
Track overflow into A.
4FF5
EX DE,HL EB
Exchange DE and HL. DE now contains new accumulated value.
4FF6
POP HL E1
Restore HL (command line pointer).
4FF7
If NZ (overflow occurred = value > 65535), JUMP to 4FC3H for error.
4FF9
INC HL 23
INCrement HL to next character.
4FFA
LOOP BACK to 4FC9H to parse next digit.

4FFCH - Check Valid Filename Character

Check if character at (HL) is a valid filename character (0-9 or A-Z).

4FFC
LD A,(HL) 7E
Load character from command line at (HL).
4FFD
CP 30H FE 30
Compare against 30H (ASCII '0'). If < '0', invalid.
4FFF
If CARRY (char < '0'), JUMP to 5016H to pad with spaces.

5001H - Continue Filename Character Check

Continuation of filename character validation - checks if character is digit or letter.

5001
CP 3AH FE 3A
Compare A against 3AH (ASCII :). Characters '0'-'9' are 30H-39H, so if < 3AH it's a digit.
5003
JUMP to 500BH to check carry result and continue.

5005H - Parse Filename and Compute Hash

Main filename parsing routine. Reads up to 8 characters from command line into buffer at 51E8H, then computes a hash value for directory lookup. Returns hash in DE.

5005
LD DE,51E7H 11 E7 51
Load DE with 51E7H - one byte before the filename buffer (will be incremented before first store).
5008
LD B,08H 06 08
Load Register B with 08H (8 decimal) - maximum filename length counter.
500A
OR A B7
Clear CARRY FLAG by ORing A with itself (preparation for character checking).
500B
If CARRY (character was valid digit), JUMP to 501EH to store it.

Character was not a digit. Check if it's an uppercase letter (A-Z).

500D
LD A,(HL) 7E
Load character from command line at (HL).
500E
CP 41H FE 41
Compare against 41H (ASCII A). If < 'A', not a letter.
5010
If CARRY (char < 'A'), JUMP to 5016H to pad remaining positions with spaces.
5012
CP 5BH FE 5B
Compare against 5BH (one past ASCII Z). If < 5BH, it's A-Z.
5014
If CARRY (char is 'A'-'Z'), JUMP to 501EH to store it.

5016H - Pad Filename with Spaces

[LOOP] Pad remaining filename positions with spaces (20H) when filename is shorter than 8 characters.

5016
INC DE 13
[PAD LOOP] INCrement DE to point to next buffer position.
5017
LD A,20H 3E 20
Load Register A with 20H (ASCII space).
5019
LD (DE),A 12
Store space character at buffer position (DE).
501A
DECrement B and Jump if Not Zero. LOOP BACK to 5016H until all 8 positions filled.
501C
JUMP to 5023H to compute filename hash.

501EH - Store Valid Filename Character

Store a valid filename character and continue parsing.

501E
INC DE 13
INCrement DE to point to next buffer position.
501F
LD (DE),A 12
Store the valid character from A at buffer position (DE).
5020
INC HL 23
INCrement HL to point to next character in command line.
5021
DECrement B and Jump if Not Zero. LOOP BACK to 4FFCH to check next character.

5023H - Compute Filename Hash

Compute a 16-bit hash value from the 8-character filename buffer. This hash is used for fast directory lookups. The algorithm XORs rotated character values to produce a unique identifier.

5023
PUSH HL E5
Save HL (command line pointer) onto the stack.
5024
EX DE,HL EB
Exchange DE and HL. HL now points to end of filename buffer (51EFH).
5025
LD DE,FFFFH 11 FF FF
Initialize DE with FFFFH - starting value for hash accumulator.
5028
LD B,08H 06 08
Load Register B with 08H (8) - loop counter for 8 characters.

[HASH LOOP START] Process each character through a series of rotations and XORs to compute hash.

502A
PUSH BC C5
[HASH LOOP] Save BC (loop counter) onto the stack.
502B
LD A,E 7B
Load Register A with low byte of hash (E).
502C
AND 07HAND 00000111 E6 07
Mask A with 07H to get bits 0-2 of E.
502E
LD C,A 4F
Save masked value in C.
502F
LD A,E 7B
Load A with E again.
5030
RLCA 07
Rotate A left (multiply by 2, bit 7 to bit 0).
5031
RLCA 07
Rotate A left again (multiply by 4).
5032
RLCA 07
Rotate A left (multiply by 8, bits wrapped around).
5033
XOR C A9
XOR A with C (combine rotated value with original low bits).
5034
RLCA 07
Rotate A left again.
5035
LD C,A 4F
Save intermediate result in C.
5036
AND 0F0HAND 11110000 E6 F0
Mask A with F0H to keep only high nibble.
5038
LD B,A 47
Save high nibble in B.
5039
LD A,C 79
Load A with C (intermediate value).
503A
RLCA 07
Rotate A left.
503B
AND 1FHAND 00011111 E6 1F
Mask A with 1FH to keep only bits 0-4.
503D
XOR B A8
XOR A with B (combine with saved high nibble).
503E
XOR D AA
XOR A with D (combine with high byte of hash).
503F
LD E,A 5F
Store result as new low byte of hash in E.
5040
LD A,C 79
Load A with C again.
5041
AND 0FHAND 00001111 E6 0F
Mask A with 0FH to keep only low nibble.
5043
LD B,A 47
Save low nibble in B.
5044
LD A,C 79
Load A with C.
5045
RLCA 07
Rotate A left.
5046
RLCA 07
Rotate A left.
5047
RLCA 07
Rotate A left.
5048
RLCA 07
Rotate A left (total: swap nibbles).
5049
XOR B A8
XOR A with B.
504A
POP BC C1
Restore BC (loop counter).
504B
XOR (HL) AE
XOR A with the filename character at (HL).
504C
LD D,A 57
Store result as new high byte of hash in D.

Clear the character in buffer (replace with space) and move to previous character.

504D
LD (HL),20H 36 20
Store 20H (space) at (HL) - clear the buffer position after hashing.
504F
DEC HL 2B
DECrement HL to point to previous character in buffer.
5050
DECrement B and Jump if Not Zero. LOOP BACK to 502AH until all 8 characters processed.
5052
POP HL E1
Restore HL (command line pointer) from the stack.
5053
RET C9
RETURN with filename hash in DE.

5054H - Attribute Command Keyword Table (Table 1)

This table is referenced from 4E11H via JP 4F78H. The search routine at 4F78H sets D=02H, meaning each entry has a 2-byte handler address after the null-terminated keyword string.

Table Format: [keyword_string][00H][handler_addr_low][handler_addr_high]

Entry: "INV" - Set Invisible Attribute

Makes file invisible in directory listings unless the I option is specified in DIR.

5054
DEFM 'INV' 49 4E 56
Keyword: "INV" - Invisible attribute command
5057
DEFB 00H 00
Null terminator
5058
DEFW 4E54H 54 4E
Handler: 4E54H - INV attribute handler

Entry: "VIS" - Clear Invisible Attribute

Takes away the invisible attribute, whether the file had it or not.

505A
DEFM 'VIS' 56 49 53
Keyword: "VIS" - Visible attribute command
505D
DEFB 00H 00
Null terminator
505E
DEFW 4E58H 58 4E
Handler: 4E58H - VIS attribute handler

Entry: "PROT=" - Protection Level

Specifies the access level if passwords are enabled and the access (not update) password was used to open the file.

5060
DEFM 'PROT=' 50 52 4F 54 3D
Keyword: "PROT=" - Protection level command
5065
DEFB 00H 00
Null terminator
5066
DEFW 4E6AH 6A 4E
Handler: 4E6AH - PROT= handler (searches PROT level table at 5093H)

Entry: "ACC=" - Access Password

Assigns an access password (1-8 characters, first must be A-Z, others A-Z or 0-9). This is the only way to enable PROT=xxx protection.

5068
DEFM 'ACC=' 41 43 43 3D
Keyword: "ACC=" - Access password command
506C
DEFB 00H 00
Null terminator
506D
DEFW 4E78H 78 4E
Handler: 4E78H - ACC= handler (offset 12H)

Entry: "UPD=" - Update Password

Assigns the update password. If passwords are enabled and the update password matches at file open, FULL access is allowed.

506F
DEFM 'UPD=' 55 50 44 3D
Keyword: "UPD=" - Update password command
5073
DEFB 00H 00
Null terminator
5074
DEFW 4E7CH 7C 4E
Handler: 4E7CH - UPD= handler (offset 10H)

Entry: "ASE=" - Auto-Space-Extend

ASE=Y (default) allows DOS to automatically allocate diskette space. ASE=N disallows further allocation.

5076
DEFM 'ASE=' 41 53 45 3D
Keyword: "ASE=" - Auto-space-extend flag
507A
DEFB 00H 00
Null terminator
507B
DEFW 4E31H 31 4E
Handler: 4E31H - ASE= handler (bit 7, mask 80H)

Entry: "ASC=" - Auto-Space-Compress

ASC=Y (default) allows DOS to deallocate space beyond EOF during CLOSE. ASC=N disallows deallocation.

507D
DEFM 'ASC=' 41 53 43 3D
Keyword: "ASC=" - Auto-space-compress flag
5081
DEFB 00H 00
Null terminator
5082
DEFW 4E35H 35 4E
Handler: 4E35H - ASC= handler (bit 6, mask 40H)

Entry: "UDF=" - User-Defined Flag (Updated)

UDF=Y marks file as updated. UDF=N clears the updated mark. DOS marks files updated when writing sectors.

5084
DEFM 'UDF=' 55 44 46 3D
Keyword: "UDF=" - User-defined/updated flag
5088
DEFB 00H 00
Null terminator
5089
DEFW 4E2AH 2A 4E
Handler: 4E2AH - UDF= handler (bit 5, mask 20H)

Entry: "LRL=" - Logical Record Length

Sets the logical record length for random access files (0-255 bytes).

508B
DEFM 'LRL=' 4C 52 4C 3D
Keyword: "LRL=" - Logical record length
508F
DEFB 00H 00
Null terminator
5090
DEFW 4E17H 17 4E
Handler: 4E17H - LRL= handler

End of Table 1

5092
DEFB 00H 00
End marker: Null byte indicates end of attribute keyword table

5093H - Protection Level Keyword Table (Table 2)

This table is referenced from 4E6AH via CALL 4F84H. The calling code sets D=01H, meaning each entry has a 1-byte protection level value (not an address) after the null-terminated keyword string.

Table Format: [keyword_string][00H][protection_level_byte]

These keywords are used with the PROT= command to specify access levels 0-7.

Entry: "LOCK" - Level 7

No access allowed to the file at all, except by the system's overlay loader.

5093
DEFM 'LOCK' 4C 4F 43 4B
Keyword: "LOCK" - Maximum protection
5097
DEFB 00H 00
Null terminator
5098
DEFB 07H 07
Value: Protection level 7 (LOCK)

Entry: "EXEC" - Level 6

Access allowed only to execute the file as a program. BASIC requires RUN or LOAD with R option, disables BREAK key.

5099
DEFM 'EXEC' 45 58 45 43
Keyword: "EXEC" - Execute only
509D
DEFB 00H 00
Null terminator
509E
DEFB 06H 06
Value: Protection level 6 (EXEC)

Entry: "READ" - Level 5

Access allowed for execute or to read the file's contents.

509F
DEFM 'READ' 52 45 41 44
Keyword: "READ" - Read access
50A3
DEFB 00H 00
Null terminator
50A4
DEFB 05H 05
Value: Protection level 5 (READ)

Entry: "WRITE" - Level 4

Access allowed for execute, read or write of the file.

50A5
DEFM 'WRITE' 57 52 49 54 45
Keyword: "WRITE" - Write access
50AA
DEFB 00H 00
Null terminator
50AB
DEFB 04H 04
Value: Protection level 4 (WRITE)

Entry: "RENAME" - Level 2

Access allowed for execute, read, write or to rename the file.

50AC
DEFM 'RENAME' 52 45 4E 41 4D 45
Keyword: "RENAME" - Rename access
50B2
DEFB 00H 00
Null terminator
50B3
DEFB 02H 02
Value: Protection level 2 (RENAME)

Entry: "NAME" - Level 2 (alias)

Same as RENAME - alternate keyword for level 2 protection.

50B4
DEFM 'NAME' 4E 41 4D 45
Keyword: "NAME" - Rename access (alias)
50B8
DEFB 00H 00
Null terminator
50B9
DEFB 02H 02
Value: Protection level 2 (NAME)

Entry: "KILL" - Level 1

Access allowed for execute, read, write, rename or to kill (delete) the file.

50BA
DEFM 'KILL' 4B 49 4C 4C
Keyword: "KILL" - Kill access
50BE
DEFB 00H 00
Null terminator
50BF
DEFB 01H 01
Value: Protection level 1 (KILL)

Entry: "FULL" - Level 0

All operations are allowed on the file (no protection).

50C0
DEFM 'FULL' 46 55 4C 4C
Keyword: "FULL" - Full access
50C4
DEFB 00H 00
Null terminator
50C5
DEFB 00H 00
Value: Protection level 0 (FULL)

End of Table 2

50C6
DEFB 00H 00
End marker: Null byte indicates end of protection level table

50C7H - Password/File Operation Keyword Table (Table 3)

This table is referenced from 4ED2H via JP 4F78H. The search routine at 4F78H sets D=02H, meaning each entry has a 2-byte handler address after the null-terminated keyword string.

Table Format: [keyword_string][00H][handler_addr_low][handler_addr_high]

Entry: "PW=" - Password Specification

Specifies password for file operations.

50C7
DEFM 'PW=' 50 57 3D
Keyword: "PW=" - Password command
50CA
DEFB 00H 00
Null terminator
50CB
DEFW 4F09H 09 4F
Handler: 4F09H - Store directory entry pointer

Entry: "UNLOCK" - Unlock File

Removes lock protection from a file.

50CD
DEFM 'UNLOCK' 55 4E 4C 4F 43 4B
Keyword: "UNLOCK" - Remove lock
50D3
DEFB 00H 00
Null terminator
50D4
DEFW 4EFAH FA 4E
Handler: 4EFAH - UNLOCK handler (sets flag 01H)

Entry: "LOCK" - Lock File

Applies lock protection to a file.

50D6
DEFM 'LOCK' 4C 4F 43 4B
Keyword: "LOCK" - Apply lock (in PW context)
50DA
DEFB 00H 00
Null terminator
50DB
DEFW 4EFEH FE 4E
Handler: 4EFEH - LOCK handler (sets flag 02H)

Entry: "NAME=" - New Name

Renames a file to a new name. The DOS command "NNAME=" uses this entry (the "N" prefix is parsed separately).

50DD
DEFM 'NAME=' 4E 41 4D 45 3D
Keyword: "NAME=" - Name command (used for NNAME=)
50E2
DEFB 00H 00
Null terminator
50E3
DEFW 4EDDH DD 4E
Handler: 4EDDH - NAME= handler (copies 8 chars to 43D0H)

Entry: "DATE=" - New Date

Sets a new date for the file's directory entry. The DOS command "NDATE=" uses this entry.

50E5
DEFM 'DATE=' 44 41 54 45 3D
Keyword: "DATE=" - Date command (used for NDATE=)
50EA
DEFB 00H 00
Null terminator
50EB
DEFW 4ED8H D8 4E
Handler: 4ED8H - DATE= handler (copies 8 chars to 43D8H)

Entry: "RUF" - Random Update Flag

Controls the random update flag for the file.

50ED
DEFM 'RUF' 52 55 46
Keyword: "RUF" - Random update flag
50F0
DEFB 00H 00
Null terminator
50F1
DEFW 4EF6H F6 4E
Handler: 4EF6H - RUF handler (sets flag 04H)

End of Table 3

50F3
DEFB 00H 00
End marker: Null byte indicates end of password/file operation table

50F4H - DUMP Command Entry Point (Sub-function 7)

This handler implements the DUMP command, which displays memory contents in hexadecimal format. It parses start and end addresses from the command line, then outputs the data via RST 18H to the configured output device.

50F4
LD HL,4D68H 21 68 4D
Load HL with 4D68H - address of alternate handler for PROT function (used as callback).
50F7
LD (4483H),HL 22 83 44
Store HL at 4483H - save callback address for later use in FCB or system area.
50FA
POP AF F1
Restore AF from the stack (discard SVC caller state).
50FB
POP HL E1
Restore HL from the stack (command line pointer).
50FC
GOSUB to 4FA0H to check for valid parameter character and return error if invalid.
50FF
PUSH DE D5
Save DE (parsed first address) onto the stack.
5100
GOSUB to 4FA0H to parse second address (end address) into DE.
5103
EX DE,HL EB
Exchange DE and HL. HL now contains end address, DE contains command line pointer.
5104
EX (SP),HL E3
Exchange HL with stack. HL gets start address, stack gets end address.
5105
EX DE,HL EB
Exchange DE and HL. DE now contains start address, HL contains command line pointer.
5106
PUSH DE D5
Save DE (start address) onto the stack.
5107
LD DE,402DH 11 2D 40
Load DE with 402DH - DOS warm start/ready entry point address.
510A
GOSUB to 4F9AH to skip whitespace and check for optional parameter.
510D
LD A,D 7A
Load Register A with high byte of DE (parsed value or default).
510E
AND E A3
AND A with E. If both D and E are FFH, result is FFH.
510F
INC A 3C
INCrement A. If A was FFH, it becomes 00H and Z flag is set.
5110
EX DE,HL EB
Exchange DE and HL.
5111
EX (SP),HL E3
Exchange HL with stack.
5112
EX DE,HL EB
Exchange DE and HL.
5113
PUSH DE D5
Save DE onto the stack.
5114
If NZ FLAG is set (third parameter present), GOSUB to 4F9AH to parse it.
5117
GOSUB to 4D5FH to check for end of line.

Organize stack: retrieve all parameters for DUMP operation.

511A
POP BC C1
Restore BC from the stack.
511B
POP AF F1
Restore AF from the stack.
511C
POP HL E1
Restore HL from the stack.
511D
PUSH AF F5
Save AF back onto the stack.
511E
PUSH BC C5
Save BC back onto the stack.
511F
PUSH HL E5
Save HL back onto the stack.
5120
PUSH DE D5
Save DE (end address) onto the stack.

Validate that end address >= start address.

5121
OR A B7
Clear CARRY FLAG for subtraction.
5122
SBC HL,BC ED 42
Subtract BC (start address) from HL (end address). If HL < BC, CARRY is set.
5124
PUSH HL E5
Save result (byte count) onto the stack.
5125
If CARRY (end < start), JUMP to 4DD7H for parameter error.

Calculate number of 256-byte blocks and handle partial block.

5128
LD BC,0005H 01 05 00
Load BC with 0005H - adjustment value for block calculation.
512B
ADD HL,BC 09
ADD BC to HL (byte count + 5).
512C
If NO CARRY (result fits in 16 bits), JUMP to 5133H.
512E
LD HL,0104H 21 04 01
Load HL with 0104H (260) - maximum block size indicator.
5131
JUMP to 5138H to store block parameters.
5133
LD A,FCH 3E FC
Load A with FCH (-4 in two's complement) for division adjustment.
5135
GOSUB to SYS0 routine at 4C59H to perform division/calculation.
5138
LD (448AH),HL 22 8A 44
Store the block count at 448AH - FCB parameter area.
513B
LD DE,4480H 11 80 44
Load DE with 4480H - FCB/parameter block address.
513E
LD BC,E908H 01 08 E9
Load BC with E908H: B=E9H (SVC code), C=08H (sub-function for continuation).
5141
LD HL,4978H 21 78 49
Load HL with 4978H - address of continuation handler in SYS0.
5144
PUSH BC C5
Save BC (SVC parameters) onto the stack.
5145
PUSH HL E5
Save HL (continuation address) onto the stack.
5146
JUMP to SYS0 routine at 4439H to set up and execute DUMP operation.

5149H - DUMP Continuation Handler (Sub-function 8)

This handler continues the DUMP output after setup. It outputs memory bytes in hexadecimal format, one line at a time, using RST 18H for each character.

5149
POP AF F1
Restore AF from the stack.
514A
GOSUB to SYS0 routine at 443FH to check operation status.
514D
If NZ FLAG is set (error occurred), JUMP to 519FH to handle error.

Retrieve stored parameters using alternate register set.

514F
EXX D9
Exchange BC, DE, HL with their shadow registers BC', DE', HL'.
5150
POP DE D1
Restore DE' from the stack (end address or count).
5151
POP HL E1
Restore HL' from the stack.
5152
INC DE 13
INCrement DE' (adjust pointer).
5153
LD (51CCH),HL 22 CC 51
Store HL' at 51CCH - self-modifying code storing address parameter.
5156
POP HL E1
Restore another HL' from the stack.
5157
LD (51BEH),HL 22 BE 51
Store at 51BEH - self-modifying code for end address.
515A
POP HL E1
Restore HL' from the stack (start address).
515B
LD (51C5H),HL 22 C5 51
Store at 51C5H - self-modifying code for start address.
515E
POP BC C1
Restore BC' from the stack.
515F
EX DE,HL EB
Exchange DE' and HL'.
5160
LD A,B 78
Load A with B' (high byte of parameter).
5161
AND C A1
AND A with C'. If both are FFH, result is FFH.
5162
INC A 3C
INCrement A. If FFH, becomes 00H and Z flag is set.
5163
If Z FLAG is set (special case - no limit), JUMP to 51A4H for continuous dump.

Normal dump with byte count limit. Set up loop.

5165
PUSH BC C5
Save BC' (parameters) onto the stack.
5166
LD A,H 7C
Load A with H (high byte of address/count).
5167
OR L B5
OR with L. If HL is zero, Z flag is set.
5168
If NZ (count not zero), JUMP to 5172H for normal processing.

Count is zero - output remaining bytes (less than 254).

516A
LD BC,00FEH 01 FE 00
Load BC with 00FEH (254) - maximum single line output.
516D
OR A B7
Clear CARRY for subtraction.
516E
SBC HL,BC ED 42
Subtract BC from HL.
5170
JUMP to 517AH to continue.

5172H - DUMP Output Loop

[DUMP OUTPUT LOOP] Output one line of dump (up to 254 bytes), then loop until all bytes output.

5172
LD BC,00FEH 01 FE 00
[OUTER LOOP] Load BC with 00FEH (254) - bytes per line.
5175
OR A B7
Clear CARRY for subtraction.
5176
SBC HL,BC ED 42
Subtract BC from HL (remaining count). If < 254, CARRY is set.
5178
If CARRY (remaining < 254), JUMP to 518DH to handle last partial line.
517A
INC C 0C
INCrement C (adjust byte count).
517B
INC C 0C
INCrement C again. C now contains line length.
517C
LD B,01H 06 01
Load B with 01H - line type indicator.
517E
GOSUB to 51B3H to output header bytes (type and count).

[BYTE OUTPUT LOOP] Output each memory byte as hex.

5181
DEC C 0D
[INNER LOOP] DECrement C (remaining bytes in line).
5182
DEC C 0D
DECrement C again (account for checksum).
5183
LD A,(DE) 1A
[BYTE LOOP] Load A with byte from memory at (DE).
5184
INC DE 13
INCrement DE to next memory address.
5185
GOSUB to 51DAH to output byte in A as two hex digits.
5188
DEC C 0D
DECrement C (remaining bytes).
5189
If NZ (more bytes), LOOP BACK to 5183H.
518B
JUMP BACK to 5172H to output next line.

518DH - Handle Last Partial Line

Handle the last line of dump when fewer than 254 bytes remain.

518D
OR A B7
Clear CARRY.
518E
ADC HL,BC ED 4A
ADD BC back to HL (restore original remaining count).
5190
LD C,L 4D
Copy L to C (remaining bytes as line count).
5191
LD L,H 6C
Copy H to L (high byte).
5192
If NZ (more bytes), JUMP to 517AH to output line.

Dump complete. Output end record.

5194
POP DE D1
Restore DE from the stack.
5195
LD B,02H 06 02
Load B with 02H - end record type indicator.
5197
LD C,B 48
Copy B to C (record length = 2).
5198
GOSUB to 51B3H to output end record header.
519B
EXX D9
Exchange back to main register set.
519C
GOSUB to SYS0 routine at 443FH to finalize operation.
519F
If NZ (error), JUMP to 51E0H for error handling.
51A1
JUMP to SYS0 routine at 4428H to return to DOS READY.

51A4H - Continuous Dump Mode

Handle continuous dump mode (no byte limit specified). Outputs bytes until break or end condition.

51A4
GOSUB to 51BBH to initialize output and calculate checksum.

[CONTINUOUS OUTPUT LOOP]

51A7
LD A,(DE) 1A
[LOOP] Load A with byte from memory at (DE).
51A8
INC DE 13
INCrement DE to next address.
51A9
GOSUB to 51DAH to output byte as hex.
51AC
DEC HL 2B
DECrement HL (remaining count).
51AD
LD A,H 7C
Load A with H.
51AE
OR L B5
OR with L. If HL is zero, Z flag is set.
51AF
If NZ (more bytes), LOOP BACK to 51A7H.
51B1
JUMP to 519BH to finalize and return.

51B3H - Output Record Header

Output record header bytes (type code and byte count) for dump format.

51B3
LD A,B 78
Load A with B (record type).
51B4
GOSUB to 51DAH to output record type as hex.
51B7
LD A,C 79
Load A with C (byte count).
51B8
GOSUB to 51DAH to output count as hex.

51BBH - Initialize Checksum

Initialize checksum calculation for dump record. Retrieves start address from self-modifying code locations.

51BB
PUSH HL E5
Save HL onto the stack.
51BC
PUSH DE D5
Save DE onto the stack.
51BD
LD HL,0000H 21 00 00
Load HL with 0000H. (Note: bytes at 51BEH-51BFH are modified at 5157H with end address.)
51C0
RST 18H DF
Execute RST 18H - output routine for address.
51C1
EX DE,HL EB
Exchange DE and HL.
51C2
If CARRY (error), JUMP to 51D3H to output checksum and return.
51C4
LD DE,0000H 11 00 00
Load DE with 0000H. (Note: bytes at 51C5H-51C6H are modified at 515BH with start address.)
51C7
RST 18H DF
Execute RST 18H - output routine for start address.
51C8
If CARRY (error), JUMP to 51D3H.

Calculate negative checksum (for verification).

51CA
PUSH HL E5
Save HL (current position).
51CB
LD HL,0000H 21 00 00
Load HL with 0000H. (Note: bytes at 51CCH-51CDH are modified at 5153H.)
51CE
OR A B7
Clear CARRY.
51CF
SBC HL,DE ED 52
Subtract DE from HL (calculate difference for checksum).
51D1
POP DE D1
Restore DE.
51D2
ADD HL,DE 19
ADD DE to HL.
51D3
LD A,L 7D
Load A with L (low byte of checksum).
51D4
GOSUB to 51DAH to output low byte as hex.
51D7
LD A,H 7C
Load A with H (high byte of checksum).
51D8
POP DE D1
Restore DE from the stack.
51D9
POP HL E1
Restore HL from the stack.

51DAH - Output Byte as Hexadecimal

Output the byte in Register A as two hexadecimal ASCII characters via RST 18H. Uses alternate register set for the actual output.

51DA
EXX D9
Exchange to alternate register set BC', DE', HL'.
51DB
GOSUB to ROM routine at 001BH - output byte in A as two hex ASCII characters.
51DE
EXX D9
Exchange back to main register set.
51DF
RET Z C8
If Z FLAG is set (output successful), RETURN.

51E0H - Error Exit

Jump to error handler when output fails or other error occurs.

51E0
JUMP to 4D65H to invoke the DOS error handler.

51E3H - Reserved Data Area

Reserved bytes at end of module - used as buffer space or padding.

51E3
NOP 00
Data: Reserved/padding byte (00H)
51E4
NOP 00
Data: Reserved/padding byte (00H)
51E5
NOP 00
Data: Reserved/padding byte (00H)
51E6
NOP 00
Data: Reserved/padding byte (00H)
51E7
NOP 00
Data: Reserved/padding byte (00H) - End of SYS7 module