UNPKG

@nataliapc/mcp-openmsx

Version:

Model context protocol server for openMSX automation and control

698 lines (481 loc) 113 kB
# MSX-DOS 2 Function Specification The advanced disk operating system for MSX 2 computers # CONTENTS * [Introduction](#introduction) * [List of functions](#list-of-functions) * [Function By Function Definitions](#function-by-function-definitions) This manual describes in detail the MSX-DOS function calls provided by MSX-DOS version 2.20 ## INTRODUCTION This document describes in detail each of the MSX-DOS 2 function calls. It should be read in conjunction with the "Program Interface specification" which describes system features such as file handles, fileinfo blocks and environment strings in general terms. There are two ways of doing MSX-DOS function calls, reflecting the two different environments (MSX-DOS and disk BASIC) in which the system can run. Transient programs running in the MSX-DOS environment must access the functions with a `CALL 00005h` instruction. Disk BASIC and other MSX programs running in the disk BASIC environment (usually executing from ROM) must access the system via a `CALL 0F37Dh` instruction. There are some limitations when calling the system via `0F37Dh`, particularly to do with error handling and abort routines. Also no parameters may be passed in page-1, unless they are in the master disk ROM (as they will be for disk BASIC) since the master disk ROM will be paged into page-1 when such a function call is made. The individual function descriptions mention the differences for particular functions. ## LIST OF FUNCTIONS Below there is a complete list of the functions calls. `CPM` indicates that the function is compatible with the equivalent CP/M 2.2 function, `MSX1` indicates compatibility with MSX-DOS version 1, and `NEW` indicates a function which is new to this system. An asterisk (`*`) indicates that the function may be safely called from a user disk error routine (see function `64h` and function `70h`). ### List of MSX-DOS 2 Function Calls ``` CPM MSX1 00h - [Program terminate](#_TERM0) CPM MSX1* 01h - [Console input](#_CONIN) CPM MSX1* 02h - [Console output](#_CONOUT) CPM MSX1* 03h - [Auxiliary input](#_AUXIN) CPM MSX1* 04h - [Auxiliary output](#_AUXOUT) CPM MSX1* 05h - [Printer output](#_LSTOUT) CPM MSX1* 06h - [Direct console I/O](#_DIRIO) MSX1* 07h - [Direct console input](#_DIRIN) MSX1* 08h - [Console input without echo](#_INNOE) CPM MSX1* 09h - [String output](#_STROUT) CPM MSX1* 0Ah - [Buffered line input](#_BUFIN) CPM MSX1* 0Bh - [Console status](#_CONST) CPM MSX1* 0Ch - [Return version number](#_CPMVER) CPM MSX1 0Dh - [Disk reset](#_DSKRST) CPM MSX1 0Eh - [Select disk](#_SELDSK) CPM MSX1 0Fh - [Open file (FCB)](#_FOPEN) CPM MSX1 10h - [Close file (FCB)](#_FCLOSE) CPM MSX1 11h - [Search for first entry (FCB)](#_SFIRST) CPM MSX1 12h - [Search for next entry (FCB)](#_SNEXT) CPM MSX1 13h - [Delete file (FCB)](#_FDEL) CPM MSX1 14h - [Sequential read (FCB)](#_RDSEQ) CPM MSX1 15h - [Sequential write FCB)](#_WRSEQ) CPM MSX1 16h - [Create file (FCB)](#_FMAKE) CPM MSX1 17h - [Rename file (FCB)](#_FREN) CPM MSX1* 18h - [Get login vector](#_LOGIN) CPM MSX1* 19h - [Get current drive](#_CURDRV) CPM MSX1 1Ah - [Set disk transfer address](#_SETDTA) MSX1 1Bh - [Get allocation information](#_ALLOC) 1Ch - Unused 1Dh - Unused 1Eh - Unused 1Fh - Unused 20h - Unused CPM MSX1 21h - [Random read (FCB)](#_RDRND) CPM MSX1 22h - [Random write(FCB)](#_WRRND) CPM MSX1 23h - [Get file size (FCB)](#_FSIZE) CPM MSX1 24h - [Set random record (FCB)](#_SETRND) 25h - Unused MSX1 26h - [Random block write (FCB)](#_WRBLK) MSX1 27h - [Random block read (FCB)](#_RDBLK) CPM MSX1 28h - [Random write with zero fill (FCB)](#_WRZER) 29h - Unused MSX1* 2Ah - [Get date](#_GDATE) MSX1* 2Bh - [Set date](#_SDATE) MSX1* 2Ch - [Get time](#_GTIME) MSX1* 2Dh - [Set time](#_STIME) MSX1* 2Eh - [Set/reset verify flag](#_VERIFY) MSX1* 2Fh - [Absolute sector read](#_RDABS) MSX1* 30h - [Absolute sector write](#_WRABS) NEW* 31h - [Get disk parameters](#_DPARM) ``` ``` 32h - \ . . \ Unused . . / 3Fh - / ``` ``` NEW 40h - [Find first entry](#_FFIRST) NEW 41h - [Find next entry](#_FNEXT) NEW 42h - [Find new entry](#_FNEW) NEW 43h - [Open file handle](#_OPEN) NEW 44h - [Create file handle](#_CREATE) NEW 45h - [Close file handle](#_CLOSE) NEW 46h - [Ensure file handle](#_ENSURE) NEW 47h - [Duplicate file handle](#_DUP) NEW 48h - [Read from file handle](#_READ) NEW 49h - [Write to file handle](#_WRITE) NEW 4Ah - [Move file handle pointer](#_SEEK) NEW 4Bh - [I/O control for devices](#_IOCTL) NEW 4Ch - [Test file handle](#_HTEST) NEW 4Dh - [Delete file or subdirectory](#_DELETE) NEW 4Eh - [Rename file or subdirectory](#_RENAME) NEW 4Fh - [Move file or subdirectory](#_MOVE) NEW 50h - [Get/set file attributes](#_ATTR) NEW 51h - [Get/set file date and time](#_FTIME) NEW 52h - [Delete file handle](#_HDELETE) NEW 53h - [Rename file handle](#_HRENAME) NEW 54h - [Move file handle](#_HMOVE) NEW 55h - [Get/set file handle attributes](#_HATTR) NEW 56h - [Get/set file handle date and time](#_HFTIME) NEW * 57h - [Get disk transfer address](#_GETDTA) NEW * 58h - [Get verify flag setting](#_GETVFY) NEW 59h - [Get current directory](#_GETCD) NEW 5Ah - [Change current directory](#_CHDIR) NEW 5Bh - [Parse pathname](#_PARSE) NEW 5Ch - [Parse filename](#_PFILE) NEW * 5Dh - [Check character](#_CHKCHR) NEW 5Eh - [Get whole path string](#_WPATH) NEW 5Fh - [Flush disk buffers](#_FLUSH) NEW 60h - [Fork a child process](#_FORK) NEW 61h - [Rejoin parent process](#_JOIN) NEW 62h - [Terminate with error code](#_TERM) NEW 63h - [Define abort exit routine](#_DEFAB) NEW 64h - [Define disk error handler routine](#_DEFER) NEW * 65h - [Get previous error code](#_ERROR) NEW * 66h - [Explain error code](#_EXPLAIN) NEW 67h - [Format a disk](#_FORMAT) NEW 68h - [Create or destroy RAM disk](#_RAMD) NEW 69h - [Allocate sector buffers](#_BUFFER) NEW * 6Ah - [Logical drive assignment](#_ASSIGN) NEW * 6Bh - [Get environment item](#_GENV) NEW * 6Ch - [Set environment item](#_SENV) NEW * 6Dh - [Find environment item](#_FENV) NEW * 6Eh - [Get/set disk check status](#_DSKCHK) NEW * 6Fh - [Get MSX-DOS version number](#_DOSVER) NEW * 70h - [Get/set redirection status](#_REDIR) ``` ## FUNCTION BY FUNCTION DEFINITIONS Below are detailed descriptions of each of the MSX-DOS functions including both the old and new ones. The names in brackets after the function numbers are the public labels for the function codes which are defined in "CODES.MAC". Programs should use these names whenever possible. Many of the functions below 40h return an error flag rather than an error code. If the error flag is set then the actual error code indicating the cause of the error can be obtained by the "get previous error code" function (function 65h). All of the functions above 40h return an error code in register A. The "Program Interface Specification" document describes the general errors which can be returned from many of the functions. The individual function specifications here describe the main error conditions which are specific to particular functions. Note that many of the function calls which modify the information on a disk do not automatically flush disk buffers and so the disk is not necessarily correctly updated immediately after the function call is made. Such calls include all types of "create", "write", "delete", "rename", "change file attributes" and "change file date and time" function calls. The only functions which always flush disk buffers are "flush buffers", "close" and "ensure". After these operations the disk will always be correctly updated. ### 3.1 PROGRAM TERMINATE (00H) Parameters: C = 00H (_TERM0) Results: Does not return This function terminates program with a zero return code. It is provided for compatibility with MSX-DOS 1 and CP/M, the preferred method of exiting a program is to use the "terminate with error code" function call (function 62h), passing a zero error code if that is what is desired. See the description of that function call, and also the "Program Interface Specification", for details of what happens when a program terminates. This function call never returns to the caller. ### 3.2 CONSOLE INPUT (01H) Parameters: C = 01H (_CONIN) Results: L=A = Character from keyboard A character will be read from the standard input (file handle 0 - usually the keyboard) and echoed to the standard output (file handle 1 - usually the screen). If no character is ready then this function will wait for one. Various control characters, as specified for the "console status" function (function 0Bh), will be trapped by this function for various control purposes. If one of these characters is detected then it will be processed and this function will wait for another character. Thus these characters will never be returned to the user by this function. ### 3.3 CONSOLE OUTPUT (02H) Parameters: C = 02H (_CONOUT) E = Character to be output Results: None The character passed in register E is written to the standard output (file handle 1 - usually the screen). If printer echo is enabled then the character is also written to the printer. Various control codes and escape sequences are interpreted as screen control codes. A list of these is included in the "Program Interface Specification", they are a sub-set of the standard VT-52 control codes. TABs will be expanded to every eighth column. A console input status check is done, and if any of the special control characters described for the "console status" function (function 0Bh) is found then it will be processed as for that function. Any other character will be saved internally for a later "console input" function call. ### 3.4 AUXILIARY INPUT (03H) Parameters: C = 03H (_AUXIN) Results: L=A = Input character A character is read from the auxiliary input device (file handle 3) and if no character is ready then it will wait for one. The auxiliary input device must have been installed before this function may be used. If no such device has been installed then this function will always return the end of file character ("Ctrl-Z"). ### 3.5 AUXILIARY OUTPUT (04H) Parameters: C = 04H (_AUXOUT) E = Character to be output Results: None The character passed in register E will be written to the auxiliary output device (file handle 3). The auxiliary output device must have been installed before this function may be used. If no such device has been installed then this function will simply throw the character away. ### 3.6 PRINTER OUTPUT (05H) Parameters: C = 05H (_LSTOUT) E = Character to be output Results: None The character passed in register E will be sent to the standard printer device (file handle 4 - usually the parallel printer). The same channel is used for console output which is echoed to the printer. TABs are not expanded by this function, although they are expanded when screen output is echoed to the printer with "Ctrl-P". ### 3.7 DIRECT CONSOLE I/O (06H) Parameters: C = 06H (_DIRIO) E = 00H...FEH - character for output = FFH - requests input Results: A=L = input - 00H - no character ready else input character undefined for output If E=FFh on entry then the keyboard will be examined for a characterfrom the standard input (file handle 0) and 00h returned if no character is ready. If a character is ready then it will be read from the standard input (file handle 0) and returned in register A without being echoed and with no check for control characters. If E<>FFh on entry then the character in register E will be printed directly to the standard output (file handle 1) with no TAB expansion or printer echo. Also no console status check is done by this function. Note that although this function does not expand TABs, the VT-52 control codes include TAB expansion so the effect on the screen is the same. ### 3.8 DIRECT CONSOLE INPUT (07H) Parameters: C = 07H (_DIRIN) Results: L=A = Input character This function is identical to the input option of function 06h, except that if no character is ready it will wait for one. Like function 06h, no echo or control characters checks will be done. This function is not compatible with CP/M which uses this function number for "get I/O byte". ### 3.9 CONSOLE INPUT WITHOUT ECHO (08H) Parameters: C = 08H (_INNOE) Results: L=A = Input character This function is identical to function 01h except that the input character will not be echoed to the standard output. The same control character checks will be done. This function is not compatible with CP/M which uses this function number for "set I/O byte". ### 3.10 STRING OUTPUT (09H) Parameters: C = 09H (_STROUT) DE = Address of string Results: None The characters of the string pointed to by register DE will be output using the normal console output routine (function call 02h). The string is terminated by "$" (ASCII 24h). ### 3.11 BUFFERED LINE INPUT (0AH) Parameters: C = 0AH (_BUFIN) DE = Address of an input buffer Results: None DE must point to a buffer to be used for input. The first byte of this buffer must contain the number of characters which the buffer can hold (0...255). A line of input will be read from the standard input device (file handle 0 - usually the keyboard) and stored in the buffer. The input will be terminated when a CR is read from the standard input. The number of characters entered, which does not include the CR itself, will be stored at (DE+1). If there is room in the buffer then the CR will be stored after the last character. When inputting from the keyboard (which will normally be the case), a simple line editor is provided, and also a 256 byte circular buffer of previous lines which can be edited and re-entered. The details of these editing facilities are described in the separate "Command Specification" document, so they are not included here. When the input buffer becomes full, the console bell will be rung for each character typed which cannot be put in the buffer. Each character entered will be echoed to the standard output and also to the printer if printer echo is enabled. ### 3.12 CONSOLE STATUS (0BH) Parameters: C = 0BH (_CONST) Results: L=A = 00H if no key was pressed = FFH if a key was pressed A flag is returned in register A to indicate whether a character is ready (that is, a key was pressed) for input from the keyboard. If a character is ready then it will be read and tested for certain special control characters. If it is not one of these then it is stored in an internal single byte buffer and subsequent call to this function will return "character ready" immediately without checking the keyboard. If this function says that a character is ready then the character may be read by function 02h or 08h. If the character is "Ctrl-C" then the program will be terminated with a ".CTRLC" error via the user's abort routine if one is defined. If the character is "Ctrl-P" then printer echo will be enabled and it will be disabled if it is "Ctrl-N". If the character is "Ctrl-S" then the routine will hang up waiting for another character to be pressed and then return "no character ready", thus providing a "wait" facility. The character typed to continue operation will be ignored, except that of it is "Ctrl-C" then the program will be terminated. These same input checks are also done for functions 01h, 02h, 08h, 09h and 0Ah. ### 3.13 RETURN VERSION NUMBER (0CH) Parameters: C = 0CH (_CPMVER) Results: L=A = 22H H=B = 00H This function simply returns the CP/M version number which is being emulated. This is always version 2.2 in current systems. ### 3.14 DISK RESET (0DH) Parameters: C = 0DH (_DSKRST) Results: None Any data which is waiting in internal buffers is written out to disk. It is not necessary to call this function in order to allow a disk change as is the case with CP/M. The disk transfer address is also set back to its default value of 80h by this function. ### 3.15 SELECT DISK (0EH) Parameters: C = 0EH (_SELDSK) E = Drive number. 0=A: 1=B: etc. Results: L=A = Number of drives (1...8) This function simply selects the specified drive as the default drive. The current drive is also stored at address 0004h for CP/M compatibility. The number of drives available is returned in register A but this will not include the RAM disk. ### 3.16 OPEN FILE \[FCB\] (0FH) Parameters: C = 0FH (_FOPEN) DE = Pointer to unopened FCB Results: L=A = 0FFH if file not found = 0 if file is found The unopened FCB must contain a drive which may be zero to indicate the current drive and a filename and extension which may be ambiguous. The current directory of the specified drive will be searched for a matching file and if found it will be opened. Matching entries which are sub-directories or system files will be ignored, and if the filename is ambiguous then the first suitable matching entry will be opened. Device names may be put in the FCB (without a colon) to allow devices to be accessed as if they were actually disk files. The standard device names are defined in the "Program Interface Specification". The low byte of the extent number is not altered by this function, and a file will only be opened if it is big enough to contain the specified extent. Normally the transient program will set the extent number to zero before calling this function. The high byte of the extent number will be set to zero to ensure compatibility with CP/M. The filename and extension in the FCB will be replaced by the actual name of the file opened from the directory entry. This will normally be the same as what was there before but may be different if an ambiguous filename or one with lower case letters in was used. The record count will be set to the number of 128 byte records in the specified extent, which is calculated from the file size. The file size field itself, the volume-id and the 8 reserved bytes will also be set up. The current record and random record fields will not be altered by this function, it is the application program's responsibility to initialize them before using the read or write functions. If the file cannot be found, then the "APPEND" environment item will be examined. If this is set then it is interpreted as a drive/path string which specifies a second directory in which to look for the file. The specified directory will be searched for the file and if found it will be opened as above. In this case the drive byte of the FCB will be set to the drive on which the file was found to ensure correct accessing of the file if the original drive byte was zero (default). ### 3.17 CLOSE FILE \[FCB\] (10H) Parameters: C = 10H (_FCLOSE) DE = Pointer to opened FCB Results: L=A = 0FFH if not successful = 0 if successful The FCB must have previously been opened with either an OPEN or a CREATE function call. If the file has only been read then this function does nothing. If the file has been written to then any buffered data will be written to disk and the directory entry updated appropriately. The file may still be accessed after a close, so the function can be regarded as doing an "ensure" function. ### 3.18 SEARCH FOR FIRST \[FCB\] (11H) Parameters: C = 11H (_SFIRST) DE = Pointer to unopened FCB Results: L=A = 0FFH if file not found = 0 if file found. This function searches the current directory of the drive specified in the FCB (default drive if FCB contains zero) for a file which matches the filename and extension in the FCB. The filename may be ambiguous (containing "?" characters) in which case the first match will be found. The low byte of the extent field will be used, and a file will only be found if it is big enough to contain this extent number. Normally the extent field will be set to zero by the program before calling this function. System file and sub-directory entries will not be found. If a suitable match is found (A=0) then the directory entry will be copied to the DTA address, preceded by the drive number. This can be used directly as an FCB for an OPEN function call if desired. The extent number will be set to the low byte of the extent from the search FCB, and the record count will be initialized appropriately (as for OPEN). The attributes byte from the directory entry will be stored in the S1 byte position, since its normal position (immediately after the filename extension field) is used for the extent byte. If no match is found (A=0FFh) then the DTA will not be altered. In no case will the FCB pointed to by DE be modified at all. This function remembers sufficient information internally to allow it to continue the search with a SEARCH FOR NEXT function, so it is not necessary for the FCB to be preserved if doing a SEARCH FOR NEXT function. In CP/M, if the drive number is set to "?" in this function then all directory entries, allocated or free will be matched. Also if the extent field is set to "?" then any extent of a file will be matched. Both of these features are normally only used by special purpose CP/M programs which are generally specific to the CP/M filing system (such as "STAT"). Neither feature is present in MSX-DOS 1/2. ### 3.19 SEARCH FOR NEXT \[FCB\] (12H) Parameters: C = 12H (_SNEXT) Results: L=A = 0FFH if file not found = 0 if file found. It continues the search to look for the next match with the filename. The results returned from this function are identical to SEARCH FOR FIRST and all the same comments apply. The information used to continue the search is held internally within MSX-DOS and so the original FCB used in the SEARCH FOR FIRST need not still exist. ### 3.20 DELETE FILE \[FCB\] (13H) Parameters: C = 13H (_FDEL) DE = Pointer to unopened FCB Results: L=A = 0FFH if no files deleted = 0 if files deleted OK All files in the current directory of the disk specified by the FCB, and which match the ambiguous filename in the FCB, are deleted. Sub-directories, system files, hidden files and read only files are not deleted. If any files at all are successfully deleted then this function returns with A=0. A return with A=FFh indicates that no files were deleted. ### 3.21 SEQUENTIAL READ \[FCB\] (14H) Parameters: C = 14H (_RDSEQ) DE = Pointer to opened FCB Results: L=A = 01H if error (end of file) = 0 if read was successful This function reads the next sequential 128 byte record from the file into the current disk transfer address. The record is defined by the current extent (high and low bytes) and the current record. After successfully reading the record, this function increments the current record and if it reaches 080h, sets it back to zero and increments the extent number. The record count field is also kept updated when necessary. Unlike CP/M it is possible to have partially filled records, since the file size is not necessarily a multiple of 128 bytes. If this occurs then the partial record is padded out with zeroes when it is copied to the transient program's DTA address. ### 3.22 SEQUENTIAL WRITE \[FCB\] (15H) Parameters: C = 15H (_WRSEQ) DE = Pointer to opened FCB Results: L=A = 01H if error (disk full) = 0 if write was successful This function writes the 128 bytes from the current disk transfer address to the file at the position defined by the current record and extent, which are then incremented appropriately. The record count byte is kept updated correctly if the file is extended or if the write moves into a new extent. The file size in the FCB is also updated if the file is extended. ### 3.23 CREATE FILE \[FCB\] (16H) Parameters: C = 16H (_FMAKE) DE = Pointer to unopened FCB Results: L=A = 0FFH if unsuccessful = 0 if successful This function creates a new file in the current directory of the specified drive and opens it ready for reading and writing. The drive, filename and low byte of the extent number must be set up in the FCB and the filename must not be ambiguous. Checks will be done to ensure that invalid filenames are not created. If there is already a file of the required name then the action depends on the value of the extent number byte. Normally this will be zero and in this case the old file will be deleted and a new one created. However if the extent number is non-zero then the existing file will be opened without creating a new file. This ensures compatibility with early versions of CP/M where each extent had to be explicitly created. In all cases the resulting file will be opened with the required extent number exactly as if an OPEN function call had been done. ### 3.24 RENAME FILE \[FCB\] (17H) Parameters: C = 17H (_FREN) DE = Pointer to unopened FCB Results: L=A = 0FFH not if successful = 0 if successful The unopened FCB has the normal drive and filename, and also a second filename starting at (DE+17). Every file in the current directory of the specified drive which matches the first filename, is changed to the second filename with "?" characters in the second filename leaving the appropriate character unchanged. Checks are done to prevent duplicate or illegal filenames from being created. Entries for sub-directories, hidden files and system files will not be renamed. ### 3.25 GET LOGIN VECTOR (18H) Parameters: C = 18H (_LOGIN) Results: HL = Login vector This function returns a bit set in HL for each drive which is available, bit-0 of L corresponding to drive "A:". Up to eight drives ("A:" to "H:") are supported by the system currently, so register H will usually be zero on return. ### 3.26 GET CURRENT DRIVE (19H) Parameters: C = 19H (_CURDRV) Results: L=A = Current drive (0=A: etc) This function just returns the current drive number. ### 3.27 SET DISK TRANSFER ADDRESS (1AH) Parameters: C = 1AH (_SETDTA) DE = Required Disk Transfer Address Results: None This function simply records the address passed in DE as the disk transfer address. This address will be used for all subsequent FCB read and write calls, for "search for first" and "search for next" calls to store the directory entry, and for absolute read and write calls. It is not used by the new MSX-DOS read and write functions. The address is set back to 80h by a DISK RESET call. ### 3.28 GET ALLOCATION INFORMATION (1BH) Parameters: C = 1BH (_ALLOC) E = Drive number (0=current, 1=A: etc) Results: A = Sectors per cluster BC = Sector size (always 512) DE = Total clusters on disk HL = Free clusters on disk IX = Pointer to DPB IY = Pointer to first FAT sector This function returns various information about the disk in the specified drive. It is not compatible with CP/M which uses this function number to return the address of an allocation vector. Note that unlike MSX-DOS 1, only the first sector of the FAT may be accessed from the address in IY, and the data there will only remain valid until the next MSX-DOS call. ### 3.29 RANDOM READ \[FCB\] (21H) Parameters: C = 21H (_RDRND) DE = Pointer to opened FCB Results: L=A = 01H if error (end of file) 0 if read was successful This function reads a 128 byte record from the file to the current disk transfer address. The file position is defined by the three byte random record number in the FCB (bytes 21h...23h). Unlike CP/M all three bytes of the random record number are used. A partial record at the end of the file will be padded with zeroes before being copied to the user's DTA. The random record number is not altered so successive calls to this function will read the same record unless the transient program alters the random record number. A side effect is that the current record and extent are set up to refer to the same record as the random record number. This means that sequential reads (or writes) can follow a random read and will start from the same record. The record count byte is also set up correctly for the extent. ### 3.30 RANDOM WRITE \[FCB\] (22H) Parameters: C = 22H (_WRRND) DE = Pointer to opened FCB Results: L=A = 01H if error (disk full) = 0 if no error This function writes a 128 byte record from the current disk transfer address to the file, at the record position specified by the three byte random record number (bytes 21h...23h). All three bytes of the random record number are used. If the record position is beyond the current end of file then un-initialized disk space will be allocated to fill the gap. The random record number field will not be changed, but the current record and extent fields will be set up to refer to the same record. The record count byte will be adjusted as necessary if the file is being extended or if the write goes into a new extent. ### 3.31 GET FILE SIZE \[FCB\] (23H) Parameters: C = 23H (_FSIZE) DE = Pointer to unopened FCB Results: L=A = 0FFH if file not found = 0 if file found OK This function searches for the first match with the filename in the FCB, exactly the same as OPEN FILE (function 0FH). The size of the located file is rounded up to the nearest 128 bytes and the number of records determined. The three byte random record field of the FCB is set to the number of records, so it is the number of the first record which does not exist. The fourth byte of the random record number is not altered. ### 3.32 SET RANDOM RECORD \[FCB\] (24H) Parameters: C = 24H (_SETRND) DE = Pointer to opened FCB Results: None This function simply sets the three byte random record field in the FCB to the record determined by the current record and extent number. The fourth byte of the random record number is not altered. No check is done as to whether the record actually exists in the file. ### 3.33 RANDOM BLOCK WRITE \[FCB\] (26H) Parameters: C = 26H (_WRBLK) DE = Pointer to opened FCB HL = Number of records to write Results: A = 01H if error = 0 if no error Data is written from the current disk transfer address to the position in the file defined by the random record number. The record size is determined by the record size field in the FCB (bytes 0Eh and 0Fh) which must be set by the user after opening the file and before calling this function. If the record size is less than 64 bytes then all four bytes of the random record number are used, otherwise only the first three are used. The number of records to be written is specified by HL, and together with the record size this determines the amount of data to be written. An error will be returned if the size exceeds 64k, thus limiting the maximum size of a transfer. After writing the data, the random record field is adjusted to the next record number in the file (ie. HL is added on to it). The current record and extent fields are not used or altered. The file size field is updated if the file has been extended. The record size can be any value from 1...0FFFFh. Small record sizes are no less efficient that large record sizes so if desired the record size can be set to one and the record count then becomes a byte count. It is desirable to write as much as possible with one function call since one large transfer will be quicker than several small ones. If the number of records to write (HL) is zero then no data will be written, but the size of the file will be altered to the value specified by the random record field. This may be either longer or shorter than the file's current size and disk space will be allocated or freed as required. Additional disk space allocated in this way will not be initialized to any particular value. ### 3.34 RANDOM BLOCK READ \[FCB\] (27H) Parameters: C = 27H (_RDBLK) DE = Pointer to opened FCB HL = Number of records to read Results: A = 01H if error (usually caused by end-of-file) = 0 if no error HL = Number of records actually read This function is the complement of the BLOCK WRITE function described above and most of the same comments apply as regards its use. Again if large blocks are read then it will be much faster than the normal CP/M operation. For example if it is desired to read 20k from a file, it is better to read the 20k with one function call rather than 20 separate function calls of 1k each. However it makes no difference whether the 20k read is done with a record size of 1 and a record count of 20k, with a record size of 20k and a record count of 1, or any intermediate combination. The number of records actually read is returned in HL. This may be smaller than the number of records requested if the end of the file was encountered. In this case any partial record will be padded out with zeroes before being copied to the users DTA. The random record field is adjusted to the first record not read, ie. the value returned in HL is added on to it. ### 3.35 RANDOM WRITE WITH ZERO FILL \[FCB\] (28H) Parameters: C = 28H (_WRZER) DE = Pointer to opened FCB Results: L=A = 01H if error = 00H if no error This function is identical to RANDOM WRITE (function 22h) except that if the file has to be extended, any extra allocated disk clusters will be filled with zeroes before writing the data. ### 3.36 GET DATE (2AH) Parameters: C = 2AH (_GDATE) Results: HL = Year 1980...2079 D = Month (1=Jan...12=Dec) E = Date (1...31) A = Day of week (0=Sun...6=Sat) This function simply returns the current value of the internal calender in the format shown. ### 3.37 SET DATE (2BH) Parameters: C = 2BH (_SDATE) HL = Year 1980...2079 D = Month (1=Jan...12=Dec) E = Date (1...31) Results: A = 00H if date was valid FFH if date was invalid The supplied date is checked for validity and if it is valid then it is stored as the new date. The validity checks include full checking for the number of days in each month and leap years. If the date is invalid then the current date will be left unaltered. The date is stored in the real time clock chip so it will be remembered when the machine is turned off. ### 3.38 GET TIME (2CH) Parameters: C = 2CH (_GTIME) Results: H = Hours (0...23) L = Minutes (0...59) D = Seconds (0...59) E = Centiseconds (always zero) This function returns the current value of the system clock in the format shown. ### 3.39 SET TIME (2DH) Parameters: C = 2DH (_STIME) H = Hours (0...23) L = Minutes (0...59) D = Seconds (0...59) E = Centiseconds (ignored) Results: A = 00H if time was valid FFH if time was invalid This function sets the internal system clock to the specified time value. If the time is invalid then register A will be returned as 0FFh to indicate an error and the current time will be left unaltered. The time is stored in the real time clock chip and so it will be remembered and kept correct when the machine is turned off. ### 3.40 SET/RESET VERIFY FLAG (2EH) Parameters: C = 2EH (_VERIFY) E = 0 to disable verify <> 0 to enable verify Results: None This function simply enables or disables automatic verification of all writes. It defaults to off when MSX-DOS is started up. Enabling verify improves system reliability but also slows down write operations. Note that this function depends on the disk driver and the verification will not be done if the driver does not support it. ### 3.41 ABSOLUTE SECTOR READ (2FH) Parameters: C = 2FH (_RDABS) DE = Sector number L = Drive number (0=A: etc.) H = Number of sectors to read Results: A = Error code (0=> no error) This function reads sectors directly from the disk without interpreting them as files. The disk must be a valid DOS disk in order for the sector number to be translated into a physical position on the disk. The sectors will be read to the current disk transfer address. Any disk error will be reported by the system in the usual way. ### 3.42 ABSOLUTE SECTOR WRITE (30H) Parameters: C = 30H (_WRABS) DE = Sector number L = Drive number (0=A: etc.) H = Number of sectors to write Results: A = Error code This function writes sectors directly to the disk without interpreting them as files. The disk must be a valid DOS disk in order for the sector number to be translated into a physical position on the disk. The sectors will be written from the current disk transfer address. Any disk errors are reported by the system in the usual way. ### 3.43 GET DISK PARAMETERS (31H) Parameters: C = 31H (_DPARM) DE = Pointer to 32 byte buffer L = Drive number (0=default, 1=A: etc.) Results: A = Error code DE = Preserved This functions returns a series of parameters relating to the format of the disk in the specified drive, to the buffer allocated within the user's program. It is useful for programs which are going to do absolute sector reads and writes, in order for them to be able to interpret the absolute sector numbers. The parameters returned contain some redundant information in order to provide parameters which are most useful to transient programs. The format of the returned parameter block is: DE+0 - Physical drive number (1=A: etc) DE+1,2 - Sector size (always 512 currently) DE+3 - Sectors per cluster (non-zero power of 2) DE+4,5 - Number of reserved sectors (usually 1) DE+6 - Number of copies of the FAT (usually 2) DE+7,8 - Number of root directory entries DE+9,10 - Total number of logical sectors DE+11 - Media descriptor byte DE+12 - Number of sectors per FAT DE+13..14 - First root directory sector number DE+15..16 - First data sector number DE+17..18 - Maximum cluster number DE+19 - Dirty disk flag DE+20..23 - Volume id. (-1 => no volume id.) DE+24..31 - Reserved (currently always zero) The dirty disk flag indicates whether in the disk there is a file which can be recovered by UNDEL command. It is reset when the file allocation is done. ### 3.44 FIND FIRST ENTRY (40H) Parameters: C = 40H (_FFIRST) DE = Drive/path/file ASCIIZ string or fileinfo block pointer HL = filename ASCIIZ string (only if DE = fileinfo pointer) B = Search attributes IX = Pointer to new fileinfo block Results: A = Error (IX) = Filled in with matching entry The "drive/path" portion of the string, or the fileinfo block, specifies a directory which is to be searched. A ".IATTR" error will be returned if a fileinfo block which specifies a file is passed. The "file" portion of the string, or the filename ASCIIZ string in HL, determines what filenames will be matched. If no match is found then a ".NOFIL" error is returned, otherwise the fileinfo block pointed to by IX is filled in with the details of the matching entry. The filename may contain ambiguous filename characters ("?" or "\*") in which case the first matching entry will be returned. If the filename is null (either the ASCIIZ string pointed to by DE is null or ends in a "\\" or the filename string pointed to by HL is null), then this function will behave exactly as if the filename was "\*.\*" so any name will match. The attributes byte in register B specifies what type of entry will be matched. If it is zero then only non-hidden, non-system files will be found. If the directory, hidden or system bits in register B are set then entries with these attributes will be matched as well as ordinary files. The read only and archive bits of register B are ignored. If the volume name bit of register B is set then the search is exclusive, only the volume label entry will be found. In this case also the fileinfo block and filename or the drive/path/file string are ignored apart from specifying the drive. This means that the volume name will always be found in the root directory if it exists whether or not it matches the filename given. If DE points to a fileinfo block, then if desired, IX can point to the same fileinfo block. In this case when a match is found the new fileinfo block will overwrite the old one. ### 3.45 FIND NEXT ENTRY (41H) Parameters: C = 41H (_FNEXT) IX = Pointer to fileinfo block from previous find first function. Results: A = Error (IX) = Filled in with next matching entry This function should only be used after a "find first entry" function call. It searches the directory for the next match to the (presumably ambiguous) filename which was given to the "find first entry" function call. If there are no more matching entries then a ".NOFIL" error is returned, otherwise the fileinfo block is filled in with the information about the new matching entry. ### 3.46 FIND NEW ENTRY (42H) Parameters: C = 42H (_FNEW) DE = Drive/path/file ASCIIZ string or fileinfo block pointer HL = filename ASCIIZ string (only if DE = fileinfo pointer) B = b0..b6 = Required attributes b7 = Create new flag IX = Pointer to new fileinfo block containing template filename Results: A = Error (IX) = Filled in with new entry This function is very similar to the "find first entry" function described above. The parameters in HL and DE are used in exactly the same way to specify a directory entry. However instead of searching the selected directory for an entry which matches the specified name, a new entry will be created with this name. The fileinfo block pointed to by IX will be filled in with information about the new entry just as if it had been found with a "find first entry" call. If there are any ambiguous characters ("?" or "\*") in the filename, then they will be replaced by the appropriate character from a "template filename" in the filename position of the new fileinfo block pointed to by IX. If the result is still ambiguous, or otherwise illegal, then a ".IFNM" error is returned. This is useful for copy operations which do an automatic rename. Like "find first entry", if the filename is null, then it will be treated exactly as if it was "\*.\*". For this function that means that the template filename will be used as the new filename to create. A ".DRFUL" error will be returned if there is no room in the root directory, and a ".DKFUL" if a sub-directory must be extended and the disk is already full. The attribute byte passed in register B is the attribute which the new entry will be given. If the volume name bit is set then a volume name will be created in the root directory. If the directory bit is set then the entry created will be for a sub-directory, otherwise it will be for a file. The system, hidden and read only bits may be set for a file, and the hidden bit for a sub-directory. A file will always be created with the archive attribute bit set. A file will be created as zero length with the current date and time. A sub-directory will have a single cluster allocated to it and the "." and ".." entries will be initialized appropriately. If there is already an entry with the specified name in the directory then the action depends on the "create new" flag (bit-7 of register B) and also on the type of the entry. If the "create new" flag is set then a ".FILEX" error will always be returned. Setting this flag thereforeensures that an existing file will not be deleted. If an entry already exists and the "create new" flag is not set then the type of the existing entry is examined to see whether it can be deleted to make room for the new file. An error will be returned if the entry is a read only file (".FILRO" error), a system file (".SYSX" error) or a sub-directory (".DIRX" error) or there is a file handle already open to this file (".FOPEN" error). If we are trying to create a sub-directory then even an ordinary file will not be deleted (".FILEX" error). For all of these error codes (".FILEX", ".FILRO", ".SYSX", ".DIRX", ".FOPEN"), the fileinfo block will be filed in with the details of the already existing entry and this fileinfo block may be used exactly as if it had been returned from a "find first" function. ### 3.47 OPEN FILE HANDLE (43H) Parameters: C = 43H (_OPEN) DE = Drive/path/file ASCIIZ string or fileinfo block pointer A = Open mode. b0 set => no write b1 set => no read b2 set => inheritable b3..b7 - must be clear Results: A = Error B = New file handle The drive/path/file string or the fileinfo block should normally refer to a file rather than a sub-directory or volume name. If it is a volume name then a ".IATTR" error will be returned. If it is a sub-directory then ".DIRX" error will be returned. Assuming that a file is specified then it will be opened ready for reading and/or writing (depending on the open mode in A) and a new file handle for it will be returned in register B. The lowest available file handle number will be used and an error will result if there are no spare file handles (".NHAND" error), or insufficient memory (".NORAM" error). If the "no read" bit of register A is set then reads from the file handle will be rejected and if the "no write" bit is set then writes will be rejected, in both cases with an ".ACCV" error. Writes will also be rejected if the file is read only (".FILRO" error). If the "inheritable" bit of register A is set then the file handle will be inherited by a new process created by the "fork" function call (see function 60h). If a device file handle is opened by giving a filename which matches one of the built in devices (for example "CON" or "NUL"), then it will always be opened initially in ASCII mode. The IOCTL function (function 4Bh) can be used to change this to binary mode but great care must be taken in reading from devices in binary mode because there is no end of file condition. ### 3.48 CREATE FILE HANDLE (44H) Parameters: C = 44H (_CREATE) DE = Drive/path/file ASCIIZ string A = Open mode. b0 set => no write b1 set => no read b2 set => inheritable b3..b7 - must be clear B = b0..b6 = Required attributes b7 = Create new flag Results: A = Error B = New file handle A file or sub-directory, as specified by the attributes in register B, will be created with the name and in the directory specified by the drive/path/file string. A ".IATTR" error is returned if register B specifies a volume name. An error will be returned if the file or sub-directory cannot be created. The error conditions in this case are the same as for the "find new entry" function (function 42h) with the main error codes being ".FILEX", ".DIRX", ".SYSX", ".FILRO", ".FOPEN", ".DRFUL" and ".DKFUL". Like the "find new" function, if the "create new" flag (bit-7 of register B