Percom DoubleDOS 4.24 for the Model I - SYS3/SYS Disassembled
Page Customization
Page Index
SYS3/SYS
Other Navigation
Introduction/Summary
Percom DoubleDOS 4.24 SYS3/SYS Disassembly (Model I)
SYS3/SYS is the overlay of DoubleDOS (DBLDOS in Percom's manual) that closes and kills files. It is overlay 5 (directory record 05H): the overlay dispatcher of SYS0/SYS loads it at 4E00H when a request code with the low four bits 5 is given and calls its transfer address 4E00H with the code in Register A.
The file is 786 bytes: a name record, the copyright record of 169 bytes, one load block, 4E00H-504EH (591 bytes), and the transfer address 4E00H. Every loaded byte is on exactly one row below. SYS3/SYS is the same in DoubleDOS 4.20, 4.23 (all three sets) and 4.24.
Load Map
| Addresses | Contents |
|---|---|
| 4E00H-4E0CH | The dispatcher of the request codes 95H and A5H (4E00H) |
| 4E0DH-4E95H | Close a file: the end of file into the directory entry, the granules counted (4E0DH) |
| 4E96H-4F1CH | Give back the granules beyond the end of file, and free an extra entry left empty (4E96H) |
| 4F1DH-4F71H | Put the specification back in the FCB (4F1DH) |
| 4F72H-4FCDH | Kill a file (4F72H) |
| 4FCEH-4FFCH | Free the granules of an extent, reset a bit (4FCEH) |
| 4FFDH-504EH | Read and write the hash index table at 5100H, and small helpers (4FFDH) |
The Request Codes
| Code | Entry in SYS0/SYS, job and registers |
|---|---|
| 95H | 4428H, close the file of the open FCB at Register Pair DE (BASIC/CMD, COPY/CMD, SYS6/SYS): 4E0DH |
| A5H | 442CH, kill the file of the open FCB at Register Pair DE (BASIC/CMD, SYS6/SYS): 4F72H |
How a File Is Closed
| Step | What the code does |
|---|---|
| 1 | A changed buffer in byte mode is written through SYS0/SYS's 4878H (4E10H). |
| 2 | The end of file sector of the FCB is made the number of sectors again (5022H), and the end of file offset and the number of sectors are written into the directory entry, +03H and +14H-+15H, when they differ (4E1DH). |
| 3 | The granules of all the file's entries are counted (4E54H) and compared with the number of sectors divided by 5, rounded up (4E77H). |
| 4 | The granules beyond the end of file are given back one at a time from the last extent, through the GAT at 4D00H (4E96H); an extra entry whose extents are all given back is freed and the entry before it ends its extents with FFH again. |
| 5 | The entry and the GAT are written, and the FCB is written over with NAME/EXT:D and 03H (4F1DH). |
Differences From the Manual
Percom's manual has nothing on closing or killing files; it refers to the TRSDOS manual for the commands.
Notes
The result of the buffer write at 4E10H is not tested: a write error is lost and the close goes on.
Kill tests the access level of the FCB (levels 0 and 1 allow it, 4F7AH), but SYS2/SYS opens every file with level 0, so every open file can be killed.
After the close, 4F1DH reads the sector of Register B again when it is not the sector of the file's first entry. Register B is then the record of the entry last read, which for a file with an extra entry in another sector is that entry, so the bytes copied as the name are those at the first entry's place in the extra entry's sector. The password is never put back.
SYS3/SYS reads the hash index table into 5100H, past its own end, because the GAT is at 4D00H during a kill and while granules are given back.
The byte at 4E95H after the jump to 5047H is never reached. Read as an instruction it is RET NZ; 5047H runs CALL 4AF0H and RET NZ before the INC DE that 4E96H needs.
The operands at 4EB0H, 4F6AH and 4FFBH are written while SYS3/SYS runs (the Variables below).
Variables
SYS3/SYS's Own Bytes
| Address Size | Contents |
|---|---|
| 4EB0H 1 byte | Blocks After the Extent's Block Operand of ADD A,nn at 4EAFH, stored by 4EA6H. |
| 4F6AH 1 byte | Drive Digit Operand of LD A,nn at 4F69H, stored by 4F2EH. |
| 4FFBH 1 byte | Second Byte of RES n,B Stored by 4FF7H. |
Memory Outside SYS3/SYS
| Address Size | Contents |
|---|---|
| 4200H-42FFH 256 bytes | Sector Buffer The directory sectors read by 4AC1H and written by 4AD6H. |
| 4304H-4307H 4 bytes | Directory Blocks Of drives 0-3, read through 4B55H (503DH). |
| 4D00H-4DFFH 256 bytes | GAT Read by 4AF0H, written by 4B03H; one byte a block, one bit a granule. |
| 5100H-51FFH 256 bytes | Hash Index Table Read by 4FFDH, written by 500CH. |
The Directory Entry as SYS3/SYS Changes It
| Offset | Contents |
|---|---|
| +00H | The attribute: 00H for a freed entry (4EDBH, 4FAAH); bit 7 marks an extra entry |
| +01H | In an extra entry, the record of the entry before it (4EF5H) |
| +03H | The end of file offset (4E40H) |
| +14H-+15H | The number of sectors (4E48H) |
| +16H-+1FH | Five extents, block and granule byte; FEH and a record links to an extra entry, FFH ends them |
Error Codes Returned by SYS3/SYS
| Code | Meaning (where set) |
|---|---|
| 11H, 12H | Directory read, directory write error (from 4AC1H, 4AD6H) |
| 14H, 15H | GAT read, GAT write error (from 4AF0H, 4B03H) |
| 16H, 17H | Hash index table read, write error (5009H, 5018H) |
| 25H | The access level does not allow a kill (4F7EH) |
| 26H | The FCB is not open (from 4892H) |
Outside Routines
| Address | Use |
|---|---|
| 45CFH | SYS0/SYS: Write a Directory Sector and Read It Back 5014H. |
| 4878H | SYS0/SYS: Write the Buffer Back When Changed 4E10H. |
| 4892H | SYS0/SYS: The Common Start of the File Routines 4E0DH, 4F72H. |
| 4AC1H | SYS0/SYS: Read a Directory Record 4E6DH, 4EF9H, 4F23H, 4F90H, 5030H. |
| 4AD6H | SYS0/SYS: Write a Directory Record 4E4FH, 4EDDH, 4F15H, 4FACH, 5042H. |
| 4AF0H, 4B03H | SYS0/SYS: Read, Write the GAT 4F8CH, 5047H; 4F0CH, 4F19H, 4FBBH. |
| 4B35H | SYS0/SYS: Read a Directory Sector 5005H. |
| 4B55H | SYS0/SYS: The Directory Block of a Drive 503DH. |
| 4B84H | SYS0/SYS: Divide 501BH. |
Disassembly
4E00H - The Request Code Dispatcher
The transfer address of SYS3/SYS. The dispatcher of SYS0/SYS (4BA2H) calls it with the request code in Register A and the FCB in Register Pair DE: bits 6-4 choose the job, the low four bits (5) name SYS3/SYS. 95H closes a file, A5H kills it.
4E0DH - Close a File
Reached for request code 95H (4428H) with Register Pair DE the FCB. A changed buffer is written, the end of file is put in the directory entry when it differs, granules beyond the end of file are given back to the GAT (and an extra entry left with no extents is freed), and the FCB is written over with the file's specification as text, NAME/EXT:D, which also marks it closed. Returns Register A 00H and the Z FLAG, or the NZ FLAG and an error code: 26H the FCB is not open, 11H, 12H, 14H, 15H, 16H or 17H a read or write error.
4E96H - Give Back the Last Granule
Entered from 4F13H with Register Pair HL the granule byte of the last extent and Register Pair DE the granules still to give back. The last granule of the extent is marked free in the GAT at 4D00H and the extent's count made one less; an extent left with no granule becomes FFH FFH and the extent before it is the last. When an extra entry is left with no extent it is freed, its place in the hash index table cleared, and the entry before it ended with FFH where it had FEH.
4F1DH - Put the Specification Back in the FCB
Reached when the directory and the GAT are up to date. The name and extension of the file's first entry and its drive are written into the FCB as NAME/EXT:D and 03H; the password is not. The first byte, a letter, clears bit 7 of FCB+00H, so the FCB is no longer open, and it can be opened again as it is. When the file has an extra entry in another sector than its first, the sector read is that of Register B, the last entry read, and the name copied is the bytes at the first entry's place in that sector.
4F72H - Kill a File
Reached for request code A5H (442CH) with Register Pair DE the FCB of an open file. The access level must be 0 or 1. The granules of every extent of the file's first entry and of its extra entries are marked free in the GAT, each entry is freed (attribute 00H) and its place in the hash index table cleared; then the GAT and the hash index table are written and the 32 bytes of the FCB cleared. Returns Register A 00H and the Z FLAG, or the NZ FLAG and an error code: 26H the FCB is not open, 25H access denied, 11H, 12H, 14H, 15H, 16H or 17H a read or write error.
4FCEH - Free the Granules of an Extent
Called from 4FA1H with Register E the block and Register D the granule byte of an extent (bits 7-5 the first granule in the block, bits 4-0 the count less 1). Each granule's bit is reset in the GAT at 4D00H, two granules a block.
4FF0H - Reset a Bit of Register B
Called with Register B a GAT byte and Register A the number of the bit (the low three bits). The routine writes the instruction RES n,B at 4FFAH and runs it.
4FFDH - Read the Hash Index Table
Called with Register C the drive. Sector 1 of the drive's directory block, the hash index table, is read into 5100H, after SYS3/SYS, since the GAT is at 4D00H. 5033H keeps Register Pairs BC and DE for it. Returns the Z FLAG, or error 16H.
500CH - Write the Hash Index Table
Called with Register C the drive. The table at 5100H is written back as sector 1 of the drive's directory block with the deleted data mark and read back. Returns the Z FLAG, or error 17H.
501BH - Divide, Rounded Down When Exact
Called from 4E80H with Register Pair HL the number of sectors and Register A 05H. Returns Register Pair HL the quotient, or the quotient less 1 when the remainder is 0, so that one more is the number of granules needed.
5022H - The Number of Sectors, Then Read the Entry
Called from 4E19H with Register B the record and Register C the drive. FCB+0CH-+0DH, the end of file sector, is made the number of sectors again when the last sector is partly filled (SYS2/SYS made it one less, 5180H there). Then the directory entry is read.
5033H - Keep Register Pairs BC and DE Around the Rest of a Routine
Called as the first instruction of 4FFDH and 500CH. The return address, the rest of the routine, is taken off the stack; Register Pairs DE and BC are saved; the rest of the routine is called through 4B55H, which loads Register D with the drive's directory block; when it returns, Register Pairs BC and DE are restored and 5033H returns to the routine's caller.
5040H - Step Back and Write the Entry
Called from 4F08H with Register Pair HL entry +1EH of the entry before a freed extra entry. Register Pair HL is made entry +1DH, the granule byte of that entry's last extent, and the sector is written.
5047H - Read the GAT, Then Give Back Granules
Reached from 4E92H with Register Pair HL the granule byte of the last extent and Register Pair DE the granules to give back.