TRS-80 DOS - TRSDOS v2.3 for the Model I - SYS4/SYS Disassembled

Page Customization

Introduction/Summary:

Program Overview

SYS4/SYS is the TRSDOS 2.3 error display overlay for the TRS-80 Model I, loaded into memory at 4E00H when an error condition is reported via the SVC code 86H (LD A,86H / RST 28H) dispatcher at SYS0. SYS4 converts a numeric error code into a human-readable multi-word error message and displays it on screen.

The overlay uses a compact dictionary-based message system rather than storing complete error message strings. A vocabulary of 53 common words (such as "READ", "WRITE", "ERROR", "DISK", "FILE", etc.) is stored in a string pool at 5030H-515AH. Each error code maps through a two-level lookup: first, an offset table at 4F84H translates the error code to a pointer into a descriptor chain at 515BH-51F2H. Each descriptor byte encodes a word index (bits 0-5) and a continuation flag (bit 7). The display loop walks the chain, printing each word separated by spaces, until it reaches a descriptor with bit 7 set (marking the last word).

Word addresses are stored in a DEFW address table at 4FC2H using a clever overlapping-entry scheme: each word's start address is a 2-byte entry, and the word's length is computed by subtracting the current entry from the next entry (SBC HL,DE). This eliminates the need to store separate length fields.

Beyond the core error message, SYS4 optionally displays contextual information. When bit 6 of the original error code is clear, the overlay first prints "*** ERRCODE=XX, " with the error number converted to a two-digit decimal value. After the error message words, if bit 6 is clear, it also displays extended context: the device name and drive number (from the FCB at 430AH), the associated filename (extracted from the FCB or directory entry), and the return address in hexadecimal format. The return address display uses the saved overlay return address at 430CH, adjusted by subtracting 3 to point back to the LD A,xxH instruction that triggered the error.

SYS4 terminates by testing bit 7 of the original error code. If bit 7 is set, it performs a cold restart via JP 0000H. If bit 7 is clear, it jumps to the error-already-displayed exit at 4030H to return to the DOS READY prompt.

Variable and Data Area List

Address RangePurpose
430AH-430BH
(2 bytes)
Saved FCB pointer (set by SYS0 overlay call context setup)
430CH-430DH
(2 bytes)
Saved overlay return address (points past the RST 28H that invoked SYS4)
4F36H-4F46H
(17 bytes)
Error code display template: LF + "*** ERRCODE=XX, " + ETX (XX at 4F42H-4F43H are self-modified)
4F42H-4F43H
(2 bytes)
Self-modified error code digits (tens and units, ASCII) within the 4F36H template
4F47H-4F4AH
(4 bytes)
Closing error marker string: "***" + CR
4F4BH-4F58H
(14 bytes)
Device display template (screen code + "<DEVICE=*XX>" + CR; bytes at 4F55H-4F56H are self-modified with drive/info)
4F55H-4F56H
(2 bytes)
Self-modified device context bytes within the 4F4BH template (drive number and info byte from FCB)
4F59H-4F5FH
(7 bytes)
File display prefix (screen code + "<FILE=")
4F60H-4F6FH
(16 bytes)
Filename buffer (filled at runtime with NAME/EXT:D> string + CR terminator)
4F70H-4F81H
(18 bytes)
Return address display prefix (screen code + "REFERENCED AT X'" + ETX)
4F82H-4F83H
(2 bytes)
Return address display suffix ("'" + CR)
4F84H-4FC1H
(62 bytes)
Error code offset table (one byte per error code 00H-3DH, indexing into 51xxH descriptor area; codes 27H-3DH all map to 51F0H default)
4FC2H-4F2DH
(108 bytes)
Word address DEFW table (54 entries, each a 2-byte little-endian pointer to the start of a word in the string pool; word length derived from next entry)
5030H-515AH
(299 bytes)
Error message word string pool (53 words: "NO", "ERROR", "FORMAT", "PARITY", "DURING", "HEADER", "DATA", "SEEK", "READ", "WRITE", "LOST", "NOT", "ATTEMPTED TO", "LOCKED/DELETED", "SYSTEM", "DIRECTORY", "MEMORY", "ON", "DISK", "DISKETTE", "FAULT", "PROTECTED", "ILLEGAL", "LOGICAL", "NUMBER", "FILE", "RECORD", "END", "OF", "OUT", "RANGE", "ENCOUNTERED", "CODE", "GAT", "HIT", "OVERLAY", "UNKNOWN", "LOAD", "SPACE", "ONLY", "NAME", "DEVICE", "FORMAT", "FOUND", "IN", "ACCESS", "FULL", "DRIVE", "DENIED", "PROGRAM", "AVAILABLE", "- CAN'T EXTEND", "OPEN")
515BH-51F2H
(152 bytes)
Error message descriptor chains (variable-length byte sequences; bits 0-5 = word index, bit 6 = context flag, bit 7 = last-word-in-chain flag)

Self-Modifying Code Locations

WriterTargetPurpose
4E20H4F42H-4F43HError code decimal digits (tens digit at 4F42H, units digit at 4F43H) written into the "*** ERRCODE=XX, " template string
4E94H4F55H-4F56HDrive number (C) and directory info byte (B) from the FCB, stored into the "<DEVICE=*XX>" template string
4E6EH4E6EHOverlay return address stored by EX (SP),HL at entry (4E00H-4E01H); the LD (4E6EH),HL at 4E01H saves the return address for later JP M,0000H target

Major Routine List

AddressPurpose
4E00HError Display Entry Point
Main entry; saves context, converts error code to decimal, displays "*** ERRCODE=XX, " prefix (if bit 6 clear), then falls through to message lookup
4E2AHError Message Lookup and Display
Uses error code as index into offset table (4F84H), reads descriptor chain from 51xxH, looks up each word from DEFW table (4FC2H), and prints words separated by spaces
4E5CHError Display Completion
Optionally displays extended context (device, file, return address) via 4E73H, outputs CR, restores registers, and exits via JP M,0000H or JP 4030H
4E73HExtended Error Context Display
Displays "***" closing, then device info, filename (from FCB or directory), and return address in hex
4EC4HFilename From Directory Entry
Reads directory sector via 4AC1H, extracts 8-char filename and 3-char extension into 4F60H buffer as NAME/EXT:D format
4EF9HAppend Drive and Terminator
Appends ":D>" + CR to filename buffer, then displays file and return address context strings
4F06HDisplay Return Address
Displays "REFERENCED AT X'nnnn'" using the saved return address at 430CH minus 3
4F1BHDisplay HL as Hexadecimal
Outputs H then L as 2-digit hex values via the nibble converter at 4F20H
4F20HHex Byte Display
Converts a byte in A to two hex ASCII characters and outputs them via ROM 0033H

Cross-Reference Notes

SYS4 is invoked by SYS0 via SVC code 86H (LD A,86H / RST 28H). The RST 28H overlay loader at 4BA2H loads SYS4 from disk into 4E00H and transfers control. SYS4 calls back into SYS0 for three services: 4467H (display message string on screen), 4AC1H (read directory sector into 4200H buffer), and 4030H (error-already-displayed exit). SYS4 also calls ROM routine 0033H directly for individual character output during the error message word display loop and the hex display routine.

Error Code Table

SYS4 handles error codes 00H through 26H with unique messages. Codes 27H through 3DH all display the default message "UNKNOWN ERROR". The complete error message for each code is assembled from dictionary words:

CodeMessage
00HNO ERROR
01HPARITY ERROR DURING HEADER READ
02HSEEK ERROR DURING READ
03HLOST DATA DURING READ
04HPARITY ERROR DURING READ
05HDATA RECORD NOT FOUND DURING READ
06HATTEMPTED TO READ LOCKED/DELETED DATA RECORD
07HATTEMPTED TO READ SYSTEM DATA RECORD
08HDEVICE NOT AVAILABLE
09HPARITY ERROR DURING HEADER WRITE
0AHSEEK ERROR DURING WRITE
0BHLOST DATA DURING WRITE
0CHPARITY ERROR DURING WRITE
0DHDATA RECORD NOT FOUND DURING WRITE
0EHWRITE FAULT ON DISK DRIVE
0FHWRITE PROTECTED DISKETTE
10HILLEGAL LOGICAL FILE NUMBER
11HDIRECTORY READ ERROR
12HDIRECTORY WRITE ERROR
13HILLEGAL FILE NAME
14HGAT READ ERROR
15HGAT WRITE ERROR
16HHIT READ ERROR
17HHIT WRITE ERROR
18HFILE NOT IN DIRECTORY
19HFILE ACCESS DENIED
1AHDIRECTORY SPACE FULL
1BHDISK SPACE FULL
1CHEND OF FILE ENCOUNTERED
1DHRECORD NUMBER OUT OF RANGE
1EHDIRECTORY FULL - CAN'T EXTEND FILE
1FHPROGRAM NOT FOUND
20HILLEGAL DRIVE NUMBER
21HNO DEVICE SPACE AVAILABLE
22HLOAD FILE FORMAT ERROR
23HMEMORY FAULT
24HATTEMPTED TO LOAD READ ONLY MEMORY
25HILLEGAL ACCESS ATTEMPTED TO PROTECTED FILE
26HFILE NOT OPEN
27H+UNKNOWN ERROR (default for all undefined codes)

Disassembly:

4E00H - Error Display Entry Point

Main entry point for the error display overlay. Called by the RST 28H overlay loader when SVC code 86H is invoked. On entry, the stack contains the saved return address, the original Register A (error code), and the caller's saved registers. This routine saves context, converts the error code to a two-digit decimal number, and optionally displays the "*** ERRCODE=XX, " prefix before falling through to the message lookup.

4E00
EX (SP),HL E3
Exchange Register Pair HL with the value on top of the stack. HL now contains the return address that was on the stack (the address in SYS0's overlay loader where control should return after the overlay completes), and the previous value of HL is pushed onto the stack in its place.
4E01
LD (4E6EH),HL 22 6E 4E
Self-Modifying Code
Store the overlay return address (now in HL) into the operand of the JP M instruction at 4E6DH. The two bytes at 4E6EH-4E6FH form the target address of that JP M instruction. At assembly time the target is 0000H, but at runtime this stores the actual return address so that if the error code has bit 7 set, the JP M will jump to the overlay loader's return point (which in practice is 0000H for a cold restart, since SYS0 sets bit 7 for fatal errors requiring reboot).
4E04
POP HL E1
Restore the caller's original HL value from the stack (which was placed there by the EX (SP),HL at 4E00H).
4E05
POP AF F1
Restore the caller's original AF from the stack. Register A now contains the error code value that was passed to the RST 28H dispatcher. This is the error code that will be decoded and displayed.
4E06
PUSH HL E5
Save Register Pair HL onto the stack for later restoration at exit.
4E07
PUSH DE D5
Save Register Pair DE onto the stack for later restoration at exit.
4E08
PUSH BC C5
Save Register Pair BC onto the stack for later restoration at exit.
4E09
PUSH AF F5
Save Register AF (containing the original error code in A and the flags in F) onto the stack. This preserved copy is restored at 4E5CH to test bit 6 and bit 7 of the original error code for exit path decisions.
4E0A
LD B,A 47
Copy the full original error code from Register A into Register B for safekeeping. Register B retains all 8 bits, including bits 6 and 7 which control display options.
4E0B
AND A,3FH E6 3F
Mask Register A to keep only bits 0-5 (the actual error code number, range 00H-3FH). This strips bit 6 (the extended-context flag) and bit 7 (the fatal-error/reboot flag), isolating the error code index for table lookup.
4E0D
LD C,A 4F
Store the masked error code (00H-3FH) into Register C. This will be used as the byte index into the error code offset table at 4F84H.
4E0E
BIT 6,B CB 70
Test bit 6 of Register B (the original unmasked error code). Bit 6 controls whether the "*** ERRCODE=XX, " prefix is displayed. If bit 6 is clear (Z), the prefix is displayed. If bit 6 is set (NZ), the prefix is skipped and only the error message words are shown.
4E10
LD B,00H 06 00
Clear Register B to 00H so that BC forms a 16-bit index value where B=00H and C=error code. This prepares BC for the ADD HL,BC table offset calculation at 4E2DH.
4E12
If bit 6 was set (NZ FLAG from the BIT 6,B test at 4E0EH), JUMP to 4E2AH to skip the error code prefix display and go directly to the error message word lookup. This path is used when the caller wants only the message text without the "*** ERRCODE=XX, " prefix.

Error Code to Decimal Conversion
The following loop converts the binary error code in Register A (range 00H-3FH, maximum 63 decimal) into a two-digit decimal number. Register E accumulates the tens digit as an ASCII character (starting at 30H = '0'), and the units digit remains in Register A after the loop.

4E14
LD E,30H 1E 30
Initialize Register E to 30H (ASCII '0'). Register E will hold the tens digit of the decimal error code. It starts at '0' and is incremented for each group of 10 subtracted from A.
4E16
SUB A,0AH D6 0A
Loop Start
SUBtract 10 (0AH) from Register A. If the result is negative (A was less than 10), the CARRY FLAG is set, meaning all tens have been extracted and the remainder is the units digit.
4E18
If the CARRY FLAG has been set (Register A was less than 10 before the subtraction), JUMP to 4E1DH to fix up the units digit. The tens digit in Register E is complete.
4E1A
INC E 1C
INCrement Register E by 1. This advances the tens digit ASCII character (e.g., from '0' to '1', from '1' to '2', etc.) for each group of 10 successfully subtracted.
4E1B
Loop End
LOOP BACK to 4E16H to subtract another 10 from A and check again.
4E1D
ADD A,3AH C6 3A
Add 3AH (58 decimal) to Register A. Since the SUB 0AH at 4E16H overshot by 10, Register A is currently negative (in the range F6H-FFH, representing -10 to -1). Adding 3AH converts this to the correct ASCII digit: if A was -1 (FFH), result = FFH+3AH = 39H = '9'. If A was -10 (F6H), result = F6H+3AH = 30H = '0'. This is equivalent to adding back 10 (to undo the overshoot) and then adding 30H (to convert to ASCII).
4E1F
LD D,A 57
Copy the units digit ASCII character from Register A into Register D. Now DE contains the two-digit decimal error code: D=units digit, E=tens digit.
4E20
LD (4F42H),DE ED 53 42 4F
Self-Modifying Code
Store the two ASCII decimal digits (DE) into the error code template string at 4F42H-4F43H. The template at 4F36H reads: LF + "*** ERRCODE=XX, " + ETX. The "XX" placeholder bytes at 4F42H-4F43H are now overwritten with the actual tens digit (E at 4F42H) and units digit (D at 4F43H) of the error code. Note: the Z80 stores DE as E first (low byte at 4F42H) then D (high byte at 4F43H), which correctly places tens-then-units since E holds the tens digit and D holds the units digit.
4E24
LD HL,4F36H 21 36 4F
Point Register Pair HL to the error code display template string at 4F36H. This string begins with 0AH (line feed), followed by "*** ERRCODE=", the two decimal digits just written, ", ", and terminates with 03H (ETX).
4E27
GOSUB to the SYS0 display message routine at 4467H to output the error code prefix string. This prints: line feed, "*** ERRCODE=XX, " on screen, where XX is the decimal error code. The routine reads characters from (HL) and outputs them via ROM 0033H until a 03H (ETX) or 0DH (CR) terminator is reached.

4E2AH - Error Message Lookup and Display Loop

Looks up the error code in the offset table to find the descriptor chain, then walks the chain displaying each word from the dictionary. Each descriptor byte encodes a word index (bits 0-5) and a continuation flag (bit 7). Words are separated by spaces. The loop continues until a descriptor with bit 7 set is encountered.

4E2A
LD HL,4F84H 21 84 4F
Point Register Pair HL to the error code offset table at 4F84H. This table has one byte per error code (indexed by the masked error code in C), and each byte is an offset into the 51xxH page where the descriptor chain for that error code begins.
4E2D
ADD HL,BC 09
ADD Register Pair BC (where B=00H and C=masked error code) to HL. HL now points to the specific offset table entry for this error code: 4F84H + error_code.
4E2E
LD L,(HL) 6E
Fetch the offset byte from the table entry. This byte is the low byte of the address in the 51xxH page where the descriptor chain starts for this error code.
4E2F
LD H,51H 26 51
Set the high byte of Register Pair HL to 51H. Combined with the offset byte just loaded into L, HL now points to the first descriptor byte in the chain at 51xxH. For example, error code 00H loads offset 5BH, so HL = 515BH.

Descriptor Chain Display Loop
The following loop reads descriptor bytes from the chain at (HL). Each descriptor byte contains a word index in bits 0-5 (0-63), which is doubled and used as an offset into the DEFW address table at 4FC2H. From that table, two consecutive DEFWs are read: the first gives the word's start address, the second gives the address past the end of the word. The word length is computed by subtraction, and the word characters are output one at a time via ROM 0033H. After each word, a space is printed. Then the descriptor byte's bit 7 is checked: if clear, the next descriptor byte is read and the loop continues. If set, this was the last word in the message.

4E31
LD A,(HL) 7E
Fetch the current descriptor byte from the chain at (HL). This byte encodes: bits 0-5 = word index into the DEFW table, bit 6 = context flag (used later during extended display), bit 7 = last-word flag (1 = this is the final word in the error message).
4E32
AND A,3FH E6 3F
Mask Register A to keep only bits 0-5, isolating the word index (range 0-53). This strips the bit 6 context flag and bit 7 continuation flag.
4E34
ADD A,A 87
Double Register A (multiply by 2). Each entry in the DEFW address table at 4FC2H is 2 bytes wide, so the word index must be doubled to get the byte offset into that table.
4E35
PUSH HL E5
Save the current descriptor chain pointer (HL) onto the stack. This preserves the position in the descriptor chain so it can be resumed after the word is printed.
4E36
LD C,A 4F
Copy the doubled word index from Register A into Register C. BC will be used as a 16-bit offset (B is still 00H from 4E10H).
4E37
LD B,00H 06 00
Ensure Register B is 00H so that BC = doubled word index as a clean 16-bit value.
4E39
LD HL,4FC2H 21 C2 4F
Point Register Pair HL to the start of the word address DEFW table at 4FC2H. This table contains 54 consecutive 2-byte (DEFW) entries, each pointing to the start of a word in the string pool at 5030H-515AH.
4E3C
ADD HL,BC 09
ADD the doubled word index (BC) to HL. HL now points to the DEFW entry for the current word: the 2 bytes at (HL) are the word's start address, and the 2 bytes at (HL+2) are the next word's start address (which serves as the end boundary).
4E3D
LD E,(HL) 5E
Fetch the low byte of the current word's start address from (HL) into Register E.
4E3E
INC HL 23
INCrement HL to point to the high byte of the start address.
4E3F
LD D,(HL) 56
Fetch the high byte of the current word's start address from (HL) into Register D. DE now holds the complete start address of the word in the string pool (e.g., 5057H for "READ").
4E40
INC HL 23
INCrement HL to point to the low byte of the NEXT word's start address (the end boundary).
4E41
LD A,(HL) 7E
Fetch the low byte of the next word's start address into Register A. This will become the low byte of the end boundary.
4E42
INC HL 23
INCrement HL to point to the high byte of the next word's start address.
4E43
LD H,(HL) 66
Fetch the high byte of the next word's start address into Register H.
4E44
LD L,A 6F
Move the low byte (from Register A) into Register L. HL now holds the complete end boundary address (the start address of the next word in the table).
4E45
OR A,A B7
Clear the CARRY FLAG by ORing A with itself. This prepares for the SBC HL,DE subtraction which requires the carry to be clear for an accurate result.
4E46
SBC HL,DE ED 52
SUBtract DE (word start address) from HL (next word start address) with borrow. The result in HL is the length of the current word in bytes. For example, if DE=5057H ("READ" start) and HL=505BH ("WRITE" start), then HL = 505BH - 5057H = 0004H (4 characters).
4E48
LD B,L 45
Copy the word length from Register L into Register B. This becomes the loop counter for printing individual characters. The length is always less than 256, so only the low byte is needed.
4E49
EX DE,HL EB
Exchange DE and HL. HL now points to the start of the word in the string pool (was in DE), and DE holds the word length (no longer needed in DE).

Word Character Print Loop
Print B characters starting at (HL), outputting each via the ROM character display routine at 0033H.

4E4A
LD A,(HL) 7E
Loop Start
Fetch the next character of the word from the string pool at (HL) into Register A.
4E4B
INC HL 23
INCrement HL to point to the next character in the word.
4E4C
GOSUB to the Model I ROM character output routine at 0033H to display the character in Register A on screen.
4E4F
Loop End
DECrement Register B (character count) and loop back to 4E4AH if not zero. When B reaches zero, all characters of the current word have been printed.
4E51
LD A,20H 3E 20
Load Register A with 20H (ASCII space character). A space is printed between each word in the error message.
4E53
GOSUB to ROM 0033H to display the space character, separating the just-printed word from the next word.
4E56
POP HL E1
Restore the descriptor chain pointer from the stack (saved at 4E35H). HL points back to the descriptor byte that was just processed.
4E57
LD A,(HL) 7E
Re-fetch the current descriptor byte from (HL) to test its bit 7 continuation flag. The word index was already used; now only the flags matter.
4E58
INC HL 23
INCrement HL to advance to the next descriptor byte in the chain, in case the loop continues.
4E59
RLCA 07
Rotate Register A Left through Carry. This shifts bit 7 (the last-word flag) into the CARRY FLAG. If bit 7 was 0 (more words follow), CARRY is clear. If bit 7 was 1 (this was the last word), CARRY is set.
4E5A
If the CARRY FLAG is clear (bit 7 was 0, meaning more words remain in the message), LOOP BACK to 4E31H to read the next descriptor byte and print the next word. If CARRY is set (bit 7 was 1, last word), fall through to the completion code.

4E5CH - Error Display Completion

After all error message words have been displayed, this section optionally calls the extended context display (device, file, return address), outputs a carriage return, restores all saved registers, and exits. The exit path depends on bit 7 of the original error code: bit 7 set causes a cold restart via JP M,0000H; bit 7 clear exits to the error-already-displayed handler at 4030H.

4E5C
POP AF F1
Restore the original AF (error code in A, original flags in F) from the stack. This is the copy saved at 4E09H.
4E5D
PUSH AF F5
Immediately save AF back onto the stack again. It will be needed once more at 4E68H for the final exit decision. This POP/PUSH sequence makes A available for the BIT test below without permanently consuming the stack entry.
4E5E
BIT 6,A CB 77
Test bit 6 of Register A (the original error code). If bit 6 is clear (Z), the extended error context should be displayed. If bit 6 is set (NZ), skip the extended context.
4E60
If the Z FLAG is set (bit 6 of the error code is clear), GOSUB to the extended error context display routine at 4E73H. This displays the "***" closing, device info, filename, and the return address where the error was triggered.
4E63
LD A,0DH 3E 0D
Load Register A with 0DH (carriage return). This terminates the error message display line on screen.
4E65
GOSUB to ROM 0033H to output the carriage return, moving the cursor to the beginning of the next line.
4E68
POP AF F1
Restore the original AF from the stack (the copy re-saved at 4E5DH). Register A again contains the full original error code.
4E69
POP BC C1
Restore the caller's original BC from the stack.
4E6A
POP DE D1
Restore the caller's original DE from the stack.
4E6B
POP HL E1
Restore the caller's original HL from the stack.
4E6C
OR A,A B7
OR Register A with itself. This sets the flags based on the value in A without changing it. Specifically, the SIGN FLAG (S) is set if bit 7 of A is 1 (negative/fatal error), or clear if bit 7 is 0. This prepares for the conditional JP M below.
4E6D
JP M,0000H FA 00 00
Self-Modifying Code
If the SIGN FLAG is set (bit 7 of the original error code is 1, indicating a fatal error requiring reboot), JUMP to the address stored at 4E6EH-4E6FH. The target address was written by the LD (4E6EH),HL instruction at 4E01H during entry setup. For fatal errors, this typically jumps to 0000H (cold restart). If the SIGN FLAG is clear, execution falls through to 4E70H.
4E70
JUMP to the SYS0 error-already-displayed exit at 4030H. This routine (LD A,A3H / RST 28H) loads the DOS READY overlay and returns to the command prompt, since the error message has already been displayed on screen and no further error processing is needed.

4E73H - Extended Error Context Display

Called when bit 6 of the error code is clear. Displays the "***" closing marker, then the device/drive information from the FCB, the associated filename (either copied directly from the FCB filespec or read from the directory entry), and the return address where the error was triggered. This routine provides the user with full diagnostic context about which file and operation caused the error.

4E73
PUSH HL E5
Save Register Pair HL onto the stack. HL currently points into the descriptor chain (past the last descriptor byte), and must be preserved for potential later use by the caller.
4E74
LD HL,4F47H 21 47 4F
Point Register Pair HL to the closing error marker string at 4F47H. This string contains "***" followed by 0DH (carriage return), which closes the error message line before the extended context lines begin.
4E77
GOSUB to the SYS0 display message routine at 4467H to output "***" followed by a carriage return on screen.
4E7A
POP HL E1
Restore Register Pair HL from the stack.
4E7B
PUSH IX DD E5
Save Register Pair IX onto the stack. IX will be loaded with the FCB pointer from 430AH and used to extract file and device information.
4E7D
LD IX,(430AH) DD 2A 0A 43
Load Register Pair IX with the saved FCB pointer from the SYS0 work area at 430AH. This pointer was stored by the overlay call context setup routine at 4892H/4878H in SYS0 when the calling overlay began its operation. IX now points to the FCB (File Control Block) of the file involved in the error.
4E81
DEC HL 2B
DECrement HL by 1 to point back to the last descriptor byte that was processed (the one with bit 7 set). This byte's bit 6 will now be tested to determine how to display the filename.
4E82
BIT 6,(HL) CB 76
Test bit 6 of the last descriptor byte in the chain (the byte at (HL)). Bit 6 in the descriptor serves as a context flag: if set (NZ), the filename should be taken from the FCB's filespec string (the file was processed via a path that stored a NAME/EXT:D string in the FCB). If clear (Z), the filename must be extracted from the directory entry on disk.
4E84
If bit 6 is set (NZ FLAG), JUMP to 4EA0H to handle the FCB-based filename extraction path.

Directory-Based Filename Path
When bit 6 of the last descriptor byte is clear, the file is still open and has a valid FCB with drive and directory info. The filename is extracted by reading the directory sector and copying the name/extension fields. First, the drive number and directory info byte are saved into the device template string.

4E86
LD C,(IX+06H) DD 4E 06
Fetch the drive number from the FCB at offset IX+06H into Register C. This is the drive (0-3) where the file resides.
4E89
LD B,(IX+07H) DD 46 07
Fetch the directory entry info byte from the FCB at offset IX+07H into Register B. This byte identifies which directory sector and entry position contain this file's directory record.
4E8C
BIT 7,(IX+00H) DD CB 00 7E
Test bit 7 of the FCB status byte at IX+00H. Bit 7 indicates whether the file is currently open. If bit 7 is set (NZ), the file is open and has valid directory information that can be used to read the filename from the directory sector. If bit 7 is clear (Z), the file is not open, so the directory path cannot be used.
4E90
If bit 7 is set (file is open, NZ FLAG), JUMP to 4EC4H to read the directory sector and extract the filename from the directory entry.

File Not Open Path
If the file is not open (bit 7 of IX+00H is clear), the directory cannot be read to get the filename. Instead, display only the device information with the drive/info bytes, and show the generic "DEVICE=*XX" message.

4E92
POP IX DD E1
Restore Register Pair IX from the stack (saved at 4E7BH).
4E94
LD (4F55H),BC ED 43 55 4F
Self-Modifying Code
Store BC (C=drive number, B=directory info byte) into the device template string at 4F55H-4F56H. The template at 4F4BH contains a screen code followed by "<DEVICE=*XX>" where XX at 4F55H-4F56H are the placeholders. After this store, the two bytes become the actual drive number and directory info byte values (displayed as their raw character representations).
4E98
LD HL,4F4BH 21 4B 4F
Point Register Pair HL to the device display template string at 4F4BH.
4E9B
GOSUB to the SYS0 display message routine at 4467H to output the device information string on screen.
4E9E
JUMP to 4F06H to display the return address context ("REFERENCED AT X'nnnn'") and complete the extended error display. The filename display is skipped in this path since the file was not open.

4EA0H - FCB Filespec Extraction Path

When the last descriptor byte has bit 6 set, the FCB contains a filespec string (NAME/EXT:D format terminated by 03H) starting at IX+00H. This path copies that string directly into the filename display buffer at 4F60H. The FCB status byte is first checked for the special value 2AH (which indicates the FCB pointer is actually a chained pointer to another FCB).

4EA0
LD A,(IX+00H) DD 7E 00
Fetch the FCB status byte from offset IX+00H into Register A. This byte is checked for the special chain marker value 2AH.
4EA3
CP A,2AH FE 2A
Compare Register A against 2AH (ASCII '*'). The value 2AH at IX+00H is a special marker indicating that the FCB pointer at IX+01H/IX+02H contains the actual address of the real FCB whose filespec should be used.
4EA5
If the status byte is NOT 2AH (NZ FLAG), JUMP to 4EAFH to copy the filespec directly from the current FCB position at IX.

FCB Chain Follow
The FCB status byte is 2AH, meaning IX+01H/IX+02H contain a pointer to the real FCB. Load BC with this pointer and jump back to 4E92H to store the device info and display from the redirected FCB's context.

4EA7
LD C,(IX+01H) DD 4E 01
Fetch the low byte of the chained FCB pointer from IX+01H into Register C.
4EAA
LD B,(IX+02H) DD 46 02
Fetch the high byte of the chained FCB pointer from IX+02H into Register B. BC now holds the address of the real FCB.
4EAD
JUMP back to 4E92H to store BC as the device info and display the device template. Since the chain was followed, this path shows the redirected FCB's drive/info rather than reading the directory.

Direct Filespec Copy From FCB
The FCB at IX contains a filespec string (such as "MYFILE/BAS:0>" terminated by 03H). Copy up to 24 bytes from IX into the filename buffer at 4F60H, stopping early if a 03H terminator is encountered.

4EAF
PUSH IX DD E5
Save the current IX value onto the stack.
4EB1
POP HL E1
Pop the value into HL. This is a standard technique to transfer IX into HL (since there is no direct LD HL,IX instruction). HL now points to the start of the FCB filespec string at IX+00H.
4EB2
LD DE,4F60H 11 60 4F
Point Register Pair DE to the filename display buffer at 4F60H. Characters will be copied from the FCB (HL) to this buffer (DE).
4EB5
LD BC,0018H 01 18 00
Load Register Pair BC with 0018H (24 decimal). B = 00H acts as the safety padding, and the value 18H in C is not directly used as a counter here. Actually, B receives the value 00H and the full BC = 24 serves as a maximum length. However, looking at the loop, B=00H is loaded at 4EB5 but the DJNZ at 4EC0H uses B as a counter. Since B=00H, DJNZ would decrement to FFH and loop 256 times. This means the ETX check at 4EB9H must terminate the loop before B wraps.

Filespec Copy Loop
Copy characters from (HL) to (DE), stopping when a 03H (ETX) terminator is found. The loop counter B starts at 00H (from the high byte of 0018H), so DJNZ would wrap to FFH - the 03H check is the real loop terminator.

4EB8
LD A,(HL) 7E
Loop Start
Fetch the next character from the FCB filespec string at (HL) into Register A.
4EB9
CP A,03H FE 03
Compare Register A against 03H (ETX terminator). If Register A equals 03H, the Z FLAG is set, indicating the end of the filespec string has been reached.
4EBB
If the Z FLAG is set (character is 03H ETX), JUMP to 4EF9H to append the drive letter, ">" terminator, and CR to the buffer, then display it.
4EBD
INC HL 23
INCrement HL to point to the next character in the FCB filespec string.
4EBE
LD (DE),A 12
Store the character from Register A into the filename buffer at (DE).
4EBF
INC DE 13
INCrement DE to point to the next position in the filename buffer.
4EC0
Loop End
DECrement Register B and loop back to 4EB8H if not zero. Since B started at 00H, the first DJNZ decrements to FFH and continues. The loop is effectively terminated by the 03H check at 4EB9H, not by B reaching zero.
4EC2
JUMP to 4EF9H to append the drive letter and terminator. This path is taken if the loop completes without finding a 03H terminator (safety exit after 256 characters).

4EC4H - Filename From Directory Entry

When the file is open and the descriptor byte's bit 6 is clear, the filename is read from the actual directory sector on disk. The directory sector is loaded via the SYS0 routine at 4AC1H, and the 8-character filename and 3-character extension are extracted into the display buffer at 4F60H in NAME/EXT:D format.

4EC4
GOSUB to the SYS0 routine at 4AC1H to read the directory sector into the 4200H buffer. On entry, B contains the directory info byte (from IX+07H, loaded at 4E89H) and C contains the drive number (from IX+06H, loaded at 4E86H). The routine decodes the info byte to determine which directory sector to read and positions HL to point to the start of the file's directory entry within the buffer.
4EC7
LD BC,0005H 01 05 00
Load Register Pair BC with 0005H. This offset skips the first 5 bytes of the directory entry (flags byte, chain pointer, reserved bytes, and EOF byte offset) to reach the 8-byte filename field at offset +05H.
4ECA
ADD HL,BC 09
ADD 5 to HL. HL now points to the start of the 8-byte filename field within the directory entry in the 4200H buffer.
4ECB
LD DE,4F60H 11 60 4F
Point Register Pair DE to the filename display buffer at 4F60H. The filename characters will be copied here.
4ECE
LD B,08H 06 08
Load Register B with 08H (8 decimal). The directory entry's filename field is exactly 8 characters, space-padded. B serves as the loop counter.

Filename Copy Loop
Copy up to 8 characters of the filename from the directory entry to the display buffer, stopping early if a space (20H) is encountered. Spaces in the filename indicate the end of the actual name (the rest is padding).

4ED0
LD A,(HL) 7E
Loop Start
Fetch the next filename character from the directory entry at (HL) into Register A.
4ED1
CP A,20H FE 20
Compare Register A against 20H (ASCII space). If the character is a space, the actual filename has ended and the remaining bytes are padding.
4ED3
If the Z FLAG is set (character is a space), JUMP to 4EDAH to skip the remaining filename characters and proceed to the extension field.
4ED5
INC L 2C
INCrement Register L to advance HL to the next character in the directory entry. Using INC L instead of INC HL saves one byte and one T-state, and is safe because the directory buffer at 4200H is page-aligned so L will not overflow.
4ED6
LD (DE),A 12
Store the filename character from Register A into the display buffer at (DE).
4ED7
INC DE 13
INCrement DE to the next position in the display buffer.
4ED8
Loop End
DECrement Register B and loop back to 4ED0H if not zero. After all 8 filename characters have been processed (or a space was found), fall through.

Filename/Extension Separator and Extension Copy
After the filename, append a '/' separator and then copy the 3-character extension, again stopping on spaces.

4EDA
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII '/'). This is the TRSDOS filename/extension separator character (TRSDOS uses '/' rather than '.').
4EDC
LD (DE),A 12
Store the '/' separator into the display buffer at (DE).
4EDD
INC DE 13
INCrement DE to the next buffer position.
4EDE
LD C,B 48
Copy the remaining filename character count from Register B into Register C. If the filename was shorter than 8 characters (space terminated early), B still holds the remaining count. This value tells us how many bytes to skip forward in the directory entry to reach the extension field.
4EDF
LD B,00H 06 00
Clear Register B so BC = remaining character count as a 16-bit value.
4EE1
ADD HL,BC 09
ADD BC to HL to skip past any remaining (unprocessed) filename padding characters. HL now points to the start of the 3-byte extension field in the directory entry (at the filename field base + 8, which is directory entry offset +0DH).
4EE2
LD B,03H 06 03
Load Register B with 03H (3 decimal). The extension field is exactly 3 characters, space-padded.
4EE4
LD A,(HL) 7E
Loop Start
Fetch the next extension character from the directory entry at (HL) into Register A.
4EE5
INC L 2C
INCrement Register L to advance to the next character in the directory entry.
4EE6
CP A,20H FE 20
Compare Register A against 20H (ASCII space). A space indicates the extension field's actual content has ended.
4EE8
If the Z FLAG is set (character is a space), JUMP to 4EEEH to skip remaining extension characters and proceed to append the drive specifier.
4EEA
LD (DE),A 12
Store the extension character from Register A into the display buffer at (DE).
4EEB
INC DE 13
INCrement DE to the next buffer position.
4EEC
Loop End
DECrement Register B and loop back to 4EE4H if not zero. After all 3 extension characters have been processed, fall through to append the drive specifier.

Append Drive Specifier and Terminator
After the filename and extension, append ":D>" (colon, drive number as ASCII digit, closing angle bracket) followed by a carriage return to complete the display string. Then display the file information and return address strings.

4EEE
EX DE,HL EB
Exchange DE and HL. HL now points to the current position in the filename display buffer (was DE), and DE holds the directory entry pointer (no longer needed).
4EEF
LD (HL),3AH 36 3A
Store 3AH (ASCII ':') into the display buffer at (HL). This is the drive specifier separator in the TRSDOS filespec format.
4EF1
INC HL 23
INCrement HL to the next buffer position.
4EF2
LD A,(IX+06H) DD 7E 06
Fetch the drive number (0-3) from the FCB at offset IX+06H into Register A.
4EF5
ADD A,30H C6 30
ADD 30H to Register A to convert the binary drive number (0-3) to an ASCII digit ('0'-'3').
4EF7
LD (HL),A 77
Store the ASCII drive digit into the display buffer at (HL).
4EF8
INC HL 23
INCrement HL to the next buffer position.
4EF9
LD (HL),3EH 36 3E
Store 3EH (ASCII '>') into the display buffer at (HL). This is the closing angle bracket of the filename display format "<FILE=NAME/EXT:D>".
4EFB
INC HL 23
INCrement HL to the next buffer position.
4EFC
LD (HL),0DH 36 0D
Store 0DH (carriage return) into the display buffer at (HL). This terminates the filename display string for the 4467H message output routine.
4EFE
POP IX DD E1
Restore Register Pair IX from the stack (saved at 4E7BH).
4F00
LD HL,4F59H 21 59 4F
Point Register Pair HL to the file display prefix string at 4F59H. This string contains a screen code followed by "<FILE=" which will be displayed before the filename that was just assembled in the 4F60H buffer. The 4467H routine will continue reading into 4F60H since the strings are contiguous in memory and the terminator (0DH) is at the end of the assembled filename.
4F03
GOSUB to the SYS0 display message routine at 4467H to output the file information string. This displays the prefix "<FILE=" followed by the filename "NAME/EXT:D>" and a carriage return, all read sequentially from 4F59H through the 4F60H buffer.

4F06H - Display Return Address

Displays the return address where the error was triggered, formatted as "REFERENCED AT X'nnnn'" where nnnn is the 4-digit hexadecimal address. The return address is obtained from the saved overlay return address at 430CH, minus 3 bytes to point back to the LD A,xxH instruction that originally invoked the error handler.

4F06
LD HL,4F70H 21 70 4F
Point Register Pair HL to the return address display prefix string at 4F70H. This string contains a screen code followed by "REFERENCED AT X'" and terminates with 03H (ETX).
4F09
GOSUB to the SYS0 display message routine at 4467H to output "REFERENCED AT X'" on screen.
4F0C
LD HL,(430CH) 2A 0C 43
Load Register Pair HL with the saved overlay return address from 430CH-430DH. This address was stored by SYS0's overlay call context setup at 4878H when the error-causing overlay was invoked. It points to the instruction following the RST 28H that triggered the overlay call.
4F0F
DEC HL 2B
DECrement HL by 1. This is the first of three decrements to adjust the return address backward by 3 bytes.
4F10
DEC HL 2B
DECrement HL by 1 again.
4F11
DEC HL 2B
DECrement HL by 1 a third time. HL now points 3 bytes before the post-RST-28H return address. Since the SVC stub pattern is: LD A,xxH (2 bytes: 3E xx) followed by RST 28H (1 byte: EF), subtracting 3 from the return address points HL back to the LD A,xxH instruction itself. This gives the user the address of the code that triggered the error, which is more useful for debugging than the return address.
4F12
GOSUB to the hex display routine at 4F1BH to output the 4-digit hexadecimal value in HL (the adjusted return address) on screen.
4F15
LD HL,4F82H 21 82 4F
Point Register Pair HL to the return address display suffix string at 4F82H. This string contains "'" (closing single quote) followed by 0DH (carriage return).
4F18
JUMP to the SYS0 display message routine at 4467H to output the closing "'" and carriage return. Since this is a JP (not CALL), when 4467H returns it will return directly to the caller of 4E73H (the extended context display routine), which is the CALL Z at 4E60H. This completes the extended error context display.

4F1BH - Display HL as 4-Digit Hexadecimal

Converts the 16-bit value in Register Pair HL to four hexadecimal ASCII characters and outputs them on screen. Displays H first (high byte), then L (low byte), each as two hex digits.

4F1B
LD A,H 7C
Copy the high byte of the address from Register H into Register A for hex conversion.
4F1C
GOSUB to the hex byte display routine at 4F20H to output the high byte as two hex ASCII digits.
4F1F
LD A,L 7D
Copy the low byte of the address from Register L into Register A for hex conversion.

4F20H - Hex Byte Display

Converts a single byte in Register A to two hexadecimal ASCII characters and outputs them via ROM 0033H. The high nibble is output first, then the low nibble. Each nibble is converted using the standard hex-to-ASCII algorithm: digits 0-9 map to '0'-'9' (30H-39H), and digits A-F map to 'A'-'F' (41H-46H).

4F20
PUSH AF F5
Save Register AF onto the stack. The full byte value in A is preserved so the low nibble can be processed after the high nibble is output.
4F21
RRA 1F
Rotate Register A Right through carry. This shifts the high nibble rightward. First rotation: bit 0 goes to carry, bits 7-1 shift right, carry goes to bit 7.
4F22
RRA 1F
Second rotation rightward.
4F23
RRA 1F
Third rotation rightward.
4F24
RRA 1F
Fourth rotation rightward. After four RRA operations, the high nibble of the original byte is now in bits 0-3 of A (the low nibble position). Bits 4-7 contain residual carry rotations, but the AND 0FH at 4F29H will mask them out.
4F25
GOSUB to the nibble-to-ASCII conversion and output routine at 4F29H. This outputs the high nibble as a hex character.
4F28
POP AF F1
Restore the original byte value from the stack into Register A. The low nibble will now be processed by falling through to 4F29H.
4F29
AND A,0FH E6 0F
Mask Register A to keep only the low nibble (bits 0-3). The value is now 0-15 (0H-FH).
4F2B
ADD A,30H C6 30
ADD 30H to Register A to convert the nibble value to an ASCII character. Values 0-9 become 30H-39H ('0'-'9'). Values 10-15 become 3AH-3FH (which are ':' through '?', not yet the correct hex letters).
4F2D
CP A,3AH FE 3A
Compare Register A against 3AH (ASCII ':'). If A is less than 3AH, the value was 0-9 and the ASCII digit is correct. If A is 3AH or greater, the value was 10-15 (A-F) and needs an additional adjustment to reach the hex letter range.
4F2F
If the CARRY FLAG is set (A is less than 3AH, meaning the digit is 0-9), JUMP to 4F33H to output the character as-is.
4F31
ADD A,07H C6 07
ADD 07H to Register A. This adjusts values 3AH-3FH (which represent hex digits A-F) to 41H-46H (ASCII 'A'-'F'). The gap of 7 between '9' (39H) and 'A' (41H) in the ASCII table requires this correction.
4F33
JUMP to the ROM character output routine at 0033H to display the hex ASCII character. Since this is JP (not CALL), 0033H returns directly to the caller of this routine. For the high nibble call from 4F25H, it returns to 4F28H. For the low nibble fall-through, it returns to the caller of 4F20H (or 4F1BH).

4F36H - Error Code Display Template String

Template string displayed when bit 6 of the error code is clear. Contains LF + "*** ERRCODE=XX, " + ETX, where the "XX" bytes at 4F42H-4F43H are overwritten at runtime with the decimal error code digits.

4F36
DEFM 0AH,"*** ERRCODE=" 0A 2A 2A 2A 20 45 52 52 43 4F 44 3D
Line feed (0AH) followed by "*** ERRCODE=" - the prefix of the error code display string. The line feed starts the error message on a new line.
4F42
DEFM "XX" 58 58
Self-Modifying Code
Placeholder for the two-digit decimal error code. At assembly time these bytes are "XX" (58H 58H). At runtime, the LD (4F42H),DE instruction at 4E20H overwrites them with the actual tens digit (at 4F42H) and units digit (at 4F43H) as ASCII characters.
4F44
DEFM ", ",03H 2C 20 03
Comma, space, and 03H (ETX) terminator. The ETX marks the end of this template string for the 4467H display routine. The full displayed string reads: LF + "*** ERRCODE=XX, " where XX is the decimal error code.

4F47H - Closing Error Marker String

Displayed by the extended context routine at 4E74H to close the error message line before showing device and file details.

4F47
DEFM "***",0DH 2A 2A 2A 0D
"***" followed by 0DH (carriage return). This closes the error message with the matching "***" bookend and moves to a new line before the extended context information is displayed.

4F4BH - Device Display Template String

Template for displaying device (drive/directory info) context. Shown when the file is not open and only device identification is available.

4F4B
DEFM 0C6H,"<DEVICE=*" C6 3C 44 45 56 49 43 45 3D 2A
Screen display code (C6H, a TRS-80 semigraphics block character used as a visual marker) followed by "<DEVICE=*". The asterisk precedes the two device identification bytes.
4F55
DEFM "XX" 58 58
Self-Modifying Code
Placeholder for the drive number (low byte at 4F55H) and directory info byte (high byte at 4F56H). The LD (4F55H),BC instruction at 4E94H overwrites these with the actual FCB values at runtime.
4F57
DEFM ">",0DH 3E 0D
Closing angle bracket followed by 0DH (carriage return) terminator. The full displayed string reads: [block]<DEVICE=*XX> followed by a newline.

4F59H - File Display Prefix String

Prefix for the filename display line. This string is immediately followed in memory by the filename buffer at 4F60H, so the 4467H display routine reads through both contiguously.

4F59
DEFM 0C5H,"<FILE=" C5 3C 46 49 4C 45 3D
Screen display code (C5H, a TRS-80 semigraphics block character) followed by "<FILE=". The filename assembled in the buffer at 4F60H will be displayed immediately after this prefix. The 4467H routine continues reading from 4F60H since there is no terminator between 4F59H and 4F60H.

4F60H - Filename Display Buffer

16-byte work area where the filename is assembled at runtime in NAME/EXT:D> format followed by a 0DH terminator. Filled by either the FCB filespec copy loop (4EB8H) or the directory entry extraction routine (4EC4H).

4F60-4F6F
DEFM "NNNNNNNN/EEE:D>",0DH 4E 4E 4E 4E 4E 4E 4E 4E 2F 45 45 45 3A 44 3E 0D
Filename display buffer (16 bytes). At assembly time contains placeholder data. At runtime, filled with the actual filename in TRSDOS format: up to 8 name characters, '/' separator, up to 3 extension characters, ':' separator, drive number as ASCII digit, '>' closing bracket, and 0DH (carriage return) terminator. The actual length depends on the filename; the terminator is placed after the last character written.

4F70H - Return Address Display Prefix String

Prefix for the "REFERENCED AT X'nnnn'" line that shows where the error was triggered.

4F70
DEFM 0C3H,"REFERENCED AT X'",03H C3 52 45 46 45 52 45 4E 43 45 44 20 41 54 20 58 27 03
Screen display code (C3H, a TRS-80 semigraphics block character) followed by "REFERENCED AT X'" and terminated by 03H (ETX). After this string is displayed, the hex display routine at 4F1BH outputs the 4-digit hexadecimal return address, followed by the closing "'" from the suffix string at 4F82H. The "X'" prefix and closing "'" use the TRSDOS hexadecimal literal notation (X'nnnn').

4F82H - Return Address Display Suffix String

Closing suffix for the return address display: a single quote and carriage return.

4F82
DEFM "'",0DH 27 0D
Closing single quote (27H) followed by 0DH (carriage return). Completes the "REFERENCED AT X'nnnn'" display line.

4F84H - Error Code Offset Table

Lookup table with one byte per error code (00H-3DH, 62 entries). Each byte is a page offset into the 51xxH descriptor area. The code at 4E2AH uses the masked error code as an index into this table, loads the byte, and combines it with H=51H to form the descriptor chain address. Error codes 27H through 3DH all map to offset F0H (address 51F0H), which is the "UNKNOWN ERROR" default descriptor.

4F84
DEFB 5BH,5DH, 62H,66H,6AH, 6EH,74H,79H 5B 5D 62 66 6A 6E 74 79
Offsets for error codes 00H-07H: 515BH (NO ERROR), 515DH (PARITY ERROR DURING HEADER READ), 5162H (SEEK ERROR DURING READ), 5166H (LOST DATA DURING READ), 516AH (PARITY ERROR DURING READ), 516EH (DATA RECORD NOT FOUND DURING READ), 5174H (ATTEMPTED TO READ LOCKED/DELETED DATA RECORD), 5179H (ATTEMPTED TO READ SYSTEM DATA RECORD).
4F8C
DEFB 7EH,81H, 86H,8AH,8EH, 92H,98H,9DH 7E 81 86 8A 8E 92 98 9D
Offsets for error codes 08H-0FH: 517EH (DEVICE NOT AVAILABLE), 5181H (PARITY ERROR DURING HEADER WRITE), 5186H (SEEK ERROR DURING WRITE), 518AH (LOST DATA DURING WRITE), 518EH (PARITY ERROR DURING WRITE), 5192H (DATA RECORD NOT FOUND DURING WRITE), 5198H (WRITE FAULT ON DISK DRIVE), 519DH (WRITE PROTECTED DISKETTE).
4F94
DEFB 0A0H,0A4H, 0A7H,0AAH,0ADH, 0B0H,0B3H,0B6H A0 A4 A7 AA AD B0 B3 B6
Offsets for error codes 10H-17H: 51A0H (ILLEGAL LOGICAL FILE NUMBER), 51A4H (DIRECTORY READ ERROR), 51A7H (DIRECTORY WRITE ERROR), 51AAH (ILLEGAL FILE NAME), 51ADH (GAT READ ERROR), 51B0H (GAT WRITE ERROR), 51B3H (HIT READ ERROR), 51B6H (HIT WRITE ERROR).
4F9C
DEFB 0B9H,0BDH, 0C0H,0C3H,0C6H, 0CAH,0CFH,0D3H B9 BD C0 C3 C6 CA CF D3
Offsets for error codes 18H-1FH: 51B9H (FILE NOT IN DIRECTORY), 51BDH (FILE ACCESS DENIED), 51C0H (DIRECTORY SPACE FULL), 51C3H (DISK SPACE FULL), 51C6H (END OF FILE ENCOUNTERED), 51CAH (RECORD NUMBER OUT OF RANGE), 51CFH (DIRECTORY FULL - CAN'T EXTEND FILE), 51D3H (PROGRAM NOT FOUND).
4FA4
DEFB 0D6H,0D9H, 0DDH,0E1H,0E3H, 0E8H,0EDH D6 D9 DD E1 E3 E8 ED
Offsets for error codes 20H-26H: 51D6H (ILLEGAL DRIVE NUMBER), 51D9H (NO DEVICE SPACE AVAILABLE), 51DDH (LOAD FILE FORMAT ERROR), 51E1H (MEMORY FAULT), 51E3H (ATTEMPTED TO LOAD READ ONLY MEMORY), 51E8H (ILLEGAL ACCESS ATTEMPTED TO PROTECTED FILE), 51EDH (FILE NOT OPEN).
4FAB
DEFB 0F0H x 23 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0
Offsets for error codes 27H-3DH: all F0H, pointing to 51F0H (UNKNOWN ERROR). These 23 entries provide a catch-all default for any error code beyond the 39 defined messages. The table extends to 4FC1H (total 62 entries covering error codes 00H-3DH).

4FC2H - Word Address DEFW Table

Table of 54 two-byte (DEFW) little-endian addresses, each pointing to the start of a word in the string pool at 5030H-515AH. The word's length is determined by subtracting its start address from the next entry's address (the overlapping-entry technique used by the SBC HL,DE at 4E46H). Entry 0 (F0F0H) is padding and unused; entries 1-53 correspond to the 53 vocabulary words.

4FC2
DEFW 0F0F0H F0 F0
Entry 0: F0F0H (unused padding). No descriptor uses word index 0.
4FC4
DEFW 5030H,5032H, 5037H,503DH 30 50 32 50 37 50 3D 50
Entries 1-4: 5030H="NO" (2), 5032H="ERROR" (5), 5037H="FORMAT" (6), 503DH="PARITY" (6). Numbers in parentheses are word lengths in bytes.
4FCC
DEFW 5043H,5049H, 504FH,5053H 43 50 49 50 4F 50 53 50
Entries 5-8: 5043H="DURING" (6), 5049H="HEADER" (6), 504FH="DATA" (4), 5053H="SEEK" (4).
4FD4
DEFW 5057H,505BH, 5060H,5064H 57 50 5B 50 60 50 64 50
Entries 9-12: 5057H="READ" (4), 505BH="WRITE" (5), 5060H="LOST" (4), 5064H="NOT" (3).
4FDC
DEFW 5067H,5073H, 5081H,5087H 67 50 73 50 81 50 87 50
Entries 13-16: 5067H="ATTEMPTED TO" (12), 5073H="LOCKED/DELETED" (14), 5081H="SYSTEM" (6), 5087H="DIRECTORY" (9).
4FE4
DEFW 5090H,5096H, 5098H,509CH 90 50 96 50 98 50 9C 50
Entries 17-20: 5090H="MEMORY" (6), 5096H="ON" (2), 5098H="DISK" (4), 509CH="DISKETTE" (8).
4FEC
DEFW 50A4H,50A9H, 50B2H,50B9H A4 50 A9 50 B2 50 B9 50
Entries 21-24: 50A4H="FAULT" (5), 50A9H="PROTECTED" (9), 50B2H="ILLEGAL" (7), 50B9H="LOGICAL" (7).
4FF4
DEFW 50C0H,50C6H, 50CAH,50D0H C0 50 C6 50 CA 50 D0 50
Entries 25-28: 50C0H="NUMBER" (6), 50C6H="FILE" (4), 50CAH="RECORD" (6), 50D0H="END" (3).
4FFC
DEFW 50D3H,50D5H, 50D8H,50DDH D3 50 D5 50 D8 50 DD 50
Entries 29-32: 50D3H="OF" (2), 50D5H="OUT" (3), 50D8H="RANGE" (5), 50DDH="ENCOUNTERED" (11).
5004
DEFW 50E8H,50ECH, 50EFH,50F2H E8 50 EC 50 EF 50 F2 50
Entries 33-36: 50E8H="CODE" (4), 50ECH="GAT" (3), 50EFH="HIT" (3), 50F2H="OVERLAY" (7).
500C
DEFW 50F9H,5100H, 5104H,5109H F9 50 00 51 04 51 09 51
Entries 37-40: 50F9H="UNKNOWN" (7), 5100H="LOAD" (4), 5104H="SPACE" (5), 5109H="ONLY" (4).
5014
DEFW 510DH,5111H, 5117H,511DH 0D 51 11 51 17 51 1D 51
Entries 41-44: 510DH="NAME" (4), 5111H="DEVICE" (6), 5117H="FORMAT" (6), 511DH="FOUND" (5).
501C
DEFW 5122H,5124H, 512AH,512EH 22 51 24 51 2A 51 2E 51
Entries 45-48: 5122H="IN" (2), 5124H="ACCESS" (6), 512AH="FULL" (4), 512EH="DRIVE" (5).
5024
DEFW 5133H,5139H, 5140H,5149H 33 51 39 51 40 51 49 51
Entries 49-52: 5133H="DENIED" (6), 5139H="PROGRAM" (7), 5140H="AVAILABLE" (9), 5149H="- CAN'T EXTEND" (14).
502C
DEFW 5157H,515BH 57 51 5B 51
Entries 53-54: 5157H="OPEN" (4). Entry 54 (515BH) serves as the end boundary for the last word "OPEN" (515BH - 5157H = 4 bytes). It also happens to be the start of the descriptor chain area.

5030H - Error Message Word String Pool

Contiguous block of 53 error message vocabulary words stored as plain ASCII text without any separators or terminators between them. Word boundaries are defined entirely by the DEFW address table at 4FC2H. The words are arranged sequentially from "NO" at 5030H through "OPEN" at 5157H.

5030
DEFM "NO" 4E 4F
Word 1: "NO" (2 bytes). Used in error 00H "NO ERROR" and error 21H "NO DEVICE SPACE AVAILABLE".
5032
DEFM "ERROR" 45 52 52 4F 52
Word 2: "ERROR" (5 bytes). Used in errors 00H-04H, 09H-0CH, 11H-12H, 14H-15H, 16H-17H, 22H, and 27H+ as part of compound messages.
5037
DEFM "FORMAT" 46 4F 52 4D 41 54
Word 3: "FORMAT" (6 bytes). Used in error 22H "LOAD FILE FORMAT ERROR". Note: a second copy of "FORMAT" exists at word 43 (5117H) for use in different error contexts.
503D
DEFM "PARITY" 50 41 52 49 54 59
Word 4: "PARITY" (6 bytes). Used in errors 01H, 04H, 09H, 0CH for FDC parity/CRC error conditions.
5043
DEFM "DURING" 44 55 52 49 4E 47
Word 5: "DURING" (6 bytes). Used in errors 01H-07H, 09H-0DH to indicate the operation in progress when the error occurred.
5049
DEFM "HEADER" 48 45 41 44 45 52
Word 6: "HEADER" (6 bytes). Used in errors 01H and 09H for sector header parity errors.
504F
DEFM "DATA" 44 41 54 41
Word 7: "DATA" (4 bytes). Used in errors 05H-07H, 0DH for data record operations.
5053
DEFM "SEEK" 53 45 45 4B
Word 8: "SEEK" (4 bytes). Used in errors 02H and 0AH for FDC seek failures.
5057
DEFM "READ" 52 45 41 44
Word 9: "READ" (4 bytes). Used in errors 01H-07H, 11H, 14H, 16H, 24H for read operations.
505B
DEFM "WRITE" 57 52 49 54 45
Word 10: "WRITE" (5 bytes). Used in errors 09H-0FH, 12H, 15H, 17H for write operations.
5060
DEFM "LOST" 4C 4F 53 54
Word 11: "LOST" (4 bytes). Used in errors 03H and 0BH for FDC lost data conditions.
5064
DEFM "NOT" 4E 4F 54
Word 12: "NOT" (3 bytes). Used in errors 05H-08H, 0DH, 18H, 1FH for negation.
5067
DEFM "ATTEMPTED TO" 41 54 54 45 4D 50 54 45 44 20 54 4F
Word 13: "ATTEMPTED TO" (12 bytes, includes embedded space). Used in errors 06H-07H, 24H-25H for attempted-operation descriptions.
5073
DEFM "LOCKED/DELETED" 4C 4F 43 4B 45 44 2F 44 45 4C 45 54 45 44
Word 14: "LOCKED/DELETED" (14 bytes). Used in error 06H for attempting to read a record marked as locked or deleted in the FDC data address mark.
5081
DEFM "SYSTEM" 53 59 53 54 45 4D
Word 15: "SYSTEM" (6 bytes). Used in error 07H for attempting to read a system data record.
5087
DEFM "DIRECTORY" 44 49 52 45 43 54 4F 52 59
Word 16: "DIRECTORY" (9 bytes). Used in errors 11H-12H, 18H, 1AH, 1EH for directory-related errors.
5090
DEFM "MEMORY" 4D 45 4D 4F 52 59
Word 17: "MEMORY" (6 bytes). Used in errors 23H and 24H for memory-related errors.
5096
DEFM "ON" 4F 4E
Word 18: "ON" (2 bytes). Used in error 0EH "WRITE FAULT ON DISK".
5098
DEFM "DISK" 44 49 53 4B
Word 19: "DISK" (4 bytes). Used in errors 0EH and 1BH for disk-related messages.
509C
DEFM "DISKETTE" 44 49 53 4B 45 54 54 45
Word 20: "DISKETTE" (8 bytes). Used in error 0FH "WRITE PROTECTED DISKETTE".
50A4
DEFM "FAULT" 46 41 55 4C 54
Word 21: "FAULT" (5 bytes). Used in errors 0EH and 23H for hardware fault conditions.
50A9
DEFM "PROTECTED" 50 52 4F 54 45 43 54 45 44
Word 22: "PROTECTED" (9 bytes). Used in errors 0FH and 25H for write-protection and access-protection.
50B2
DEFM "ILLEGAL" 49 4C 4C 45 47 41 4C
Word 23: "ILLEGAL" (7 bytes). Used in errors 10H, 13H, 20H, 25H for invalid parameter errors.
50B9
DEFM "LOGICAL" 4C 4F 47 49 43 41 4C
Word 24: "LOGICAL" (7 bytes). Used in error 10H "ILLEGAL LOGICAL FILE NUMBER".
50C0
DEFM "NUMBER" 4E 55 4D 42 45 52
Word 25: "NUMBER" (6 bytes). Used in errors 10H, 1DH, 20H for numeric parameter errors.
50C6
DEFM "FILE" 46 49 4C 45
Word 26: "FILE" (4 bytes). Used in errors 10H, 13H, 18H, 1CH, 1EH, 22H, 25H-26H for file-related messages.
50CA
DEFM "RECORD" 52 45 43 4F 52 44
Word 27: "RECORD" (6 bytes). Used in errors 05H-07H, 0DH, 1DH for record-level operations.
50D0
DEFM "END" 45 4E 44
Word 28: "END" (3 bytes). Used in error 1CH "END OF FILE ENCOUNTERED".
50D3
DEFM "OF" 4F 46
Word 29: "OF" (2 bytes). Used in errors 1CH and 1DH as a connecting word.
50D5
DEFM "OUT" 4F 55 54
Word 30: "OUT" (3 bytes). Used in error 1DH "RECORD NUMBER OUT OF RANGE".
50D8
DEFM "RANGE" 52 41 4E 47 45
Word 31: "RANGE" (5 bytes). Used in error 1DH.
50DD
DEFM "ENCOUNTERED" 45 4E 43 4F 55 4E 54 45 52 45 44
Word 32: "ENCOUNTERED" (11 bytes). Used in error 1CH "END OF FILE ENCOUNTERED".
50E8
DEFM "CODE" 43 4F 44 45
Word 33: "CODE" (4 bytes). Used in error 1EH.
50EC
DEFM "GAT" 47 41 54
Word 34: "GAT" (3 bytes). Used in errors 14H-15H for Granule Allocation Table errors.
50EF
DEFM "HIT" 48 49 54
Word 35: "HIT" (3 bytes). Used in errors 16H-17H for Hash Index Table errors.
50F2
DEFM "OVERLAY" 4F 56 45 52 4C 41 59
Word 36: "OVERLAY" (7 bytes). Used in error 1EH.
50F9
DEFM "UNKNOWN" 55 4E 4B 4E 4F 57 4E
Word 37: "UNKNOWN" (7 bytes). Used in default error codes 27H+ "UNKNOWN ERROR".
5100
DEFM "LOAD" 4C 4F 41 44
Word 38: "LOAD" (4 bytes). Used in errors 22H and 24H.
5104
DEFM "SPACE" 53 50 41 43 45
Word 39: "SPACE" (5 bytes). Used in errors 1AH-1BH and 21H for space-exhaustion errors.
5109
DEFM "ONLY" 4F 4E 4C 59
Word 40: "ONLY" (4 bytes). Used in error 24H "ATTEMPTED TO LOAD READ ONLY MEMORY".
510D
DEFM "NAME" 4E 41 4D 45
Word 41: "NAME" (4 bytes). Used in error 13H "ILLEGAL FILE NAME".
5111
DEFM "DEVICE" 44 45 56 49 43 45
Word 42: "DEVICE" (6 bytes). Used in errors 08H and 21H.
5117
DEFM "FORMAT" 46 4F 52 4D 41 54
Word 43: "FORMAT" (6 bytes, second copy). Used in error 22H "LOAD FILE FORMAT ERROR". This duplicate exists because the original "FORMAT" (word 3 at 5037H) may have been allocated to a different descriptor chain position; the duplicate allows independent indexing.
511D
DEFM "FOUND" 46 4F 55 4E 44
Word 44: "FOUND" (5 bytes). Used in errors 05H, 0DH, 1FH for "NOT FOUND" and "RECORD NOT FOUND" messages.
5122
DEFM "IN" 49 4E
Word 45: "IN" (2 bytes). Used in error 18H "FILE NOT IN DIRECTORY".
5124
DEFM "ACCESS" 41 43 43 45 53 53
Word 46: "ACCESS" (6 bytes). Used in errors 19H and 25H for access-related errors.
512A
DEFM "FULL" 46 55 4C 4C
Word 47: "FULL" (4 bytes). Used in errors 1AH-1BH and 1EH for capacity-exhaustion messages.
512E
DEFM "DRIVE" 44 52 49 56 45
Word 48: "DRIVE" (5 bytes). Used in errors 0EH and 20H.
5133
DEFM "DENIED" 44 45 4E 49 45 44
Word 49: "DENIED" (6 bytes). Used in error 19H "FILE ACCESS DENIED".
5139
DEFM "PROGRAM" 50 52 4F 47 52 41 4D
Word 50: "PROGRAM" (7 bytes). Used in error 1FH "PROGRAM NOT FOUND".
5140
DEFM "AVAILABLE" 41 56 41 49 4C 41 42 4C 45
Word 51: "AVAILABLE" (9 bytes). Used in errors 08H and 21H.
5149
DEFM "- CAN'T EXTEND" 2D 20 43 41 4E 27 54 20 45 58 54 45 4E 44
Word 52: "- CAN'T EXTEND" (14 bytes, includes spaces and apostrophe). Used in error 1EH "DIRECTORY FULL - CAN'T EXTEND FILE".
5157
DEFM "OPEN" 4F 50 45 4E
Word 53: "OPEN" (4 bytes). Used in error 26H "FILE NOT OPEN".

515BH - Error Message Descriptor Chains

Variable-length byte sequences that define the word composition of each error message. Each byte encodes: bits 0-5 = word index (1-53) into the DEFW table at 4FC2H, bit 6 = context flag (when set on the last byte, indicates the FCB contains a filespec string for filename display), bit 7 = last-word flag (when set, this is the final word in the message). Chains for different error codes are stored contiguously; the offset table at 4F84H provides the start address of each chain. The descriptor chain area spans from 515BH to 51F2H (152 bytes).

515B
DEFB 01H,82H 01 82
Error 00H: word 1 "NO", word 2 "ERROR" (bit 7 set = last). Message: "NO ERROR".
515D
DEFB 04H,02H,05H, 06H,89H 04 02 05 06 89
Error 01H: "PARITY" "ERROR" "DURING" "HEADER" "READ" (bit 7 set = last). Message: "PARITY ERROR DURING HEADER READ".
5162
DEFB 08H,02H,05H, 89H 08 02 05 89
Error 02H: "SEEK" "ERROR" "DURING" "READ" (last). Message: "SEEK ERROR DURING READ".
5166
DEFB 0BH,07H,05H, 89H 0B 07 05 89
Error 03H: "LOST" "DATA" "DURING" "READ" (last). Message: "LOST DATA DURING READ".
516A
DEFB 04H,02H,05H, 89H 04 02 05 89
Error 04H: "PARITY" "ERROR" "DURING" "READ" (last). Message: "PARITY ERROR DURING READ".
516E
DEFB 07H,1BH,0CH, 2CH,05H,89H 07 1B 0C 2C 05 89
Error 05H: "DATA" "RECORD" "NOT" "FOUND" "DURING" "READ" (last). Message: "DATA RECORD NOT FOUND DURING READ".
5174
DEFB 0DH,09H,0EH, 07H,9BH 0D 09 0E 07 9B
Error 06H: "ATTEMPTED TO" "READ" "LOCKED/DELETED" "DATA" "RECORD" (bit 7 set = last). Message: "ATTEMPTED TO READ LOCKED/DELETED DATA RECORD".
5179
DEFB 0DH,09H,0FH, 07H,9BH 0D 09 0F 07 9B
Error 07H: "ATTEMPTED TO" "READ" "SYSTEM" "DATA" "RECORD" (last). Message: "ATTEMPTED TO READ SYSTEM DATA RECORD".
517E
DEFB 2AH,0CH,0F3H 2A 0C F3
Error 08H: "DEVICE" "NOT" "AVAILABLE" (bit 7 set + bit 6 set = C3H mask applied; 0F3H = word 51 + 80H + 40H). Message: "DEVICE NOT AVAILABLE". The bit 6 flag on the last byte indicates the FCB contains a filespec for display.
5181
DEFB 04H,02H,05H, 06H,8AH 04 02 05 06 8A
Error 09H: "PARITY" "ERROR" "DURING" "HEADER" "WRITE" (last). Message: "PARITY ERROR DURING HEADER WRITE".
5186
DEFB 08H,02H,05H, 8AH 08 02 05 8A
Error 0AH: "SEEK" "ERROR" "DURING" "WRITE" (last). Message: "SEEK ERROR DURING WRITE".
518A
DEFB 0BH,07H,05H, 8AH 0B 07 05 8A
Error 0BH: "LOST" "DATA" "DURING" "WRITE" (last). Message: "LOST DATA DURING WRITE".
518E
DEFB 04H,02H,05H, 8AH 04 02 05 8A
Error 0CH: "PARITY" "ERROR" "DURING" "WRITE" (last). Message: "PARITY ERROR DURING WRITE".
5192
DEFB 07H,1BH,0CH, 2CH,05H,8AH 07 1B 0C 2C 05 8A
Error 0DH: "DATA" "RECORD" "NOT" "FOUND" "DURING" "WRITE" (last). Message: "DATA RECORD NOT FOUND DURING WRITE".
5198
DEFB 0AH,15H,12H, 13H,0B0H 0A 15 12 13 B0
Error 0EH: "WRITE" "FAULT" "ON" "DISK" "DRIVE" (bit 7 set; 0B0H = word 48 + 80H). Message: "WRITE FAULT ON DISK DRIVE".
519D
DEFB 0AH,16H,94H 0A 16 94
Error 0FH: "WRITE" "PROTECTED" "DISKETTE" (last; 94H = word 20 + 80H). Message: "WRITE PROTECTED DISKETTE".
51A0
DEFB 17H,18H,1AH, 99H 17 18 1A 99
Error 10H: "ILLEGAL" "LOGICAL" "FILE" "NUMBER" (last; 99H = word 25 + 80H). Message: "ILLEGAL LOGICAL FILE NUMBER".
51A4
DEFB 10H,09H,82H 10 09 82
Error 11H: "DIRECTORY" "READ" "ERROR" (last). Message: "DIRECTORY READ ERROR".
51A7
DEFB 10H,0AH,82H 10 0A 82
Error 12H: "DIRECTORY" "WRITE" "ERROR" (last). Message: "DIRECTORY WRITE ERROR".
51AA
DEFB 17H,1AH,0E9H 17 1A E9
Error 13H: "ILLEGAL" "FILE" "NAME" (last; 0E9H = word 41 + 80H + 40H). Message: "ILLEGAL FILE NAME".
51AD
DEFB 22H,09H,82H 22 09 82
Error 14H: "GAT" "READ" "ERROR" (last). Message: "GAT READ ERROR".
51B0
DEFB 22H,0AH,82H 22 0A 82
Error 15H: "GAT" "WRITE" "ERROR" (last). Message: "GAT WRITE ERROR".
51B3
DEFB 23H,09H,82H 23 09 82
Error 16H: "HIT" "READ" "ERROR" (last). Message: "HIT READ ERROR".
51B6
DEFB 23H,0AH,82H 23 0A 82
Error 17H: "HIT" "WRITE" "ERROR" (last). Message: "HIT WRITE ERROR".
51B9
DEFB 1AH,0CH,2DH, 0D0H 1A 0C 2D D0
Error 18H: "FILE" "NOT" "IN" "DIRECTORY" (last; 0D0H = word 16 + 80H + 40H). Message: "FILE NOT IN DIRECTORY".
51BD
DEFB 1AH,2EH,0F1H 1A 2E F1
Error 19H: "FILE" "ACCESS" "DENIED" (last; 0F1H = word 49 + 80H + 40H). Message: "FILE ACCESS DENIED".
51C0
DEFB 10H,27H,0EFH 10 27 EF
Error 1AH: "DIRECTORY" "SPACE" "FULL" (last; 0EFH = word 47 + 80H + 40H). Message: "DIRECTORY SPACE FULL".
51C3
DEFB 13H,27H,0AFH 13 27 AF
Error 1BH: "DISK" "SPACE" "FULL" (last; 0AFH = word 47 + 80H). Message: "DISK SPACE FULL".
51C6
DEFB 1CH,1DH,1AH, 0A0H 1C 1D 1A A0
Error 1CH: "END" "OF" "FILE" "ENCOUNTERED" (last; 0A0H = word 32 + 80H). Message: "END OF FILE ENCOUNTERED".
51CA
DEFB 1BH,19H,1EH, 1DH,9FH 1B 19 1E 1D 9F
Error 1DH: "RECORD" "NUMBER" "OUT" "OF" "RANGE" (last; 9FH = word 31 + 80H). Message: "RECORD NUMBER OUT OF RANGE".
51CF
DEFB 10H,2FH,34H, 9AH 10 2F 34 9A
Error 1EH: "DIRECTORY" "FULL" "- CAN'T EXTEND" "FILE" (last; 9AH = word 26 + 80H). Message: "DIRECTORY FULL - CAN'T EXTEND FILE".
51D3
DEFB 32H,0CH,0ACH 32 0C AC
Error 1FH: "PROGRAM" "NOT" "FOUND" (last; 0ACH = word 44 + 80H). Message: "PROGRAM NOT FOUND".
51D6
DEFB 17H,30H,0D9H 17 30 D9
Error 20H: "ILLEGAL" "DRIVE" "NUMBER" (last; 0D9H = word 25 + 80H + 40H). Message: "ILLEGAL DRIVE NUMBER".
51D9
DEFB 01H,2AH,27H, 0F3H 01 2A 27 F3
Error 21H: "NO" "DEVICE" "SPACE" "AVAILABLE" (last; 0F3H = word 51 + 80H + 40H). Message: "NO DEVICE SPACE AVAILABLE".
51DD
DEFB 26H,1AH,2BH, 82H 26 1A 2B 82
Error 22H: "LOAD" "FILE" "FORMAT" "ERROR" (last). Message: "LOAD FILE FORMAT ERROR". Note: word 43 (2BH) is used here, which is the second "FORMAT" at 5117H.
51E1
DEFB 11H,95H 11 95
Error 23H: "MEMORY" "FAULT" (last; 95H = word 21 + 80H). Message: "MEMORY FAULT".
51E3
DEFB 0DH,26H,09H, 28H,91H 0D 26 09 28 91
Error 24H: "ATTEMPTED TO" "LOAD" "READ" "ONLY" "MEMORY" (last; 91H = word 17 + 80H). Message: "ATTEMPTED TO LOAD READ ONLY MEMORY".
51E8
DEFB 17H,2EH,0DH, 16H,9AH 17 2E 0D 16 9A
Error 25H: "ILLEGAL" "ACCESS" "ATTEMPTED TO" "PROTECTED" "FILE" (last; 9AH = word 26 + 80H). Message: "ILLEGAL ACCESS ATTEMPTED TO PROTECTED FILE".
51ED
DEFB 1AH,0CH,0F5H 1A 0C F5
Error 26H: "FILE" "NOT" "OPEN" (last; 0F5H = word 53 + 80H + 40H). Message: "FILE NOT OPEN".
51F0
DEFB 25H,02H,0A1H 25 02 A1
Default (errors 27H+): "UNKNOWN" "ERROR" (last; 0A1H = word 33? No - let me verify. 25H AND 3FH = 37 = "UNKNOWN". 02H = "ERROR". 0A1H = word (21H AND 3FH)=33="CODE"? No, 0A1H AND 3FH = 21H = 33. Wait: A1H = 10100001. Bits 0-5 = 100001 = 21H = 33 decimal. But word 33 = "CODE". That would make "UNKNOWN ERROR CODE". Actually, reviewing the bit pattern: 0A1H in binary = 10100001. Bits 0-5 = 100001 = 33. Bit 6 = 0. Bit 7 = 1 (last). So word 33 = "CODE" at 50E8H. The default message is "UNKNOWN ERROR CODE".