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

Page Customization

General:

SYS0/SYS is the core resident module of NEWDOS/80 v2.0 for the TRS-80 Model I. Loaded by the bootstrap routine from Track 0, Granules 1-3 (sectors 05-19), this module occupies memory from 4000H to 4CFFH and remains permanently resident throughout DOS operation, except for the DOS initialization routines in the overlay area which are overlaid when no longer needed. It provides the fundamental operating system services including disk I/O, file management, interrupt handling, and the command interface.

SYS0/SYS handles DOS initialization, disk I/O, clock interrupts, load of other system modules, keyboard intercept, etc.

SYS0/SYS resides in all the non-data areas from 4000H to 4CFFH and is located on Track 0 gran 1 of the DOS DISK and runs for 3 grans - sectors 05-19.

SYS0/SYS is actually comprised of a bunch of random snippets of code and so you will note Object Code load blocks being identified.

For lack of anywhere better to put this information, RST 28H is used heavily in NEWDOS/80 to call the various system files and the routines inside of them. A RST 28H call requires, at the very least, that Register A contain a value which is comprised of 3 binary parts: xxx yy zzz. zzz is the sector of the directory (less 2) to check for the system file. yy is the number of the system file in that directory sector. xxx is the function being called within that SYS file. The SYS file breakdown is:

  • Directory Sector 02H (zzz=0 or 000): BOOT/SYS (yy=00), SYS6/SYS (yy=01), SYS14/SYS (yy=10)
  • Directory Sector 03H (zzz=1 or 001): DIR/SYS (yy=00), SYS7/SYS (yy=01), SYS15/SYS (yy=10)
  • Directory Sector 04H (zzz=2 or 010): SYS0/SYS (yy=00), SYS8/SYS (yy=01), SYS16/SYS (yy=10)
  • Directory Sector 05H (zzz=3 or 011): SYS1/SYS (yy=00), SYS9/SYS (yy=01), SYS17/SYS (yy=10)
  • Directory Sector 06H (zzz=4 or 100): SYS2/SYS (yy=00), SYS10/SYS (yy=01), SYS18/SYS (yy=10)
  • Directory Sector 07H (zzz=5 or 101): SYS3/SYS (yy=00), SYS11/SYS (yy=01), SYS19/SYS (yy=10)
  • Directory Sector 08H (zzz=6 or 110): SYS4/SYS (yy=00), SYS12/SYS (yy=01), SYS20/SYS (yy=10)
  • Directory Sector 09H (zzz=7 or 111): SYS5/SYS (yy=00), SYS13/SYS (yy=01), SYS21/SYS (yy=10)

Memory Map

Address RangeFunction
400CH-4014HDOS Jump Table - Fixed entry points for system services
402DH-4035HWarm Start and DOS Ready vectors
403EH-4052HSystem timers, date/time storage, cursor position
4053H-407FHSystem configuration flags and limits
4308H-4367HDisk parameter blocks and I/O control
4368H-43DFHDrive FCB templates and device driver chain storage
4400H-4435HDOS Ready handler and SVC dispatch points
4436H-4475HFile operation jump table (open, close, read, write, seek)
4480H-44A6HDefault FCB template and sector buffer
44A7H-44C8HDate/time display routines
44CDH-4515HTimer interrupt callback and time increment
4516H-45F1HKeyboard driver and input handling
45F2H-4608HInterrupt service routine entry
4609H-466FHExit handlers and error recovery
4670H-47FFHDisk controller interface and sector I/O
4809H-497FHFile open, directory search, and FCB operations
4980H-49FBHSVC setup, FCB validation, and file I/O handler
49FCH-4AB7HSequential read/write operations
4AB8H-4B46HDisk write with retry and device driver chain
4B47H-4BA5HFile positioning (seek, rewind, tell)
4BA6H-4C27HConsole I/O and character output handler
4C28H-4C9CHDriver module loader and sector calculations
4C9DH-4CECHMultiply routines and command line parser
4CEDH-4CFFHDelay routine
4D00H-4F3AHBoot initialization and system configuration
4F3DH-4FFFHDate/time prompts and message strings
5000H-51FFHBoot sector buffer and overlay area

Boot Process (4D00H)

The boot entry point performs critical initialization:

  • RAM Detection - Scans downward from FFFFH writing complement patterns to determine actual memory size
  • Warm/Cold Boot Detection - Checks for signature byte A5H at 43ABH to determine if this is a warm restart
  • Boot Sector Validation - Reads and validates the DOS signature (A5H) from the boot sector
  • System Configuration - Copies drive parameters, step rates, and option flags from boot sector to system variables
  • Drive Initialization - Sets up parameter blocks for up to 4 drives
  • Hardware Detection - Tests for lowercase support to identify Model I vs Model III hardware
  • Device Driver Setup - Initializes the installable device driver chain
  • Autorun Check - Examines boot sector for automatic command execution

File Control Block (FCB) Management

FCBs are 32-byte structures managing open files:

  • +00H: Status byte (open/closed, access mode)
  • +01H: Flags (dirty buffer, position changed, write mode)
  • +02H: Extended flags
  • +03H-04H: Buffer address
  • +05H: Current sector offset within buffer
  • +08H: EOF sector number
  • +09H: Record size
  • +0AH-0BH: Current record number
  • +0CH-0DH: EOF position
  • +0EH-1FH: Extent table (8 entries, 2 bytes each - granule + length)

Disk I/O System

The disk subsystem provides:

  • Sector Read (4630H) - Reads 256-byte sectors with retry capability
  • Sector Write (463CH) - Writes sectors with optional verify
  • Directory Operations (492FH-496FH) - Search, read, and update directory entries
  • Extent Management (4875H-48F2H) - Handles file allocation via granule-based extents
  • Error Recovery - 3-retry mechanism for failed disk operations

Supervisor Call Interface (RST 28H)

The SVC mechanism uses a function code in Register A with the format xxx yy zzz:

  • zzz (bits 0-2): Directory sector minus 2
  • yy (bits 3-4): System file number within that sector
  • xxx (bits 5-7): Function number within the SYS file

This allows access to 8 directory sectors × 3 files × 8 functions = 192 possible system calls.

Device Driver Chain (4ADBH)

Installable device drivers are linked in a chain structure:

  • Each entry contains: device code (2 bytes), flags, handler address, next link
  • Drivers are searched sequentially until a matching device code is found
  • The chain terminates with marker byte C0H
  • Allows runtime extension of I/O capabilities

Interrupt Handler (45F2H)

The interrupt service routine handles:

  • Timer Ticks - Increments system clock at 4040H
  • Time Updates - Cascades seconds→minutes→hours→date via callback at 44CDH
  • Keyboard Scanning - Processes keyboard input during interrupts
  • Disk Motor Timeout - Manages drive motor shutoff timing

Variables:

AddressSizeDescription
4040H1Timer tick counter
4041H-4043H3Date storage (Year, Month, Day)
4044H-4046H3Time storage (Hours, Minutes, Seconds)
4049H2High memory pointer
4369H1Driver status flags (bit 6 = output in progress)
4370H1Disk parameter from boot sector
4380H-IY base pointer - DOS system area
439FH1Maximum drive number
43ABH1Warm boot signature (A5H when booted)
43ACH6Date/time backup for warm restart
43DCH2Cached driver address

Error Codes

CodeMeaning
11HDisk read error
12HDisk write error
1CHPosition error (before start)
1DHPosition error (past EOF)
22HInvalid module type
24HMemory write error
25HAccess denied
27HSystem disk error
2AHGeneral error
2BHSVC error
2CHDirectory full
2DHFile not found
2EHDevice not ready
34HParse error

Some Common Calls:

Directory Entry Search

This routine scans the disk directory for a file specification or attempts to locate the next entry after a successful search. It is a fundamental component of commands like DIR, PURGE, and KILL.

Routine:
Directory Entry Search
Address:
495EH (Common entry point for file search)
Description:
Searches the disk directory for a file entry matching the name provided in the FCB pointed to by IX. Upon completion, it leaves the directory entry information available in a work buffer. This is used to implement DIR, PURGE, and KILL commands. If found, returns A=00H and updates the FCB. If not found, returns an error code in A.
VariableEntryExitDescription
IXRequired: Pointer to the File Control Block (FCB) containing the target file name.Modified: The FCB pointed to by IX is updated with the directory entry information.File Control Block pointer.
HLRequired (For iteration): Must point to the start of the current directory sector buffer.Modified: Used internally; its final value is not typically relied upon by the caller.Directory buffer pointer.
AN/ASet: A=00H on success (file found), A=XXH (error code) if not found.Status/Error register.
FlagsN/ASet: Z FLAG set on success (A=00H), NZ FLAG set on error.Status flags (Z, C, etc.).



Sector Read Primitive

This routine is the lowest-level logical I/O function, responsible for reading a 256-byte sector from the disk controller into a specified memory buffer. High-level routines like file search, file read, and GAT access rely on this primitive.

Routine:
Sector Read Primitive
Address:
4630H (SectorRead)
Description:
Reads a single 256-byte sector from the specified track and sector into a memory buffer. This routine includes the standard 3-retry mechanism for disk I/O errors and reports the result via the Carry flag.
Function
Reads the sector identified by the Track, Sector, and Drive into the buffer pointed to by BC. Returns success/failure via the Carry flag and the status code in A.
VariableEntryExitDescription
ARequired: Disk Drive number (01H-04H).Modified: Contains the disk status/error code on exit.Drive number/Status register.
HLRequired: Track number (00H-23H).Modified: Preserved after the call (but may be volatile).Track number register.
DERequired: Sector number (01H-1AH).Modified: Preserved after the call (but may be volatile).Sector number register.
BCRequired: Starting address of the 256-byte memory buffer where the sector data is stored.Modified: Used internally, usually preserved across the call.Buffer address register.
FlagsN/ASet: C FLAG clear on success (read OK), C FLAG set on error (read failed after retries).Status flags (Z, C, etc.).



Character Output Handler

Routine:
Character Output Handler
Address:
4BC2H (CharOut_Main)
Description:
The primary low-level routine responsible for displaying a single 8-bit ASCII character to the currently active console device (e.g., screen or printer). This routine is essential for all text output.
Function
Accepts an ASCII character in A and routes it to the currently active console device.
VariableEntryExitDescription
ARequired: The 8-bit ASCII character to be displayed.Modified: Contents are passed through and modified.Character input/output register.
FlagsN/AModified: Flags are changed by the routine's operations.Status flags (Z, C, etc.).



Hex to ASCII Conversion (8-bit)

Routine:
Hex to ASCII Conversion (8-bit)
Address:
4068H (HexToAscii8)
Description:
Converts an 8-bit binary value into its 2-character hexadecimal ASCII string equivalent.
Function
Converts the 8-bit value in A into its 2-character ASCII hexadecimal equivalent, storing the result at the address pointed to by HL.
VariableEntryExitDescription
ARequired: The 8-bit binary value to convert.Modified: Holds the last converted ASCII character.8-bit value input register.
HLRequired: Pointer to the destination memory buffer where the ASCII string (2 bytes) will be stored.Modified: Incremented by 2; points past the stored string.Output buffer address pointer.
B, CN/AModified: Used as scratchpad and modified.General purpose registers (used for loop/scratchpad).
FlagsN/AModified: Flags are changed by the routine's operations.Status flags (Z, C, etc.).



FCB Open/Close Primitive

This is the high-level Disk SVC routine used to perform file opening and closing operations. SYS4 (ATTRIB) uses this to open files for reading/modifying attributes, and SYS5 (DEBUG) may call it indirectly when loading or saving blocks.

Routine:
File Control Block Open/Close Primitive
Address:
46D8H (Common entry point, often dispatched via RST 28H with A=01H or A=02H)
Description:
Handles the high-level logic for opening a file (locating the directory entry, reading the GAT, and preparing the FCB for I/O) or closing a file (writing updated GAT/Directory data, if necessary).
Function
Executes the file system operation specified by A on the file defined by the FCB at IX, typically managing GAT and Directory information.
VariableEntryExitDescription
ARequired: Function Code (e.g., A=01H for OPEN, A=02H for CLOSE).Set: A=00H on success; A=XXH (error code) if the operation failed.Function code/Status register.
IXRequired: Pointer to the File Control Block (FCB) defining the file name and I/O state.Modified: FCB fields (like GAT cluster, record pointer) are updated on entry and exit.File Control Block pointer.
FlagsN/ASet: Z FLAG set on success (A=00H), NZ FLAG set on error. C FLAG may be used for status.Status flags (Z, C, etc.).



String Compare

This is a low-level memory utility essential for parsing command line arguments and comparing strings (like file names, extensions, or command keywords). SYS4 uses it to compare input strings for attributes (SET, RESET), and SYS5 uses it heavily for command parsing (D, M, R, etc.).

Routine:
String Compare (HL vs. DE)
Address:
43BCH (Common entry point for a general-purpose string compare utility)
Description:
Compares two strings in memory, character by character, until a mismatch is found or a specified length is reached. Used widely for DOS command parsing and file operations. Compares BC bytes starting at HL with bytes starting at DE. Returns the result of the comparison via the Z80 Flag Register.
VariableEntryExitDescription
HLRequired: Pointer to the first string.Modified: Incremented during comparison; points past the last byte compared.Pointer to String 1.
DERequired: Pointer to the second string.Modified: Incremented during comparison; points past the last byte compared.Pointer to String 2.
BCRequired: The maximum number of bytes to compare.Modified: Decremented during comparison; returns number of bytes remaining.Length counter.
FlagsN/ASet: Z FLAG set if the strings are identical for the length specified. C FLAG and sign flags set based on the first differing character (A-B).Status flags (Z, C, etc.).



DOS Error Handler/Return Vector

While not a standard function, this is the guaranteed exit point that all commands eventually use to return control to the main DOS prompt after completing execution or encountering an error. All SYS files will eventually jump or call back to this address.

Routine:
DOS Error and Exit Handler (Vector)
Address:
400FH (DOS Jump Table Entry Point)
Description:
This is the primary vector used by overlay files (SYS1-SYS5) to return control to the resident DOS kernel, either upon successful command completion or following an error. It handles setting up the prompt and waiting for the next command. Receives control from an executing DOS command, processes any potential error code in A, re-initializes the DOS environment, displays the command prompt, and awaits the next user input.
VariableEntryExitDescription
AOptional: If returning with an error, A should contain the error code (non-zero). If successful, it's often 00H or ignored.Modified: Contents are typically cleared or used for internal status.Error code/Status register.
All RegistersN/ARestored/Cleared: All registers are usually modified or ignored as the routine re-initializes DOS state.All general-purpose registers.
FlagsN/AModified: Flags are changed as DOS state is reset.Status flags (Z, C, etc.).



Memory Move/Block Copy

This routine is the backbone of any large data operation, like moving file contents, copying sectors, or shifting buffers. It is heavily utilized by disk utilities like SYS6 (BACKUP) and SYS7 (FORMAT) for block-level data manipulation.

Routine:
Memory Block Copy (HL to DE)
Address:
43B7H (Common entry point for a general-purpose memory copy utility)
Function:
Copies BC bytes from the memory location starting at HL to the location starting at DE. Note: This is a non-overlapping copy (for overlapping moves, a different routine or technique is usually required). This is a faster alternative to LDIR when registers are already set up.
VariableEntryExitDescription
HLRequired: Pointer to the source memory block (start of data to be copied).Modified: Incremented during copy; points past the last byte copied.Source memory pointer.
DERequired: Pointer to the destination memory block (where data is written).Modified: Incremented during copy; points past the last byte written.Destination memory pointer.
BCRequired: The number of bytes to copy (the length of the block).Modified: Decremented until zero (loop counter).Length counter.
FlagsN/AModified: Flags are changed by the routine's operations.Status flags (Z, C, etc.).



Set/Change Disk Drive

All disk commands (BACKUP, FORMAT, COPY, DIR, etc.) must first communicate the target drive number to the resident kernel so that subsequent disk I/O calls (like the Sector Read/Write Primitives) operate on the correct physical drive.

Routine:
Set Current Disk Drive
Address:
4B67H (Common entry point for setting the active drive)
Description:
Sets the internal DOS variables to specify which disk drive (0-3 or 1-4) is the currently active one for all subsequent disk I/O operations. This must be called before using disk primitives. Updates the resident DOS kernel's state variables to designate the drive specified in A as the current working drive. Returns status via the Carry flag.
VariableEntryExitDescription
ARequired: The desired physical drive number (typically 00H for Drive 0, 01H for Drive 1, etc.).Modified: Typically preserved, or may contain an internal status code.Drive number/Status register.
CN/AModified: Often used as scratchpad or holds a register value.General purpose register.
FlagsN/ASet: C FLAG is often cleared on success, set on error (e.g., if the drive is invalid/not mounted).Status flags (Z, C, etc.).

Disassembly

400CH - DOS Jump Table Entry Points

This is the beginning of the DOS communication region. These jump vectors allow programs to access DOS services at fixed addresses regardless of internal code changes between versions.

400C
JUMP to the character output handler. This vector (at 400CH) is called to display a character.
400F
JUMP to exit/return handler. This is typically used after SVC calls complete.
4012
JUMP to interrupt service routine. Called by hardware interrupts for disk and timer services.

4015H-402CH - NO CODE

The disassembly I had did not have any code showing in this region. Just skipped right over it.

402DH - Error Handler and DOS Ready Jump

The DOS Ready jump at 402DH is the standard warm-start entry point. When a program terminates or an error occurs, execution returns here.

402D
JUMP to DOS Ready/warm start handler at 4400H. This is the error recovery entry point.
4030
LD A,43H 3E 43
Load Register A with 43H (SVC function code). This is the "DOS Ready" command indicator.
4032
RST 28H EF
Call Supervisor Call dispatcher. RST 28H is the DOS system call mechanism - function 43H displays the DOS READY prompt.
4033
JUMP to device driver chain handler. After displaying ready prompt, process any pending driver requests.

4036H-403DH - NO CODE

The disassembly I had did not have any code showing in this region. Just skipped right over it.

403EH - System Variables and Counters

This area contains system variables used by the DOS. The NOPs represent zero-initialized storage locations. At runtime, these hold timer counts, cursor positions, and state flags.

403E
NOP 00
Reserved byte (system variable storage).
403F
NOP 00
Reserved byte.
4040
NOP 00
Timer tick counter - incremented by interrupt handler at 4610H.
4041
NOP 00
Date/time storage: Year (low byte).
4042
NOP 00
Date/time storage: Month.
4043
NOP 00
Date/time storage: Day.
4044
NOP 00
Time storage: Hours.
4045
NOP 00
Time storage: Minutes.
4046
NOP 00
Time storage: Seconds.
4047
NOP 00
Reserved.
4048
LD D,D 52
Data byte 52H ('R' in ASCII) - part of version string or identifier.
4049
RST 38H FF
High memory pointer (low byte) - set during boot to top of available RAM.
404A
RST 38H FF
High memory pointer (high byte).
404B
NOP 00
Reserved byte.
404C
NOP 00
Reserved byte.
404D
NOP 00
Reserved byte.
404E
NOP 00
Reserved byte.
404F
NOP 00
Reserved byte.
4050
NOP 00
Reserved byte.
4051
NOP 00
Reserved byte.
4052
NOP 00
Reserved byte.

4053H - Disk Interrupt Handler Hook (unpatched)

This small routine is called during disk operations to handle FDC interrupts. It checks if carry flag is set (indicating a disk event) and calls the appropriate handler.

4053
NOP 00
NO OPERATION (Unpatched Code)
4054
NOP 00
NO OPERATION (Unpatched Code)
4055
NOP 00
NO OPERATION (Unpatched Code)
4056
NOP 00
NO OPERATION (Unpatched Code)
4057
NOP 00
NO OPERATION (Unpatched Code)
4058
NOP 00
NO OPERATION (Unpatched Code)
4059
NOP 00
NO OPERATION (Unpatched Code)

405AH - Nothing!

405A
NOP 00
Reserved byte.
405B
NOP 00
Reserved byte.
405C
NOP 00
Reserved byte.

405DH-4062H - NO CODE

The disassembly I had did not have any code showing in this region. Just skipped right over it.

4063H - Hex to ASCII Conversion Routine

This routine converts a 16-bit value in DE to a 4-character hexadecimal ASCII string stored at the address in HL. It processes the high byte (D) first, then the low byte (E).

4063
LD A,D 7A
Load Register A with the high byte of the value to convert (from Register D).
4064
GOSUB to convert the byte in A to two hex ASCII characters.
4067
LD A,E 7B
Load Register A with the low byte of the value to convert (from Register E).

Fall through to 4068H to convert the low byte. The routine below converts one byte to two ASCII hex digits.

4068
PUSH AF F5
Save the full byte onto the stack (we'll need both nibbles).
4069
RRCA 0F
Rotate A right (shift high nibble toward low nibble).
406A
RRCA 0F
Rotate A right again.
406B
RRCA 0F
Rotate A right again.
406C
RRCA 0F
Rotate A right again. Now the high nibble is in the low 4 bits of A.
406D
GOSUB to convert this nibble to ASCII and store it.
4070
POP AF F1
Restore the original byte from the stack to process the low nibble.

Fall through to convert the low nibble. This clever routine uses DAA (Decimal Adjust Accumulator) to convert 0-15 to '0'-'9' or 'A'-'F'.

4071
AND 0FHAND 00001111 E6 0F
Mask off high nibble, keeping only bits 0-3 (value 0-15).
4073
ADD 90H C6 90
Add 90H. This sets up for the DAA trick: values 0-9 become 90H-99H, values 10-15 become 9AH-9FH.
4075
DAA 27
Decimal Adjust. For 0-9: result is 90H-99H (no adjust). For 10-15: adds 60H giving F0H-F5H + sets carry.
4076
ADC 40H CE 40
Add 40H plus carry. For 0-9: 90H+40H=D0H. For A-F: F0H+40H+1=31H-36H (but wraps).
4078
DAA 27
Decimal Adjust again. This produces final ASCII: '0'-'9' (30H-39H) or 'A'-'F' (41H-46H).
4079
LD (HL),A 77
Store the ASCII hex character at the buffer address pointed to by HL.
407A
INC HL 23
INCrement HL to point to the next character position in the output buffer.
407B
RET C9
RETURN to caller.

407CH - Time Limit Data

These bytes appear to be limit values for date/time validation (used by the increment routine at 44CDH).

407C
DEC SP 3B
Data: 59 (3BH) - maximum seconds value.
407D
DEC SP 3B
Data: 59 (3BH) - maximum minutes value.
407E
RLA 17
Data: 23 (17H) - maximum hours value.
407F
NOP 00
Padding/reserved.

4080H-4307H - No Code

The disassembly I had did not have any code showing in this region. Just skipped right over it.

4308H - Drive Configuration Table

This area contains drive configuration data. Each drive has parameters for number of cylinders, sectors per track, step rate, etc.

4308
NOP 00
Current drive number (0-3). Modified during drive selection.
4309
NOP 00
Drive select mask - bit pattern for selecting drive (01H, 02H, 04H, or 08H).
430A
LD DE,0323H 11 23 03
Data: DE loaded with 0323H - likely sectors/track (23H=35) and heads configuration.
430D
INC HL 23
Data: 35 (23H) - number of tracks per drive.
430E
LD A,(BC) 0A
Data: 10 (0AH) - sectors per track.
430F
LD (BC),A 02
Data: 2 - granules per track or similar parameter.
4310
NOP 00
Reserved.
4311
NOP 00
Drive flags - configuration bits for current drive.
4312
JUMP vector for return with A=0 (success return).
4315
LD BC,0000H 01 00 00
Data: BC = 0000H - placeholder or counter.

4316H-4367H - No Code

The disassembly I had did not have any code showing in this region. Just skipped right over it.

4368H - DOS System Variables and FCB Storage

This area contains DOS system variables, drive parameter blocks, and FCB (File Control Block) templates. Many values are initialized at boot time from the disk's boot sector.

4368
AND L A5
Data byte A5H - DOS signature/marker byte.
4369
LD B,B 40
Data byte 40H - system flag.
436A
NOP 00
Reserved storage.
436B
NOP 00
Reserved storage.
436C
NOP 00
System option flags (low) - loaded from boot sector.
436D
NOP 00
System option flags (high).
436E
NOP 00
Extended system flags (low).
436F
NOP 00
Extended system flags (high).
4370
LD E,D 5A
Data byte 5AH - disk parameter loaded from 42A8H.
4371
LD DE,0323H 11 23 03
Drive parameter block pointer (initialized at boot).
4374
INC HL 23
Data byte.
4375
LD A,(BC) 0A
Data byte.
4376
LD (BC),A 02
Data byte.
4377
NOP 00
Reserved - loaded from boot sector offset F7H.
4378
NOP 00
Reserved - loaded from boot sector offset F8H.
4379
LD DE,FF02H 11 02 FF
Drive 0 parameter block start.
437C
LD BC,0100H 01 00 01
Drive 0 sector size/count.
437F
NOP 00
Drive 0 track count.

4380H - Drive 0 FCB Template (IY base pointer points here)

4380
NOP 00
Drive 0 FCB+00: Status byte.
4381
NOP 00
Drive 0 FCB+01: Flags.
4382
NOP 00
Drive 0 FCB+02: Extended flags.
4383
RST 38H FF
Drive 0 FCB+03: Buffer address low (FFH = uninitialized).
4384
NOP 00
Drive 0 FCB+04: Buffer address high.
4385
RST 38H FF
Drive 0 FCB+05: Sector position (FFH = uninitialized).
4386
LD BC,0100H 01 00 01
Drive 1 parameter block.
4389
NOP 00
Drive 1 status.
438A
NOP 00
Drive 1 reserved.
438B
NOP 00
Drive 1 reserved.
438C
NOP 00
Drive 1 reserved.
438D
RST 38H FF
Drive 1 FCB buffer (uninitialized).
438E
NOP 00
Drive 1 FCB.
438F
RST 38H FF
Drive 1 FCB (uninitialized).
4390
LD BC,0100H 01 00 01
Drive 2 parameter block.
4393
NOP 00
Drive 2 status.
4394
NOP 00
Drive 2 reserved.
4395
NOP 00
Drive 2 reserved.
4396
NOP 00
Drive 2 reserved.
4397
RST 38H FF
Drive 2 FCB (uninitialized).
4398
NOP 00
Drive 2 FCB.
4399
LD (HL),C 71
Data byte 71H - pointer reference.
439A
LD B,E 43
Data byte 43H - high byte of 4371H pointer.
439B
NOP 00
Reserved.
439C
NOP 00
Reserved.
439D
NOP 00
Reserved.
439E
NOP 00
Reserved.
439F
INC B 04
Data byte 04H - max drive number (loaded from 42A0H).
43A0
LD BC,0100H 01 00 01
Drive 3 parameter block (or system param loaded from 42A2H/42A3H).
43A3
NOP 00
Reserved.
43A4
LD BC,0000H 01 00 00
Additional parameters.
43A7
DEC C 0D
Data byte.
43A8
DEC C 0D
Data byte.

43A9H-43B1H - High Memory Pointer

Contains the high memory pointer determined at boot time, and warm boot signature area.

43A9
NOP 00 00
High memory address (2 bytes) - set during RAM detection.
43AB
NOP 00
Warm boot signature - set to A5H after first boot.
43AC
NOP 00 00 00 00 00 00
Date/time backup (6 bytes) - saved during boot for warm restart.

43B2H - Device Driver Chain and System Buffers

Device driver chain storage and additional system FCB templates for drives.

43B2
NOP 00
Device driver chain area start.
43B3
NOP 00
Driver chain link.
43B4
NOP 00
Driver flags.
43B5
RST 38H FF
Driver address (uninitialized).
43B6
RST 38H FF
Driver address high.
43B7-43B9
DB 00 00 00
NO OPERATION (Unpatched Code)
43BA
NOP 00
Reserved.
43BB
NOP 00
Reserved.
43BC
RST 38H FF
FCB template (uninitialized).
43BD
RST 38H FF
FCB template.
43BE
NOP 00
FCB reserved.
43BF
NOP 00
FCB reserved.
43C0
NOP 00
FCB reserved.
43C1
NOP 00
FCB reserved.
43C2
NOP 00
FCB reserved.
43C3
RST 38H FF
FCB extent (uninitialized).
43C4
RST 38H FF
FCB extent.
43C5
NOP 00
FCB reserved.
43C6
NOP 00
FCB reserved.
43C7
NOP 00
FCB reserved.
43C8
NOP 00
FCB reserved.
43C9
NOP 00
FCB reserved.
43CA
RST 38H FF
FCB extent.
43CB
RST 38H FF
FCB extent.
43CC
NOP 00
FCB reserved.
43CD
NOP 00
FCB reserved.
43CE
ADD A,B 80
Data byte 80H - driver load buffer reference.
43CF
JR Z,43D1H 28 00
Data bytes.
43D1
NOP 00
Reserved.
43D2
LD B,D 42
Data byte 42H - buffer page reference.
43D3
NOP 00
Reserved.
43D4
NOP 00
Reserved.
43D5
RST 38H FF
Uninitialized marker.
43D6
NOP 00
Reserved.
43D7
NOP 00
Reserved.
43D8
NOP 00
Device state - cleared during driver setup.
43D9
NOP 00
Reserved.
43DA
LD B,B 40
Data byte 40H.
43DB
NOP 00
Reserved.
43DC
NOP 00 00
Driver address storage (2 bytes) - written by 4BFFH.
43DE
RST 38H FF
Uninitialized marker.
43DF
RST 38H FF
Uninitialized marker.

43E0H-43FFH - No Code

The disassembly I had did not have any code showing in this region. Just skipped right over it.

4400H - DOS Ready / Warm Start Handler

This is the warm start entry point (jumped to from 402DH). It resets the system state and displays the DOS Ready prompt. Various SVC functions are called via RST 28H.

4400
LD A,23H 3E 23
Load Register A with SVC function 23H (Clear screen or reset display).
4402
RST 28H EF
Execute Supervisor Call - clears screen and initializes display.
4403
NOP 00
Padding (SVCs can have parameter bytes after them).
4404
NOP 00
Padding.
4405
LD A,63H 3E 63
Load Register A with SVC function 63H (Display "READY" message).
4407
RST 28H EF
Execute Supervisor Call - displays the DOS Ready prompt.
4408
RET Z C8
If Z FLAG is set (no error), RETURN. Otherwise fall through to error handling.
4409
PUSH AF F5
Save Register A (error code) onto the stack.
440A
LD A,26H 3E 26
Load Register A with SVC function 26H (Display error message).
440C
RST 28H EF
Execute Supervisor Call - displays the error message for the code pushed earlier.
440D
JUMP to cleanup and return routine.

4410H - Additional SVC Jump Points

These are entry points for various DOS supervisor calls. Each loads a function code and calls RST 28H.

4410
LD A,65H 3E 65
Load SVC function 65H.
4412
RST 28H EF
Execute Supervisor Call.
4413
LD A,85H 3E 85
Load SVC function 85H.
4415
RST 28H EF
Execute Supervisor Call.
4416
JUMP to check drive ready status.
4419
LD A,C3H 3E C3
Load SVC function C3H.
441B
RST 28H EF
Execute Supervisor Call.
441C
LD A,83H 3E 83
Load SVC function 83H.
441E
RST 28H EF
Execute Supervisor Call.

441FH - Additional SVC Calls

More SVC function entries. These load various function codes and call RST 28H.

441F
NOP 00
Padding/reserved byte.
4420
LD A,44H 3E 44
Load SVC function 44H.
4422
RST 28H EF
Execute Supervisor Call.
4423
NOP 00
Padding.
4424
LD A,24H 3E 24
Load SVC function 24H.
4426
RST 28H EF
Execute Supervisor Call.
4427
ADD A,D 82
Data byte 82H - parameter for SVC.
4428
LD A,25H 3E 25
Load SVC function 25H.
442A
RST 28H EF
Execute Supervisor Call.
442B
LD BC,453EH 01 3E 45
Load BC with 453EH - buffer address or parameter.
442E
RST 28H EF
Execute Supervisor Call.
442F
NOP 00
Padding.
4430
LD A,A4H 3E A4
Load SVC function A4H.
4432
RST 28H EF
Execute Supervisor Call.
4433
LD A,C4H 3E C4
Load SVC function C4H.
4435
RST 28H EF
Execute Supervisor Call.

4436H - Sector Read Entry Point

This jump table continues with more DOS function vectors. 4436H is particularly important as it's the sector I/O entry used during boot.

4436
JUMP to sequential sector read routine.
4439
JUMP to sector write (type 1) routine.
443C
JUMP to sector write (type 2) routine.
443F
JUMP to rewind/reset file position.
4442
JUMP to seek to position.
4445
JUMP to get current position.
4448
JUMP to get file info.
444B
JUMP to open file routine.
444E
JUMP to close file routine.

4451H - Additional Jump Table Entries

More DOS function vectors and jump table entries.

4451
LD A,C5H 3E C5
Load SVC function C5H.
4453
RST 28H EF
Execute Supervisor Call.
4454
NOP 00
Padding.
4455
NOP 00
Padding.
4456
NOP 00
Padding.
4457
LD A,2AH 3E 2A
Load A with error code 2AH.
4459
JUMP to error handler at 4409H.
445B
JUMP to drive select routine.
445E
JUMP to wait for index pulse.
4461
LD A,2BH 3E 2B
Load SVC function 2BH.
4463
RST 28H EF
Execute Supervisor Call.
4464
LD A,4BH 3E 4B
Load SVC function 4BH.
4466
RST 28H EF
Execute Supervisor Call.
4467
JUMP to print string routine.
446A
JUMP to printer output routine.
446D
JUMP to display date routine.
4470
JUMP to display time routine.
4473
LD A,A3H 3E A3
Load SVC function A3H.
4475
RST 28H EF
Execute Supervisor Call.
4476
NOP 00
Padding.
4477
NOP 00
Padding.
4478
NOP 00
Padding.
4479
NOP 00
Padding.
447A
NOP 00
Padding.
447B
NOP 00
Padding.
447C
JUMP back to error handler entry.
447E
XOR A AF
Clear A to zero.
447F
RET C9
RETURN - simple success return point.

4480H - Default FCB and Sector Buffer Area

This area contains the default FCB template and sector buffer space. Boot sector data is read into this area at 4480H.

4480
ADD A,D 82
Data byte 82H - FCB status flags.
4481
JR NZ,4483H 20 00
Data bytes - FCB flags/conditional.
4483
NOP 00
FCB reserved.
4484
LD B,D 42
Data byte 42H - buffer page reference.
4485
NOP 00
FCB reserved.
4486
NOP 00
FCB reserved.
4487
RST 38H FF
FCB buffer (uninitialized).
4488
NOP 00
FCB reserved.
4489
NOP 00
FCB reserved.
448A
LD (BC),A 02
Data byte.
448B
NOP 00
FCB reserved.
448C
RST 38H FF
FCB extent (uninitialized).
448D
RST 38H FF
FCB extent.
448E
RST 38H FF
FCB extent.
448F
RST 38H FF
FCB extent.
4490
RST 38H FF
FCB extent.
4491
RST 38H FF
FCB extent.
4492
RST 38H FF
FCB extent.
4493
RST 38H FF
FCB extent.
4494
RST 38H FF
FCB extent.
4495
RST 38H FF
FCB extent.
4496
RST 38H FF
FCB extent.
4497
RST 38H FF
FCB extent.
4498
RST 38H FF
FCB extent.
4499
RST 38H FF
FCB extent.
449A
RST 38H FF
FCB extent.
449B
RST 38H FF
FCB extent.
449C
RST 38H FF
FCB extent.
449D
RST 38H FF
FCB extent.
449E
RST 38H FF
FCB extent.
449F
RST 38H FF
FCB extent (end of 32-byte FCB).
44A0
NOP 00
Reserved.
44A1
NOP 00
Reserved.
44A2
JR Z,44A5H 28 01
Conditional jump (data/code).
44A4
LD HL,3C35H 21 35 3C
Load HL with 3C35H - video RAM position for date display.

44A7H - Display Date Routine

This routine displays the current date by converting the binary values at 4041H-4043H to ASCII and writing them to video RAM at 3C35H (second row of screen).

44A7
LD DE,4043H 11 43 40
Point DE to day counter at 4043H (the date storage area, starting with day).
44AA
LD B,3AH 06 3A
Load Register B with 3AH (ASCII colon ':'). This is the separator character.
44AC
LD C,03H 0E 03
Load Register C with 3 - we have 3 fields to convert (DD/MM/YY or MM/DD/YY).

[LOOP START] - Convert each date component (day, month, year) to two ASCII digits.

44AE
LD (HL),2FH 36 2F
Store '/' (2FH) at current position. This gets incremented to become the first digit.
44B0
LD A,(DE) 1A
Fetch the current date component (day/month/year) from the address in DE.
44B1
INC (HL) 34
[INNER LOOP] INCrement the tens digit character at (HL).
44B2
SUB 0AH D6 0A
SUBtract 10 from A. Each subtraction represents one "tens" digit.
44B4
If NO CARRY (A >= 0), LOOP BACK to continue incrementing tens digit.
44B6
INC HL 23
Move to next video RAM position (for units digit).
44B7
ADD 3AH C6 3A
ADD back 10 (to correct the overshoot) + 30H to convert to ASCII. 3AH = 10 + '0'.
44B9
LD (HL),A 77
Store the units digit character at current video position.
44BA
INC HL 23
Move to next video RAM position (for separator).
44BB
DEC DE 1B
DECrement DE to point to next date component (year→month→day, working backwards).
44BC
DEC C 0D
DECrement field counter C.
44BD
RET Z C8
If Z FLAG (all 3 fields done), RETURN.
44BE
LD (HL),B 70
Store the separator character (':'from B) at current position.
44BF
INC HL 23
Move to next video position.
44C0
[LOOP] Jump back to process next date field.

44C2H - Display Time Routine

Similar to date display but for time (HH:MM:SS). Points to seconds storage and uses '/' as separator (or reuses same conversion logic).

44C2
LD DE,4046H 11 46 40
Point DE to seconds counter at 4046H.
44C5
LD B,2FH 06 2F
Load Register B with 2FH (ASCII '/'). Used as separator between time fields.
44C7
JUMP to the shared conversion loop (reuses code at 44ACH).

44C9H - Timer Callback Table

This is the timer callback table used by the interrupt handler. Contains pointers to routines called on timer ticks.

44C9
EX DE,HL EB
Data byte EBH - callback table entry or opcode.
44CA
LD B,H 44
Data byte 44H - high byte of callback address.
44CB
JR Z,44CEH 28 01
Jump over next byte if Z flag set (or data bytes).

44CDH - Increment Time Counter

This routine increments the system time. It handles rollover from seconds→minutes→hours and uses the limit values at 407CH. Called by the interrupt handler.

44CD
LD HL,4041H 21 41 40
Point HL to the time storage area starting at 4041H (year, but we work on seconds first).
44D0
PUSH HL E5
Save HL onto the stack for later restoration.
44D1
LD DE,43ACH 11 AC 43
Point DE to backup/restore area at 43ACH.
44D4
LD BC,0006H 01 06 00
Set BC to 6 bytes (year, month, day, hour, minute, second).
44D7
LDIR ED B0
Block copy: backup current date/time from (HL) to (DE), 6 bytes.
44D9
LD DE,407CH 11 7C 40
Point DE to time limits table at 407CH (59, 59, 23 for sec, min, hour).
44DC
POP HL E1
Restore HL (points to 4041H, but we need seconds at 4046H).
44DD
LD B,03H 06 03
Load B with 3 - three time fields to potentially increment (sec, min, hour).

[LOOP START] - Try to increment each time field, checking for rollover.

44DF
INC (HL) 34
INCrement the current time field (seconds first).
44E0
LD A,(DE) 1A
Fetch the maximum value for this field from the limits table.
44E1
SUB (HL) 96
SUBtract current value from max. If result is negative (carry), we haven't exceeded limit.
44E2
RET NC D0
If NO CARRY (current ≤ max), no rollover needed - RETURN.
44E3
LD (HL),C 71
Reset this field to C (which is 0 from the LDIR operation) - rollover!
44E4
INC DE 13
Move to next limit value.
44E5
INC HL 23
Move to next time field.
44E6
[LOOP] DECrement B and JUMP if Not Zero - continue checking fields.
44E8
INC HL 23
Skip to day field (if hours rolled over to next day).
44E9
INC (HL) 34
INCrement the day counter (rollover from 23:59:59 to next day).
44EA
RET C9
RETURN to caller.

4516H - Keyboard BREAK Check

This routine checks for special key combinations and handles the BREAK key. Used by the keyboard scanner during disk operations and other interruptible processes.

4516
LD A,(4369H) 3A 69 43
Fetch system flags from 4369H to check current operating mode.
4519
XOR 20H EE 20
Toggle bit 5. This checks a specific mode flag.
451B
AND 68HAND 01101000 E6 68
Mask with 68H (bits 3, 5, 6). Tests multiple condition flags.
451D
LD A,CBH 3E CB
Load A with CBH - potential FDC command or control byte.
451F
If Z FLAG (conditions met), GOSUB to 49DDH (I/O handler).
4522
RET Z C8
If Z FLAG is set (success), RETURN.
4523
LD HL,45BEH 21 BE 45
Point HL to flag location at 45BEH.
4526
LD (HL),C9H 36 C9
Store C9H (RET opcode) - this creates a self-modifying "return immediately" stub.
4528
PUSH HL E5
Save this address onto the stack.
4529
LD HL,4036H 21 36 40
Point HL to keyboard state storage at 4036H.
452C
LD A,(HL) 7E
Fetch previous keyboard state.
452D
OR A B7
Test if previous state was zero.
452E
LD A,00H 3E 00
Load A with 0 (preparing to clear something).
4530
If NZ FLAG (previous state non-zero), skip the store.
4532
LD (4580H),A 32 80 45
Store 0 into keyboard buffer flag at 4580H.

4543H - Keyboard Scan Loop

This section scans the keyboard matrix by reading each row (at memory-mapped addresses 3801H-3880H) and comparing with previous state to detect key presses.

4543
LD L,36H 2E 36
Load L with 36H. Combined with H=40H from context, HL points to keyboard shadow buffer at 4036H.
4545
LD BC,3801H 01 01 38
Load BC with 3801H - the first keyboard row address (@ A B C D E F G).
4548
LD D,FFH 16 FF
Load D with FFH - used as key code counter/index, starts at -1.

[KEYBOARD SCAN LOOP] - Read each keyboard row and detect changes.

454A
LD A,(BC) 0A
Read the current keyboard row from the memory-mapped address in BC.
454B
LD E,A 5F
Copy current row state to E.
454C
XOR (HL) AE
XOR with previous state in shadow buffer - result shows changed keys.
454D
LD (HL),E 73
Update shadow buffer with current state.
454E
AND E A3
AND with current state - isolates newly pressed keys (not released).
454F
If NZ FLAG (key detected), JUMP to key processing at 455EH.
4551
LD A,D 7A
Load A with current key index from D.
4552
ADD 08H C6 08
ADD 8 to move to next row (8 keys per row).
4554
LD D,A 57
Store updated index back in D.
4555
INC L 2C
Move to next shadow buffer location.
4556
RLC C CB 01
Rotate C left - this doubles the value to get next keyboard row address (3801→3802→3804→3808...).
4558
If P FLAG (positive/bit 7 clear), continue scanning. When C overflows past 80H, we're done.
455B
XOR A AF
Clear A (no key found).
455C
JUMP to return path.

455EH - Process Detected Key

A key was detected in the scan loop. Now we need to determine which specific key by finding which bit is set.

455E
LD E,A 5F
Save the key bit pattern in E.
455F
INC D 14
[BIT SCAN LOOP] INCrement key code index.
4560
RRCA 0F
Rotate A right, shifting bits toward carry flag.
4561
If NO CARRY (bit was 0), LOOP to check next bit position.
4563
PUSH BC C5
Save BC (keyboard row address) onto stack.
4564
PUSH DE D5
Save DE (key code and bit pattern) onto stack.
4565
LD (452AH),HL 22 2A 45
Store current shadow buffer pointer (self-modifying code target).
4568
CALL 040BH CD 0B 04
GOSUB to ROM routine at 040BH to see if the key we just got it is shifted.
456B
POP HL E1
Restore DE into HL (for further processing).
456C
POP BC C1
Restore BC.
456D
OR A B7
Test if A is zero (no key or invalid key).
456E
LD D,A 57
Save ASCII code in D.
456F
If Z FLAG (no valid key), JUMP to cleanup at 4589H.

45BFH - Check System Flags

This routine checks system flags to determine operating mode and whether certain features are enabled.

45BF
LD HL,4369H 21 69 43
Point HL to system flags byte at 4369H.
45C2
LD A,(HL) 7E
Fetch the system flags.
45C3
AND 6CH E6 6C
Mask with 6CH (bits 2, 3, 5, 6). Tests specific condition flags.
45C5
If NZ FLAG (any flag set), JUMP to return at 45EDH.
45C7
LD A,(3801H) 3A 01 38
Read keyboard row 0 (@ A B C D E F G).
45CA
CP D0H FE D0
Compare with D0H - checking for specific key combination.
45CC
JUMP to continue checking other rows.

45F2H - Interrupt Service Routine Entry

This is the main interrupt service routine. It's jumped to from 4012H when hardware interrupts occur. It handles disk and timer interrupts.

45F2
PUSH AF F5
Save Register A and Flags onto the stack (preserve interrupted program's state).
45F3
PUSH HL E5
Save HL onto the stack.
45F4
PUSH DE D5
Save DE onto the stack.
45F5
PUSH BC C5
Save BC onto the stack.
45F6
LD A,(37ECH) 3A EC 37
Read the Floppy Disk Controller Status, and do absolutely nothing with it! (Unpatched Code)
45F9
LD A,(37E0H) 3A E0 37
Read the drive select latch at 37E0H to check which drive caused interrupt (Unpatched Code)
45FC
RLCA 07
Rotate left - moves drive select bits into position for testing (Unpatched Code)
45FD
If CARRY FLAG set (timer interrupt), GOSUB to timer handler at 4610H.
4600
GOSUB to additional interrupt processing (or return stub if disabled).
4603
POP BC C1
Restore BC from the stack.
4604
POP DE D1
Restore DE from the stack.
4605
POP HL E1
Restore HL from the stack.
4606
POP AF F1
Restore A and Flags from the stack.
4607
EI FB
Enable Interrupts - allow further interrupts to occur.
4608
RET C9
RETURN from interrupt to the interrupted program.

4609H - Exit/Return Handler

This routine is called to return from DOS operations. It pushes AF and performs SVC 27H which handles the actual return.

4609
PUSH AF F5
Save Register A (usually contains error/status code) onto the stack.
460A
LD A,27H 3E 27
Load A with SVC function 27H (return from SVC handler).
460C
RST 28H EF
Execute Supervisor Call to perform the return.
460D
LD (HL),B 70
This may be part of the return data or a no-op in this context.
460E
INC HL 23
Increment HL (part of return sequence).
460F
JP (HL) E9
JUMP to address in HL - returns to the calling program.

4610H - Timer Tick Handler

This routine handles timer interrupts. It increments the tick counter and potentially updates the system time. Called from the interrupt service routine when carry is set.

4610
LD HL,4040H 21 40 40
Point HL to timer tick counter at 4040H.
4613
INC (HL) 34
INCrement the tick counter.
4614
LD HL,4537H 21 37 45
Point HL to keyboard repeat delay counter at 4537H.
4617
LD A,(HL) 7E
Fetch current repeat delay value.
4618
OR A B7
Test if delay counter is zero.
4619
If Z FLAG (counter is zero), skip decrement.
461B
DEC (HL) 35
DECrement the repeat delay counter.
461C
LD HL,44C9H 21 C9 44
Point HL to timer callback table at 44C9H.
461F
LD A,H 7C
Load A with high byte of pointer.
4620
OR L B5
OR with low byte - tests if pointer is 0000H (end of list).
4621
RET Z C8
If Z FLAG (null pointer), RETURN - no more callbacks.
4622
LD E,(HL) 5E
Fetch low byte of callback address.
4623
INC HL 23
Move to next byte.
4624
LD D,(HL) 56
Fetch high byte of callback address.
4625
PUSH DE D5
Save callback address onto stack.
4626
INC HL 23
Move to parameter byte.
4627
LD B,(HL) 46
Fetch callback parameter into B.
4628
INC HL 23
Move to countdown byte.
4629
DEC (HL) 35
DECrement the countdown timer.
462A
If Z FLAG (countdown reached 0), GOSUB to execute the callback.
462D
POP HL E1
Restore callback address (now in HL for next iteration).
462E
[LOOP] Continue processing callback list.

4630H - Disk Read Sector Entry

This routine initiates a disk sector read operation. It sets up the FDC command byte and falls through to the main disk I/O routine.

4630
LD A,88H 3E 88
Load A with 88H - FDC Read Sector command (80H + flags for head load, verify).
1771 FDC Command: 88H (1000 1000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
100mbE00Command=Read Sector
Bit 7-5: Read Command (100)
m: 1=Multiple Records, 0=Single Record
b: 1=IBM format, 0=Non-IBM Format
E: 1=Enable HLD, HLT, and 10ms Delay, 0=Assume Head Already Engaged, no Delay
Remainder: Unused (00)
4632
JUMP to common disk I/O setup at 4642H.

4634H - Disk Read with Retry

This routine reads a sector with automatic retry capability. It preserves registers and calls the base read routine.

4634
PUSH HL E5
Save HL (buffer address) onto the stack.
4635
LD H,01H 26 01
Load H with 01H - retry count flag.
4637
GOSUB to sector read routine.
463A
POP HL E1
Restore HL from the stack.
463B
RET C9
RETURN to caller.

463CH - Disk Write Sector Entry

463C
LD A,A9H 3E A9
Load A with A9H - FDC Write Sector command with flags
1771 FDC Command: A9H (1010 1001)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
101mbEa1a0Command=Write Sector
Bit 7-5: Write Command (101)
m: 1=Multiple Records, 0=Single Record
b: 1=IBM format, 0=Non-IBM Format
E: 1=Enable HLD, HLT, and 10ms Delay, 0=Assume Head Already Engaged, no Delay
a1, a0: Data Address Mark Select (00=Normal, 01=Deleted)
463E
JUMP to common disk I/O setup.

4640H - Disk Read Track Entry

4640
LD A,A8H 3E A8
Load A with A8H - variant sector read command
1771 FDC Command: A8H (1010 1000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
101mbEa1a0Command=Write Sector
Bit 7-5: Write Command (101)
m: 1=Multiple Records, 0=Single Record
b: 1=IBM format, 0=Non-IBM Format
E: 1=Enable HLD, HLT, and 10ms Delay, 0=Assume Head Already Engaged, no Delay
a1, a0: Data Address Mark Select (00=Normal, 01=Deleted)

4642H - Disk I/O Setup and Execute

This is the main disk I/O entry point. It stores the command, sets up parameters based on command type (read vs write), then executes the FDC operation.

4642
LD (46C4H),A 32 C4 46
Store the FDC command byte at 46C4H for later use.
4645
AND 20HAND 00100000 E6 20
Test bit 5 - this distinguishes read (bit 5=0) from write (bit 5=1) operations.
4647
PUSH BC C5
Save BC onto the stack.
4648
LD BC,021AH 01 1A 02
Default values: B=02H (retries?), C=1AH (sector count/parameter).
464B
If Z FLAG (read operation), JUMP past write-specific setup.
464D
LD A,08H 3E 08
For writes: load A with 08H.
464F
LD BC,0A12H 01 12 0A
Write parameters: B=0AH, C=12H.
4652
LD (4731H),A 32 31 47
Store parameter byte at 4731H (self-modifying code location).
4655
LD (46FCH),BC ED 43 FC 46
Store BC parameters at 46FCH.
4659
LD B,0AH 06 0A
Load B with 10 - retry count for drive operations.
465B
GOSUB to drive select routine at 4773H.
465E
If NZ FLAG (drive error), JUMP to error handling at 4678H.

4660H - Sector Read/Write Main Loop

After drive selection succeeds, this section calculates the physical track and sector from logical address and initiates the FDC operation.

4660
PUSH BC C5
Save retry counter onto the stack.
4661
PUSH DE D5
Save DE (usually buffer pointer) onto the stack.
4662
PUSH HL E5
Save HL onto the stack.
4663
LD A,(430EH) 3A 0E 43
Fetch sectors per track (typically 10) from 430EH.
4666
EX DE,HL EB
Exchange DE and HL (move sector address to DE).
4667
GOSUB to division routine - divides logical sector by sectors/track.
466A
LD D,L 55
Move quotient (track number) to D.
466B
LD E,A 5F
Move remainder (sector number within track) to E.
466C
LD HL,430DH 21 0D 43
Point HL to total tracks parameter at 430DH.
466F
LD A,D 7A
Load A with calculated track number.
4670
CP (HL) BE
Compare track number against maximum tracks.
4671
If CARRY (track < max), JUMP to continue - track is valid.
4673
LD A,14H 3E 14
Load A with error code 14H (seek error / track out of range).
4675
POP HL E1
Restore HL from stack.
4676
POP DE D1
Restore DE from stack.
4677
POP BC C1
Restore BC from stack.
4678
OR A B7
Test error code (set flags based on A).
4679
JUMP to error return path at 4737H.

467CH - Configure Drive Flags for Operation

Track is valid. Now we configure the FDC based on drive-specific flags (stepping rate, head load, etc.).

467C
LD A,(4311H) 3A 11 43
Fetch drive flags from 4311H.
467F
LD B,A 47
Copy flags to B for bit testing.
4680
BIT 0,B CB 40
Test bit 0 of drive flags.
4682
If Z FLAG (bit 0 clear), skip flag modification.
4684
LD HL,46C4H 21 C4 46
Point HL to stored FDC command at 46C4H.
4687
RES 1,(HL) CB 8E
Clear bit 1 of command byte (modify head load timing).
4689
LD HL,4309H 21 09 43
Point HL to drive configuration at 4309H.
468C
BIT 1,B CB 48
Test bit 1 of drive flags.
468E
If Z FLAG (bit 1 clear), skip track adjustment.
4690
INC D 14
INCrement track number D (adjust for drive geometry).
4691
PUSH DE D5
Save track/sector onto the stack.
4692
BIT 2,B CB 50
Test bit 2 of drive flags (double-sided?).
4694
If Z FLAG (single-sided), skip head selection.
4696
RLC D CB 02
Rotate D left - adjusts track for double-sided operation (track = track * 2 + side).
4698
BIT 6,B CB 70
Test bit 6 of drive flags.
469A
If Z FLAG, skip sector adjustment.
469C
RRC C CB 09
Rotate C right (halve it for interleave calculation).
469E
LD A,E 7B
Load A with sector number.
469F
SUB C 91
SUBtract interleave offset.
46A0
If CARRY (underflow), skip adjustment.
46A2
LD E,A 5F
Store adjusted sector number in E.
46A3
SET 3,(HL) CB DE
SET bit 3 of drive config (mark adjustment made).

46A5H - Send Track and Sector to FDC

Now we send the track and sector numbers to the FDC registers and initiate the seek operation.

46A5
GOSUB to set drive select register at 4767H.
46A8
BIT 4,B CB 60
Test bit 4 of drive flags (sector numbering offset?).
46AA
If Z FLAG (no offset), skip increment.
46AC
INC E 1C
INCrement sector number E (some drives number from 1 instead of 0).
46AD
LD (37EEH),DE ED 53 EE 37
Store track (D) and sector (E) to FDC track and sector registers at 37EDH/37EEH.
46B1
LD C,18H 0E 18
Load C with 18H - seek command (Type I)
1771 FDC Command: 18H (0001 1000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
0001hVr1r0Command=Seek
Bit 7-4: Command Code (0001)
h: 1=Enable Head Load/Settle, 0=No delay
V: 1=Verify Destination Track ID, 0=No verification
r1, r0: Stepping Motor Rate (00=3ms, 01=6ms, 10=10ms, 11=15ms)
46B3
GOSUB to execute FDC command at 4747H (perform seek).
46B6
POP AF F1
Restore track/sector into AF.
46B7
POP BC C1
Restore BC.
46B8
PUSH BC C5
Save BC again (will need for retry loop).
46B9
LD (37EDH),A 32 ED 37
Store track number to FDC track register at 37EDH.
46BC
PUSH DE D5
Save DE (buffer pointer).
46BD
LD DE,37EFH 11 EF 37
Point DE to FDC data register at 37EFH.
46C0
LD HL,37ECH 21 EC 37
Point HL to FDC command/status register at 37ECH.
46C3
LD (HL),00H 36 00
Write 00H to command register - NOP/prepare before actual command.

46C5H - FDC Data Transfer Loop

This is the critical data transfer loop. It issues the read/write command and performs byte-by-byte transfer with the FDC, checking DRQ (Data Request) status.

46C5
GOSUB to short delay routine - wait for FDC to settle.
46C8
DI F3
Disable Interrupts - critical timing section, cannot be interrupted.
46C9
BIT 0,(HL) CB 46
Test bit 0 of FDC status (BUSY flag).
46CB
If Z FLAG (not busy/complete), JUMP to completion handling at 4717H.
46CD
LD A,(46C4H) 3A C4 46
Fetch the stored FDC command byte.
46D0
BIT 5,A CB 6F
Test bit 5 - this determines read (0) or write (1) direction.
46D2
If Z FLAG (read operation), JUMP to read loop at 46F6H.

[WRITE PATH] - Send data bytes to the FDC.

46D4
LD A,83H 3E 83
Load A with 83H - mask for status bits (BUSY | DRQ | LOST DATA).
46D6
AND (HL) A6
AND with FDC status register.
46D7
If Parity Odd (waiting for DRQ), LOOP BACK to keep polling.
46DA
LD A,(BC) 0A
Fetch byte from source buffer at address in BC.
46DB
LD (DE),A 12
Write byte to FDC data register.
46DC
INC BC 03
INCrement buffer pointer.
46DD
LD A,(BC) 0A
Pre-fetch next byte from buffer.
46DE
LD (46E8H),A 32 E8 46
Store next byte (self-modifying code optimization).
46E1
INC BC 03
INCrement buffer pointer again.
46E2
LD A,01H 3E 01
Load A with 01H for BUSY test.
46E4
CP (HL) BE
Compare with FDC status - wait for command completion.
46E5
If Z FLAG (still exactly 01H/BUSY only), LOOP and wait.
46E7
LD A,00H 3E 00
This byte gets modified by the pre-fetch at 46DEH.
46E9
LD (DE),A 12
Write the pre-fetched byte to FDC data register.
46EA
LD A,(BC) 0A
Fetch next byte from buffer.
46EB
INC BC 03
INCrement buffer pointer.
46EC
BIT 1,(HL) CB 4E
Test bit 1 of FDC status (DRQ - Data Request).
46EE
If NZ FLAG (DRQ active), JUMP to continue transfer.
46F0
BIT 1,(HL) CB 4E
Test DRQ again (double-check timing).
46F2
If NZ FLAG, JUMP to continue.
46F4
No DRQ - JUMP to check completion status.

46F6H - FDC Read Data Loop

[READ PATH] - Receive data bytes from the FDC.

46F6
LD A,83H 3E 83
Load A with 83H - mask for BUSY | DRQ | LOST DATA bits.
46F8
AND (HL) A6
AND with FDC status register to isolate these bits.
46F9
If Parity Odd (waiting for DRQ), LOOP BACK and keep polling.
46FC
LD A,(DE) 1A
Read byte from FDC data register.
46FD
LD (BC),A 02
Store byte to destination buffer at address in BC.
46FE
INC BC 03
INCrement buffer pointer.
46FF
BIT 1,(HL) CB 4E
Test DRQ bit - is more data available?
4701
If NZ FLAG (DRQ active), LOOP to read next byte.
4703
BIT 1,(HL) CB 4E
Double-check DRQ (timing sensitivity).
4705
If NZ FLAG, continue reading.
4707
BIT 1,(HL) CB 4E
Triple-check DRQ.
4709
If NZ FLAG, continue reading.
470B
BIT 0,(HL) CB 46
Test BUSY bit - is command still active?
470D
If Z FLAG (not busy), JUMP to completion at 4717H.
470F
BIT 1,(HL) CB 4E
One more DRQ check.
4711
If NZ FLAG (late DRQ), continue reading.
4713
BIT 7,(HL) CB 7E
Test bit 7 (NOT READY status).
4715
If Z FLAG (drive ready), go back to check for more data.

4717H - FDC Operation Complete

The FDC operation has completed. Now we check the status register for errors and clean up.

4717
LD A,(HL) 7E
Fetch final FDC status into A.
4718
LD (HL),0D0H 36 D0
Write D0H to FDC command register - Force Interrupt command to reset state.
1771 FDC Command: D0H (1101 0000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
1101I3I2I1I0Command=Force Interrupt
Bit 7-4: Command Code (1101)
I3: 1=Interrupt Immediately
    0=No Interrupt Immediately
I2: 1=Interrupt on the next Index Pulse
    0=No Interrupt on the next Index Pulse
I1: 1=Interrupt the next time Ready goes to Not Ready
    0=No Interrupt the next time Ready goes to Not Ready
I0: 1=Interrupt the next time Not Ready goes to Ready
    0=No Interrupt the next time Not Ready goes to Ready
471A
INC HL 23
Point HL to FDC track register.
471B
POP BC C1
Restore BC (was pushed with track number).
471C
LD (HL),B 70
Store track number to track register.
471D
POP HL E1
Restore HL.
471E
POP DE D1
Restore DE.
471F
POP BC C1
Restore BC.
4720
EI FB
Enable Interrupts - critical section is over.
4721
AND FCH E6 FC
Mask FDC status with FCH - isolate error bits (ignore BUSY and INDEX).
4723
If Z FLAG (no errors), JUMP to success return at 4737H.
4725
LD C,A 4F
Copy error status to C for analysis.
4726
AND 9CH E6 9CH
Mask with 9CH - isolate specific error bits.
4728
If Z FLAG (no critical errors), JUMP to retry logic.
472A
LD C,A 4F
Update C with critical error bits.
472B
ADD A,A 87
Double A (shift error bits left).
472C
If Z FLAG after shift, JUMP to error translation.
472E
DECrement retry counter B and JUMP if Not Zero to retry at 473AH.

4730H - Translate FDC Error to DOS Error Code

This routine converts FDC hardware error bits into a DOS error code number.

4730
LD A,00H 3E 00
Start error code at 0 (this byte may be modified at 4731H).
4732
INC A 3C
[ERROR CODE LOOP] INCrement error code.
4733
RRC C CB 09
Rotate error status bits right.
4735
If NO CARRY (this error bit not set), LOOP to check next bit.
4737
EI FB
Enable Interrupts.
4738
POP BC C1
Restore BC from stack.
4739
RET C9
RETURN to caller with error code in A (0 = success, nonzero = error).

473AH - Disk Retry Logic

When a disk error occurs, this routine determines if a retry is appropriate and performs head recalibration if needed.

473A
BIT 4,C CB 61
Test bit 4 of error status (Record Not Found).
473C
If NZ FLAG (sector not found), GOSUB to recalibration check at 4742H.
473F
JUMP back to retry the operation at 4660H.
4742
BIT 0,B CB 40
Test bit 0 of retry counter (check if odd retry count).
4744
RET Z C8
If Z FLAG (even count), RETURN without recalibration.
4745
LD C,08H 0E 08
Load C with 08H - Restore (recalibrate) command for FDC
1771 FDC Command: 08H (0000 1000)Function Description
Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Summary of Bits
0000hVr1r0Command=Restore
Bit 7-4: Command Code (0000)
h: 1=Enable Head Load/Settle, 0=No delay
V: 1=Verify Track 0 ID, 0=No verification
r1, r0: Stepping Motor Rate (00=3ms, 01=6ms, 10=10ms, 11=15ms)

4747H - Execute FDC Type I Command

This routine executes FDC Type I commands (Restore, Seek, Step) which don't transfer data but move the head.

4747
LD A,(430CH) 3A 0C 43
Fetch drive step rate from 430CH.
474A
AND 03H E6 03
Mask to keep only bits 0-1 (step rate: 0=6ms, 1=12ms, 2=20ms, 3=30ms).
474C
OR C B1
OR with command in C to add step rate bits to command byte.
474D
LD (37ECH),A 32 EC 37
Write complete command to FDC command register at 37ECH.
4750
GOSUB to delay routine - wait for command to start.
4753
BIT 0,A CB 47
Test BUSY bit of returned status.
4755
RET Z C8
If Z FLAG (not busy/complete), RETURN.
4756
RLCA 07
Rotate status left to test bit 7 (NOT READY).
4757
If CARRY (drive not ready), JUMP to force interrupt at 475EH.
4759
GOSUB to update drive select register.
475C
[LOOP] Go back and wait for command completion.
475E
LD A,D0H 3E D0
Load A with D0H - Force Interrupt command.
4760
JUMP to write command and exit loop.

4762H - Check Drive Ready Status

4762
LD A,(37ECH) 3A EC 37
Read FDC status register at 37ECH.
76543210
Not
Ready
ProtectedHead
Loaded
Seek
Error
CRC
Error
Track 00IndexBusy
4765
RLCA 07
Rotate left to move NOT READY bit (bit 7) into carry.
4766
RET C D8
If CARRY (drive not ready), RETURN with carry set indicating error.

4767H - Set Drive Select Register

4767
LD A,(4309H) 3A 09 43
Fetch drive select mask from 4309H.
476A
LD (37E1H),A 32 E1 37
Write to drive select latch at 37E1H to activate drive.
476D
RET C9
RETURN to caller.

4773H - Select Drive by Number

This routine selects a drive by its number (0-3). It saves registers, compares with current drive, and loads the appropriate configuration parameters.

4773
LD A,(4308H) 3A 08 43
Fetch requested drive number from 4308H.
4776
PUSH HL E5
Save HL onto the stack.
4777
PUSH DE D5
Save DE onto the stack.
4778
PUSH BC C5
Save BC onto the stack.
4779
CP 01H FE 01
Compare drive number against 01H. Sets carry if A=0 (drive 0).
477B
LD C,A 4F
Copy drive number to C.
477C
LD A,20H 3E 20
Load A with error code 20H (invalid drive number).
477E
If NO CARRY (drive ≥ 1), JUMP to check if valid at 47DEH.
4780
GOSUB to force interrupt - reset FDC state.
4783
LD HL,4308H 21 08 43
Point HL to current drive number storage.
4786
LD A,(HL) 7E
Fetch current drive number.
4787
LD (HL),C 71
Store new drive number from C.
4788
CP C B9
Compare old drive with new drive.
4789
PUSH AF F5
Save comparison result (Z flag indicates same drive).
478A
LD L,A 6F
Use old drive number as low byte of pointer.
478B
LD A,(37EDH) 3A ED 37
Fetch current FDC track register value.
478E
LD (HL),A 77
Store track to old drive's track storage (at 4300H+drive#).
478F
LD L,C 69
Point L to new drive's track storage.
4790
PUSH HL E5
Save pointer to new drive's track.
4791
LD B,C 41
Copy drive number to B for loop.
4792
LD A,80H 3E 80
Initialize select mask with 80H.
4794
INC B 04
INCrement B (drive count + 1).
4795
RLCA 07
[LOOP] Rotate mask left.
4796
DECrement B and LOOP until done. Result: mask for selected drive.
4798
LD (4309H),A 32 09 43
Store drive select mask (01H, 02H, 04H, or 08H depending on drive).
479B
LD A,C 79
Load A with drive number.
479C
RLCA 07
Rotate left (multiply by 2).
479D
RLCA 07
Rotate left again (multiply by 4).
479E
ADD A,C 81
Add original drive number (total = drive × 5).
479F
ADD A,A 87
Double result (total = drive × 10).
47A0
ADD 71H C6 71
ADD base address offset 71H. Points to drive config table entry.
47A2
LD L,A 6F
Low byte of config table pointer.
47A3
LD (4399H),HL 22 99 43
Store drive config pointer at 4399H.
47A6
LD C,08H 0E 08
Set C to 8 bytes to copy.
47A8
LD DE,430AH 11 0A 43
Point DE to active config area at 430AH.
47AB
LDIR ED B0
Block copy 8 bytes of drive configuration.

47E3H - Short Delay Routine

A small delay loop used to wait for FDC timing requirements. Delays approximately 18 microseconds at 1.77 MHz.

47E3
LD A,06H 3E 06
Load A with 6 - loop counter.
47E5
DEC A 3D
[DELAY LOOP] DECrement counter.
47E6
If NZ FLAG (counter not zero), LOOP BACK.
47E8
LD A,(37ECH) 3A EC 37
Read FDC status register at 37ECH after delay.
76543210
Not
Ready
ProtectedHead
Loaded
Seek
Error
CRC
Error
Track 00IndexBusy
47EB
RET C9
RETURN with status in A.

47ECH - Wait for Index Pulse with Timeout

This routine waits for the disk's index pulse, used to ensure the disk is spinning. Returns error 08H if timeout occurs.

47EC
GOSUB to drive select routine.
47EF
RET NZ C0
If NZ FLAG (drive select failed), RETURN with error.
47F0
PUSH HL E5
Save HL onto the stack.
47F1
PUSH DE D5
Save DE onto the stack.
47F2
PUSH BC C5
Save BC onto the stack.
47F3
LD DE,0000H 11 00 00
Initialize DE to 0 as timeout counter.
47F6
LD HL,37ECH 21 EC 37
Point HL to FDC status register.
47F9
LD B,(HL) 46
Read initial status into B.
47FA
LD A,(HL) 7E
[INDEX WAIT LOOP] Read current status.
76543210
Not
Ready
ProtectedHead
Loaded
Seek
Error
CRC
Error
Track 00IndexBusy
47FB
XOR B A8
XOR with previous status to detect changes.
47FC
AND 02H E6 02
Mask bit 1 (INDEX bit).
47FE
If NZ FLAG (index pulse detected), JUMP to success return.
4800
DEC DE 1B
DECrement timeout counter.
4801
LD A,D 7A
Load A with high byte of counter.
4802
OR E B3
OR with low byte to check if zero.
4803
If NZ FLAG (counter not zero), LOOP BACK to keep waiting.
4805
LD A,08H 3E 08
Load A with error code 08H (disk not spinning / timeout).
4807
JUMP to error return path.

4809H - Open File / Directory Search

This is the main file open routine. It searches the directory for a matching filename and sets up the FCB (File Control Block) for subsequent operations.

4809
GOSUB to SVC setup - save registers and set IX to FCB.
480C
GOSUB to validate FCB - check file status flags.
480F
XOR A AF
Clear A to zero.
4810
LD (48BBH),A 32 BB 48
Store zero at 48BBH - clear search state flag.
4813
GOSUB to select drive routine.
4816
If NZ FLAG (drive error), JUMP to error handler.
4818
GOSUB to get FCB position info.
481B
EX DE,HL EB
Exchange DE and HL registers.
481C
LD A,(IX+00H) DD 7E 00
Fetch FCB status byte from FCB+0.
481F
RRCA 0F
Rotate right to test bit 0.
4820
RRCA 0F
Rotate right again to test bit 1.
4821
If CARRY (file already open), JUMP to return file info.
4823
RRCA 0F
Rotate right to test bit 2.
4824
LD A,2DH 3E 2D
Load A with error code 2DH (file not found).
4826
If CARRY (search failed), JUMP to error handler.
4828
EX DE,HL EB
Exchange DE and HL back.
4829
GOSUB to divide by 5 (sectors per granule calculation).
482C
LD C,0EH 0E 0E
Load C with 0EH (14) - offset to extent info in FCB.
482E
EX DE,HL EB
Exchange DE and HL.
482F
PUSH IX DD E5
Save IX (FCB pointer) onto stack.
4831
POP HL E1
Pop into HL - now HL points to FCB.
4832
ADD HL,BC 09
Add offset - HL now points to FCB+0EH (extent area).
4833
PUSH AF F5
Save AF onto stack.
4834
PUSH HL E5
Save HL (extent pointer) onto stack.
4835
PUSH DE D5
Save DE onto stack.
4836
LD A,08H 3E 08
Load A with 08H - extent counter (8 extents max).
4838
EX AF,AF' 08
Save counter in alternate A register.
4839
LD A,(HL) 7E
Fetch extent granule number.
483A
INC A 3C
INCrement to test for FFH (end marker).
483B
INC HL 23
Move to next byte.
483C
If Z FLAG (was FFH - end of extents), JUMP to extend file.
483E
LD A,(HL) 7E
Fetch extent length byte.
483F
GOSUB to calculate extent size.
4842
If NO CARRY (position within this extent), JUMP to process.
4844
ADD HL,BC 09
Add extent size to pointer.
4845
EX DE,HL EB
Exchange DE and HL.
4846
XOR (HL) AE
XOR with extent data.
4847
RLCA 07
Rotate left.
4848
RLCA 07
Rotate left again.
4849
RLCA 07
Rotate left third time.
484A
ADD A,E 83
Add E to calculate sector.
484B
LD E,A 5F
Store result in E.
484C
POP AF F1
Restore AF from stack.
484D
POP AF F1
Restore AF again (discard saved value).
484E
POP AF F1
Restore AF third time.
484F
DEC HL 2B
DECrement HL pointer.
4850
GOSUB to calculate physical sector.
4853
LD L,(IX+03H) DD 6E 03
Fetch load address low byte from FCB+03.
4856
LD H,(IX+04H) DD 66 04
Fetch load address high byte from FCB+04.
4859
XOR A AF
Clear A (success return code).
485A
RET C9
RETURN to caller with file info.

485BH - Directory Entry Processing

This routine processes directory entries during file search operations.

485B
POP BC C1
Restore BC from stack.
485C
POP BC C1
Restore BC again.
485D
POP HL E1
Restore HL from stack.
485E
SBC HL,DE ED 52
Subtract DE from HL with borrow.
4860
ADD HL,BC 09
Add BC to HL.
4861
LD B,H 44
Copy H to B.
4862
LD C,L 4D
Copy L to C.
4863
PUSH AF F5
Save AF onto stack.
4864
GOSUB to read directory sector.
4867
If NZ FLAG (read error), JUMP to error handler.
4869
LD A,FFH 3E FF
Load A with FFH (end-of-directory marker).
486B
INC HL 23
INCrement HL pointer.
486C
CP (HL) BE
Compare with directory entry byte.
486D
DEC HL 2B
DECrement HL back.
486E
If Z FLAG (end of directory), JUMP to complete.
4870
LD A,2CH 3E 2C
Load A with error code 2CH (directory full).
4872
JUMP to error exit routine.

4875H - Process File Extent

Processes file extent information to locate the correct disk sector.

4875
EX DE,HL EB
Exchange DE and HL.
4876
INC HL 23
INCrement HL to next extent entry.
4877
BIT 3,(IX+01H) DD CB 01 5E
Test bit 3 of FCB flags (write mode?).
487B
SCF 37
Set Carry Flag.
487C
If Z FLAG (read mode), JUMP back to continue search.
487E
EX AF,AF' 08
Restore alternate A (extent counter).
487F
CP 05H FE 05
Compare with 5.
4881
If NZ FLAG, JUMP to continue.
4883
LD C,(HL) 4E
Fetch extent size low byte.
4884
INC HL 23
Move to next byte.
4885
LD B,(HL) 46
Fetch extent size high byte.
4886
INC HL 23
Move to next byte.
4887
POP DE D1
Restore DE from stack.
4888
PUSH DE D5
Save DE back onto stack.
4889
EX DE,HL EB
Exchange DE and HL.
488A
SBC HL,BC ED 42
Subtract BC from HL.
488C
EX DE,HL EB
Exchange back.
488D
If CARRY, JUMP to extend file.
488F
DEC A 3D
DECrement extent counter.
4890
If NZ FLAG (more extents), LOOP BACK.
4892
LD BC,0000H 01 00 00
Load BC with 0000H.
4895
POP DE D1
Restore DE from stack.
4896
GOSUB to directory lookup.
4899
If NZ FLAG (error), JUMP back to error check.
489B
LD A,(IX+07H) DD 7E 07
Fetch FCB byte 7 (flags).
489E
PUSH AF F5
Save AF onto stack.
489F
POP AF F1
Restore AF from stack.
48A0
LD (486AH),A 32 6A 48
Store at 486AH (self-modifying code).
48A3
BIT 4,(HL) CB 66
Test bit 4 of directory entry (system file?).
48A5
If Z FLAG, JUMP to error (directory full).
48A7
PUSH DE D5
Save DE onto stack.
48A8
PUSH BC C5
Save BC onto stack.
48A9
LD A,L 7D
Load A with L.
48AA
ADD 16H C6 16
Add 16H offset.
48AC
LD L,A 6F
Store back in L.
48AD
PUSH HL E5
Save HL onto stack.
48AE
LD A,(HL) 7E
Fetch byte from directory.
48AF
CP FEH FE FE
Compare with FEH.
48B1
INC HL 23
INCrement pointer.
48B2
LD A,(HL) 7E
Fetch next byte.
48B3
INC HL 23
INCrement pointer.
48B4
If CARRY, JUMP ahead.
48B6
If Z FLAG, JUMP back to directory processing.
48B8
LD A,3EH 3E 3E
Load A with 3EH.
48BA
JUMP to next instruction (fall through).
48BC
POP AF F1
Restore AF from stack.
48BD
LD A,64H 3E 64
Load A with 64H.
48BF
GOSUB to RST 28H handler.
48C2
POP BC C1
Restore BC from stack.
48C3
POP DE D1
Restore DE from stack.
48C4
JUMP back to continue processing.
48C6
BIT 4,L CB 65
Test bit 4 of L.
48C8
If Z FLAG, JUMP to error.
48CA
GOSUB to extent calculation.
48CD
EX DE,HL EB
Exchange DE and HL.
48CE
If NO CARRY, JUMP back to continue.
48D0
POP BC C1
Restore BC from stack.
48D1
POP DE D1
Restore DE from stack.
48D2
POP AF F1
Restore AF from stack.
48D3
POP HL E1
Restore HL from stack.
48D4
POP AF F1
Restore AF from stack.
48D5
PUSH BC C5
Save BC onto stack.
48D6
LD BC,0008H 01 08 00
Load BC with 0008H.
48D9
LD A,D 7A
Load A with D.
48DA
OR E B3
OR with E to test if DE is zero.
48DB
If Z FLAG (DE=0), skip storing.
48DD
ADD HL,BC 09
Add BC to HL.
48DE
LD (HL),E 73
Store E at (HL).
48DF
INC HL 23
INCrement pointer.
48E0
LD (HL),D 72
Store D at (HL).
48E1
INC HL 23
INCrement pointer.
48E2
EX DE,HL EB
Exchange DE and HL.
48E3
POP HL E1
Restore HL from stack.
48E4
LDIR ED B0
Block transfer BC bytes from (HL) to (DE).
48E6
JUMP back to continue file operation.

48E9H - Calculate Extent Size

Calculates the size of a file extent from the extent descriptor byte.

48E9
AND 1FHAND 00011111 E6 1F
Mask to get extent length (bits 0-4).
48EB
LD C,A 4F
Copy to C.
48EC
LD B,00H 06 00
Clear B.
48EE
INC BC 03
INCrement BC (extent length + 1).
48EF
EX DE,HL EB
Exchange DE and HL.
48F0
SBC HL,BC ED 42
Subtract extent size from position.
48F2
RET C9
RETURN - carry set if position beyond this extent.

48F3H - Update Directory Sector

Updates a directory sector after file modifications.

48F3
LD A,(4202H) 3A 02 42
Fetch byte from 4202H (disk buffer).
48F6
LD HL,(4399H) 2A 99 43
Fetch pointer from 4399H.
48F9
LD (HL),A 77
Store byte at pointer location.
48FA
LD A,(4930H) 3A 30 49
Fetch current sector number.
48FD
GOSUB to calculate sector parameters.
4900
GOSUB to read sector.
4903
If NZ FLAG (read error), skip OR.
4905
OR 31H F6 31
OR with 31H to set flags.
4907
CP 06H FE 06
Compare with error code 06H.
4909
RET C9
RETURN to caller.

490AH - Read Directory with Retry

Reads a directory sector with error retry capability.

490A
PUSH DE D5
Save DE onto stack.
490B
PUSH BC C5
Save BC onto stack.
490C
GOSUB to calculate sector and read.
490F
If Z FLAG (success), JUMP to cleanup.
4911
LD DE,0000H 11 00 00
Load DE with 0000H.
4914
GOSUB to read sector (retry).
4917
If Z FLAG (success), GOSUB to update directory.
491A
LD A,11H 3E 11
Load A with error code 11H.
491C
POP BC C1
Restore BC from stack.
491D
POP DE D1
Restore DE from stack.
491E
RET C9
RETURN to caller.

491FH - Write Directory Sector

Writes a modified directory sector back to disk.

491F
LD A,(4930H) 3A 30 49
Fetch current sector number.
4922
PUSH DE D5
Save DE onto stack.
4923
PUSH BC C5
Save BC onto stack.
4924
GOSUB to calculate sector parameters.
4927
OR H B4
OR A with H.
4928
GOSUB to write sector routine.
492B
LD A,12H 3E 12
Load A with error code 12H.
492D
JUMP to cleanup and return.

492FH - Read Directory Entry

Reads a specific directory entry from disk.

492F
LD L,FFH 2E FF
Load L with FFH.
4931
JUMP to common entry point.
4933
LD A,(IX+07H) DD 7E 07
Fetch FCB byte 7.
4936
LD L,FFH 2E FF
Load L with FFH.
4938
PUSH AF F5
Save AF onto stack.
4939
AND 1FHAND 00011111 E6 1F
Mask to bits 0-4.
493B
INC A 3C
INCrement A.
493C
INC A 3C
INCrement A again (sector = entry + 2).
493D
CP L BD
Compare with L.
493E
If NZ FLAG, GOSUB to read directory.
4941
POP HL E1
Restore HL from stack.
4942
RET NZ C0
If NZ FLAG (error), RETURN.
4943
LD A,E0H 3E E0
Load A with E0H mask.
4945
AND H A4
AND with H to get high bits.
4946
LD L,A 6F
Store in L.
4947
LD H,42H 26 42
Set H to 42H (buffer page).
4949
CP A BF
Set Z FLAG (success).
494A
RET C9
RETURN to caller.

494BH - Directory Lookup

Looks up a file in the directory by name.

494B
GOSUB to select drive.
494E
If Z FLAG, GOSUB to read directory entry.
4951
RET NZ C0
If NZ FLAG (error), RETURN.
4952
PUSH HL E5
Save HL onto stack.
4953
ADD 16H C6 16
Add 16H offset to A.
4955
LD L,A 6F
Store in L.
4956
LD A,(IX+0EH) DD 7E 0E
Fetch FCB+0EH (extent info).
4959
CP (HL) BE
Compare with directory entry.
495A
POP HL E1
Restore HL from stack.
495B
If Z FLAG (match), JUMP ahead.
495D
INC A 3C
INCrement A.
495E
If NZ FLAG, JUMP to set error.
4960
LD A,(HL) 7E
Fetch directory entry byte.
4961
AND 90H E6 90
Mask bits 4 and 7.
4963
CP 10H FE 10
Compare with 10H.
4965
LD A,2DH 3E 2D
Load A with error code 2DH (file not found).
4967
RET C9
RETURN to caller.

4968H - Get FCB Position Info

Retrieves the current file position information from the FCB.

4968
LD C,(IX+05H) DD 4E 05
Fetch FCB+05H (sector within record) to C.
496B
LD L,(IX+0AH) DD 6E 0A
Fetch FCB+0AH (record number low) to L.
496E
LD H,(IX+0BH) DD 66 0B
Fetch FCB+0BH (record number high) to H.
4971
LD A,H 7C
Load A with record high byte.
4972
CP (IX+0DH) DD BE 0D
Compare with FCB+0DH (EOF high).
4975
RET NZ C0
If NZ FLAG (not at EOF), RETURN.
4976
LD A,L 7D
Load A with record low byte.
4977
CP (IX+0CH) DD BE 0C
Compare with FCB+0CH (EOF low).
497A
RET NZ C0
If NZ FLAG (not at EOF), RETURN.
497B
LD A,C 79
Load A with sector offset.
497C
CP (IX+08H) DD BE 08
Compare with FCB+08H (EOF sector offset).
497F
RET C9
RETURN - Z flag set if at exact EOF.

4980H - SVC Setup / File Operation Prologue

This routine sets up the environment for file operations. It saves all registers, sets up IX to point to the FCB (File Control Block), and initializes IY to the DOS system area.

4980
LD A,(DE) 1A
Fetch first byte of FCB (File Control Block) from address in DE.
4981
RLCA 07
Rotate left to test bit 7 (file flags).
4982
LD A,26H 3E 26
Load A with 26H (SVC function for error display).
4984
If NO CARRY (bit 7 was 0), keep the 26H.
4986
XOR A AF
Otherwise, clear A to 0.
4987
EX AF,AF' 08
Save A in alternate register set.
4988
EX (SP),HL E3
Exchange return address with HL (save HL, get return address).
4989
LD (49A6H),HL 22 A6 49
Store return address at 49A6H (for CALL self-modification).
498C
POP HL E1
Restore original HL from stack.
498D
PUSH IY FD E5
Save IY onto the stack.
498F
PUSH HL E5
Save HL onto the stack.
4990
PUSH DE D5
Save DE (FCB pointer) onto the stack.
4991
PUSH BC C5
Save BC onto the stack.
4992
PUSH AF F5
Save AF onto the stack.
4993
PUSH DE D5
Push DE again for IX exchange.
4994
EX (SP),IX DD E3
Exchange IX with stack - now IX points to FCB.
4996
PUSH HL E5
Save current HL.
4997
LD HL,(49CEH) 2A CE 49
Fetch saved stack pointer from 49CEH.
499A
EX (SP),HL E3
Exchange with stack - save old SP value, put HL back.
499B
LD (49CEH),SP ED 73 CE 49
Store current SP at 49CEH (for error recovery).
499F
LD IY,4380H FD 21 80 43
Load IY with 4380H - base of DOS system variables.
49A3
EX AF,AF' 08
Restore alternate A register.
49A4
OR A B7
Test if A is zero.
49A5
CALL Z,0000H CC 00 00
If Z FLAG, CALL address at 0000H (this is modified at runtime via 49A6H).
49A8
POP HL E1
Restore HL from stack.
49A9
LD (49CEH),HL 22 CE 49
Restore saved SP value.
49AC
EX AF,AF' 08
Swap to alternate A.
49AD
POP IX DD E1
Restore IX from stack.
49AF
POP AF F1
Restore AF from stack.
49B0
POP BC C1
Restore BC from stack.
49B1
POP DE D1
Restore DE from stack.
49B2
POP HL E1
Restore HL from stack.
49B3
POP IY FD E1
Restore IY from stack.
49B5
EX AF,AF' 08
Swap back to main A (contains return code).
49B6
RET C9
RETURN to original caller.

49B7H - Validate FCB Status

Validates that the FCB is in a proper state for the requested operation.

49B7
LD B,05H 06 05
Load B with 05H (minimum access level).
49B9
LD A,(IX+01H) DD 7E 01
Fetch FCB flags from FCB+01.
49BC
AND 07HAND 00000111 E6 07
Mask to bits 0-2 (access mode).
49BE
CP B B8
Compare with required level.
49BF
RET C D8
If CARRY (access OK), RETURN.
49C0
LD A,25H 3E 25
Load A with error code 25H (access denied).
49C2
JUMP to error exit.
49C4
GOSUB to get FCB position.
49C7
RET C D8
If CARRY, RETURN.
49C8
LD A,1CH 3E 1C
Load A with error code 1CH.
49CA
If Z FLAG, JUMP to error exit.
49CC
INC A 3C
INCrement to error code 1DH.
49CD
LD SP,0000H 31 00 00
Load SP from 49CEH (self-modifying - address stored here).
49D0
OR A B7
Set flags based on A (error code).
49D1
JUMP to register restore and return.
49D3
If NZ FLAG, JUMP to error handler.
49D6
XOR A AF
Clear A.
49D7
If NZ FLAG, JUMP to error exit.
49D9
EX (SP),HL E3
Exchange stack with HL.
49DA
LD A,H 7C
Load A with H.
49DB
LD C,L 4D
Load C with L.
49DC
POP HL E1
Restore HL from stack.
49DD
RST 28H EF
Execute Supervisor Call with function code in A.

49DEH - File I/O Handler

Handles file read/write operations, transferring data between memory and disk.

49DE
BIT 7,(IX+01H) DD CB 01 7E
Test bit 7 of FCB flags (file open?).
49E2
RET Z C8
If Z FLAG (not open), RETURN.
49E3
POP DE D1
Pop return address into DE.
49E4
LD B,(IX+09H) DD 46 09
Fetch record size from FCB+09.
49E7
PUSH AF F5
Save AF onto stack.
49E8
PUSH HL E5
Save HL (buffer address) onto stack.
49E9
PUSH BC C5
Save BC onto stack.
49EA
LD C,(HL) 4E
Fetch byte from buffer.
49EB
GOSUB to byte transfer routine.
49EE
If NZ FLAG (error), JUMP to error exit.
49F0
LD E,A 5F
Store result byte in E.
49F1
POP BC C1
Restore BC from stack.
49F2
POP HL E1
Restore HL from stack.
49F3
POP AF F1
Restore AF from stack.
49F4
If NO CARRY (read mode), skip store.
49F6
LD (HL),E 73
Store read byte at buffer.
49F7
INC HL 23
INCrement buffer pointer.
49F8
DJNZ 49E7H 10 ED
DECrement B and LOOP if not zero.
49FA
XOR A AF
Clear A (success).
49FB
RET C9
RETURN to caller.

4A19H - Read File Sector

Reads a sector from the current file position into the buffer.

4A19
LD B,06H 06 06
Load B with 06H (access level check value).
4A1B
GOSUB to validate access level.
4A1E
GOSUB to check FCB position.
4A21
LD A,B6H 3E B6
Load A with B6H (read command variant).
4A23
GOSUB to store command byte.
4A26
GOSUB to disk read sector.
4A29
RES 5,(IX+01H) DD CB 01 AE
RESset bit 5 of FCB flags.
4A2D
RES 4,(IX+01H) DD CB 01 A6
RESset bit 4 of FCB flags (clear buffer dirty).
4A31
RET C9
RETURN to caller.

4A32H - Sequential Write Entry Points

Entry points for sequential file write operations with different modes.

4A32
LD A,F6H 3E F6
Load A with F6H (write mode 1 - with verify).
4A34
JUMP to common write setup.
4A36
LD A,E6H 3E E6
Load A with E6H (write mode 2 - no verify).
4A38
LD (4A8BH),A 32 8B 4A
Store write mode at 4A8BH (self-modifying).
4A3B
GOSUB to SVC setup.
4A3E
GOSUB to file I/O handler.
4A41
GOSUB to write preparation.
4A44
RET NZ C0
If NZ FLAG (error), RETURN.
4A45
LD A,(IX+05H) DD 7E 05
Fetch FCB sector position.
4A48
OR A B7
Test if zero.
4A49
If Z FLAG, GOSUB to increment position.
4A4C
GOSUB to get FCB position.
4A4F
If NO CARRY, JUMP to store position.
4A51
BIT 6,(IX+01H) DD CB 01 76
Test bit 6 of FCB flags.
4A55
If NZ FLAG, JUMP to success.
4A57
LD (IX+08H),C DD 71 08
Store C at FCB+08H (sector offset in record).
4A5A
LD (IX+0CH),L DD 75 0C
Store L at FCB+0CH (EOF low).
4A5C
INC C 0C
INCrement C.
4A5D
LD (IX+0DH),H DD 74 0D
Store H at FCB+0DH (EOF high).
4A5F
DEC C 0D
DECrement C back.
4A60
XOR A AF
Clear A (success).
4A61
RET C9
RETURN to caller.

4A62H - Check Write Buffer Status

Checks if the write buffer needs to be flushed to disk.

4A62
BIT 4,(IX+01H) DD CB 01 66
Test bit 4 of FCB flags (buffer dirty?).
4A66
RET Z C8
If Z FLAG (buffer clean), RETURN.
4A67
GOSUB to directory validation.
4A6A
BIT 5,(IX+02H) DD CB 02 6E
Test bit 5 of FCB+02.
4A6E
If NZ FLAG, JUMP to write sector.
4A70
BIT 1,(IX+00H) DD CB 00 4E
Test bit 1 of FCB+00.
4A74
If NZ FLAG, JUMP to write sector.
4A76
PUSH HL E5
Save HL onto stack.
4A77
GOSUB to directory lookup.
4A7A
If NZ FLAG (not found), skip SET.
4A7C
INC HL 23
INCrement HL to flags byte.
4A7D
SET 5,(HL) CB EE
SET bit 5 (file modified flag).
4A7F
If Z FLAG, GOSUB to write directory.
4A82
POP HL E1
Restore HL from stack.
4A83
RET NZ C0
If NZ FLAG (error), RETURN.
4A84
SET 5,(IX+02H) DD CB 02 EE
SET bit 5 of FCB+02.
4A88
LD A,(IX+01H) DD 7E 01
Fetch FCB flags byte.
4A8B
AND 90H E6 90
Mask bits 4 and 7 (byte modified at runtime).
4A8D
BIT 0,(IX+00H) DD CB 00 46
Test bit 0 of FCB status.
4A91
GOSUB to write sector.
4A94
RET NZ C0
If NZ FLAG (error), RETURN.
4A95
XOR A AF
Clear A.
4A96
JUMP to clear buffer dirty flags.

4A98H - Write Sector with Pre-read

Writes a sector, pre-reading if necessary for partial sector updates.

4A98
If Z FLAG, skip pre-read.
4A9A
PUSH BC C5
Save BC onto stack.
4A9B
GOSUB to directory validation.
4A9E
GOSUB to get FCB position.
4AA1
If NZ FLAG, skip OR.
4AA3
OR A B7
Set flags based on A.
4AA4
If NZ FLAG, GOSUB to read sector first.
4AA7
POP BC C1
Restore BC from stack.
4AA8
RET NZ C0
If NZ FLAG (error), RETURN.
4AA9
GOSUB to reset FCB flags.
4AAC
GOSUB to calculate buffer offset.
4AAF
LD (HL),C 71
Store byte C at buffer position.
4AB0
SET 4,(IX+01H) DD CB 01 E6
SET bit 4 of FCB flags (buffer dirty).
4AB4
If Z FLAG, JUMP back to write check.
4AB6
JUMP back to position update.

4AB8H - Write Sector to Disk

Performs the actual disk write operation with retry capability.

4AB8
LD C,A 4F
Copy A to C (flags).
4AB9
LD B,03H 06 03
Load B with 03H (retry count).
4ABB
If NZ FLAG (write mode), JUMP to write path.
4ABD
GOSUB to read track (for verify).
4AC0
RET NZ C0
If NZ FLAG (error), RETURN.
4AC1
LD A,C 79
Restore flags from C.
4AC2
OR A B7
Test if zero.
4AC3
If NZ FLAG, GOSUB to read with retry.
4AC6
RET Z C8
If Z FLAG (success), RETURN.
4AC7
DJNZ 4ABDH 10 F4
DECrement retry and LOOP if not zero.
4AC9
RET C9
RETURN (all retries exhausted).
4ACA
GOSUB to write sector.
4ACD
RET NZ C0
If NZ FLAG (error), RETURN.
4ACE
LD A,C 79
Restore flags from C.
4ACF
OR A B7
Test if verify needed.
4AD0
RET Z C8
If Z FLAG (no verify), RETURN.
4AD1
GOSUB to read with retry (verify).
4AD4
GOSUB to check read result.
4AD7
RET Z C8
If Z FLAG (verify passed), RETURN.
4AD8
DJNZ 4ACAH 10 F0
DECrement retry and LOOP if not zero.
4ADA
RET C9
RETURN (verify failed after retries).

4ADBH - Device Driver Chain Handler

Processes the device driver chain to handle I/O requests to installable devices.

4ADB
LD HL,0000H 21 00 00
Load HL with driver chain pointer (modified at runtime via 4ADCH).
4ADE
LD A,(DE) 1A
Fetch device code from FCB.
4ADF
CP C0H FE C0
Compare with C0H (end of chain marker).
4AE1
If Z FLAG (end of chain), JUMP to exit.
4AE3
GOSUB to SVC setup.
4AE6
SET 7,(IX+01H) DD CB 01 FE
SET bit 7 of FCB flags (file open).
4AEA
LD A,B 78
Load A with B (function code).
4AEB
CP 02H FE 02
Compare with 02H (write function).
4AED
BIT 5,(IX+01H) DD CB 01 6E
Test bit 5 of FCB flags.
4AF1
If NO CARRY (write), JUMP to write path.
4AF3
If NZ FLAG, GOSUB to read file sector.
4AF6
RET NZ C0
If NZ FLAG (error), RETURN.
4AF7
GOSUB to check FCB position.
4AFA
GOSUB to calculate buffer offset.
4AFD
If NZ FLAG, skip flush check.
4AFF
PUSH HL E5
Save buffer pointer.
4B00
GOSUB to check write buffer.
4B03
POP HL E1
Restore buffer pointer.
4B04
RET NZ C0
If NZ FLAG (error), RETURN.
4B05
GOSUB to increment position.
4B08
LD A,(HL) 7E
Fetch byte from buffer.
4B09
CP A BF
Set Z FLAG (CP A always sets Z).
4B0A
RET C9
RETURN with byte in A, Z flag set.

4B0BH - Calculate Buffer Offset

Calculates the offset into the disk buffer for the current file position.

4B0B
GOSUB to get file buffer address.
4B0E
LD E,(IX+05H) DD 5E 05
Fetch sector offset to E.
4B11
LD D,A 57
Copy A (high offset) to D.
4B12
ADD HL,DE 19
Add offset to buffer base.
4B13
INC (IX+05H) DD 34 05
INCrement sector offset in FCB.
4B16
RET C9
RETURN with HL pointing to buffer byte.

4B17H - Driver Chain Search Loop

Searches the device driver chain for a matching device code.

4B17
LD A,(HL) 7E
Fetch driver entry byte.
4B18
CP E BB
Compare with device code low.
4B19
INC HL 23
INCrement table pointer.
4B1A
If NZ FLAG (no match), skip next compare.
4B1C
LD A,(HL) 7E
Fetch second byte.
4B1D
CP D BA
Compare with device code high.
4B1E
INC HL 23
INCrement pointer.
4B1F
If NZ FLAG (no match), JUMP to next entry.
4B21
PUSH HL E5
Save table pointer.
4B22
PUSH DE D5
Save device code.
4B23
PUSH BC C5
Save BC.
4B24
LD A,(HL) 7E
Fetch driver flags byte.
4B25
AND B A0
AND with B (function mask).
4B26
INC HL 23
Skip to driver address.
4B27
INC HL 23
Continue skipping.
4B28
INC HL 23
Continue skipping.
4B29
LD E,(HL) 5E
Fetch driver address low.
4B2A
INC HL 23
INCrement pointer.
4B2B
LD D,(HL) 56
Fetch driver address high.
4B2C
PUSH DE D5
Push driver address.
4B2D
POP IX DD E1
Pop into IX (driver entry point).
4B2F
CALL 03D4H CD D4 03
GOSUB to ROM driver call at 03D4H.
4B32
POP BC C1
Restore BC.
4B33
POP DE D1
Restore device code.
4B34
POP HL E1
Restore table pointer.
4B35
BIT 0,B CB 40
Test bit 0 of B (exclusive flag?).
4B37
If Z FLAG, continue chain search.
4B39
OR A B7
Test driver return code.
4B3A
RET NZ C0
If NZ FLAG (handled), RETURN.
4B3B
INC HL 23
Move to link pointer.
4B3C
LD A,(HL) 7E
Fetch next link low.
4B3D
INC HL 23
INCrement pointer.
4B3E
LD H,(HL) 66
Fetch next link high.
4B3F
LD L,A 6F
Complete link address in HL.
4B40
LD A,H 7C
Load A with H.
4B41
OR L B5
OR with L to test for null.
4B42
If NZ FLAG (more entries), LOOP BACK.
4B44
JUMP to chain end handler.

4B47H - File Positioning Routines

Various entry points for file positioning operations (seek, rewind, tell, etc.).

4B47
GOSUB to SVC setup.
4B4A
JUMP to set position flag.
4B4C
GOSUB to SVC setup (rewind entry).
4B4F
LD H,A 67
Copy A to H.
4B50
LD L,A 6F
Copy A to L (HL = 0 for rewind).
4B51
LD C,A 4F
Copy A to C.
4B52
JUMP to position update.
4B54
GOSUB to SVC setup (seek to EOF entry).
4B57
LD C,(IX+08H) DD 4E 08
Fetch EOF sector offset.
4B5A
LD L,(IX+0CH) DD 6E 0C
Fetch EOF record low.
4B5D
LD H,(IX+0DH) DD 66 0D
Fetch EOF record high.
4B60
JUMP to position comparison.
4B62
GOSUB to SVC setup (backspace entry).
4B65
GOSUB to get current position.
4B68
XOR A AF
Clear A.
4B69
SUB (IX+09H) DD 96 09
Subtract record size (gives negative).
4B6C
ADD A,C 81
Add current sector offset.
4B6D
LD C,A 4F
Store result in C.
4B6E
If CARRY (underflow), Store sector offset, Clear A (success), and RETurn (Unpatched Code)
4B70
DEC HL 2B
DECrement record number.
4B71
JUMP to set flag (Unpatched Code)
4B73
GOSUB to SVC setup (seek by record entry).
4B76
LD H,B 60
Copy B to H (record high).
4B77
LD L,C 69
Copy C to L (record low).
4B78
LD A,(IX+09H) DD 7E 09
Fetch record size.
4B7B
OR A B7
Test if zero.
4B7C
LD C,A 4F
Copy to C.
4B7D
If NZ FLAG, GOSUB to multiply.
4B80
SET 6,(IX+01H) DD CB 01 F6
SET bit 6 of FCB flags (position changed).
4B84
LD A,H 7C
Load A with new record high.
4B85
CP (IX+0BH) DD BE 0B
Compare with current high.
4B88
If NZ FLAG (different), JUMP to update.
4B8A
LD A,L 7D
Load A with new record low.
4B8B
CP (IX+0AH) DD BE 0A
Compare with current low.
4B8E
If Z FLAG (same position), skip update.
4B90
PUSH HL E5
Save new position.
4B91
PUSH BC C5
Save sector offset.
4B92
GOSUB to flush write buffer if dirty.
4B95
POP BC C1
Restore sector offset.
4B96
POP HL E1
Restore new position.
4B97
RET NZ C0
If NZ FLAG (flush error), RETURN.
4B98
GOSUB to set FCB flags.
4B9B
LD (IX+0AH),L DD 75 0A
Store new record low.
4B9E
LD (IX+0BH),H DD 74 0B
Store new record high.
4BA1
LD (IX+05H),C DD 71 05
Store sector offset.
4BA4
XOR A AF
Clear A (success).
4BA5
RET C9
RETURN to caller.

4BA6H - Print String Routines

Prints null-terminated or carriage-return terminated strings to the console device.

4BA6
PUSH DE D5
Save DE onto stack.
4BA7
LD DE,401DH 11 1D 40
Load DE with 401DH (video output DCB).
4BAA
PUSH HL E5
Save string pointer.
4BAB
LD A,(HL) 7E
Fetch character from string.
4BAC
CP 03H FE 03
Compare with ETX (03H end marker).
4BAE
If Z FLAG (end of string), JUMP to cleanup.
4BB0
CALL 001BH CD 1B 00
GOSUB to ROM character output at 001BH.
4BB3
LD A,(HL) 7E
Re-fetch character.
4BB4
CP 0DH FE 0D
Compare with CR (carriage return).
4BB6
INC HL 23
INCrement string pointer.
4BB7
If NZ FLAG (not CR), LOOP for next character.
4BB9
POP HL E1
Restore string pointer.
4BBA
POP DE D1
Restore DE.
4BBB
RET C9
RETURN to caller.
4BBC
PUSH DE D5
Save DE (alternate print entry).
4BBD
LD DE,4025H 11 25 40
Load DE with 4025H (printer DCB).
4BC0
JUMP to common print loop.

4BC2H - Keyboard/Display Driver Handler

Main character output handler for the display. This is called via the JP at 400CH. Handles display output with integrated keyboard and printer support.

4BC2
INC SP 33
Adjust stack (discard return low).
4BC3
INC SP 33
Adjust stack (discard return high).
4BC4
CP 20H FE 20
Compare character with space (20H).
4BC6
If CARRY (control char), JUMP to control handler.
4BC9
PUSH HL E5
Save HL.
4BCA
PUSH DE D5
Save DE.
4BCB
PUSH BC C5
Save BC.
4BCC
PUSH AF F5
Save character and flags.
4BCD
LD HL,4369H 21 69 43
Point HL to driver status flags.
4BD0
SET 6,(HL) CB F6
SET bit 6 (output in progress).
4BD2
LD HL,45BEH 21 BE 45
Point HL to 45BEH.
4BD5
LD (HL),00H 36 00
Clear flag byte.
4BD7
EI FB
Enable Interrupts.
4BD8
AND 1FHAND 00011111 E6 1F
Mask to 5 bits (device select).
4BDA
LD HL,4317H 21 17 43
Point HL to current device number.
4BDD
CP (HL) BE
Compare with current device.
4BDE
If Z FLAG (same device), skip setup.
4BE0
LD (HL),A 77
Store new device number.
4BE1
AND 07HAND 00000111 E6 07
Mask to device bits 0-2.
4BE3
LD C,A 4F
Copy to C.
4BE4
XOR A AF
Clear A.
4BE5
LD (43D8H),A 32 D8 43
Clear device state at 43D8H.
4BE8
GOSUB to drive/device select.
4BEB
LD A,(HL) 7E
Fetch device status.
4BEC
SUB C 91
Subtract device number.
4BED
RLCA 07
Rotate left.
4BEE
RLCA 07
Rotate left again.
4BEF
ADD A,C 81
Add device number back.
4BF0
GOSUB to read device entry.
4BF3
If NZ FLAG (error), JUMP to error.
4BF5
BIT 6,(HL) CB 76
Test bit 6 of entry.
4BF7
If Z FLAG (invalid), JUMP to error.
4BF9
ADD 16H C6 16
Add 16H offset to get driver address.
4BFB
LD L,A 6F
Store in L.
4BFC
LD E,(HL) 5E
Fetch driver address low.
4BFD
INC HL 23
INCrement pointer.
4BFE
LD D,(HL) 56
Fetch driver address high.
4BFF
LD (43DCH),DE ED 53 DC 43
Store driver address at 43DCH.
4C03
LD HL,43CEH 21 CE 43
Point HL to 43CEH.
4C06
GOSUB to load driver module.
4C09
LD (4C1EH),HL 22 1E 4C
Store entry point at 4C1EH (self-mod).
4C0C
If Z FLAG (loaded OK), continue.
4C0E
LD A,(4317H) 3A 17 43
Fetch device number.
4C11
CP 06H FE 06
Compare with 6 (console device).
4C13
LD A,2EH 3E 2E
Load error code 2EH (device not ready).
4C15
If NZ FLAG, JUMP to error handler.
4C18
HALT 76
HALT - critical error, stop CPU.
4C19
POP AF F1
Restore character.
4C1A
POP BC C1
Restore BC.
4C1B
POP DE D1
Restore DE.
4C1C
POP HL E1
Restore HL.
4C1D
CALL nnnnH CD 00 00
CALL to driver (address at 4C1EH, self-modified).
4C20
PUSH HL E5
Save HL.
4C21
LD HL,4369H 21 69 43
Point HL to driver status.
4C24
RES 6,(HL) CB B6
RESset bit 6 (output complete).
4C26
POP HL E1
Restore HL.
4C27
RET C9
RETURN to caller.

4C28H - Load Driver Module

Loads a device driver module from disk into memory.

4C28
LD (4C6AH),HL 22 6A 4C
Store buffer address at 4C6AH.
4C2B
LD DE,42FFH 11 FF 42
Load DE with 42FFH (disk buffer end).
4C2E
GOSUB to get next module byte.
4C31
LD C,A 4F
Save module type in C.
4C32
LD A,1FH 3E 1F
Load A with 1FH (max type).
4C34
CP C B9
Compare with module type.
4C35
LD A,22H 3E 22
Load error code 22H.
4C37
RET C D8
If CARRY (invalid type), RETURN error.
4C38
GOSUB to get length byte.
4C3B
LD B,A 47
Save length in B.
4C3C
GOSUB to get address low.
4C3F
LD L,A 6F
Store in L.
4C40
LD H,C 61
Use type as high byte (temporary).
4C41
DEC C 0D
DECrement type.
4C42
If Z FLAG (type 1), JUMP to entry point.
4C44
DEC C 0D
DECrement type again.
4C45
If NZ FLAG (type > 2), skip to data load.
4C47
GOSUB to get address high.
4C4A
LD H,A 67
Store in H.
4C4B
XOR A AF
Clear A (success).
4C4C
RET C9
RETURN with entry point in HL.
4C4D
GOSUB to get address high.
4C50
LD H,A 67
Store in H.
4C51
DEC B 05
DECrement length.
4C52
DEC B 05
DECrement length again.
4C53
GOSUB to get data byte.
4C56
LD (HL),A 77
Store at destination.
4C57
CP (HL) BE
Verify write (compare read-back).
4C58
INC HL 23
INCrement destination pointer.
4C59
If Z FLAG (verify OK), continue.
4C5B
LD A,24H 3E 24
Load error code 24H (memory error).
4C5D
INC C 0C
INCrement C (test).
4C5E
DEC C 0D
DECrement C back.
4C5F
If Z FLAG, JUMP to return.
4C61
DJNZ 4C53H 10 F0
DECrement B and LOOP for more bytes.
4C63
JUMP back for next module record.

4C65H - Get Next Byte from Buffer

Retrieves the next byte from the disk buffer, reading a new sector if necessary.

4C65
INC E 1C
INCrement buffer index.
4C66
LD A,(DE) 1A
Fetch byte from buffer.
4C67
RET NZ C0
If NZ FLAG (index not wrapped), RETURN.
4C68
PUSH DE D5
Save buffer pointer.
4C69
LD DE,0000H 11 00 00
Load DE with 0 (sector number at 4C6AH, self-mod).
4C6C
GOSUB to read sector.
4C6F
POP DE D1
Restore buffer pointer.
4C70
If NZ FLAG (read error), JUMP to cleanup.
4C72
LD A,(DE) 1A
Fetch first byte of new sector.
4C73
RET C9
RETURN with byte in A.

4C74H - Calculate Sector Parameters

Calculates the physical sector number and buffer address from logical parameters.

4C74
LD (4930H),A 32 30 49
Store sector number at 4930H.
4C77
LD E,00H 1E 00
Clear E.
4C79
LD HL,(4399H) 2A 99 43
Fetch pointer from 4399H.
4C7C
LD C,A 4F
Copy sector to C.
4C7D
LD L,(HL) 6E
Fetch low byte from pointer.
4C7E
LD A,(430FH) 3A 0F 43
Fetch value from 430FH.
4C81
GOSUB to multiply routine.
4C84
LD B,A 47
Save result high in B.
4C85
LD D,A 57
Copy to D.
4C86
ADD HL,DE 19
Add DE to HL.
4C87
LD A,05H 3E 05
Load A with 5 (sectors per granule).
4C89
GOSUB to multiply again.
4C8C
ADD HL,BC 09
Add BC to HL.
4C8D
EX DE,HL EB
Exchange DE and HL.
4C8E
LD HL,4200H 21 00 42
Load HL with 4200H (buffer address).
4C91
RET C9
RETURN with buffer in HL, sector in DE.
4C92
LD H,00H 26 00
Clear H.
4C94
PUSH BC C5
Save BC.
4C95
GOSUB to multiply 8-bit by 16-bit.
4C98
LD A,H 7C
Move high result.
4C99
LD H,L 65
Shift result down.
4C9A
LD L,C 69
Complete result in HL.
4C9B
POP BC C1
Restore BC.
4C9C
RET C9
RETURN.

4C9DH - 8-bit by 16-bit Multiplication

This routine multiplies A by HL. Result is returned in HL (low 16 bits) and C (overflow). Used for address calculations.

4C9D
PUSH DE D5
Save DE onto the stack.
4C9E
EX DE,HL EB
Move multiplicand to DE.
4C9F
LD C,80H 0E 80
Load C with 80H - bit counter (8 bits, shifted out).
4CA1
LD HL,0000H 21 00 00
Clear HL (product accumulator).
4CA4
RRCA 0F
[MULTIPLY LOOP] Rotate A right, LSB into carry.
4CA5
If NO CARRY (bit was 0), skip addition.
4CA7
ADD HL,DE 19
ADD multiplicand to product (bit was 1).
4CA8
SRL H CB 3C
Shift H right (divide product by 2).
4CAA
RR L CB 1D
Rotate L right through carry.
4CAC
RR C CB 19
Rotate C right - shifts out bit counter, collects overflow.
4CAE
If NO CARRY (not done), LOOP BACK.
4CB0
POP DE D1
Restore DE from the stack.
4CB1
RET C9
RETURN with product in HL.

4CB4H - 16-Bit Division Routine

This routine divides HL by C. Quotient is returned in HL, remainder in A. Used for track/sector calculations.

4CB2
LD A,05H 3E 05
Load A with 5 (sectors per granule default, or entry point).
4CB4
LD C,A 4F
Copy divisor from A to C.
4CB5
LD B,10H 06 10
Load B with 16 - number of bits to process.
4CB7
XOR A AF
Clear A (will hold remainder during division).
4CB8
ADD HL,HL 29
[DIVISION LOOP] Shift HL left, moving MSB into carry.
4CB9
RLA 17
Rotate carry into A (building remainder).
4CBA
If CARRY set (overflow), definitely subtract divisor.
4CBC
CP C B9
Compare remainder with divisor.
4CBD
If CARRY (A < C), skip subtraction.
4CBF
SUB C 91
SUBtract divisor from remainder.
4CC0
INC L 2C
Set quotient bit (add 1 to result).
4CC1
[LOOP] DECrement B and continue until all 16 bits processed.
4CC3
OR A B7
Set flags based on remainder (Z if remainder is 0).
4CC4
RET C9
RETURN with quotient in HL, remainder in A.

4CC5H - String Comparison and Parsing

String comparison routine - compares string at (BC) with string at (HL). Used for command parsing and filename matching.

4CC5
PUSH HL E5
Save HL (string pointer) onto stack.
4CC6
LD A,(BC) 0A
[COMPARE LOOP] Fetch character from first string.
4CC7
OR A B7
Test if null terminator (00H).
4CC8
INC BC 03
Advance first string pointer.
4CC9
If NZ FLAG (not end), JUMP to compare character.
4CCB
EX (SP),HL E3
Exchange HL with top of stack (restore original HL).
4CCC
POP HL E1
Pop saved value into HL.
4CCD
RET C9
RETURN - strings matched (or first ended).
4CCE
CP (HL) BE
Compare character in A with character at (HL).
4CCF
INC HL 23
Advance second string pointer.
4CD0
If Z FLAG (characters match), LOOP for next character.
4CD2
POP HL E1
Restore HL from stack (mismatch case).
4CD3
JUMP to return with mismatch.

4CD5H - Command Line Parser

Parses command line input, handling delimiters (comma, space) and returning tokens.

4CD5
LD A,(HL) 7E
Fetch character from command line.
4CD6
CP 0DH FE 0D
Compare with CR (carriage return - end of line).
4CD8
RET Z C8
If Z FLAG (end of line), RETURN.
4CD9
LD A,(HL) 7E
Re-fetch character.
4CDA
CP 2CH FE 2C
Compare with ',' (comma delimiter).
4CDC
INC HL 23
Advance pointer.
4CDD
If Z FLAG (comma found), JUMP to return success.
4CDF
CP 20H FE 20
Compare with space.
4CE1
DEC HL 2B
Back up pointer.
4CE2
SCF 37
Set Carry Flag (indicate error/special case).
4CE3
If NZ FLAG (not space), JUMP to error return.
4CE5
INC HL 23
[SKIP SPACES] Advance past space.
4CE6
CP (HL) BE
Compare next character with space (still in A).
4CE7
If Z FLAG (another space), LOOP to skip it.
4CE9
OR A B7
Clear Carry Flag (success).
4CEA
LD A,34H 3E 34
Load A with 34H (parse status/error code).
4CEC
RET C9
RETURN to caller.

4CEDH - Wait Routine with Key Check

A delay routine that waits for approximately the value in B iterations, calling the ROM wait routine.

4CED
LD D,B 50
Copy delay count from B to D.
4CEE
LD E,01H 1E 01
Load E with 1 - inner loop count.
4CF0
LD B,D 42
DELAY LOOP - Reset B from D.
4CF1
CALL 0060H CD 60 00
GOSUB to ROM wait/keyboard scan routine at 0060H.
4CF4
DEC E 1D
DECrement inner loop counter.
4CF5
If NZ FLAG, LOOP BACK.
4CF7
RET C9
RETURN to caller.

4D00H - DOS Boot Entry Point (PROGRAM ENTRY)

This is the main entry point for the DOS. At boot, control transfers here. The routine determines available RAM by writing complement patterns, initializes system variables, loads configuration from the disk boot sector, and eventually displays the DOS Ready prompt.

4D00
AND L A5
Data byte A5H (appears at entry - may be signature check).
4D01
IM1 ED 56
Set Interrupt Mode 1 - interrupts call address 0038H.
4D03
LD HL,FFFFH 21 FF FF
Point HL to top of memory (FFFFH).

[RAM SIZE DETECTION LOOP] - Scan down from FFFFH to find actual RAM. Writes complement of byte, reads back, decrements if it doesn't match.

4D06
LD A,(HL) 7E
Read current byte at (HL).
4D07
CPL 2F
ComPLement A (invert all bits).
4D08
LD (HL),A 77
Write complemented value back.
4D09
CP (HL) BE
Read back and compare - if RAM, it will match.
4D0A
DEC HL 2B
Move down one address.
4D0B
If NZ FLAG (didn't match - not RAM), continue scanning down.
4D0D
CPL 2F
Restore original value (complement again).
4D0E
INC HL 23
Point back to last good RAM address.
4D0F
LD (HL),A 77
Write back original value.
4D10
LD (43A9H),HL 22 A9 43
Store high memory address at 43A9H.
4D13
LD (4049H),HL 22 49 40
Also store at 4049H (public high memory pointer).

Now check if this is a warm boot (system variables already initialized) by looking for signature byte A5H at 43ABH.

4D16
LD HL,43ABH 21 AB 43
Point HL to warm boot signature location.
4D19
LD A,A5H 3E A5
Load A with expected signature A5H.
4D1B
CP (HL) BE
Compare signature.
4D1C
If NZ FLAG (cold boot), JUMP to full initialization.
4D1E
INC HL 23
This is a warm boot - restore previous state.
4D1F
LD DE,4041H 11 41 40
Point DE to date/time storage.
4D22
LD BC,0006H 01 06 00
6 bytes to restore.
4D25
LDIR ED B0
Block copy - restore date/time from backup.
4D27
LD IY,4380H FD 21 80 43
Initialize IY to DOS system variable base 4380H.
4D2B
LD BC,(42FEH) ED 4B FE 42
Fetch boot sector parameters from 42FEH.
4D2F
LD (IY+F8H),B FD 70 F8
Store high byte at IY offset F8H (4378H).
4D32
LD (IY+F3H),C FD 71 F3
Store low byte at IY offset F3H (4373H).
4D35
LD A,(42FDH) 3A FD 42
Fetch another boot parameter.
4D38
LD (IY+F7H),A FD 77 F7
Store at IY offset F7H (4377H).
4D3B
LD DE,4480H 11 80 44
Point DE to sector buffer at 4480H.
4D3E
GOSUB to read sector - read the boot sector into buffer.
4D41
If NZ FLAG (read error), JUMP to error handler at 4DD3H.

Boot sector read successfully. Now verify the signature and copy configuration data.

4D44
LD A,(42EFH) 3A EF 42
Fetch DOS signature byte from boot sector.
4D47
CP A5H FE A5
Compare with expected signature A5H.
4D49
If NZ FLAG (wrong signature), JUMP to error - not a valid NEWDOS/80 disk.

4D4CH - Boot Configuration Copy

Copies boot sector configuration data to system variables. Validates drive count and initializes system parameters.

4D4C
LD HL,42F8H 21 F8 42
Point HL to boot sector data at 42F8H.
4D4F
LD DE,505BH 11 5B 50
Point DE to destination at 505BH.
4D52
LD BC,0008H 01 08 00
Load BC with 8 bytes to copy.
4D55
LDIR ED B0
Block copy boot parameters.
4D57
LD HL,(42F0H) 2A F0 42
Fetch word from 42F0H.
4D5A
LD (436CH),HL 22 6C 43
Store at 436CH - system option flags.
4D5D
LD HL,(42F2H) 2A F2 42
Fetch word from 42F2H.
4D60
LD (436EH),HL 22 6E 43
Store at 436EH - extended flags.
4D63
LD A,(42A0H) 3A A0 42
Fetch drive count from boot sector.
4D66
LD (439FH),A 32 9F 43
Store at 439FH - max drive number.
4D69
LD (477AH),A 32 7A 47
Store at 477AH - drive select reference.
4D6C
DEC A 3D
Decrement drive count.
4D6D
CP 04H FE 04
Compare with 4 (max drives).
4D6F
If NC (invalid drive count), JUMP to error.
4D71
LD A,(42A1H) 3A A1 42
Fetch step rate from boot sector.
4D74
LD (4ABAH),A 32 BA 4A
Store at 4ABAH - disk step rate.
4D77
LD A,(42A2H) 3A A2 42
Fetch parameter from boot sector.
4D7A
LD (43A0H),A 32 A0 43
Store at 43A0H.
4D7D
LD A,(42A3H) 3A A3 42
Fetch parameter from boot sector.
4D80
LD (43A1H),A 32 A1 43
Store at 43A1H.
4D83
LD A,(42A6H) 3A A6 42
Fetch parameter from boot sector.
4D86
LD (465AH),A 32 5A 46
Store at 465AH - disk I/O parameter.
4D89
LD A,(42A9H) 3A A9 42
Fetch delay value from boot sector.
4D8C
LD (43A2H),A 32 A2 43
Store at 43A2H.
4D8F
LD (4CEFH),A 32 EF 4C
Store at 4CEFH - delay loop parameter.
4D92
LD L,06H 2E 06
Load L with 6.
4D94
LD DE,2400H 11 00 24
Load DE with 2400H.
4D97
PUSH AF F5
Save AF onto stack.
4D98
GOSUB to multiply routine.
4D9B
OR H B4
OR H with A to check for overflow.
4D9C
If NZ FLAG (overflow), JUMP to error.
4D9E
LD A,L 7D
Copy L to A.
4D9F
LD (47E4H),A 32 E4 47
Store at 47E4H.
4DA2
POP AF F1
Restore AF from stack.
4DA3
EX DE,HL EB
Exchange DE and HL.
4DA4
GOSUB to multiply routine.
4DA7
OR A B7
Test A for zero.
4DA8
If NZ FLAG (error), JUMP to error handler.
4DAA
LD (47F4H),HL 22 F4 47
Store HL at 47F4H.
4DAD
LD A,(42A8H) 3A A8 42
Fetch disk parameter.
4DB0
LD (4370H),A 32 70 43
Store at 4370H.
4DB3
LD HL,(4049H) 2A 49 40
Fetch high memory pointer.
4DB6
LD DE,(42D0H) ED 5B D0 42
Fetch memory limit from boot sector.
4DBA
LD A,D 7A
Copy D to A.
4DBB
OR E B3
OR with E to test if zero.
4DBC
If Z FLAG (no limit), skip comparison.
4DBE
OR A B7
Clear carry for subtraction.
4DBF
SBC HL,DE ED 52
Subtract limit from high memory.
4DC1
If CARRY (limit is higher), skip exchange.
4DC3
EX DE,HL EB
Use the smaller value.
4DC4
LD (4049H),HL 22 49 40
Store final high memory value.
4DC7
XOR A AF
Clear A.
4DC8
LD DE,4371H 11 71 43
Point DE to drive parameter table.
4DCB
LD IX,4200H DD 21 00 42
Point IX to sector buffer.
4DCF
JUMP to drive initialization loop.

4DD3H - Boot Error Handler

When a boot error occurs (disk read failure or invalid signature), this handler displays an error message and attempts to continue with alternate drives.

4DD1
LD A,27H 3E 27
Load A with error code 27H (system disk error).
4DD3
PUSH AF F5
Save error code onto the stack.
4DD4
LD A,46H 3E 46
Load A with SVC function 46H (display system message).
4DD6
RST 28H EF
Execute Supervisor Call to display the error message.

4DD7H - Drive Initialization Loop

Initializes drive parameter blocks by copying boot sector data for each configured drive.

4DD7
LD BC,000AH 01 0A 00
Load BC with 10 bytes per drive entry.
4DDA
PUSH AF F5
Save drive counter.
4DDB
CP (IY+1FH) FD BE 1F
Compare with max drives at IY+1FH.
4DDE
If NC (past max), skip copy.
4DE0
PUSH IX DD E5
Save buffer pointer.
4DE2
POP HL E1
Pop into HL.
4DE3
LDIR ED B0
Block copy drive parameters.
4DE5
LD A,(IX+02H) DD 7E 02
Fetch drive flags.
4DE8
AND 1CH E6 1C
Mask relevant bits.
4DEA
If Z FLAG (no drives), JUMP to error.
4DEC
LD C,10H 0E 10
Load C with 16 (offset to next drive).
4DEE
ADD IX,BC DD 09
Advance IX to next drive entry.
4DF0
POP AF F1
Restore drive counter.
4DF1
INC A 3C
Increment drive number.
4DF2
CP 0AH FE 0A
Compare with 10 (max drives).
4DF4
If CARRY (more drives), LOOP back.
4DF6
LD A,(42FAH) 3A FA 42
Fetch system options from boot sector.
4DF9
BIT 7,A CB 7F
Test bit 7 (double-density flag?).
4DFB
If Z FLAG (single density), skip.
4DFD
LD A,ABH 3E AB
Load A with ABH (double-density code).
4DFF
LD (463DH),A 32 3D 46
Store at 463DH - density flag.
4E02
LD BC,(42F8H) ED 4B F8 42
Fetch boot config word.
4E06
LD DE,(436CH) ED 5B 6C 43
Fetch system option flags.
4E0A
BIT 6,E CB 73
Test bit 6 of flags.
4E0C
If Z FLAG, skip flag modification.
4E0E
SET 2,(IY+E9H) FD CB E9 D6
SET bit 2 at IY offset E9H.
4E12
RES 6,(IY+EDH) FD CB ED B6
RESset bit 6 at IY offset EDH.
4E16
BIT 0,C CB 41
Test bit 0 of C.
4E18
If Z FLAG, skip keyboard setup.
4E1A
LD A,20H 3E 20
Load A with 20H (space character).
4E1C
LD (4538H),A 32 38 45
Store at 4538H.
4E1F
LD A,(42A7H) 3A A7 42
Fetch keyboard parameter.
4E22
LD (4578H),A 32 78 45
Store at 4578H.
4E25
LD (452FH),A 32 2F 45
Store at 452FH.
4E28
LD A,(42A5H) 3A A5 42
Fetch system parameter.
4E2B
OR A B7
Test if zero.
4E2C
If Z FLAG, skip store.
4E2E
LD (4501H),A 32 01 45
Store at 4501H.
4E31
BIT 1,C CB 49
Test bit 1 of C.
4E33
If Z FLAG, skip vector setup.
4E35
LD A,(3840H) 3A 40 38
Fetch system status from 3840H.
4E38
BIT 3,A CB 5F
Test bit 3.
4E3A
If NZ FLAG, skip vector modification.
4E3C
LD HL,4516H 21 16 45
Load HL with 4516H - interrupt vector.
4E3F
LD (4016H),HL 22 16 40
Store at 4016H - set interrupt handler.
4E42
LD HL,4505H 21 05 45
Load HL with 4505H.
4E45
LD (401EH),HL 22 1E 40
Store at 401EH.
4E48
LD HL,3C00H 21 00 3C
Point HL to video RAM start.
4E4B
LD A,61H 3E 61
Load A with 'a' (lowercase test).
4E4D
LD (HL),A 77
Write to video RAM.
4E4E
CP (HL) BE
Read back and compare (test for lowercase support).
4E4F
LD (HL),20H 36 20
Clear with space character.
4E51
If NZ FLAG (no lowercase), skip Model III setup.
4E53
BIT 2,B CB 50
Test bit 2 of B.
4E55
If Z FLAG, skip.
4E57
LD A,4FH 3E 4F
Load A with 4FH.
4E59
LD (4593H),A 32 93 45
Store at 4593H.
4E5C
LD A,38H 3E 38
Load A with 38H.
4E5E
LD (4505H),A 32 05 45
Store at 4505H.
4E61
BIT 1,B CB 48
Test bit 1 of B.
4E63
If NZ FLAG, skip.
4E65
LD A,00H 3E 00
Load A with zero.
4E67
LD (45B4H),A 32 B4 45
Store at 45B4H.
4E6A
BIT 0,B CB 40
Test bit 0 of B.
4E6C
If Z FLAG, skip.
4E6E
LD A,C8H 3E C8
Load A with C8H.
4E70
LD (4502H),A 32 02 45
Store at 4502H.
4E73
BIT 7,C CB 79
Test bit 7 of C.
4E75
If NZ FLAG, skip.
4E77
LD A,3EH 3E 3E
Load A with 3EH.
4E79
LD (457DH),A 32 7D 45
Store at 457DH.
4E7C
BIT 6,C CB 71
Test bit 6 of C.
4E7E
If Z FLAG, skip.
4E80
LD A,C0H 3E C0
Load A with C0H.
4E82
LD (45EEH),A 32 EE 45
Store at 45EEH.
4E85
BIT 4,C CB 61
Test bit 4 of C.
4E87
If Z FLAG, skip.
4E89
LD A,20H 3E 20
Load A with 20H.
4E8B
LD (45CCH),A 32 CC 45
Store at 45CCH.
4E8E
BIT 2,C CB 51
Test bit 2 of C.
4E90
If Z FLAG, skip.
4E92
XOR A AF
Clear A.
4E93
LD (4590H),A 32 90 45
Store at 4590H.
4E96
BIT 5,C CB 69
Test bit 5 of C.
4E98
If Z FLAG, skip.
4E9A
LD A,20H 3E 20
Load A with 20H.
4E9C
LD (45D8H),A 32 D8 45
Store at 45D8H.
4E9F
BIT 5,E CB 6B
Test bit 5 of E (extended flags).
4EA1
If Z FLAG, skip.
4EA3
SET 4,(IY+E9H) FD CB E9 E6
SET bit 4 at IY offset E9H.
4EA7
LD HL,4FA8H 21 A8 4F
Point HL to banner string at 4FA8H.
4EAA
GOSUB to print string.
4EAD
LD A,(42F9H) 3A F9 42
Fetch more boot options.
4EB0
BIT 5,A CB 6F
Test bit 5 (device driver flag?).
4EB2
If Z FLAG, skip driver setup.
4EB4
DI F3
Disable Interrupts for critical setup.
4EB5
LD HL,43B2H 21 B2 43
Point HL to driver chain.
4EB8
LD (4ADCH),HL 22 DC 4A
Store driver chain pointer.
4EBB
LD DE,401DH 11 1D 40
Point DE to 401DH.
4EBE
LD (HL),E 73
Store low byte.
4EBF
INC HL 23
Advance pointer.
4EC0
LD (HL),D 72
Store high byte.
4EC1
INC HL 23
Advance pointer.
4EC2
LD A,(DE) 1A
Fetch original value.
4EC3
LD (HL),A 77
Store in chain.
4EC4
INC HL 23
Advance pointer.
4EC5
LD A,C0H 3E C0
Load A with C0H (end marker).
4EC7
LD (DE),A 12
Store end marker at original location.
4EC8
XOR A AF
Clear A.
4EC9
LD (HL),A 77
Store zero.
4ECA
INC HL 23
Advance pointer.
4ECB
LD (HL),A 77
Store zero (end of chain).
4ECC
EI FB
Enable Interrupts.
4ECD
LD HL,4FABH 21 AB 4F
Point HL to second banner string.
4ED0
GOSUB to print string.
4ED3
LD A,(43ABH) 3A AB 43
Fetch warm boot signature.
4ED6
CP A5H FE A5
Compare with expected value.
4ED8
LD A,(42F9H) 3A F9 42
Fetch boot options.
4EDB
If NZ FLAG (cold boot), skip.
4EDD
RES 7,A CB BF
RESset bit 7 (warm boot - skip some init).
4EDF
AND C0H E6 C0
Mask bits 6-7.
4EE1
If NZ FLAG, GOSUB to date/time prompt.
4EE4
LD HL,5089H 21 89 50
Point HL to 5089H - next string.
4EE7
PUSH HL E5
Save string pointer.
4EE8
GOSUB to display time routine.
4EEB
LD HL,5093H 21 93 50
Point HL to date prompt string at 5093H.
4EEE
GOSUB to display date routine.

4EF1H - Directory Read and System Init

Reads system directory and completes initialization. Sets up warm boot signature.

4EF1
POP HL E1
Restore string pointer.
4EF2
GOSUB to print string.
4EF5
XOR A AF
Clear A.
4EF6
LD (4930H),A 32 30 49
Clear 4930H - sector number.
4EF9
LD HL,4F05H 21 05 4F
Load HL with return address.
4EFC
PUSH HL E5
Push return address.
4EFD
PUSH DE D5
Save DE.
4EFE
PUSH BC C5
Save BC.
4EFF
LD HL,4200H 21 00 42
Point HL to sector buffer.
4F02
JUMP to read directory sector.
4F05
If NZ FLAG (error), JUMP to error handler.
4F08
LD DE,4318H 11 18 43
Point DE to system config area.
4F0B
PUSH DE D5
Save destination.
4F0C
PUSH BC C5
Save count.
4F0D
LD HL,42E0H 21 E0 42
Point HL to buffer data.
4F10
LD BC,0020H 01 20 00
Load BC with 32 bytes to copy.
4F13
LDIR ED B0
Block copy system config.
4F15
LD HL,43ABH 21 AB 43
Point HL to warm boot signature.
4F18
LD (HL),A5H 36 A5
Store A5H signature (mark as booted).
4F1A
POP BC C1
Restore BC.
4F1B
POP HL E1
Restore HL.
4F1C
XOR A AF
Clear A.
4F1D
BIT 6,(IY+ECH) FD CB EC 76
Test bit 6 at IY offset ECH.
4F21
If NZ FLAG, skip to final print.
4F23
LD A,(505CH) 3A 5C 50
Fetch autorun flag.
4F26
BIT 3,A CB 5F
Test bit 3.
4F28
If Z FLAG, skip to final print.
4F2A
LD A,(3840H) 3A 40 38
Fetch keyboard status.
4F2D
RRCA 0F
Rotate right to test bit 0.
4F2E
If CARRY (key pressed), JUMP to DOS Ready.
4F31
LD A,(HL) 7E
Fetch character from command buffer.
4F32
CP 0DH FE 0D
Compare with CR.
4F34
If Z FLAG (no command), JUMP to DOS Ready.
4F37
GOSUB to print string.
4F3A
JUMP to DOS Ready prompt display.

4F3DH - Date/Time Input Handler

Prompts user for date and time entry during boot. Parses ASCII digit input and validates against range limits.

4F64
GOSUB to print string (prompt message).
4F67
LD HL,4318H 21 18 43
Point HL to system config area at 4318H.
4F6A
LD B,09H 06 09
Load B with 9 (input buffer size).
4F6C
JP 0040H C3 40 00
JUMP to ROM input routine at 0040H.

4F6FH - Parse Date/Time Digits

Parses 3 two-digit fields (YY/MM/DD or HH:MM:SS) from ASCII input at (HL), stores binary values at (DE) counting down. Validates each field against min/max limits on stack.

4F6F
LD (4FA0H),A 32 A0 4F
Store A at 4FA0H (save field type flag).
4F72
DI F3
Disable Interrupts during time update.
4F73
PUSH BC C5
Save BC (contains validation limits pointer).
4F74
LD B,03H 06 03
Load B with 3 - parse 3 fields.
4F76
LD A,(HL) 7E
[PARSE LOOP] Fetch first digit character.
4F77
SUB 30H D6 30
Convert ASCII '0'-'9' to binary 0-9.
4F79
CP 0AH FE 0A
Check if valid digit (0-9).
4F7B
INC HL 23
Advance to second digit.
4F7C
If NC (invalid), JUMP to error exit.
4F7E
LD C,A 4F
Save first digit in C.
4F7F
RLCA 07
A = digit × 2.
4F80
RLCA 07
A = digit × 4.
4F81
ADD A,C 81
A = digit × 5.
4F82
ADD A,A 87
A = digit × 10 (tens place value).
4F83
LD C,A 4F
Save tens value in C.
4F84
LD A,(HL) 7E
Fetch second digit character.
4F85
SUB 30H D6 30
Convert ASCII to binary.
4F87
CP 0AH FE 0A
Check if valid digit.
4F89
INC HL 23
Advance past second digit.
4F8A
If NC (invalid), JUMP to error exit.
4F8C
ADD A,C 81
A = (tens × 10) + units = final value.
4F8D
LD (DE),A 12
Store parsed value at destination.
4F8E
DEC DE 1B
Move to previous storage byte.
4F8F
EX (SP),HL E3
Swap HL with limits pointer on stack.
4F90
SUB (HL) 96
Subtract minimum valid value.
4F91
INC HL 23
Point to maximum value.
4F92
CP (HL) BE
Compare with (max - min) range.
4F93
INC HL 23
Advance limits pointer for next field.
4F94
If NC (out of range), JUMP to error exit.
4F96
EX (SP),HL E3
Restore input pointer, save updated limits.
4F97
DECREMENT B, if NZ JUMP to check separator.
4F99
POP BC C1
Discard limits pointer.
4F9A
EI FB
Enable Interrupts.
4F9B
JUMP to command parser - continue processing.
4F9E
LD A,(HL) 7E
[CHECK SEPARATOR] Fetch delimiter character.
4F9F
CP 00H FE 00
Compare with null (accept any non-null).
4FA1
INC HL 23
Skip separator.
4FA2
If Z (null found??), LOOP for next field.
4FA4
EI FB
[ERROR EXIT] Enable Interrupts.
4FA5
POP AF F1
Clean up stack.
4FA6
OR A B7
Clear Zero flag (indicate error).
4FA7
RET C9
RETURN with NZ = error.

4FA8H - Boot Banner and Message Strings

This area contains encoded message strings and control data. The bytes represent packed text with high bit set for end-of-string markers and special characters.

4FA8
DB 1CH,1FH,03H 1C 1F 03
Control codes: cursor home (1CH), clear (1FH), position (03H).
4FAB-4FD6
DB BF B4 80 BF 20 BE 83 83 BD 20 BF 80 80 BF 20 BF 83 83 BD 20 BE 83 83 BD 20 BE 83 83 8D 20 80 80 B8 87 20 BE 83 83 BD 20 BE 83 83 BD
Banner graphics - box drawing characters (high bit set).
4FD7-40E5
DEFM " APPARAT, INC." + 0AH
4FE7-5012
BF 82 AD BF 20 BF 83 83 B3 20 BF 9E AD BF 20 BF 80 80 BF 20 BF 80 80 BF 20 B2 83 83 BD 20 A0 9E 81 80 20 BE 83 83 BD 20 BF 80 80 BF
5013-5021
DEFM " VERSION 2.0"+0AH
5022-504D
83 80 80 83 20 82 83 83 81 20 83 80 80 83 20 83 83 83 81 20 82 83 83 81 20 82 83 83 81 20 83 80 80 80 20 82 83 83 81 20 82 83 83 81
504E-505A
DEFM " MODEL I"+0AH+0DH

505BH - Boot Parameter Copy Area

8-byte area where boot parameters from 42F8H are copied during initialization.

505B
DB 00H,00H,00H,00H 00 00 00 00
Boot parameter storage (8 bytes, initialized to zero).
505F
DB 00H,00H,00H,00H 00 00 00 00
Boot parameters continued.

5063H - Date Input Prompt

Prompt string displayed when requesting date entry during boot.

5063
DB "DATE?" 44 41 54 45 3F
Text: "DATE?"
5068
DB 20H,20H 20 20
Two spaces.
506A
DB "(MM/DD/YY)" 28 4D 4D 2F 44 44 2F 59 59 29
Format hint: "(MM/DD/YY)"
5074
DB 20H,03H 20 03
Space + control code (cursor position).

5076H - Time Input Prompt

Prompt string displayed when requesting time entry during boot.

5076
DB "TIME?" 54 49 4D 45 3F
Text: "TIME?"
507B
DB 20H,20H 20 20
Two spaces.
507D
DB "(HH:MM:SS)" 28 48 48 3A 4D 4D 3A 53 53 29
Format hint: "(HH:MM:SS)"
5087
DB 20H,03H 20 03
Space + control code.

5089H - Date Display Format

Format string for displaying current date on screen.

5089
DB "MM/DD/YY" 4D 4D 2F 44 44 2F 59 59
Date format: "MM/DD/YY"
5091
DB 20H,20H 20 20
Trailing spaces.

5093H - Time Display Format

Format string for displaying current time on screen.

5093
DB "HH:MM:SS" 48 48 3A 4D 4D 3A 53 53
Time format: "HH:MM:SS"
509B
DB 0DH 0D
Carriage return (end of string).

509CH - Date/Time Validation Tables

Validation limits for date and time input parsing. Each field has (minimum, range) pairs. Used by the parser at 4F6FH to validate user input.

509C
DB 01H,0CH 01 0C
Month limits: min=1, range=12 (valid: 1-12).
509E
DB 01H,1FH 01 1F
Day limits: min=1, range=31 (valid: 1-31).
50A0
DB 00H,64H 00 64
Year limits: min=0, range=100 (valid: 00-99).
50A2
DB 00H,18H 00 18
Hour limits: min=0, range=24 (valid: 0-23).
50A4
DB 00H,3CH 00 3C
Minute limits: min=0, range=60 (valid: 0-59).
50A6
DB 00H,3CH 00 3C
Second limits: min=0, range=60 (valid: 0-59).
50A8
DB 00H 00
Table terminator or padding.

50A9H - Reserved Buffer Space

Reserved buffer area initialized to zeros. Used as temporary storage during boot operations and later available for overlay programs. This space extends to the end of the SYS0 module.

50A9
DS 306 00...
Reserved buffer (306 bytes, all 00H). Addresses 50A9H-51DAH.

Program Entry Point

The DOS bootstrap loader jumps here after loading SYS0/SYS from disk.

ENTRY
ORG 4D00H
PROGRAM ENTRY = 4D00H - Boot initialization starts at 4D00H.