From d830f0539862af2b9081d5d25fd4a7331b15ad14 Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Tue, 21 Apr 2026 18:36:19 +0200 Subject: [PATCH 1/2] 21.40: FlashTek pointer is meant to be a note not BUG --- .../INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt index 99b4a2dcf..e8720fba4 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt @@ -21,11 +21,11 @@ Notes: if CX is zero, no data is written, and the file is truncated or the "extended size" flag in order to expand the file beyond 2GB; otherwise the write will fail with error code 0005h (access denied) the usual cause for AX < CX on return is a full disk + under the FlashTek X-32 DOS extender, the pointer is in DS:EDX BUGS: a write of zero bytes will appear to succeed when it actually failed if the write is extending the file and there is not enough disk space for the expanded file (DOS 5.0-6.0); one should therefore check whether the file was in fact extended by seeking to 0 bytes from the end of the file (INT 21/AX=4202h with CX:Dx=0000h:0000h) - under the FlashTek X-32 DOS extender, the pointer is in DS:EDX SeeAlso: AH=28h,AH=3Fh"DOS",AH=93h,INT 2F/AX=1109h From c48763198a82a491cee15002ed2eb1dc7c7ab480 Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Tue, 21 Apr 2026 22:38:59 +0200 Subject: [PATCH 2/2] several updates to 21.31, .3F, .40, .50, .51, .56, .59 --- ...2131 DOS 2 TERMINATE AND STAY RESIDENT.txt | 8 ++++-- ...3F DOS 2 READ READ FROM FILE OR DEVICE.txt | 3 +-- ...40 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt | 25 +++++++++++++++++-- ...SET CURRENT PROCESS ID SET PSP ADDRESS.txt | 14 ++++++++++- ...GET CURRENT PROCESS ID GET PSP ADDRESS.txt | 7 +++++- .../INT 2156 DOS 2 RENAME RENAME FILE.txt | 8 +++--- ...T 2158 DOS 5 GET OR SET UMB LINK STATE.txt | 4 ++- ... DOS 30 GET EXTENDED ERROR INFORMATION.txt | 8 +++--- ... internal GET DOS SWAPPABLE DATA AREAS.txt | 2 +- 9 files changed, 62 insertions(+), 17 deletions(-) diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 2131 DOS 2 TERMINATE AND STAY RESIDENT.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 2131 DOS 2 TERMINATE AND STAY RESIDENT.txt index 7bf6c62a5..963869b38 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 2131 DOS 2 TERMINATE AND STAY RESIDENT.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 2131 DOS 2 TERMINATE AND STAY RESIDENT.txt @@ -12,8 +12,12 @@ Return: never Notes: the value in DX only affects the memory block containing the PSP; additional memory such as the environment block and memory allocated via AH=48h is not affected + like AH=4Ah if DX indicates to grow the block, and there is not + enough free memory, the block is grown to the maximum size. + likewise, if the requested size can be fulfilled then the owner + of the PSP's MCB is rewritten to the terminating PSP. the minimum number of paragraphs which will remain resident is 11h - for DOS 2.x and 06h for DOS 3.0+ + for DOS 2.x and 06h for DOS 3.0+ and FreeDOS most TSRs can save some memory by releasing their environment block before terminating (see #01378 at AH=26h,AH=49h). to aid tools that want to inspect resident processes, the PSP field that refers @@ -21,7 +25,7 @@ Notes: the value in DX only affects the memory block containing the PSP; any open files remain open, so one should close any files which will not be used before going resident; to access a file which is left open from the TSR, one must switch PSP segments first (see AH=50h) - or patch the Job File Table associated with another PSP + or patch the PHT / Job File Table associated with another PSP (TSRs that do not need their file handles while resident frequently fail to close them; running such a TSR with for example > NUL output redirection will leak an SFT entry.) diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 213F DOS 2 READ READ FROM FILE OR DEVICE.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 213F DOS 2 READ READ FROM FILE OR DEVICE.txt index bae60d594..cd967feb4 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 213F DOS 2 READ READ FROM FILE OR DEVICE.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 213F DOS 2 READ READ FROM FILE OR DEVICE.txt @@ -16,11 +16,10 @@ Return: CF clear if successful Notes: data is read beginning at current file position, and the file position is updated after a successful read the returned AX may be smaller than the request in CX if a partial - read occurred + read occurred, generally indicating that EOF has been reached. if reading from CON, read stops at first CR under the FlashTek X-32 DOS extender, the pointer is in DS:EDX BUGS: Novell NETX.EXE v3.26 and 3.31 do not set CF if the read fails due to a record lock (see AH=5Ch), though it does return AX = 0005h; this has been documented by Novell SeeAlso: AH=27h,AH=40h,AH=93h,INT 2F/AX=1108h,INT 2F/AX=1229h - diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt index e8720fba4..05a6eedbe 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 2140 DOS 2 WRITE WRITE TO FILE OR DEVICE.txt @@ -21,11 +21,32 @@ Notes: if CX is zero, no data is written, and the file is truncated or the "extended size" flag in order to expand the file beyond 2GB; otherwise the write will fail with error code 0005h (access denied) the usual cause for AX < CX on return is a full disk + when a file must be extended (it was shorter than the current seek + plus input CX) but there isn't enough disk space free, FreeDOS will + allocate all remaining free clusters to the file, and may do a + partial write. it may return AX = 0000h or 0 < AX < CX in this case. + MS-DOS instead always returns AX = 0000h with the file size + preserved from what it was prior to this call (no partial write and + not even extending to the file seek prior to this call). + a portable check that a write succeeded in full should first check + that the returned CF is clear, then check that the returned AX == CX + (only applicable if CX was nonzero, see BUGS below). + dosemu2 mfs redirected drives return error 0005h if CX = 0000h and + the file cannot grow to the indicated size, with the prior file size + preserved. non-zero writes are passed to the Linux write syscall. under the FlashTek X-32 DOS extender, the pointer is in DS:EDX BUGS: a write of zero bytes will appear to succeed when it actually failed if the write is extending the file and there is not enough disk space for the expanded file (DOS 5.0-6.0); one should therefore check whether the file was in fact extended by seeking to 0 bytes from - the end of the file (INT 21/AX=4202h with CX:Dx=0000h:0000h) + the end of the file (INT 21/AX=4202h with CX:DX=0000h:0000h) + FreeDOS kernel bug #241 concerns seeking to a position larger than the + disk free space, then writing using this function. it will allocate + all free clusters to the file but fail to update the file size field. + MS-DOS v4 and v5 (at least) will truncate the "amount of clusters to + allocate" to a 16-bit quantity so if trying to allocate eg 256 MiB + on a FAT12 1440 KiB diskette (512 BpC) the needed amount is truncated + and the file is corrupted. this bug does not exist on MS-DOS v7.10, + presumably because it calculates the amount as a 32-bit number as it + needs to support large values for FAT32 drives. SeeAlso: AH=28h,AH=3Fh"DOS",AH=93h,INT 2F/AX=1109h - diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 2150 DOS 2 internal SET CURRENT PROCESS ID SET PSP ADDRESS.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 2150 DOS 2 internal SET CURRENT PROCESS ID SET PSP ADDRESS.txt index 729d5dda7..8b031eaec 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 2150 DOS 2 internal SET CURRENT PROCESS ID SET PSP ADDRESS.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 2150 DOS 2 internal SET CURRENT PROCESS ID SET PSP ADDRESS.txt @@ -9,6 +9,9 @@ INT 21 - DOS 2+ internal - SET CURRENT PROCESS ID (SET PSP ADDRESS) BX = segment of PSP for new process Notes: DOS uses the current PSP address to determine which processes own files and memory; it corresponds to process identifiers used by other OSs + some of the code for process termination uses the current PSP to + find the terminating process. on MS-DOS INT 20 and INT 21/AH=00h may + use the CS of their caller for part of their code however. under DOS 2.x, this function cannot be invoked inside an INT 28h handler without setting the Critical Error flag under MS-DOS 3.0+ and DR DOS 3.41+, this function does not use any of @@ -22,5 +25,14 @@ Notes: DOS uses the current PSP address to determine which processes own files invalid addresses this function is supported by the OS/2 compatibility box this call was undocumented prior to the release of DOS 5.0 + FreeDOS Debug/X, lDebug/X, and Enhanced Debug/X may directly write + the PSP field in the SDA (offset 10h in #01687 at AX=5D05h). + lDebug checks for this field matching its PSP initially and will + disable the direct SDA access on a mismatch. lDebug also uses the + INT 31 segment to track DOSDATA relocations (see INT 2F/AX=1203h). +BUGS: amuramatsu's fork of emu2 prior to 2026-01-02 would keep an internal + variable indicating the current PSP, with the SDA field only + reflecting changes to the variable. writing the SDA field without + using this function would fail to set the internal variable. SeeAlso: AH=26h,AH=51h,AH=62h - + diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 2151 DOS 2 internal GET CURRENT PROCESS ID GET PSP ADDRESS.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 2151 DOS 2 internal GET CURRENT PROCESS ID GET PSP ADDRESS.txt index dd29abbc9..09de13613 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 2151 DOS 2 internal GET CURRENT PROCESS ID GET PSP ADDRESS.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 2151 DOS 2 internal GET CURRENT PROCESS ID GET PSP ADDRESS.txt @@ -17,5 +17,10 @@ Notes: DOS uses the current PSP address to determine which processes own files supported by OS/2 compatibility box identical to the documented AH=62h this call was undocumented prior to the release of DOS 5.0 + FreeDOS Debug/X, lDebug/X, and Enhanced Debug/X may directly read + the PSP field in the SDA (offset 10h in #01687 at AX=5D05h). + lDebug checks for this field matching its PSP initially and will + disable the direct SDA access on a mismatch. lDebug also uses the + INT 31 segment to track DOSDATA relocations (see INT 2F/AX=1203h). SeeAlso: AH=26h,AH=50h,AH=62h - + diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 2156 DOS 2 RENAME RENAME FILE.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 2156 DOS 2 RENAME RENAME FILE.txt index ce0298c8f..f6e03d76a 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 2156 DOS 2 RENAME RENAME FILE.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 2156 DOS 2 RENAME RENAME FILE.txt @@ -12,12 +12,13 @@ INT 21 - DOS 2+ - "RENAME" - RENAME FILE Return: CF clear if successful CF set on error AX = error code (02h,03h,05h,11h) (see #01680) -Notes: allows move between directories on same logical volume +Notes: allows move between directories on same logical volume, however + command.com's REN command doesn't support this. this function does not set the archive attribute (see #01420 at AX=4301h), which results in incremental backups not backing up the file under its new name open files should not be renamed - (DOS 2.x only) this function renames file by creating a new directory + (DOS 2.x only) this function renames a file by creating a new directory entry with the new name, then marking the old entry deleted (DOS 3.0+) allows renaming of directories (DOS 3.1+) wildcards are allowed if invoked via AX=5D00h, in which case @@ -36,4 +37,5 @@ BUGS: (DR DOS 3.41) when invoked via AX=5D00h, this function will generate which can only be removed with a sector editor SeeAlso: AH=17h,AX=4301h,AX=43FFh/BP=5053h,AX=5D00h,AH=60h,AX=7156h SeeAlso: AX=F257h/SF=04h - + + diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 5 GET OR SET UMB LINK STATE.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 5 GET OR SET UMB LINK STATE.txt index 6f35f479d..8304f9bb2 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 5 GET OR SET UMB LINK STATE.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 5 GET OR SET UMB LINK STATE.txt @@ -27,7 +27,9 @@ Notes: a program which changes the UMB link state should restore it before allocating UMBs with AX=5801h as well enabling the UMB link will patch the last Low Memory Area MCB to hold an 'M' letter to indicate it is not the last MCB, likewise - disabling the UMB link will patch the last LMCB's letter to 'Z' + disabling the UMB link will patch the last LMCB's letter to 'Z'. + (the last LMCB is the MCB before the first UMCB. the latter is + typically at segment 9FFFh for a 640 KiB Low Memory Area.) DOS keeps track of the UMB link state in an internal variable too if the extended allocation strategy mask 100h is set (see #01679 at AH=58h), lDOS can use UMBs even with the UMB link disabled. diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 2159BX0000 DOS 30 GET EXTENDED ERROR INFORMATION.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 2159BX0000 DOS 30 GET EXTENDED ERROR INFORMATION.txt index c6bbf8d00..e662bc015 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 2159BX0000 DOS 30 GET EXTENDED ERROR INFORMATION.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 2159BX0000 DOS 30 GET EXTENDED ERROR INFORMATION.txt @@ -34,15 +34,15 @@ Values for DOS extended error code: 07h (7) memory control block destroyed 08h (8) insufficient memory 09h (9) memory block address invalid - 0Ah (10) environment invalid (usually >32K in length) - 0Bh (11) format invalid + 0Ah (10) environment invalid (usually >32 KiB in length) + 0Bh (11) format invalid (AH=4Bh) 0Ch (12) access code invalid 0Dh (13) data invalid 0Eh (14) reserved 0Eh (14) (PTS-DOS 6.51+, S/DOS 1.0+) fixup overflow 0Fh (15) invalid drive 10h (16) attempted to remove current directory - 11h (17) not same device + 11h (17) not same device (AH=56h) 12h (18) no more files ---DOS 3.0+ (INT 24 errors)--- 13h (19) disk write-protected @@ -297,4 +297,4 @@ Values for DOS Error Locus: 04h (PTS-DOS 6.51+ & S/DOS 1.0+) character device 05h memory related SeeAlso: #01680,#01682,#01683 - + diff --git a/source/Interrupt List/INT 21 DOS Function Calls/INT 215D0B DOS 4x only internal GET DOS SWAPPABLE DATA AREAS.txt b/source/Interrupt List/INT 21 DOS Function Calls/INT 215D0B DOS 4x only internal GET DOS SWAPPABLE DATA AREAS.txt index 9e5265690..93c7f0014 100644 --- a/source/Interrupt List/INT 21 DOS Function Calls/INT 215D0B DOS 4x only internal GET DOS SWAPPABLE DATA AREAS.txt +++ b/source/Interrupt List/INT 21 DOS Function Calls/INT 215D0B DOS 4x only internal GET DOS SWAPPABLE DATA AREAS.txt @@ -207,7 +207,7 @@ Notes: the above data is not actually part of the SDA, and is much more likely 2E7h WORD high word of 32-bit sector number, or temp data buffer size from disk buffer 2E9h WORD "sda_OffsetMagicPatch" -2EBh BYTE disk full on >32M partition when set to 01h +2EBh BYTE disk full when set to 01h, marked with ">32mb" comment 2ECh WORD stores DS during call to [List-of-Lists + 37h] 2EEh WORD temporary storage (various uses) 2F0h BYTE storage for drive error