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

Page Customization

Introduction/Summary

The SYS2/SYS file contains the code for several core utility and system commands in NEWDOS/80 v2.0. The routines within this module implement the essential DIR (Directory) command, which is responsible for scanning the disk directory and displaying the file list and disk usage status for a specified drive.

This overlay file also includes the logic for the DATE and TIME commands, which allow the user to view and set the system's current date and time information. As a system overlay, the code in SYS2/SYS is loaded into the transient program area when one of its contained commands is executed.

Variables:

AddressBytesPurpose
4022H1Cursor blink state storage. Non-zero = cursor was on, Zero = cursor was off.
402DH3DOS No-Error Exit vector (JP instruction). Programs jump here on successful completion.
4030H3DOS Error-Already-Displayed Exit vector. Jump here when error message already shown.
4200H256DOS Sector buffer (also aliased at 5100H-51FFH for overlay area).
4300H24Storage area including PDRIVE and SYSTEM specifications.
4312H1BREAK key enable flag. C9H = enabled (RET instruction), C3H = disabled (JP instruction).
4313H2BREAK key handler jump address (used when 4312H contains C3H).
4318H80DOS Command buffer. User input and commands are stored here (4318H-4367H).
4368H1SYSTEM storage - system state flags.
4369H1SYSTEM storage - additional flags (bit 5 checked for certain operations).
436AH1DOS system flags byte 1.
  • Bit 7 = MINI-DOS active
  • Bit 6 = DOS-CALL active
  • Bit 5 = command processing state
  • Bit 4 = additional state flag
436BH1DOS system flags byte 2.
  • Bit 7 = special return mode
  • Bit 6 = stack save mode
  • Bit 2 = error state
436CH1DOS system flags byte 3.
  • Bit 6 = chaining active flag
  • Bit 5 = additional state
436DH1DOS system flags byte 4.
  • Bit 5 = R command repeat flag
4371H42PDRIVE storage area (4371H-439AH). Contains physical drive configuration data.
439BH2Saved stack pointer for MINI-DOS. Stores SP when entering MINI-DOS for later restoration.
439DH2Saved stack pointer for DOS-CALL. Stores SP when entering DOS-CALL mode.
43A7H2Saved command buffer pointer. Stores original (4318H) value for R command repeat functionality.
4408H3DOS command execution return address vector.
4467HDOS message display routine entry point.
4480H32Filename parsing buffer. Parsed filename components stored here.
45B0HBREAK key handler routine address (stored into 4313H).
45B5HCharacter case conversion routine.
4CD5HFilespec parsing subroutine.
4CD9HFilespec validation subroutine.
4CC5HString comparison subroutine.
4F58HCommand name lookup table. Contains DOS command names with attributes.
51A7H3ASCII string "CMD" - command file extension.
51AAH3ASCII string "JCL" - job control language extension.
51ADH3ASCII string "TO" with null terminator - COPY command keyword.
51B0H5ASCII string "MINI-" - prefix for MINI-DOS ready message.
51B5H16ASCII string "NEWDOS/80 READY" with CR terminator - DOS prompt message.
51C5H4System parameter table (1CH, 1FH, 03H, 00H).
51E0H32Working buffer at end of overlay area. Used for temporary filename storage.

Disassembly

4D00H - SVC File Operations Command Dispatcher

This is the main entry point for file operations Supervisor Calls (SVCs) in NEWDOS/80. Register A contains the command code on entry. The dispatch table handles commands spaced 20H apart: 24H (OPEN), 44H (INIT), 64H (CLOSE/READ), 84H (Hash calculation), A4H (Buffer setup), C4H (RENAME/REMOVE), and E4H (multiple sub-operations based on Register C).

4D00
CP 24H FE 24
Compare Register A against 24H (OPEN file command code). If A equals 24H, the Z FLAG is set.
4D02
If Z FLAG set (command=24H OPEN), JUMP to OPEN file handler at 4E2EH.
4D05
CP 44H FE 44
Compare Register A against 44H (INIT/CREATE file command). If A equals 44H, the Z FLAG is set.
4D07
If Z FLAG set (command=44H INIT), JUMP to INIT file handler at 4DBDH.
4D0A
CP 64H FE 64
Compare Register A against 64H (CLOSE/READ command). If A equals 64H, the Z FLAG is set.
4D0C
If Z FLAG set (command=64H), JUMP to CLOSE/READ handler at 4F82H.
4D0F
CP 84H FE 84
Compare Register A against 84H (Hash calculation command). If A equals 84H, the Z FLAG is set.
4D11
If Z FLAG set (command=84H), JUMP to filename hash calculation routine at 5155H.
4D14
CP A4H FE A4
Compare Register A against A4H (Buffer setup command). If A equals A4H, the Z FLAG is set.
4D16
If Z FLAG set (command=A4H), JUMP to buffer setup routine at 4D92H.
4D18
CP C4H FE C4
Compare Register A against C4H (RENAME/REMOVE command). If A equals C4H, the Z FLAG is set.
4D1A
If Z FLAG set (command=C4H), JUMP to RENAME/REMOVE handler at 4D80H.
4D1C
CP E4H FE E4
Compare Register A against E4H (Multi-function command). If A equals E4H, the Z FLAG is set.
4D1E
If NZ FLAG set (command not E4H), JUMP to error return at 4D2EH - unknown command code.

Command E4H has sub-functions selected by the value in Register C (1-4). Register C is decremented to determine which sub-function to execute.

4D20
DEC C 0D
DECrement Register C by 1. If C was 1, Z FLAG is now set (sub-function 1).
4D21
If Z FLAG set (C was 1), JUMP to E4 sub-function 1 - KILL file at 4D32H.
4D23
DEC C 0D
DECrement Register C again. If C was 2, Z FLAG is now set (sub-function 2).
4D24
If Z FLAG set (C was 2), JUMP to E4 sub-function 2 - allocate granule at 50CAH.
4D27
DEC C 0D
DECrement Register C again. If C was 3, Z FLAG is now set (sub-function 3).
4D28
If Z FLAG set (C was 3), JUMP to E4 sub-function 3 - parse command at 4D7BH.
4D2A
DEC C 0D
DECrement Register C again. If C was 4, Z FLAG is now set (sub-function 4).
4D2B
If Z FLAG set (C was 4), JUMP to E4 sub-function 4 - INIT with OPEN at 4D72H.

4D2EH - Invalid Command Error Return

Returns error code 2AH (Invalid function) when an unrecognized command code is passed to the dispatcher.

4D2E
LD A,2AH 3E 2A
Load Register A with error code 2AH (42 decimal - "Invalid function" error).
4D30
OR A B7
OR Register A with itself. This sets the NZ FLAG (since A is non-zero) to indicate an error occurred.
4D31
RET C9
RETURN to caller with error code 2AH in A and NZ FLAG set indicating failure.

4D32H - E4/1: KILL File Handler

Sub-function 1 of command E4H: Deletes a file from the directory. On entry, DE points to the FCB (File Control Block). This routine opens the file, marks it for deletion, and updates the directory.

4D32
PUSH DE D5
Save DE (FCB pointer) onto the stack for later restoration.
4D33
POP IX DD E1
Pop the value into IX - now IX points to the FCB.
4D35
INC DE 13
INCrement DE to point to FCB+01H (file attribute/flag byte).
4D36
LD A,(DE) 1A
Fetch the file attribute byte from FCB+01H.
4D37
AND 07HAND 00000111 E6 07
Mask with 07H to extract the file type bits (bits 0-2).
4D39
CP 03H FE 03
Compare against 03H. Files with type >= 3 are system files and cannot be killed normally.
4D3B
LD A,25H 3E 25
Load A with error code 25H (37 decimal - "Illegal file access" or protected file).
4D3D
If NO CARRY (file type >= 3, system file), JUMP to error return at 4D30H.

File type is valid for deletion. Now set up to open the file and mark it deleted.

4D3F
LD HL,4E75H 21 75 4E
Load HL with address 4E75H - location of a self-modifying instruction in the OPEN routine.
4D42
LD (HL),3EH 36 3E
Store 3EH at 4E75H. This modifies the instruction to LD A,nn opcode, changing OPEN behavior.
4D44
LD DE,51E0H 11 E0 51
Load DE with 51E0H - temporary FCB buffer address for the delete operation.
4D47
GOSUB to OPEN file with B=0 - opens file using FCB at DE.
4D4A
LD (HL),18H 36 18
Restore 18H at 4E75H (original JR opcode) to undo the self-modification.
4D4C
If Z FLAG set (OPEN returned error), JUMP to return error 35H at 4D77H.
4D4E
CP 18H FE 18
Compare error code against 18H (24 decimal - "File already open").
4D50
If Z FLAG (file already open), GOSUB to directory lookup at 494BH to find the entry.
4D53
RET NZ C0
If NZ FLAG (error during lookup), RETURN with error code in A.

File entry found. Now copy the delete marker and update the directory.

4D54
LD A,L 7D
Load A with low byte of HL (directory entry offset within sector buffer).
4D55
ADD 05H C6 05
ADD 5 to A to point to offset +05H in directory entry (file status byte).
4D57
LD L,A 6F
Store result back in L - HL now points to directory entry +05H.
4D58
EX DE,HL EB
Exchange DE and HL. DE now points to directory entry +05H, HL is free.
4D59
LD HL,51CDH 21 CD 51
Load HL with 51CDH - source buffer containing updated file data.
4D5C
LD BC,000BH 01 0B 00
Load BC with 11 - number of bytes to copy (filename = 8 + extension = 3).
4D5F
LDIR ED B0
Block copy 11 bytes from (HL) to (DE), updating filename in directory buffer.
4D61
GOSUB to write directory sector - saves the updated directory entry to disk.
4D64
LD A,01H 3E 01
Load A with 01H - directory sector number to read next.
4D66
If Z FLAG (write successful), GOSUB to read directory sector at 490AH.
4D69
RET NZ C0
If NZ FLAG (error during read), RETURN with error code.

Now mark the file's granules as free in the GAT (Granule Allocation Table).

4D6A
LD L,(IX+07H) DD 6E 07
Load L with FCB+07H (first granule number of the file).
4D6D
LD (HL),00H 36 00
Store 00H at (HL) - mark the granule as FREE in the GAT.
4D6F
JUMP to write directory sector to save GAT and exit.

4D72H - E4/4: INIT with OPEN Handler

Sub-function 4 of command E4H: Creates a new file (INIT) and then opens it. Combines the INIT and OPEN operations into one call.

4D72
GOSUB to INIT file handler - create the file first.
4D75
RET NZ C0
If NZ FLAG (INIT failed), RETURN with error code in A.
4D76
RET C D8
If CARRY FLAG set (special condition from INIT), RETURN with that status.

4D77H - Return Error Code 35H

Returns error code 35H (File not found) with NZ flag set.

4D77
LD A,35H 3E 35
Load Register A with error code 35H (53 decimal - "File not found").
4D79
OR A B7
OR Register A with itself to set NZ FLAG (indicates error condition).
4D7A
RET C9
RETURN with error code 35H in A and NZ FLAG set.

4D7BH - E4/3: Parse Command and Execute

Sub-function 3 of command E4H: Parses a command line and executes the appropriate action. Uses the command line parser at 4CD5H.

4D7B
GOSUB to command line parser - parse the command at (HL).
4D7E
RET C D8
If CARRY FLAG set (parser error or complete), RETURN.
4D7F
POP AF F1
Pop return address from stack into AF - discards current return address.

4D80H - RENAME/REMOVE Command Handler (C4H)

Handles the C4H command (RENAME or REMOVE operations). Sets up file buffers and calls the A4H buffer setup routine.

4D80
EX (SP),HL E3
Exchange HL with top of stack - save current HL and get return address.
4D81
GOSUB to buffer setup routine at 4D92H - prepares file buffers.
4D84
If NZ FLAG (setup failed), JUMP to error handler at 4409H.
4D87
EX (SP),HL E3
Exchange HL with stack again - restore original HL and push result.
4D88
LD A,(4369H) 3A 69 43
Fetch driver status flags from 4369H.
4D8B
RLCA 07
Rotate A left - moves bit 7 into CARRY FLAG.
4D8C
If CARRY (bit 7 was set - output in progress), JUMP to cleanup and return at 440DH.
4D8F
JUMP to main processing routine at 4C20H to complete the operation.

4D92H - Buffer Setup Routine (A4H Command)

Sets up file buffers and validates the file operation. Called by the A4H command and by other file operations. On entry, DE points to FCB. On exit, HL points to directory entry if successful.

4D92
LD HL,4200H 21 00 42
Load HL with 4200H - base address of the sector buffer.
4D95
GOSUB to OPEN file with B=0 - attempts to open file using FCB at DE.
4D98
If Z FLAG set (OPEN returned with Z flag), JUMP to process file at 4DA0H.
4D9A
CP 18H FE 18
Compare error code against 18H (24 decimal - "File already open").
4D9C
RET NZ C0
If NZ FLAG (different error), RETURN with that error code.
4D9D
ADD 07H C6 07
ADD 7 to A - converts error 18H to 1FH (adjusted error code).
4D9F
RET C9
RETURN with adjusted error code 1FH in A.

4DA0H - Process File After OPEN

Continues file processing after successful OPEN. Validates file attributes and sets up for the requested operation.

4DA0
EX DE,HL EB
Exchange DE and HL. DE now contains buffer pointer, HL points to directory area.
4DA1
INC HL 23
INCrement HL to point to next byte in directory entry.
4DA2
LD A,(HL) 7E
Fetch the file attribute byte from directory entry.
4DA3
PUSH AF F5
Save AF (attribute byte) onto the stack.
4DA4
PUSH HL E5
Save HL (pointer to attribute byte) onto the stack.
4DA5
AND 07HAND 00000111 E6 07
Mask with 07H to extract file type (bits 0-2).
4DA7
LD B,A 47
Copy file type to Register B.
4DA8
LD A,06H 3E 06
Load A with 06H - maximum allowed file type for this operation.
4DAA
CP B B8
Compare 06H against file type in B. If type > 6, CARRY is set.
4DAB
LD A,25H 3E 25
Load A with error code 25H ("Illegal file access").
4DAD
LD (HL),2DH 36 2D
Store 2DH at (HL) - marks file for deletion/modification in directory.
4DAF
DEC HL 2B
DECrement HL to point back to start of directory entry.
4DB0
If NO CARRY (file type ≤ 6), GOSUB to load driver module at 4C28H.
4DB3
LD (4403H),HL 22 03 44
Store HL at 4403H - save directory entry pointer for later use.
4DB6
EX DE,HL EB
Exchange DE and HL registers.
4DB7
POP HL E1
Restore HL (pointer to attribute byte) from stack.
4DB8
POP BC C1
Pop saved AF into BC - B now holds original attribute byte.
4DB9
LD (HL),B 70
Restore original attribute byte at (HL) - undo the 2DH marker.
4DBA
DEC HL 2B
DECrement HL to point to start of directory entry.
4DBB
EX DE,HL EB
Exchange DE and HL. HL now has buffer pointer, DE has directory pointer.
4DBC
RET C9
RETURN to caller with Z FLAG status from previous operations.

4DBDH - INIT File Handler (44H Command)

Creates a new file entry in the directory. Called by command 44H (INIT). On entry, DE points to the FCB containing the filename. The routine searches for a free directory slot and initializes the file entry.

4DBD
GOSUB to OPEN file - check if filename already exists.
4DC0
RET Z C8
If Z FLAG set (file found), RETURN immediately - cannot create duplicate file.
4DC1
CP 18H FE 18
Compare return code against 18H ("File not found" expected for new file).
4DC3
RET NZ C0
If NZ FLAG (unexpected error), RETURN with that error code.

File does not exist (error 18H) - proceed to create it. Find a free directory slot.

4DC4
GOSUB to SVC setup - save registers and set IX to FCB, IY to DOS area.
4DC7
LD BC,(4E0AH) ED 4B 0A 4E
Fetch drive numbers from 4E0AH into BC (B=source, C=destination drive).
4DCB
LD A,B 78
Load A with source drive number from B.
4DCC
CP C B9
Compare source drive with destination drive.
4DCD
If Z FLAG (same drive), JUMP ahead to use that drive.
4DCF
LD A,(43A1H) 3A A1 43
Fetch default drive number from 43A1H (system variable).
4DD2
LD (4E0EH),A 32 0E 4E
Store selected drive number at 4E0EH (current operation drive).
4DD5
GOSUB to wait for index pulse - ensures disk is spinning and ready.
4DD8
If NZ FLAG (drive not ready), JUMP to error handling at 4DE3H.

Drive is ready. Check for wildcard filename (hash value stored at 4D6EH).

4DDA
LD HL,4D6EH 21 6E 4D
Load HL with 4D6EH - address storing filename hash/wildcard flag.
4DDD
LD B,(HL) 46
Fetch hash value into B.
4DDE
GOSUB to find free directory slot - searches for empty entry.
4DE1
If Z FLAG (slot found), JUMP to create file entry at 4DEAH.

4DE3H - INIT Error Retry Loop

Handles errors during INIT by prompting for retry. Error code 1AH means "Directory full".

4DE3
LD E,1AH 1E 1A
Load E with error code 1AH (26 decimal - "Directory full").
4DE5
GOSUB to error handler/retry routine - prompts user for action.
4DE8
[LOOP] JUMP back to 4DD2H to retry the INIT operation.

4DEAH - Create File Entry in Directory

Creates the actual file entry in the directory after finding a free slot. Initializes all fields of the directory entry.

4DEA
LD (4F56H),A 32 56 4F
Store A at 4F56H - saves directory slot/granule position.
4DED
LD (HL),10H 36 10
Store 10H at (HL) - initial file attribute (normal file, not deleted).
4DEF
GOSUB to extract file parameters - reads additional info from FCB.
4DF2
LD A,(4F5EH) 3A 5E 4F
Fetch file extension flag from 4F5EH.
4DF5
LD (HL),A 77
Store extension flag in directory entry.
4DF6
INC HL 23
INCrement HL to point to filename area of directory entry.
4DF7
EX DE,HL EB
Exchange DE and HL. DE now points to directory entry, HL is free.
4DF8
LD HL,51CDH 21 CD 51
Load HL with 51CDH - address of parsed filename buffer (8+3 format).
4DFB
LD BC,000FH 01 0F 00
Load BC with 15 - bytes to copy (11 for name + 4 for additional info).
4DFE
LDIR ED B0
Block copy 15 bytes from filename buffer (HL) to directory entry (DE).
4E00
GOSUB to write directory sector - saves the new entry to disk.
4E03
RET NZ C0
If NZ FLAG (write failed), RETURN with error code.
4E04
GOSUB to finalize file creation - sets up FCB and allocates initial space.
4E07
SCF 37
SET the Carry flag to signal to the calling routine that there is a special condition from INIT; there will be a RET C for this.
4E08
RET C9
RETURN to caller.

4E09H - Error Handler with Retry Option

Handles errors by checking retry count and returning appropriate status. On entry, D contains the previous error code, E contains the new error code. Returns with Z flag if retry should occur, or with NZ and error code in A if giving up.

4E09
LD HL,0000H 21 00 00
Load HL with 0000H - this is self-modifying; actual value stored at 4E0AH.
4E0C
LD D,A 57
Copy current error code from A to D for preservation.
4E0D
LD A,00H 3E 00
Load A with 00H - this is self-modifying; retry count stored at 4E0EH.
4E0F
INC A 3C
INCrement retry counter in A.
4E10
CP L BD
Compare retry count against L (max retries). Sets CARRY if count < max.
4E11
RET C D8
If CARRY (more retries allowed), RETURN to retry the operation.
4E12
POP HL E1
Pop return address from stack - abort current call level.
4E13
If Z FLAG (retry count = max exactly), JUMP to use error code E.
4E15
LD A,D 7A
Load A with previous error code from D.
4E16
OR A B7
OR A with itself - sets NZ if there was a previous error.
4E17
RET NZ C0
If NZ FLAG (previous error exists), RETURN with that error code.
4E18
LD A,E 7B
Load A with new error code from E.
4E19
OR A B7
OR A with itself - sets flags based on error code.
4E1A
RET C9
RETURN with error code in A and appropriate flags.

4E1BH - Return Space Error (20H)

Returns error code 20H (space/parameter error) with NZ flag set.

4E1B
LD A,20H 3E 20
Load Register A with error code 20H (32 decimal - "Parameter error" or invalid input).
4E1D
OR A B7
OR A with itself - sets NZ FLAG to indicate error condition.
4E1E
RET C9
RETURN with error code 20H and NZ FLAG set.

4E1FH - Extract File Parameters from Directory Entry

Extracts file parameters from the directory entry pointed to by HL and stores them in working variables for later use.

4E1F
INC HL 23
INCrement HL to point to next field in directory entry.
4E20
LD A,(HL) 7E
Fetch byte from directory entry (file parameter 1).
4E21
LD (4F46H),A 32 46 4F
Store parameter at 4F46H (file size or type indicator).
4E24
INC HL 23
INCrement HL to point to next field.
4E25
INC HL 23
INCrement HL again (skip one byte).
4E26
LD A,(HL) 7E
Fetch next byte from directory entry (file parameter 2).
4E27
LD (4F58H),A 32 58 4F
Store parameter at 4F58H (protection or access flags).
4E2A
INC HL 23
INCrement HL to point past extracted fields.
4E2B
RET C9
RETURN with HL pointing to next field in directory entry.

4E2CH - OPEN File with B=0 Entry Point

Entry point for OPEN file routine with B pre-cleared to 0. Falls through to main OPEN handler.

4E2C
LD B,00H 06 00
Load B with 00H - clears B before calling OPEN (B=0 means no special options).

4E2EH - OPEN File Handler (24H Command)

Main OPEN file routine. Opens a file for access by searching the directory for the filename and setting up the FCB. On entry: DE points to FCB with filename, B contains open mode flags. On exit: Z flag set if file found, A contains error code if not.

4E2E
GOSUB to SVC setup - save registers, set IX to FCB, IY to DOS system area (4380H).
4E31
LD (4F48H),HL 22 48 4F
Store HL at 4F48H - saves buffer/work area pointer.
4E34
LD A,B 78
Load A with open mode flags from B.
4E35
LD (4F5EH),A 32 5E 4F
Store open mode at 4F5EH for later reference.
4E38
LD HL,51CDH 21 CD 51
Load HL with 51CDH - filename buffer address (11 bytes: 8 name + 3 ext).
4E3B
DEC DE 1B
DECrement DE to point to byte before FCB (position for parsing).
4E3C
XOR A AF
Clear A to zero (reset any previous state).

Parse the filename from the FCB into the 11-byte buffer at 51CDH.

4E3D
GOSUB to parse filename - extract 8-character name portion.
4E40
CP 2FH FE 2F
Compare result against 2FH (ASCII /) - check for path separator.
4E42
LD B,03H 06 03
Load B with 3 - extension length (3 characters).
4E44
GOSUB to parse extension - extract 3-character extension.
4E47
CP 2EH FE 2E
Compare against 2EH (ASCII .) - check for extension separator.
4E49
GOSUB to continue parsing - handle any additional characters.
4E4C
LD B,00H 06 00
Clear B to 0 (default drive if none specified).
4E4E
LD C,(IY+1FH) FD 4E 1F
Fetch maximum drive number from IY+1FH (address 439FH) into C.
4E51
CP 3AH FE 3A
Compare against 3AH (ASCII :) - check for drive specifier.
4E53
If NZ FLAG (no colon), JUMP to use default drive at 4E75H.

Drive specifier found (colon detected). Parse the drive number (0-9).

4E55
INC DE 13
INCrement DE to point to first digit of drive number.
4E56
LD A,(DE) 1A
Fetch the drive number character.
4E57
SUB 30H D6 30
SUBtract 30H to convert ASCII digit 0-9 to binary 0-9.
4E59
CP 0AH FE 0A
Compare against 10. If >= 10, it wasn't a valid digit.
4E5B
If NO CARRY (invalid digit), JUMP to error return 20H.
4E5D
LD C,A 4F
Store first digit in C (tens place if two-digit drive number).
4E5E
INC DE 13
INCrement DE to check for second digit.
4E5F
LD A,(DE) 1A
Fetch potential second digit.
4E60
SUB 30H D6 30
SUBtract 30H to convert ASCII to binary.
4E62
CP 0AH FE 0A
Compare against 10 to check if valid digit.
4E64
If NO CARRY (not a digit), JUMP to single digit drive at 4E74H.

Two-digit drive number: multiply first digit by 10 and add second digit.

4E66
LD L,A 6F
Store second digit in L temporarily.
4E67
LD A,C 79
Load A with first digit from C.
4E68
LD B,09H 06 09
Load B with 9 - loop counter for multiplication (add 9 more times).
4E6A
ADD A,C 81
[LOOP START] ADD C to A (accumulate first digit × 10).
4E6B
If CARRY (overflow), JUMP to error return - drive number too large.
4E6D
DECrement B and Jump if Not Zero - [LOOP] continue multiplying.
4E6F
ADD A,L 85
ADD second digit (L) to result - now A = first×10 + second.
4E70
If NO CARRY (valid), JUMP back to store result and check for more digits.
4E72
JUMP to error return - overflow in drive number calculation.
4E74
LD B,C 41
Copy single-digit drive number from C to B.

4E75H - Use Default Drive and Continue OPEN

Continues OPEN processing with drive number in B. This location contains self-modifying code - the JR instruction may be temporarily changed by other routines.

4E75
JUMP to validate drive and continue at 4E7FH. (This instruction is self-modified by KILL routine.)
4E77
LD A,C 79
Load A with drive number from C (alternate entry point).
4E78
CP B B8
Compare requested drive against maximum drive B.
4E79
If Z FLAG (drive = max, which is invalid), JUMP to error return.
4E7B
LD B,(IY+88H) FD 46 88
Fetch default drive from IY+88H (address 4408H) into B.
4E7E
LD C,B 48
Copy default drive to C as well.
4E7F
LD (4E0AH),BC ED 43 0A 4E
Store BC at 4E0AH - saves source and destination drive numbers.

Calculate filename hash for quick directory searches.

4E83
PUSH BC C5
Save BC (drive numbers) onto the stack.
4E84
GOSUB to calculate filename hash - generates 16-bit hash of filename.
4E87
LD (51D8H),HL 22 D8 51
Store hash value at 51D8H (primary hash storage).
4E8A
LD (51DAH),HL 22 DA 51
Store hash at 51DAH (secondary hash storage for comparison).
4E8D
LD HL,51CDH 21 CD 51
Load HL with 51CDH - filename buffer address.
4E90
LD B,0BH 06 0B
Load B with 11 - filename length (8 + 3).
4E92
XOR A AF
Clear A to zero for checksum calculation.

Calculate simple checksum of filename to detect wildcards.

4E93
XOR (HL) AE
[LOOP START] XOR byte at (HL) into accumulator A.
4E94
INC HL 23
INCrement HL to next character of filename.
4E95
RLCA 07
Rotate A left to mix bits for better hash distribution.
4E96
DECrement B and Jump if Not Zero - [LOOP] process all 11 bytes.
4E98
If NZ FLAG (checksum non-zero = has wildcards), JUMP ahead.
4E9A
INC A 3C
INCrement A to make it non-zero (no wildcards, exact match needed).
4E9B
LD (4D6EH),A 32 6E 4D
Store wildcard/hash indicator at 4D6EH.
4E9E
POP AF F1
Pop saved BC into AF - A now has source drive, F has dest drive in flags.
4E9F
LD (4E0EH),A 32 0E 4E
Store source drive at 4E0EH (current working drive).
4EA2
GOSUB to wait for index pulse - ensure drive is ready.
4EA5
If Z FLAG (drive ready), JUMP to search directory at 4EAEH.

Drive not ready - set up error code and retry.

4EA7
LD E,18H 1E 18
Load E with error code 18H (24 decimal - "File not found" or drive error).
4EA9
GOSUB to error handler - check for retry.
4EAC
[LOOP] JUMP back to retry drive access.

4EAEH - Search Directory for File

Searches the directory for a matching filename. Uses the hash value calculated earlier to speed up the search. Returns with Z flag set if file found, NZ if not found.

4EAE
LD DE,51ADH 11 AD 51
Load DE with 51ADH - work buffer for directory operations.
4EB1
LD BC,001FH 01 1F 00
Load BC with 001FH - B=0 (starting position), C=1FH (31 entries per sector).
4EB4
LD A,B 78
[LOOP START] Load A with current directory position from B.
4EB5
SUB C 91
SUBtract C to check if we've reached the end.
4EB6
If Z FLAG (end of directory), JUMP to not found error.
4EB8
LD A,01H 3E 01
Load A with 01H - directory sector number to read.
4EBA
GOSUB to read directory sector into buffer.
4EBD
RET NZ C0
If NZ FLAG (read error), RETURN with error code.
4EBE
LD A,B 78
Load A with current position B (also returned from read).
4EBF
LD B,A 47
[INNER LOOP] Save position in B.
4EC0
LD (DE),A 12
Store position at work buffer (DE).
4EC1
LD L,A 6F
Copy position to L for sector buffer index.
4EC2
LD A,E 7B
Load A with low byte of work buffer pointer.
4EC3
CP CCH FE CC
Compare against CCH - check if we've filled the buffer.
4EC5
If Z FLAG (buffer full), JUMP to process matches at 4EDDH.
4EC7
LD A,(4D6EH) 3A 6E 4D
Fetch wildcard indicator from 4D6EH.
4ECA
CP (HL) BE
Compare against directory entry byte at (HL).
4ECB
If NZ FLAG (no match), JUMP to advance position.
4ECD
INC DE 13
INCrement DE - add this entry to match buffer.
4ECE
LD A,B 78
Load A with current position from B.
4ECF
ADD 20H C6 20
ADD 20H (32) to move to next directory entry.
4ED1
If NO CARRY (still in same sector), [LOOP] continue searching.
4ED3
INC A 3C
INCrement A (adjust for sector wrap).
4ED4
CP C B9
Compare against C (max entries per track).
4ED5
LD B,A 47
Save new position in B.
4ED6
If CARRY (more entries), [LOOP] continue searching.
4ED8
LD A,E 7B
Load A with current buffer position.
4ED9
CP ADH FE AD
Compare against ADH - start of work buffer.
4EDB
If Z FLAG (no matches found), [LOOP] read next sector.

4EDDH - Process Directory Matches

Processes the list of potential directory matches found during the search. Verifies each match by comparing the full filename.

4EDD
DEC DE 1B
DECrement DE to point to last match in buffer.
4EDE
LD A,(DE) 1A
Fetch the directory position of the potential match.
4EDF
LD (4F56H),A 32 56 4F
Store position at 4F56H for later reference.
4EE2
GOSUB to read directory entry - load the full entry for comparison.
4EE5
RET NZ C0
If NZ FLAG (read error), RETURN with error code.
4EE6
PUSH DE D5
Save DE (match buffer pointer) onto the stack.
4EE7
PUSH BC C5
Save BC (position counters) onto the stack.
4EE8
LD A,(HL) 7E
Fetch first byte of directory entry (status/attribute).
4EE9
LD (4F24H),A 32 24 4F
Store attribute at 4F24H for processing.
4EEC
AND 90H E6 90
Mask with 90H - isolate status bits (deleted, system flags).
4EEE
CP 10H FE 10
Compare against 10H - check if entry is valid (not deleted, not system).
4EF0
If NZ FLAG (invalid entry), JUMP to skip this entry.

Entry appears valid. Extract parameters and compare full filename.

4EF2
GOSUB to extract file parameters from directory entry.
4EF5
LD DE,51CDH 11 CD 51
Load DE with 51CDH - address of search filename buffer.
4EF8
LD B,0BH 06 0B
Load B with 11 - number of bytes to compare.
4EFA
INC HL 23
[LOOP START] INCrement HL to point to directory filename.
4EFB
LD A,(DE) 1A
Fetch character from search filename.
4EFC
CP (HL) BE
Compare against character in directory entry.
4EFD
INC DE 13
INCrement DE to next search character.
4EFE
If Z FLAG (characters match), JUMP to continue comparison.
4F00
POP BC C1
Restore BC from stack.
4F01
POP DE D1
Restore DE from stack.
4F02
JUMP back to check next match in buffer.
4F04
DECrement B and Jump if Not Zero - [LOOP] compare all 11 characters.

Full filename match found! Extract file information from directory entry.

4F06
POP BC C1
Pop BC from stack (cleanup - not needed anymore).
4F07
POP DE D1
Pop DE from stack (cleanup).
4F08
INC HL 23
INCrement HL past filename to file size field.
4F09
LD E,(HL) 5E
Fetch low byte of file size into E.
4F0A
INC HL 23
INCrement HL to high byte.
4F0B
LD D,(HL) 56
Fetch high byte of file size into D. DE = file size.
4F0C
INC HL 23
INCrement HL to next field.
4F0D
LD C,(HL) 4E
Fetch low byte of record count into C.
4F0E
INC HL 23
INCrement HL to high byte.
4F0F
LD B,(HL) 46
Fetch high byte of record count into B. BC = record count.
4F10
INC HL 23
INCrement HL past record count.
4F11
PUSH HL E5
Save HL (pointer to extent info) onto the stack.
4F12
LD HL,(51D8H) 2A D8 51
Fetch hash value from 51D8H into HL.
4F15
BIT 7,(IY+ECH) FD CB EC 7E
Test bit 7 of system flag at IY+ECH (address 446CH).
4F19
If Z FLAG (bit 7 clear), JUMP to finalize open at 4F2FH.

Special file verification mode is enabled. Check file parameters.

4F1B
OR A B7
Clear CARRY flag for subtraction.
4F1C
SBC HL,DE ED 52
SUBtract file size (DE) from hash (HL) with borrow.
4F1E
If Z FLAG (match), JUMP to finalize open.
4F20
ADD HL,DE 19
Restore HL by adding DE back.
4F21
LD A,07H 3E 07
Load A with 07H.
4F23
AND 00H E6 00
AND with 00H - effectively sets A to 0 (clears A).
4F25
SBC HL,BC ED 42
SUBtract record count (BC) from HL.
4F27
If Z FLAG (match), JUMP to continue open with A=0.
4F29
POP HL E1
Pop extent pointer from stack.
4F2A
LD A,19H 3E 19
Load A with error code 19H (25 decimal - "File verification failed").
4F2C
OR A B7
Set NZ FLAG to indicate error.
4F2D
RET C9
RETURN with error code 19H.

4F2EH - Finalize File Open / FCB Setup

Completes the file open operation by setting up the FCB with all necessary information. Called after the file is found in the directory.

4F2E
PUSH DE D5
Save DE (file size) onto the stack.
4F2F
XOR A AF
Clear A to zero (no error).
4F30
PUSH IX DD E5
Save IX (FCB pointer) onto the stack.
4F32
POP HL E1
Pop IX value into HL - HL now points to FCB.
4F33
GOSUB to initialize FCB fields - clears and sets up FCB structure.
4F36
LD (HL),80H 36 80
Store 80H at FCB+00 - file status: open, read mode.
4F38
INC HL 23
INCrement HL to FCB+01.
4F39
OR 28H F6 28
OR A with 28H - set file access flags.
4F3B
LD (HL),A 77
Store access flags at FCB+01.
4F3C
LD A,(4F5EH) 3A 5E 4F
Fetch open mode from 4F5EH (passed in originally).
4F3F
OR A B7
Test if open mode is zero.
4F40
If Z FLAG (mode=0), JUMP ahead - use default settings.
4F42
SET 7,(HL) CB FE
SET bit 7 of FCB+01 - mark file as "extended open mode".
4F44
INC HL 23
INCrement HL to FCB+02.
4F45
LD (HL),00H 36 00
Store 00H at FCB+02 - clear current record position.
4F47
LD DE,0000H 11 00 00
Load DE with 0000H - initialize position to zero.
4F4A
INC HL 23
INCrement HL to FCB+03.
4F4B
LD (HL),E 73
Store low byte of position (00H) at FCB+03.
4F4C
INC HL 23
INCrement HL to FCB+04.
4F4D
LD (HL),D 72
Store high byte of position (00H) at FCB+04.
4F4E
INC HL 23
INCrement HL to FCB+05.
4F4F
INC HL 23
INCrement HL to FCB+06 (skip reserved byte).
4F50
LD A,(IY+88H) FD 7E 88
Fetch drive number from IY+88H (4408H) into A.
4F53
LD (HL),A 77
Store drive number at FCB+06.
4F54
INC HL 23
INCrement HL to FCB+07.
4F55
LD (HL),00H 36 00
Store 00H at FCB+07 - clear first granule.
4F57
LD A,00H 3E 00
Load A with 00H (self-modifying: value stored at 4F58H).
4F59
INC HL 23
INCrement HL to FCB+08.
4F5A
OR A B7
Test if A is zero.
4F5B
LD (HL),A 77
Store at FCB+08.
4F5C
INC HL 23
INCrement HL to FCB+09.
4F5D
LD (HL),00H 36 00
Store 00H at FCB+09.
4F5F
INC HL 23
INCrement HL to FCB+0AH.
4F60
INC HL 23
INCrement HL to FCB+0BH.
4F61
INC HL 23
INCrement HL to FCB+0CH.
4F62
POP DE D1
Pop extent pointer (from stack saved at 4F11) into DE.
4F63
LD A,(DE) 1A
Fetch first extent byte.
4F64
INC DE 13
INCrement DE to next byte.
4F65
If Z FLAG (from earlier OR A test), JUMP to use value as-is.
4F67
SUB 01H D6 01
SUBtract 1 from extent value.
4F69
LD (HL),A 77
Store adjusted extent at FCB+0CH.
4F6A
INC HL 23
INCrement HL to FCB+0DH.
4F6B
LD A,(DE) 1A
Fetch second extent byte.
4F6C
SBC 00H DE 00
SUBtract with borrow (continues the -1 adjustment).
4F6E
LD (HL),A 77
Store at FCB+0DH (high byte of EOF).
4F6F
INC DE 13
INCrement DE to next extent field.
4F70
INC HL 23
INCrement HL to FCB+0EH.
4F71
LD A,2CH 3E 2C
Load A with error code 2CH (44 decimal - "File extent error").
4F73
RET C D8
If CARRY (overflow in subtraction), RETURN with error.
4F74
GOSUB to copy extent info - copies remaining extent data.
4F77
XOR A AF
Clear A (no error) and set Z FLAG for success.
4F78
RET C9
RETURN with Z FLAG set (success) and A=0.

4F79H - Copy Extent Information

Copies extent information from directory entry to FCB. Copies 8 bytes of extent data.

4F79
EX DE,HL EB
Exchange DE and HL - DE now destination, HL source.
4F7A
LD A,08H 3E 08
Load A with 8 - number of bytes to copy.
4F7C
LD C,A 4F
Copy count to C.
4F7D
LD B,00H 06 00
Clear B - BC now contains byte count.
4F7F
LDIR ED B0
Block copy 8 bytes from (HL) to (DE).
4F81
RET C9
RETURN to caller.

4F82H - Close/Read Handler (64H Command)

Handles file close or sector read operations. On entry, IX points to FCB. Verifies file is open before proceeding.

4F82
LD A,3DH 3E 3D
Load A with error code 3DH (61 decimal - "File not open").
4F84
BIT 7,(IX+02H) DD CB 02 7E
Test bit 7 of FCB+02 - checks if file is open (bit 7 set = open).
4F88
If Z FLAG (file not open), GOSUB to select drive at 476EH.
4F8B
If NZ FLAG (error or file not open), JUMP to error exit at 4FFBH.

File is open. Get drive-specific parameters and locate the sector.

4F8D
LD A,(486AH) 3A 6A 48
Fetch current drive parameter from 486AH.
4F90
LD (505EH),A 32 5E 50
Store at 505EH (working variable for granule calculations).
4F93
PUSH AF F5
Save AF onto the stack.
4F94
GOSUB to read directory entry - get file's directory info.
4F97
GOSUB to validate file status - check file attributes.
4F9A
INC DE 13
INCrement DE to point to extent data in directory entry.
4F9B
PUSH DE D5
Save DE (extent pointer) onto the stack.
4F9C
GOSUB to prepare extent buffer at 50B4H.
4F9F
LD B,(IY+8FH) FD 46 8F
Fetch sectors per granule from IY+8FH (440FH) into B.
4FA2
LD C,01H 0E 01
Load C with 01H - bit mask for sector within granule.
4FA4
LD E,(HL) 5E
Fetch current granule number into E.
4FA5
INC E 1C
INCrement E to test for FFH (unused granule marker).
4FA6
If Z FLAG (granule was FFH), JUMP to allocate new granule.
4FA8
DEC E 1D
DECrement E back to original granule number.
4FA9
DEC E 1D
DECrement E again (adjust for calculation).
4FAA
INC HL 23
INCrement HL to next extent byte.
4FAB
LD A,(HL) 7E
Fetch extent flags byte.
4FAC
AND 1FHAND 00011111 E6 1F
Mask with 1FH - extract sector count within extent (bits 0-4).
4FAE
LD D,A 57
Copy sector count to D.
4FAF
INC D 14
INCrement D (sector count is 0-based).
4FB0
LD A,(HL) 7E
Fetch extent flags again.
4FB1
AND 0E0HAND 11100000 E6 E0
Mask with E0H - extract granule count (bits 5-7).
4FB3
DEC HL 2B
DECrement HL back to granule number byte.
4FB4
RLCA 07
Rotate left to shift granule count into lower bits.
4FB5
RLCA 07
Continue rotating.
4FB6
RLCA 07
Now granule count is in bits 0-2 of A.
4FB7
ADD A,D 82
ADD sector count to get total sectors in extent.

Calculate which sector within the extent we need.

4FB8
INC E 1C
[LOOP START] INCrement granule counter E.
4FB9
SUB B 90
SUBtract sectors per granule from A.
4FBA
If NO CARRY (more sectors remain), [LOOP] continue counting.
4FBC
ADD A,B 80
ADD B back to get sector offset within granule.
4FBD
If Z FLAG (exact boundary), JUMP to allocation check.

Build bit mask for the specific sector within the granule.

4FBF
RLC C CB 01
[LOOP START] Rotate C left - shift bit mask.
4FC1
DEC B 05
DECrement B (sector counter).
4FC2
DEC A 3D
DECrement A (offset counter).
4FC3
If NZ (not at target sector), [LOOP] continue shifting.

4FC5H - Allocate/Access Granule

Handles allocation of new granules or access to existing ones. E contains granule number, C contains sector bit mask.

4FC5
PUSH HL E5
Save HL (extent pointer) onto the stack.
4FC6
XOR A AF
Clear A to zero (default success code).
4FC7
GOSUB to read directory sector - read GAT (Granule Allocation Table).
4FCA
If NZ FLAG (read error), JUMP to error exit.
4FCC
LD L,E 6B
Copy granule number from E to L - L indexes into GAT.
4FCD
POP DE D1
Pop extent pointer into DE.
4FCE
LD A,01H 3E 01
Load A with 01H - granule allocation marker.
4FD0
EX AF,AF' 08
Save allocation marker in alternate AF.
4FD1
JUMP to main allocation loop at 4FE5H.

4FD3H - Granule Allocation Loop

Main loop for finding and allocating free granules. Checks GAT entries and marks allocated sectors.

4FD3
LD A,(HL) 7E
[LOOP START] Fetch GAT byte at current granule position.
4FD4
AND C A1
AND with sector bit mask - test if sector is free.
4FD5
LD A,(DE) 1A
Fetch extent byte for comparison.
4FD6
If Z FLAG (sector free), JUMP to allocate sector.
4FD8
INC A 3C
INCrement extent byte.
4FD9
If NZ (not end of extent), JUMP to next extent.

Rotate to next sector bit position within granule.

4FDB
RLC C CB 01
Rotate C left - move to next sector bit.
4FDD
DECrement B and Jump if Not Zero - [LOOP] try next sector in granule.

Finished current granule. Move to next granule in GAT.

4FDF
INC L 2C
INCrement L to next granule in GAT.
4FE0
LD B,(IY+8FH) FD 46 8F
Reload B with sectors per granule from IY+8FH.
4FE3
LD C,01H 0E 01
Reset C to 01H - first sector bit mask.
4FE5
LD A,L 7D
Load A with current GAT index L.
4FE6
CP (IY+8BH) FD BE 8B
Compare against total granules at IY+8BH (440BH).
4FE9
If CARRY (more granules), [LOOP] continue searching.

Reached end of GAT. Check if this is first pass or retry.

4FEB
EX AF,AF' 08
Swap to get allocation marker from alternate AF.
4FEC
DEC A 3D
DECrement allocation marker.
4FED
LD L,A 6F
Save decremented value in L.
4FEE
If Z FLAG (first pass complete), [LOOP] restart from beginning.

Second pass failed - no free granules. Check for allocation mode.

4FF0
BIT 0,(IY+EBH) FD CB EB 46
Test bit 0 of system flag at IY+EBH (446BH).
4FF4
If NZ (special allocation mode), JUMP to cleanup.
4FF6
GOSUB to save current state at 508CH.
4FF9
LD A,1BH 3E 1B
Load A with error code 1BH (27 decimal - "Disk full").

4FFBH - Error Exit with Code

Common error exit point. Jumps to error processing routine.

4FFB
JUMP to error processing at 503DH.

4FFDH - Allocate Free Sector

Allocates a free sector found in the GAT. Marks it as used and updates extent information.

4FFD
INC A 3C
INCrement A (test extent byte).
4FFE
If NZ (not end marker), JUMP to update extent.

New extent needed. Store granule number and position.

5000
LD A,L 7D
Load A with granule number from L.
5001
LD (DE),A 12
Store granule number in extent.
5002
INC DE 13
INCrement DE to extent flags byte.
5003
LD A,(IY+8FH) FD 7E 8F
Fetch sectors per granule from IY+8FH.
5006
SUB B 90
SUBtract remaining sectors B to get used sectors.
5007
RRCA 0F
Rotate right to pack sector offset.
5008
RRCA 0F
Continue rotating.
5009
RRCA 0F
Sector offset now in bits 5-7 of A.
500A
DEC A 3D
DECrement A (adjust for 0-based counting).
500B
INC A 3C
INCrement A (may be undone by DEC if coming from different path).
500C
LD (DE),A 12
Store extent flags at (DE).
500D
DEC DE 1B
DECrement DE back to granule byte.
500E
LD A,(HL) 7E
Fetch current GAT byte.
500F
OR C B1
OR with sector bit mask - mark sector as allocated.
5010
LD (HL),A 77
Store updated GAT byte.
5011
EX (SP),HL E3
Exchange HL with stack - get extent count, save GAT pointer.
5012
DEC HL 2B
DECrement extent count.
5013
LD A,H 7C
Load A with high byte of count.
5014
OR L B5
OR with low byte - test if zero.
5015
EX (SP),HL E3
Exchange back - restore GAT pointer, save count.
5016
If NZ (more extents needed), [LOOP] continue allocation.

Allocation complete. Check system flags for special handling.

5018
LD A,(IY+EBH) FD 7E EB
Fetch system flags from IY+EBH (446BH).
501B
AND 03H E6 03
Mask with 03H - isolate bits 0-1.
501D
If NZ (special mode bits set), JUMP to cleanup.

Normal mode. Advance extent pointer for next allocation.

501F
EX (SP),HL E3
Exchange - get count from stack.
5020
INC HL 23
INCrement to advance past allocated extents.
5021
INC HL 23
Continue incrementing.
5022
INC HL 23
Advance by 3 bytes total.
5023
EX (SP),HL E3
Exchange back - save new pointer, restore HL.
5024
SET 0,(IY+EBH) FD CB EB C6
SET bit 0 at IY+EBH - mark allocation in progress.
5028
[LOOP] JUMP back to continue allocation process.

502AH - Cleanup After Allocation

Cleans up after granule allocation. Resets flags and writes updated directory.

502A
RES 0,(IY+EBH) FD CB EB 86
RESET bit 0 at IY+EBH - clear "allocation in progress" flag.
502E
GOSUB to save state - write updated GAT.
5031
POP AF F1
Pop saved AF from stack (cleanup).
5032
POP AF F1
Pop second saved AF (extent pointer cleanup).
5033
GOSUB to read directory entry - refresh directory data.

5036H - Validate File Status

Validates file status flags. Checks if file is properly opened and not marked for special handling.

5036
If NZ FLAG (previous error), JUMP to error processing.
5038
BIT 4,(HL) CB 66
Test bit 4 of status byte at (HL) - check for special flag.
503A
RET NZ C0
If NZ (flag set), RETURN with status.
503B
LD A,2CH 3E 2C
Load A with error code 2CH (44 decimal - "Invalid file status").

503DH - Error Processing and Exit

Processes errors and exits to the DOS error handler. Calls status update routine first.

503D
GOSUB to error status update routine at 4C20H.
5040
JUMP to DOS error exit routine at 49CDH.

5043H - Update Extent Entry

Updates an existing extent entry when adding sectors to a file.

5043
INC DE 13
INCrement DE to extent flags byte.
5044
LD A,(DE) 1A
Fetch current extent flags.
5045
INC A 3C
INCrement flags (test for FFH).
5046
AND 1FHAND 00011111 E6 1F
Mask with 1FH - isolate sector count bits.
5048
LD A,(DE) 1A
Reload original flags.
5049
If NZ (sector count not maxed), JUMP to update entry.
504B
DEC DE 1B
DECrement DE back to granule byte.

504CH - Move to Next Extent

Advances to the next extent entry in the file's extent list.

504C
INC DE 13
INCrement DE past current extent.
504D
INC DE 13
INCrement DE again (each extent is 2 bytes).
504E
LD A,(DE) 1A
Fetch first byte of next extent.
504F
INC A 3C
INCrement to test for FFH (end marker).
5050
If Z FLAG (end of extents), JUMP back to main loop.
5052
BIT 0,(IY+EBH) FD CB EB 46
Test bit 0 - allocation in progress flag.
5056
If NZ (allocation active), JUMP to cleanup.

Need to save current state and read next extent from directory.

5058
PUSH HL E5
Save HL (GAT pointer) onto stack.
5059
PUSH BC C5
Save BC (counters) onto stack.
505A
GOSUB to save state - write updated GAT.
505D
LD B,00H 06 00
Clear B (self-modifying: value at 505EH).
505F
LD L,B 68
Copy B to L.
5060
PUSH BC C5
Save BC onto stack.
5061
GOSUB to find/allocate granule at 50CFH.
5064
If NZ FLAG (error), JUMP to error exit.
5066
LD C,A 4F
Copy result to C.
5067
LD (HL),90H 36 90
Store 90H at (HL) - mark entry as allocated extent.
5069
INC HL 23
INCrement HL to next field.
506A
POP DE D1
Pop BC into DE.
506B
LD (HL),D 72
Store D at (HL).
506C
GOSUB to write directory at 50AEH.
506F
LD A,D 7A
Load A with D.
5070
GOSUB to refresh directory.
5073
ADD 1FH C6 1F
ADD 1FH (31) to A.
5075
LD L,A 6F
Store result in L.
5076
LD (HL),C 71
Store C at calculated position.
5077
DEC HL 2B
DECrement HL.
5078
LD (HL),FEH 36 FE
Store FEH - extent end marker.
507A
GOSUB to write directory.
507D
LD A,C 79
Load A with C.
507E
LD (505EH),A 32 5E 50
Store at 505EH.
5081
GOSUB to refresh directory.
5084
GOSUB to prepare extent buffer.
5087
POP BC C1
Restore BC from stack.
5088
POP DE D1
Restore DE from stack.
5089
JUMP back to allocation routine to continue.

508CH - Save State to Directory

Saves current file state (extent information) back to the directory on disk.

508C
GOSUB to write directory at 50AEH.
508F
LD A,(505EH) 3A 5E 50
Fetch current extent position from 505EH.
5092
GOSUB to refresh directory.
5095
ADD 16H C6 16
ADD 16H (22) - offset to extent area in directory entry.
5097
BIT 7,(HL) CB 7E
Test bit 7 of directory entry for status flag.
5099
LD L,A 6F
Store calculated offset in L.
509A
PUSH HL E5
Save HL onto stack.
509B
PUSH IX DD E5
Save IX (FCB pointer) onto stack.
509D
POP HL E1
Pop IX value into HL.
509E
LD BC,000EH 01 0E 00
Load BC with 14 - offset to extent area in FCB.
50A1
ADD HL,BC 09
ADD offset - HL now points to FCB extent area.
50A2
LD DE,51ADH 11 AD 51
Load DE with 51ADH - work buffer address.
50A5
PUSH DE D5
Save DE onto stack.
50A6
If Z FLAG (from BIT 7 test), GOSUB to copy extent info.
50A9
POP HL E1
Restore DE into HL (work buffer address).
50AA
POP DE D1
Restore original HL into DE (directory pointer).
50AB
GOSUB to copy 8 bytes - copy extent from buffer to directory.

50AEH - Write Directory Sector

Writes the current directory sector to disk. Checks for errors and handles error exit.

50AE
GOSUB to write directory sector at 491FH.
50B1
RET Z C8
If Z FLAG (write successful), RETURN normally.
50B2
JUMP to error exit if write failed.

50B4H - Prepare Extent Buffer

Prepares the extent buffer area for file operations. Copies extent data and initializes pointers.

50B4
ADD 16H C6 16
ADD 16H (22) to A - offset to extent area.
50B6
LD L,A 6F
Store in L - HL now points to extent area.
50B7
LD DE,51ADH 11 AD 51
Load DE with 51ADH - destination buffer.
50BA
GOSUB to copy 8 bytes - copy extent to work buffer.
50BD
EX DE,HL EB
Exchange DE and HL.
50BE
LD (HL),FEH 36 FE
Store FEH - end marker for extent list.
50C0
RRCA 0F
Rotate A right.
50C1
LD B,A 47
Copy to B.
50C2
DEC HL 2B
[LOOP START] DECrement HL.
50C3
DEC HL 2B
DECrement HL again.
50C4
LD A,(HL) 7E
Fetch byte from buffer.
50C5
INC A 3C
INCrement to test for FFH.
50C6
RET NZ C0
If NZ (not end marker), RETURN.
50C7
DECrement B and Jump if Not Zero - [LOOP] scan buffer.
50C9
RET C9
RETURN when done.