Skip to content

What is the MOS API

The MOS API can be used by external applications to access MOS functionality.

Please note that this documentation uses assembler in the examples in a format that is compatible with the Zilog ZDS II assembler. The assembler syntax used in BBC BASIC is similar, but not identical. Additionally you will need to use the new ADL version of BBC BASIC to use the new eZ80 ADL mode and extended instruction set.

This documentation is not intended as a tutorial on eZ80 assembler, but as a reference for those who are already familiar with the eZ80 or Z80 instruction set and wish to use MOS APIs in their programs.

Usage from Z80 assembler

There are four RST instructions for accessing MOS functionality from Z80.

  • RST 00h: Reset the eZ80
  • RST 08h: Execute a MOS command
  • RST 10h: Output a single character to the VDP
  • RST 18h: Output a stream of characters to the VDP (MOS 1.03 or above)
  • RST 38h: Outputs a crash report (Console8 MOS 2.3.0 or above)

In addition, if you are using the Zilog ZDS II assembler you may wish to include the file mos_api.inc in your project. The Console8 version can be found in the folder src of project agon-mos. The original Quark versions of this file can be found in the folder src of project agon-mos.

NB:

  • Using the RST.LIS opcode in an eZ80 assembler will ensure the MOS RST instructions are called regardless of the eZ80s current addressing mode.
  • In the mos_api.inc file you will find:
    • EQUs for all the MOS commands, data structures and system state variables (sysvars).
    • An incomplete list of VDP control variables. For a full list, see the VDP documentation
    • A complete list FatFS APIs, however these are not yet all implemented in MOS. Those that are implemented are documented below.

Further information on the RST handlers provided by MOS are as follows:

RST 08h: Execute a MOS command

Parameters:

  • A: MOS command number to execute

NB:

  • There is a macro in mos_api.inc with EQUs for all the MOS commands
  • Other MOS-command dependant parameters may be required

Macro:

;
; Macro for calling the API
; Parameters:
; - `F`unction: One of the function numbers listed above
;
MOSCALL:    MACRO   function
            LD  A, function
            RST.LIS 08h
            ENDMACRO

Example:

; OSRDCH: Read a character in from the ESP32 keyboard handler
;
OSRDCH: MOSCALL mos_getkey
        OR  A
        JR  Z, OSRDCH       ; Loop until key is pressed
        RET

RST 10h: Output a single character to the VDP

Parameters:

  • A: Character to output

Example:

; OSWRCH: Write a character out to the ESP32 VDU handler via the MOS
; A: Character to write
;
OSWRCH: RST.LIS 10h         ; This calls a RST in the eZ80 address space
        RET

RST 18h: Output a stream of characters to the VDP (MOS 1.03 or above)

Parameters:

  • HL(U): Address of the data stream (16-bit for Z80 mode, 24-bit for ADL mode)
  • BC: Length of stream (or 0 if the stream is delimited)
  • A: Stream delimiter (if BC=0)

Returns:

  • A: Last character displayed (length mode) OR Delimiter (delimiter mode)
  • BC: 0
  • HL(U): Address of last character displayed + 1 (length mode) OR location of delimiter (delimiter mode)
  • E: Value of A upon entry

Example:

; Write a stream of characters to the VDP
; HLU: Address of buffer containing data - if in 16-bit segment, U will be replaced by MB
;  BC: Number of characters to write out, or 0 if the data is delimited
;   A: End of data delimiter, i.e. 0 for C strings
;
        LD  HL, text        ; Address of text
        LD  BC, 0           ; Set to 0, so length ignored...
        LD  A, 0            ; Use character in A as delimiter
        RST.LIS 18h         ; This calls a RST in the eZ80 address space
        RET
;
text:   DB  "Hello World", 0

RST 38h: Outputs a crash report (Console8 MOS 2.3.0 or above)

This command will output a crash report to the screen. This report will show the current processor state, and the top of the stack. This can be useful for debugging purposes.

This command works in conjunction with the fact that as of Console8 MOS 2.3.0, on initial startup memory will be reset to contain 0xFF bytes in every location, which equates to a RST 38h instruction. This means that for many system crashes execution will end up at the RST 38h instruction, and a crash report will be displayed on the screen.

The MOS API

MOS API calls can be executed from a classic 64K Z80 segment or whilst the eZ80 is running in 24-bit ADL mode. For classic mode, 16 bit registers are passed as pointers to the MOS commands; these are automatically promoted to 24 bit by adding the MB register to bits 16-23 of the register. When running in ADL mode, a 24-bit register will be passed, but MB must be set to 0.

Many, but not all, of the MOS API calls will return a status code in the A register. This status code will indicate the success or failure of the operation. If the operation was successful, the status code will be 0. If the operation failed, the status code will be non-zero, and will indicate the nature of the failure. Some API calls, such as those for I2C communications or string comparisons, use different sets of status codes, which will be documented in the API call's description.

The APIs available from MOS have changed over time, and some of the APIs described are only available in later versions of MOS. If you attempt to call an API that is not available in the version of MOS you are using the API will return the status value 23 in the A register to indicate it is not supported. Please note that Console8 MOS 2.1.0 and earlier, including Quark MOS 1.04, do support detecting unknown/unsupported API calls and will produce unexpected results if you attempt to call an API that is not supported. This is a known issue with these versions of MOS, and it is recommended to upgrade to a later version of MOS if you are using these versions.

As of MOS 3.0, all the MOS API calls that accept any kind of filepath string as a parameter, whether that is to a filename or a directory, will support the use of system variables and custom file paths within the string. These will automatically be handled in native MOS file handling API calls. This allows for more flexible and powerful file handling in your applications.

Please note that the FatFS API calls (which named with an ffs_ prefix) do not support this behaviour, and will only work with fully resolved file paths. There is an API to resolve the path which can be used to convert a path with system variables into a path suitable for use with the fatfs APIs.

In general, to read and/or write files files, it is recommended to use the MOS file APIs as these will automatically handle system variables and file paths. MOS file APIs use a "file handle" to reference an open file, whereas the FatFS APIs expect a pointer to a FIL structure. You can get a FIL structure for a MOS file handle by using the mos_getfil API. This will allow you to use the FatFS APIs directly if you need to, but in most cases it is recommended to use the MOS file APIs. It is planned that future versions of MOS (beyond 3.0) will support using the MOS file APIs to open data streams other than files, such as the serial UART, I2C devices, and the VDP connection. This will allow you to use the same APIs to read/write data across different all data streams.

The following MOS commands are supported:

0x00: mos_getkey

Read a keypress from the VDP

Parameters: None

Returns:

  • A: The keycode of the character pressed

NB: This is a blocking function. This routine will wait and only return once a key is pressed.

0x01: mos_load

Load a file from SD card

Parameters:

  • HL(U): Address of filename (zero terminated)
  • DE(U): Address at which to load
  • BC(U): Maximum allowed size (bytes)

Preserves: HL(U), DE(U), BC(U)

Returns:

  • A: Status code
  • F: Carry reset if no room for file, otherwise set

0x02: mos_save

Save a file to SD card

Parameters:

  • HL(U): Address of filename (zero terminated)
  • DE(U): Address to save from
  • BC(U): Number of bytes to save

Preserves: HL(U), DE(U), BC(U)

Returns:

  • A: Status code
  • F: Carry set

0x03: mos_cd

Change current directory on the SD card

Parameters:

  • HL(U): Address of directory path (zero terminated)

Preserves: HL(U)

Returns:

  • A: Status code

0x04: mos_dir

List SD card folder contents to screen.

This is a simple directory listing command that will list the contents of the current directory to the screen. More advanced directory listing functionality for applications to use is available via the FatFS commands API.

Parameters:

  • HL(U): Address of directory path (zero terminated)

Preserves: HL(U)

Returns:

  • A: Status code

0x05: mos_del

Delete a file or folder from the SD card

Parameters:

  • HL(U): Address of filepath (zero terminated)

Preserves: HL(U)

Returns:

  • A: Status code

0x06: mos_ren

Rename a file on the SD card

Parameters:

  • HL(U): Address of source filepath string (zero terminated)
  • DE(U): Address of destination filepath string (zero terminated)

Preserves: HL(U), DE(U)

Returns:

  • A: Status code

As of MOS 3.0 the mos_ren API can support the use of wildcards in the source filepath leaf name. This allows you to rename multiple files at once. The destination filepath must point to a directory in this case. Destination paths cannot include wildcards.

0x07: mos_mkdir

Make a folder on the SD card

Parameters:

  • HL(U): Address of path (zero terminated)

Preserves: HL(U)

Returns:

  • A: Status code

0x08: mos_sysvars

Fetch a pointer to the system state variables

Parameters: None

Returns:

  • IXU: Pointer to the MOS SysVars area (this is always 24 bit)

0x09: mos_editline

Invoke the line editor

Parameters:

  • HL(U): Address of the buffer
  • BC(U): Buffer length
  • E: Flags to control editor behaviour

Preserves: HL(U), BC(U), DE(U)

Returns:

  • A: Key that was used to exit the input loop (CR=13, ESC=27)

Editor behaviour flags are as follows:

Bit Description
0 When set, buffer will be cleared before use
1 When set, tab-completion for MOS commands and files is enabled *
2 When set, hotkeys are disabled *
3 When set, input history will be disabled *
4-7 Reserved for future use (for future compatibility, ensure these are set to zero)

* Support for editor control flags was added in Console8 MOS 2.2.0. Prior to this the only documented values for E were 0 and 1 to indicate whether the buffer should be cleared.

0x0A: mos_fopen

Get a file handle

Parameters:

  • HL(U): Address of filename (zero terminated)
  • C: File open mode

Preserves: HL(U), BC(U), DE(U), IX(U), IY(U)

Returns:

  • A: File handle, or 0 if couldn't open

File open modes

The mode is a number that indicates rules as to how the file will be opened. Several different modes are available, and these values can be combined using a bitwise OR operation. The values supported are inherited from FatFS, and are as follows:

Mode FatFS constant Description
0x01 FA_READ Open file for reading
0x02 FA_WRITE Open file for writing. Combine with FA_READ for read/write access
0x00 FA_OPEN_EXISTING Open file if it exists, fail if it doesn't
0x04 FA_CREATE_NEW Create a new file, fail if it already exists
0x08 FA_CREATE_ALWAYS Create a new file. If the file already exists it will be truncated and overwritten
0x10 FA_OPEN_ALWAYS Open file if it exists, create it if it doesn't
0x30 FA_OPEN_APPEND Same as FA_OPEN_ALWAYS, except the read/write pointer will be set to the end of the file

You may note that the "open existing" mode has a value of zero. Setting either, or both, of the "create" options will override this.

NB: If you open the file using mos_fopen, you must close it using mos_fclose, not ffs_api_fclose

0x0B: mos_fclose

Close a file handle

Parameters:

  • C: File handle, or 0 to close all open files

Preserves: HL(U), BC(U), DE(U), IX(U), IY(U)

Returns:

  • A: Number of files still open

0x0C: mos_fgetc

Get a character from an open file

Parameters:

  • C: File handle

Preserves: HL(U), BC(U), DE(U), IX(U), IY(U)

Returns:

  • A: Character read
  • F: C set if last character in file, otherwise NC (MOS 1.04 or greater)

0x0D: mos_fputc

Write a character to an open file

Parameters:

  • C: File handle
  • B: Character to write

Preserves: HL(U), BC(U), DE(U), IX(U), IY(U)

Returns:

None

0x0E: mos_feof

Check for end of file

Parameters:

  • C: File handle

Preserves: HL(U), BC(U), DE(U), IX(U), IY(U)

Returns:

  • A: 1 if at end of file, otherwise 0

0x0F: mos_getError

Translates a status code into a human-readable message.

Parameters:

  • E: The status code
  • HL(U): Address of buffer to copy message into
  • BC(U): Size of buffer

Preserves: DE(U), HL(U), BC(U)

Returns:

None

0x10: mos_oscli

Execute a MOS command

Parameters:

  • HL(U): Pointer the the MOS command string

Preserves: HL(U)

Returns:

  • A: Status code

NB previously documentation for this command was incorrect, as it documented additional parameters in DE(U) and BC(U). These registers are not currently used.

0x11: mos_copy

Copy a file on the SD card

Parameters:

  • HL(U): Address of source filepath string (zero terminated)
  • DE(U): Address of destination filepath string (zero terminated)

Preserves: HL(U), BC(U), DE(U), IX(U), IY(U)

Returns:

  • A: Status code

NB: Requires MOS 1.03 or greater

Please note that this API only supports copying files; it does not support copying directories.

As of MOS 3.0, the mos_copy API supports the use of wildcards in the source filepath leaf name. This allows you to copy multiple files at once. The destination filepath must point to a directory in this case. Destination paths cannot include wildcards.

0x12: mos_getrtc

Get a time string from the RTC (Requires MOS 1.03 or above)

Parameters:

  • HL(U): Pointer to a buffer to copy the string to (at least 32 bytes)

Preserves: HL(U)

Returns:

  • A: Length of time string

0x13: mos_setrtc

Set the RTC (Requires MOS 1.03 or above)

Parameters:

  • HL(U): Pointer to a 6-byte buffer with the time data in
+0: Year (offset from 1980, so 1989 is 9)
+1: Month (1 to 12)
+2: Day of Month (1 to 31)
+3: Hour (0 to 23)
+4: Minute (0 to 59)
+5: Second (0 to 59)

Preserves: HL(U)

Returns:

None

0x14: mos_setintvector

Set an interrupt vector (Requires MOS 1.03 or above)

Parameters:

  • E: Interrupt vector number to set
  • HLU: Address of new interrupt vector (24-bit pointer)

Preserves: HLU, DEU

Returns:

  • HL(U): Address of the previous interrupt vector (24-bit pointer)

0x15: mos_uopen

Open UART1 (Requires MOS 1.03 or above)

To handle the received interrupts, you will need to assign a handler to UART1's interrupt vector (0x1A).

Parameters:

  • IXU: Pointer to a UART struct
+0: Baud rate (24-bit, little endian)
+3: Data bits (5, 6, 7 or 8)
+4: Stop bits (1 or 2)
+5: Parity bits (0: None, 1: Odd, 3: Even)
+6: Flow control (0: None, 1: Hardware)
+7: Enabled interrupts
    - Bit 0: Set to enable received data interrupt
    - Bit 1: Set to enable transmit data interrupt
    - Bit 2: Set to enable line status change interrupt
    - Bit 3: Set to enable modem status change interrupt
    - Bit 4: Set to enable transmit complete interrupt

Preserves: HL(U)

Returns:

  • A: Error code (always 0)

0x16: mos_uclose

Close UART1 (Requires MOS 1.03 or above)

0x17: mos_ugetc

Read a character from UART1 (Requires MOS 1.03 or above)

Returns:

  • A: The character read
  • F: C if successful, NC if the UART is closed

NB: If UART1 is open, this is a blocking function which means this routine will wait and only return once a character is received.

0x18: mos_uputc

Write a character to UART1 (Requires MOS 1.03 or above)

Parameters:

  • C: The character to write

Returns:

  • F: C if successful, NC if the UART is closed

0x19: mos_getfil

Get a pointer to a FIL structure in MOS (Requires MOS 1.03 or above)

This call is useful if you wish to use the FatFS API directly, but need to pass a FIL structure to a FatFS API call.

Parameters:

  • C: File handle

Preserves: BC(U)

Returns:

  • HLU: 24-bit pointer to a FIL structure (in MOS RAM)

0x1A: mos_fread

Read a block of data from a file (Requires MOS 1.03 or above)

Parameters:

  • C: File handle
  • HLU: Pointer to a buffer to read the data into
  • DEU: Number of bytes to read

Preserves: HL(U), BC(U)

Returns:

  • DEU: Number of bytes read

0x1B: mos_fwrite

Write a block of data to a file (Requires MOS 1.03 or above)

Parameters:

  • C: File handle
  • HLU: Pointer to a buffer that contains the data to write
  • DEU: Number of bytes to write out

Preserves: HL(U), BC(U)

Returns:

  • DEU: Number of bytes written

0x1C: mos_flseek

Move the read/write pointer in a file (Requires MOS 1.03 or above)

This API can be used to expand the size of a file, although you should note that the file data in the expanded part will be undefined.

Parameters:

  • C: File handle
  • HLU: Least significant 3 bytes of the offset from the start of the file
  • E: Most significant byte of the offset (set to 0 for files < 16MB)

Preserves: HL(U), BC(U), DE(U)

Returns:

  • A: Status code

0x1D: mos_setkbvector

Allows user programs to access VDP keyboard packets without overriding the entire uart0 interrupt handler. The user program registered, will be called during the uart0 interrupt handler, being passed the address of the full VDP keyboard packet.

Parameters:

  • C: Address length in HL (0 = 24bit, 1 = 16bit). If 1 then set the top byte of HLU (callback address) to MB (for ADL=0 callers)
  • HL(U): Callback address of user program to register, or 0 to clear any previously registered vector

Returns: Nothing upon registration. The user program can expect the full VDP packet address in DE(24-bit) upon entry.

Be sure to clear the kbvector before your program exits (call mos_setkbvector again with HL=0).

example code that registers a custom handler.

0x1E: mos_getkbmap

Fetch a pointer to the virtual keyboard map (Requires MOS 1.04 RC2 or above)

Parameters: None

Returns:

  • IXU: Pointer to the keyboard bitmap (this is always 24 bit)

0x1F: mos_i2c_open

Open the I2C bus as Master (Requires MOS 1.04 RC3 or above)

Parameters:

  • C: Frequency ID (1: 57600, 2: 115200, 3: 230400)

Preserves: HL(U), BC(U), DE(U), IX(U), IY(U)

Returns: None

0x20: mos_i2c_close

Close the I2C bus (Requires MOS 1.04 RC3 or above)

Parameters: None

Preserves: HL(U), BC(U), DE(U), IX(U), IY(U)

Returns: None

0x21: mos_i2c_write

Write a block of bytes to the I2C bus (Requires MOS 1.04 RC3 or above)

Parameters:

  • C: I2C Address
  • B: Number of bytes to write (maximum 32)
  • HL(U): Pointer to a buffer to read the bytes from

Preserves: HL(U), DE(U), IX(U), IY(U)

Returns:

  • A: Status
    • 0: OK
    • 1: No response from I2C slave
    • 2: Data NACK
    • 4: Bus arbitration lost
    • 8: Bus error

0x22: mos_i2c_read

Read a block of bytes from the I2C bus (Requires MOS 1.04 RC3 or above)

Parameters:

  • C: I2C Address
  • B: Number of bytes to read (maximum 32)
  • HL(U): Pointer to a buffer to write the bytes to

Preserves: HL(U), DE(U), IX(U), IY(U)

Returns:

  • A: Status
    • 0: OK
    • 1: No response from I2C slave
    • 2: Data NACK
    • 4: Bus arbitration lost
    • 8: Bus error

0x23: mos_unpackrtc

Unpack the RTC (Real-Time Clock) data into a buffer (Requires MOS 3.0 or above)

Parameters:

  • HL(U): Pointer to a buffer to copy the RTC data to
  • C: Flags

The buffer should be at least 10 bytes long.

Flags are a bit-field to enable various different options. Currently the following bits are supported:

  • bit 0 = refresh RTC sysvar before unpacking
  • bit 1 = refresh RTC sysvar after unpacking

The RTC data sysvar is updated by sending a command to the VDP to request the current time, and MOS will store the response in the RTC system variable area. If you set bit 0, this API call will send the command to the VDP to request updated RTC data and wait for the response before unpacking the data. When you set bit 1, the command will be sent after the data has been unpacked, and the API will return without waiting for the response.

If you do not want to refresh the RTC data stored in MOS, set the flags to 0. You should note that if you do this the data may be stale or, if no request has been sent to the VDP at all for RTC information, be invalid.

NB you should not set either refresh flag if you are in the middle of sending a command to the VDP, as that will both cause the update command to not be understood by the VDP, and will cause your command to fail or produce unexpected results.

Preserves: HL(U), BC(U)

Returns:

Data returned in the buffer at HL(U) will be in the following order, with 16-bit values stored in little-endian order:

    UINT16 year;
    UINT8  month;
    UINT8  day;
    UINT8  dayOfWeek;
    UINT16 dayOfYear;
    UINT8  hour;
    UINT8  minute;
    UINT8  second;

0x28-0x2C: String functions

API calls in this range are string manipulation functions, added in MOS 3.0.

0x28: mos_pmatch

Pattern matching function, with support for various flags to control how the comparison is made.

This exposes the pattern matching function that MOS 3.0 uses internally for matching commands and filenames.

Parameters:

  • HL(U): Address of pattern (zero terminated)
  • DE(U): Address at string to compare against pattern (zero terminated)
  • C: Flags

The flags are a bit-field to enable various different pattern matching options

Bit Description
0 Case insensitive
1 Disable star (*) wildcard matching
2 Disable hash (#) wildcard matching
3 "Dot as star" mode (treats . at the end of pattern as a star, used in MOS for matching abbreviated commands)
4 "Begins with" mode (only matches if the string starts with the pattern)
5 "Up to space" mode (only matches up to the first space in the pattern)

Preserves: HL(U), DE(U) and BC(U)

Returns:

  • A: Status
    • 0 if pattern matches
    • Positive number if string does not match, and is logically sorted after the pattern
    • Negative number if string does not match, and is logically sorted before the pattern

0x29: mos_getargument

Extract a (numbered) argument from a string

Parameters:

  • HL(U): Pointer to source string
  • BC(U): Argument number

Returns:

  • HL(U): Address of the argument or zero if not found
  • DE(U): Address of the argument end (next character after the argument)

Preserves: BC(U)

0x2A: mos_extractstring

Extract a string, using a given divider.

Parameters:

  • HL(U): Pointer to a zero-terminated source string to extract from
  • DE(U): Pointer to string for divider matching, or 0 for default (space)
  • C: Flags. Depending on flags, the result string will be zero terminated or not

The flags are a bit-field to enable various different options

Bit Description
0 Zero terminate the result string
1 Omit skipping of divider characters at beginning of source string
2 Disable matching of double-quotes
3 Include double-quotes in results string

If string extraction is matching double-quotes and an end quote is not found, a status code of 25 (Bad string) will be returned. If it is not possible to extract a result, a status code of 19 (Invalid parameter) will be returned.

Returns:

  • A: status code (0 = OK, 19 = Invalid parameter, 25 = Bad string)
  • HL(U): Address of the result string
  • DE(U): Address of next character after end of result string

Preserves: BC(U)

0x2B: mos_extractnumber

Extract a number, using given divider. Various number formats are supported - for more information see notes on numbers interpreted by the MOS CLI

Parameters:

  • HL(U): Pointer to a zero-terminated source string to extract from
  • DE(U): Pointer to string for divider matching, or 0 for default (space)
  • C: Flags

The flags are a bit-field to enable various different options

Bit Description
0 Decimal numbers only
1 Positive numbers only
2 Allow h suffix to indicate hexadecimal numbers

If the source string does not contain a valid number, in accordance with the flags, a status code of 19 (Invalid parameter) will be returned.

Returns:

  • A: status code (0 = OK, 19 = Invalid parameter)
  • HL(U): Number extracted
  • DE(U): Address of next character after end of number

Preserves: BC(U)

0x2C: mos_escapestring

"Escape" a string for display, converting control characters to be pipe-prefixed

Parameters:

  • HL(U): Pointer to source string
  • DE(U): Pointer to destination buffer (optional)
  • BC(U): Length of destination buffer

If no destination buffer is provided (i.e. DE is zero), the function will return the length of the escaped string.

If the destination buffer is too short then a status code of 22 (Out of memory) will be returned, and as much of the source string that could be converted will be copied to the destination buffer.

Returns:

  • A: Status code
  • BC(U): Length of escaped string

0x30-0x37: System variables and string translations

API calls in this range are used for setting and reading system variables, and for performing string translations.

0x30: mos_setvarval

Set, update, replace or remove a System Variable

Parameters:

  • HL(U): Pointer to variable name (zero-terminated string, can include wildcards)
  • IX(U): Variable value (number, or pointer to zero-terminated string)
  • IY(U): Pointer to variable name (0 for first call)
  • C: Variable type, or -1 (255) to delete the variable

If the name used includes a wildcard, then the first matching variable will be set. Subsequent calls can be made to set the next variable that matches the pattern, so long as you preserve IY(U) between calls.

Variable types supported are:

Type Description
0 String (Will be run through GSTrans before storing)
1 Number (a 24-bit integer value)
2 Macro (A string that will be GSTrans'd each time it is used)
3 "Expanded" (Expression that will be evaluated before stored)
4 Literal string (GSTrans will not be called before storage)

NB at the time of writing the expression engine has yet to be written in MOS 3 so type 3 support is limited to either a number or a string to indicate a variable name to copy as a string type.

If either a type of 3 or 4 is used then the variable type used for storage of the variable will be either a string or a number.

Internally MOS also supports "Code" type variables, which are used for several things, such as exposing date/time information. If such a variable variable supports being set then you can call the "set" functions of these variables by using the String type with a matching name. You cannot remove a "Code" type variable using this function.

Returns:

  • A: Status code
  • C: Actual variable type
  • IY(U): Pointer to actual variable name (for next call)

Other registers will be preserved.

0x31: mos_readvarval

Read a variable value

Parameters:

  • HL(U): Pointer to variable name (can include wildcards)
  • DE(U): Length of buffer to store the value
  • IX(U): Pointer to buffer to store the value (null/0 to read length only)
  • IY(U): Pointer to variable name (0 for first call)
  • C: Flags (3 = expand value into string - other values will be ignored)

If the name includes a wildcard then the first matching variable will be read. Subsequent calls can be made to read the next value that matches the pattern, so long as you preserve IY(U) between calls.

NB Whilst numeric variables are set by providing their value directly in a register, when reading a numeric variable the value will be returned in the buffer pointed to by IX(U). That buffer must be at least 3 bytes long, unless the "flag" value is set to 3, in which case it must be large enough to contain a string representation of the number in decimal.

Returns:

  • A: Status code
  • C: Actual variable type
  • DE(U): Length of variable value
  • IY(U): Pointer to variable name (for next call)

0x32: mos_gsinit

Initialises a GSTrans operation.

GSTrans is a process of taking a source string and translating it, replacing any variables referenced, and converting any control codes into raw control bytes. The echo command in MOS is an example of a command that uses the GSTrans process, and the documentation for that command contains a more complete description of how the source string will be interpreted.

The process of translating a string is a two-step process. The first step is to call mos_gsinit to initialise the process, and the second step is to repeatedly call mos_gsread to actually perform the translation, fetching one character at a time until the whole string has been translated, and a zero character is read.

Various options are available to control how the translation process operates, and these are set using the flags parameter. By default, the translation process will continue until the end of the source string is reached. It is possible to instead translate only up to the first space. The process also supports detecting double-quotes to surround a string, in which case a request to terminate at a space will be ignored if the space is inside the double-quotes. (It should be noted that the echo command sets this flag.) Finally by default the process will translate characters preceeded by a | character as control codes, as explained in the documentation for the echo command. If you wish to disable this behaviour then you can set the "no pipe" flag.

Parameters:

  • HL(U): Pointer to source buffer to translate
  • DE(U): Address of pointer used to store trans info
  • C: Flags

DE(U) must point to an address that will be used to store a (3-byte) pointer to an information block used by the GSTrans process. It should be noted that failing to complete the GSTrans process can result in a memory leak.

The flags are a bit-field with options to control how the translation process operates. Their meanings are as follows:

Bit Description
0 Terminate at first space character in source buffer
1 No pipe (do not treat | as a control code)
2 Do not treat double-quotes " as markers surrounding a string
3-6 Reserved for future use (for future compatibility, ensure these are set to zero)
7 No tracking (do not automatically track memory used by GSTrans)

It should be noted that failing to complete translation of a string will result in some memory inside MOS remaining set aside to store the GSTrans process information. This memory will either be freed when the GSTrans process is completed, or a new call to mos_gsinit is made. If the "No tracking" flag is set however then MOS will not track the memory being used, and it will not be freed on a subsequent call to mos_gsinit - you must complete the process of reading through the string to free the memory, or you will cause a memory leak inside MOS.

In general you should not use the "No tracking" flag unless you have a need to perform two or more gstrans operations simultaneously.

Returns:

  • A: Status code

0x33: mos_gsread

Perform a GSTrans "read" operation.

When the final character of the translated string has been read, this function will return a null character (0) to indicate the end of the string.

Parameters:

  • DE(U): Address of pointer used to store trans info (same pointer as used with gsInit)

Returns:

  • A: Status code (0 = Success, various other values may indicate an invalid GSTrans string)
  • C: Character read. This will be 0 if the end of the string has been reached.

0x34: mos_gstrans

Perform a complete GSTrans operation from source into dest buffer

Parameters:

  • HL(U): Pointer to source buffer
  • IX(U): Pointer to destination buffer (can be null to just count size)
  • DE(U): Length of destination buffer
  • C: Flags

If the destination buffer given for this command is less than the size required for the translated string, then the API call will succeed, but the translated string will be truncated to fit in the buffer.

The flags here are identical those used with mos_gsinit, with the exception that the "No tracking" flag will be ignored.

Returns:

  • A: Status code
  • BC(U): Calculated total length of translated string

0x35: mos_substituteargs

Substitute arguments into a string from template

Parameters:

  • HL(U): Pointer to template string
  • IX(U): Pointer to arguments string
  • DE(U): Length of destination buffer
  • IY(U): Pointer to destination buffer (can be null to just count size)
  • C: Flags

The only flag currently supported is bit 0, which when set indicates that the "rest" arguments (i.e. those not explicitly used in the template) should be omitted from the destination string. When this bit is clear they will be automatically appended.

Returns:

  • BC(U): Calculated length of destination string

0x36: mos_evaluateexpression

As of MOS 3.0 this function has not yet been implemented. Support for this function is planned for a future release.


0x38-0x3C: File path functions

Functions in this range were added in MOS 3.0 to provide a set of functions for working with and manipulating file paths.

0x38: mos_resolvepath

Resolves a path, creating a new resolved path string that expands system variables, and also replaces prefixes and leafnames with actual values. System variables will be expanded first, and then the prefix and leafname will be resolved. The result is a fully resolved path that can be used with the FatFS API calls.

If the leafname contains wildcards then the first matching file will be returned. Please note that this will be the first match found in a directory, and owing to how directories are managed this may not be the first alphabetical match. Subsequent calls can be made to find the next matching file, so long as you provide a pointer to an empty directory object to persist between calls, and preserve the C register between calls too.

NB path resolution does not support resolving paths that contain wildcards in the directory part of the path. If you need to do this then you should gradually build the path up by calling mos_resolvepath multiple times to resolve the path up to each wildcard, using flags to filter for results that are a directory matching the wildcard until the directory part of the path is fully resolved. You can then call mos_resolvepath again with different flags to resolve the leafname part of the path.

Parameters:

  • HL(U): Pointer to the path to resolve
  • IX(U): Pointer to destination buffer to store the resolved path (optional - set to zero for length count only)
  • DE(U): Length of the destination buffer
  • IY(U): Pointer to a directory object to persist between calls (optional, set to zero to omit)
  • B: Flags
  • C: Index of the resolved path (zero for first call)

Path resolution will resolve prefixes in files paths, which are a string followed by a colon character, such as Library:. The string must match up with a corresponding system variable, in this example the variable would be named Library$Path. Prefixes are not case-sensitive, so library:, Library: and LIBRARY: would all match in this example. Such path variables can contain multiple values separated by commas. The "index" argument in the C register is used to work out which prefix to use when there are multiple matches, and must be set to zero on a first call.

If you are resolving for a file that does not exist, the path will be resolved to the first matching directory, returning a "no file" (4 status code). If no matching directory can be found the path will not be resolved, and a "no path" (5 status code) will be returned, and the returned path will be empty. If the path is resolved successfully to an existing file the status code will be 0.

The flags argument is a bit-field used to indicate which files are valid to be returned. These bits are used to filter the results based on the file attributes, which are inherited from the file system (FatFS). If you wish to always return all results you should set the flags to 0. The bits are as follows:

Bit FatFS constant Description
0 AM_RDO Read only
1 AM_HID Hidden
2 AM_SYS System
3 n/a Reserved/Unused - set to zero
4 AM_DIR Directory
5 AM_ARC Archive
6 n/a Set to disable system variable expansion
7 n/a Include/exclude in results

System variable expansion passes the source path through the GSTrans process, replacing any system variables used in the path with their values. If you have already performed this step then you can set bit 6 to disable the expansion.

Bit 7 is used to indicate how to apply the attributes to filter results. When it is set, any result must include all of the attributes set. When it is clear, the result will not include any of the attributes set. This can be used, for example, to filter out hidden or system files, or alternatively to only include results that are directories.

NB any attributes that are not set in the flags argument will be ignored, so if you perform a search with a flags value of 0x06, which will filter out hidden and system files, your results may include items that have their directory, read-only, and/or archive bits set. Similarly a search with a flags value of 0x90 will only include directories, but those directories could have any of the other attributes set.

If you wish to further filter results you should pass in a DIR object in IY(U) to persist between calls, and use the ffs_stat API call to get a FILINFO object where you can check the full attributes of the the returned result (stored in the fattrib field). If the results do not match your requirements you can then call mos_resolvepath again to find the next matching file.

If the leafname in your path contains wildcards then the first matching file will be returned. If you wish to find the next matching file then you should provide a pointer to an empty directory object in IY(U) with your first call, and use the same object with subsequent calls (also using the same C register value). If you do not include a pointer to a directory object then only the first matching file within a single directory will be returned.

Besides finding filecard matches, the other main use for this API is to resolve a path so that it can be used with FatFS API calls. This step is needed to ensure that the path is fully resolved, as the FatFS API calls do not support using path prefixes or system variables. Attempting to use an unresolved path with a fatfs API call may either fail or produce unexpected results.

It is not necessary to use this API call to resolve paths for use with the MOS-native API calls, as those will all automatically resolve paths for you.

Returns:

  • A: Status code (0 = Success, 22 = Out of memory, 5 = No path, 4 = No file)
  • C: Index of the resolved path (for next call)
  • DE(U): Length of the resolved path

If this is called with a null pointer in IX(U) then the maximum possible length of of all possible resolved paths will be returned in DE(U). This is useful if you wish to allocate a buffer for the resolved path, but do not know how long it will be.

A result of 5 indicates that no matching directory could be found in the filing system. A result of 4 indicates that a matching directory was found, but no matching file for that directory.

A result of 22 indicates that either the resolved path was too long for the buffer provided, or that there was an error allocating memory whilst searching for a matching path.

0x39: mos_getdirforpath

Get the directory for a given path.

This function works with strings only - it resolves path prefixes for the given index, but does not check whether the path actually points to a valid file or directory. The index is used which prefix to use when the path prefix variable contains multiple options.

The returned path will be the directory part of the path, and will not include the leafname.

Parameters:

  • HL(U): Pointer to the path to get the directory for
  • IX(U): Pointer to the buffer to store the directory in (optional - omit for count only)
  • DE(U): Length of the buffer
  • C: Search index

Returns:

  • A: Status code
  • DE(U): Length of the directory path

0x3A: mos_getleafname

Get the leafname for a given path.

This is a utility function that will scan a file path string and return a pointer within that string to the leafname. The leafname is the last part of a file path, and may refer to a file or a directory. This call does not check whether the path actually points to a valid file or directory, and it does not resolve any path prefixes. It should be noted that a leafname may be empty if the path is empty or ends with a / or : character.

If the path does not contain a valid leafname then the function will return a pointer to the end of the string.

Parameters:

  • HL(U): Pointer to the path to get the leafname from

Returns:

  • HL(U): Pointer to the leafname

0x3B: mos_isdirectory

Checks if a given path points to a directory

NB this call only works with fully resolved paths, and as such does not perform path prefix resolution. You may therefore need to use mos_getdirforpath or mos_resolvepath first.

Parameters:

  • HL(U): Pointer to the path to check

Returns:

  • A: Status code (0 = Success, 5 = No path)

0x3C: mos_getabsolutepath

Get the absolute version of a (relative) path

(NB currently as of MOS 3.0a2 unlike similar functions above this API call does not support being called with a null pointer to count the length of the resolved path, and does not return the length.)

Parameters:

  • HL(U): Pointer to the path to get the absolute version of
  • IX(U): Pointer to the buffer to store the absolute path in
  • DE(U): Length of the buffer

Returns:

  • A: Status code

If the buffer is too short for the resolved path then a status code of 22 (Out of memory) will be returned. Path resolution problems may result in status codes of 5 (No path) or 4 (No file).


FatFS commands

MOS makes use of the FatFS library to access the SD card. Some of FatFS's functionality is exposed as APIs in MOS. These APIs are essentially provide a way to call the underlying FatFS functions that MOS uses to perform file operations. The API calls are prefixed with ffs_ to indicate that they are FatFS functions, and the mos_ prefix is used for the native MOS API calls.

Our naming convention for FatFS APIs in MOS is to remove the f_ prefix from the FatFS function name, and replace it with ffs_, plus an optionally f or d prefix. For example, the API that exposes the f_open FatFS function is named ffs_fopen.

The variety of FatFS APIs supported in the MOS 1.x and MOS 2.x releases was limited to a restricted subset of functionality. MOS 3.0 includes support for all of the FatFS API calls that our current FatFS configuration supports. The documentation below describes all potential FatFS API calls, including those not supported by our configuration - those APIs that are not supported will a status value of 23 (Not implemented) in the A register. Future versions of MOS may include support for additional API calls, and the documentation will be updated to reflect this.

Please note that the FatFS API calls documented below expect file paths to be fully resolved, i.e. they should not include path prefixes or system variables. This means programs running on MOS 3 should use the mos_resolvepath API call to resolve any paths before using them with a FatFS API call. If you do not resolve the path then the FatFS API call may fail or produce unexpected results. For many API calls you can instead open the file using the MOS API call mos_fopen and then use mos_getfil to get a pointer to a FIL structure that many FatFS API calls require.

For more information on FatFS data structures (the FIL, DIR and FILINFO objects), functions, and info on which bits to set in fields such as "File open mode" please see the FatFS documentation. The FatFS configuration can affect the contents of these data structures - our configuration has the FF_USE_LFN and FF_USE_FIND options set, and does not set FF_READ_ONLY or FF_USE_FASTSEEK.

0x80: ffs_fopen

Open a file (Requires MOS 1.03 or above)

Parameters:

  • HL(U): Pointer to an empty FIL structure
  • DE(U): Pointer to a C (zero-terminated) filename string
  • C: File open mode

The file open mode on this API is a bit-field that is identical to the mode used in the mos_fopen API call.

Returns:

  • A: FRESULT

Preserves: HL(U), DE(U), C

Example:

            LD  HL, fil             ; FIL buffer
            LD  DE, filename            ; Filename (0 terminated)
            LD  C, fa_read          ; Mode
            MOSCALL ffs_fopen           ; Open the file
            LD  DE, buffer          ; Where to store the read file
            LD  BC, 256             ; Number of bytes to read
            MOSCALL ffs_fread           ; Read the data in
            PUSH    BC              ; Preserve number of bytes read
            MOSCALL ffs_fclose          ; Close the file
            POP BC              ; BC: Number of bytes read
            RET

filename:       DB  "example.txt", 0        ; The file to read

fil:            DS  FIL_SIZE            ; FIL buffer (defined in mos_api.inc)
buffer:         DS  256             ; Buffer for storing read data

0x81: ffs_fclose

Close a file (Requires MOS 1.03 or above)

Parameters:

  • HL(U): Pointer to a FIL structure

Returns:

  • A: FRESULT

Preserves: HL(U)

See ffs_fopen for an example.

NB: you should not use this call to close a file that had been opened using mos_fopen, as doing so will mean that MOS will be reserving an file handle for a file that has been closed.

0x82: ffs_fread

Read from a file (Requires MOS 1.03 or above)

Parameters:

  • HL(U): Pointer to a FIL structure
  • DE(U): Pointer to a buffer to store the data in
  • BC(U): Number of bytes to read (typically the size of the buffer)

Returns:

  • A: FRESULT
  • BC(U): Number of bytes read

Preserves: HL(U), DE(U)

See ffs_fopen for an example

0x83: ffs_fwrite

Write to a file (Requires MOS 1.03 or above)

Parameters:

  • HL(U): Pointer to a FIL structure
  • DE(U): Pointer to a buffer to read the data from
  • BC(U): Number of bytes to write (typically the size of the buffer)

Returns:

  • A: FRESULT
  • BC(U): Number of bytes written

Preserves: HL(U), DE(U)

Example:

            LD  HL, fil             ; FIL buffer
            LD  DE, filename            ; Filename (0 terminated)
            LD  C, fa_write | fa_create_always  ; Mode
            MOSCALL ffs_fopen           ; Open the file
            LD  DE, buffer          ; Location of data to write
            LD  BC, 256             ; Number of bytes to write
            MOSCALL ffs_write           ; Write the data
            MOSCALL ffs_fclose          ; Close the file
            RET

filename:   DB  "example.txt", 0        ; The file to read

fil:        DS  FIL_SIZE            ; FIL buffer (defined in mos_api.inc)
buffer:     DS  256             ; Buffer containing data to write out

0x84: ffs_flseek

Move the read/write pointer in a file (Requires MOS 1.03 or above)

This API call can also be used to expand the file size, by moving the pointer to a location beyond the current end of the file. It should be noted that the extra allocated disk space will not be cleared, so the data in the new space will be undefined.

Parameters:

  • HL(U): Pointer to a FIL structure
  • DE(U): Least significant 3 bytes of the offset from the start of the file
  • C: Most significant byte of the offset (set to 0 for files < 16MB)

Returns:

  • A: FRESULT

Preserves: HL(U), DE(U), BC(U)

0x85: ffs_ftruncate

Truncate a file to the current file pointer offset (Requires Console8 MOS 2.3.0 or above)

To truncate to a specified size you will need to use ffs_flseek to move the file pointer to the desired location before calling ffs_ftruncate.

Parameters:

  • HL(U): Pointer to a FIL structure

Returns:

  • A: FRESULT

Preserves: HL(U)

0x86: ffs_fsync

Flushes cached information of a writing file (Requires Console8 MOS 3.0 or above)

When writing to a file, file data may be cached in memory until the file is closed. This function will flush the cache to the SD card, ensuring that all data has been written. This can be useful to minimise the risks of data loss in the event of a power failure, SD card removal, or other unexpected shutdown.

Parameters:

  • HL(U): Pointer to a FIL structure

Returns:

  • A: FRESULT

0x87: ffs_fforward

This API is not implemented, as the FatFS f_forward function is not supported by the current configuration of the FatFS library used in MOS.

The documented purpose of the f_forward function is to read file data and forward it to a "data streaming device" (a callback function). It is unlikely that this feature would be enabled in the future as we do not have a clear use-case for it, and similar functionality can be achieved by other means.

Returns:

  • A: 23 (Not implemented)

0x88: ffs_fexpand

This API is not implemented, as the FatFS f_expand function is not supported by the current configuration of the FatFS library used in MOS.

The purpose of the f_expand function is to expand a file allocating a contiguous data area to the file. Files can be expanded using the ffs_flseek API, although this will not guarantee that the data area is contiguous. It is unlikely that this API will be implemented in the future, as on an SD card there is little advantage to be had in allocating a contiguous data area for a file.

Returns:

  • A: 23 (Not implemented)

0x89: ffs_fgets

Reads a string from a file (Requires MOS 3.0 or above)

Reads characters into a buffer until a newline \n character is reached, the end of file encountered, or the buffer is filled. The string read will be zero terminated.

It should be noted that this API does not return a status code in the A register.

Parameters:

  • HL(U): Pointer to a FIL structure
  • DE(U): Pointer to a buffer to store the string in
  • BC(U): Buffer size

Returns:

  • DE(U): Pointer to the target buffer, or NULL if an error occurred

Preserves: HL(U), BC(U)

0x8A: ffs_fputc

Writes a single character to a file (Requires MOS 3.0 or above)

It should be noted that this API does not return a status code in the A register.

Parameters:

  • HL(U): Pointer to a FIL structure
  • C: Character to write

Returns:

  • BC(U): Number of bytes written

Preserves: HL(U)

0x8B: ffs_fputs

Writes a zero-terminated string to a file. The termination character will not be written to the file. (Requires MOS 3.0 or above)

It should be noted that this API does not return a status code in the A register.

Parameters:

  • HL(U): Pointer to a FIL structure
  • DE(U): Pointer to a zero-terminated string

Returns:

  • BC(U): Number of bytes written

Preserves: HL(U), DE(U)

0x8C: ffs_fprintf

Whilst our configuration of FatFS does support the f_printf function, at this time an API call for it has not been implemented. This is because the function supports a variable number of arguments, and as of the MOS 3.0 release it is not clear how to implement this in a way that is consistent with the rest of the API calls.

This may be added in a future version of MOS, and if so would likely be restricted to code running in ADL mode, and return an error to code running in Z80 mode.

0x8D: ffs_ftell

Get the current read/write pointer of a file. (Requires MOS 3.0 or above)

Please note that this API call does not return a status code in the A register.

Parameters:

  • HL(U): Pointer to a FIL structure

Returns:

  • DE(U): Least significant 3 bytes of the offset from the start of the file
  • C: Most significant byte of the offset (set to 0 for files < 16MB). BC(U) is set to 0 before C is returned

Preserves: HL(U)

0x8E: ffs_feof

Detect end of file (Requires MOS 3.0 or above)

Please note that whilst this API has been present since MOS 1.03 its implementation had an error which meant that it would return the value of the L register passed in as a parameter, rather than the correct value. This was fixed in MOS 3.0.

Parameters:

  • HL(U): Pointer to a FIL structure

Returns:

  • A: 1 if at the end of the file, otherwise 0

Preserves: HL(U)

0x8F: ffs_fsize

Get the size of a file (Requires MOS 3.0 or above)

Please note that this API call does not return a status code in the A register.

Parameters:

  • HL(U): Pointer to a FIL structure

Returns:

  • DE(U): Least significant 3 bytes of file size
  • C: Most significant byte of the file size (set to 0 for files < 16MB). BC(U) is set to 0 before C is returned

Preserves: HL(U)

0x90: ffs_ferror

Tests for an error on a file (Requires MOS 3.0 or above)

Returns a non-zero value if a hard error has returned, otherwise will return a status of 0 (OK).

Parameters:

  • HL(U): Pointer to a FIL structure

Returns:

  • A: FRESULT

Preserves: HL(U)

0x91: ffs_dopen

Open a directory (Requires Console8 MOS 2.2.0 or above)

Parameters:

  • HL(U): Pointer to a blank DIR structure
  • DE(U): Pointer to a C (zero-terminated) directory path string

Returns:

  • A: FRESULT

Preserves: HL(U), DE(U)

0x92: ffs_dclose

Close a directory (Requires Console8 MOS 2.2.0 or above)

Parameters:

  • HL(U): Pointer to a DIR structure

Returns:

  • A: FRESULT

Preserves: HL(U)

0x93: ffs_dread

Read next directory entry into a FILINFO data structure (Requires Console8 MOS 2.2.0 or above)

Parameters:

  • HL(U): Pointer to a DIR structure
  • DE(U): Pointer to a FILINFO structure

Returns:

  • A: FRESULT

Preserves: HL(U), DE(U)

0x94: ffs_dfindfirst

Searches a directory for a matching item (Requires MOS 3.0 or above)

Parameters:

  • HL(U): Pointer to a blank DIR struct
  • DE(U): Pointer to a blank FILINFO struct
  • BC(U): Pointer to directory path string
  • IX(U): Pointer to matching pattern string

The directory path provided in BC(U) must be a fully resolved path, and the matching pattern in IX(U) should be a zero-terminated string. The matching pattern can include wildcards, such as * and ?, and will be used to match against the directory entries. Subsequent entries can be found using ffs_dfindnext passing in the same DIR structures as passed to this call, and the pattern string must also be preserved.

If a matching file is found, the FILINFO structure will be populated with information about the file.

Returns:

  • A: FRESULT

Preserves: HL(U), DE(U), BC(U), IX(U)

0x95: ffs_dfindnext

Find next matching item in a directory (Requires MOS 3.0 or above)

This API call is used to find the next matching item in a directory after a successful call to ffs_dfindfirst. It will return the next matching file or directory in the same way as ffs_dfindfirst, but will not require the path and pattern strings to be passed in again. Please note that whilst it is not a parameter for this API, the pattern string passed to ffs_dfindfirst must be preserved, as it will be used to match against the directory entries.

Parameters:

  • HL(U): Pointer to a DIR structure, as set up by ffs_dfindfirst
  • DE(U): Pointer to a FILINFO structure

Returns:

  • A: FRESULT

Preserves: HL(U), DE(U)

0x96: ffs_stat

Get file information (Requires MOS 1.03 or above)

Parameters:

  • HL(U): Pointer to a FILINFO structure
  • DE(U): Pointer to a C (zero-terminated) filename string

Returns:

  • A: FRESULT

Preserves: HL(U), DE(U)

Example:

            LD  HL, filinfo             ; FILINFO buffer
            LD  DE, filename            ; Filename (0 terminated)
            MOSCALL ffs_stat
            RET

filename:   DB  "example.txt", 0        ; The file to read

filinfo:    DS  FILINFO_SIZE            ; FILINFO buffer (defined in mos_api.inc)

Removes ("unlinks") a file or sub-directory from the volume (Requires MOS 3.0 or above)

Parameters:

  • HL(U): Pointer to a zero-terminated file path string

Returns:

  • A: FRESULT

Preserves: HL(U)

0x98: ffs_rename

Rename and/or move a file or sub-directory (Requires MOS 3.0 or above)

This is a raw rename function that does not perform any path resolution, and does not support wildcards. For more sophisticated behaviour you should use the mos_ren API instead.

Parameters:

  • HL(U): Pointer to a zero-terminated source file path string
  • DE(U): Pointer to a zero-terminated destination file path string

Returns:

  • A: FRESULT

Preserves: HL(U), DE(U)

0x99: ffs_chmod

This API is not implemented, as the FatFS f_chmod function is not supported by the current configuration of the FatFS library used in MOS.

The purpose of the f_chmod function is to change the attributes set against a file or directory. A future version of MOS may include support for this API.

Returns:

  • A: 23 (Not implemented)

0x9A: ffs_utime

This API is not implemented, as the FatFS f_utime function is not supported by the current configuration of the FatFS library used in MOS.

The purpose of the f_utime function is to change the timestamp of a file or directory. A future version of MOS may include support for this API.

Returns:

  • A: 23 (Not implemented)

0x9B: ffs_mkdir

Creates a new directory (Requires MOS 3.0 or above)

Parameters:

  • HL(U): Pointer to a zero-terminated directory name string

Returns:

  • A: FRESULT

0x9C: ffs_chdir

Change the current working directory (Requires MOS 3.0 or above)

It is strongly recommended to use the mos_cd API API call instead of this one, as it will automatically resolve the path for you. Using this API may result in MOS not understand the current working directory until a call to mos_cd is made or a version of the CD command is run.

Parameters:

  • HL(U): Pointer to a zero-terminated directory name string

Returns:

  • A: FRESULT

0x9D: ffs_chdrive

This API is not implemented, as no Agon platform computer currently supports multiple drives.

0x9E: ffs_getcwd

Get the current working directory (Requires Console8 MOS 2.2.0 or above)

Parameters:

  • HL(U): Pointer to a buffer to store the directory path in
  • BC(U): Maximum length of the buffer

Returns:

  • A: FRESULT

Preserves: HL(U), BC(U)

0x9F: ffs_mount

Mounts a volume/SD card (Requires MOS 3.0 or above)

Whilst this API has documented parameters, as the current hardware configurations of Agon machines do not support multiple volumes or drives all of the parameters will be ignored. They are documented here for completeness, and to allow for future expansion of the API in case a future Agon model is released that does support multiple SD cards. For future compatibility you are advised to set all parameters to zero.

Parameters:

  • HL(U): Pointer to a blank FATFS FATFS structure (set to zero)
  • DE(U): Pointer to a zero-terminated volume path string (set to zero)
  • C: Options byte (set to zero)

Returns:

  • A: FRESULT

0xA0: ffs_mkfs

This API is not implemented, as the FatFS f_mkfs function is not supported by the current configuration of the FatFS library used in MOS.

Returns:

  • A: 23 (Not implemented)

0xA1: ffs_fdisk

This API is not implemented, as the FatFS f_fdisk function is not supported by the current configuration of the FatFS library used in MOS.

Returns

  • A: 23 (Not implemented)

0xA2: ffs_getfree

Get free space information on a volume (Requires MOS 3.0 or above)

Please note that this call does not directly return the number of free bytes on the volume, but instead returns the number of free clusters and the size of each cluster. The number of free bytes can be calculated by multiplying these two values together.

Parameters:

  • HL(U): Pointer to a path string (ideally caller should set this to zero)
  • DE(U): Pointer to a block of memory to store number of free clusters, 32-bit value
  • BC(U): Pointer to a block of memory to store cluster size, 32-bit value

Returns:

  • A: FRESULT

Whilst this API will let you pass in a pointer to a path in the HL(U) register, you are recommended to set this to 0, as the way that MOS uses FatFS means that the path is not needed, and the call will likely fail if any path other than an empty string is provided. This API call also differs slightly from the underlying f_getfree function which does not directly return the cluster size, but instead returns a pointer to the FATFS structure for the volume, which will contain the cluster size. As the FATFS structure is sensitive to the FatFS configuration and may change in future versions of MOS, we have chosen to return the cluster size directly instead.

0xA3: ffs_getlabel

Gets the label of a volume (Requires MOS 3.0 or above)

  • HL(U): Pointer to a path string (ideally caller should set this to zero)
  • DE(U): Pointer to a buffer to store the label in (for safety and future proofing this should be 23 bytes long)
  • BC(U): Pointer to a block of memory to store the 32-bit volume serial number

Returns:

  • A: FRESULT

As with the ffs_getfree API you should set the HL(U) parameter to 0, as the way that MOS uses FatFS means that the path is not needed, and the call will likely fail if any path other than an empty string is provided.

It should be noted that this API call does not include a parameter for the size of the buffer to store the label in. If your buffer is not large enough any memory after the label may be overwritten. As of MOS 3.0 the maximum size of a volume label is 12 bytes (11 characters plus a zero terminator), however for future proofing you are advised to ensure your buffer is 23 bytes long. The reason for this is that in the future we may enable support for discs using the exFAT filing system, which supports longer volume labels.

0xA4: ffs_setlabel

Sets the label of a volume (Requires MOS 3.0 or above)

Please note that the label string must be a valid FAT volume label, which basically means that it must be 11 characters or less. Setting a label to an empty string will remove the label.

Owing to how filing systems work some labels may be rejected, and characters may be converted to upper-case. The f_setlabel function that this API calls will attempt to look for a "drive prefix" in the label to specify a drive number, but owing to how we use FatFS in MOS this will not work. As such you should not include a drive prefix in the label.

Parameters:

  • HL(U): Pointer to a zero-terminated volume label string

Returns:

  • A: FRESULT

0xA5: ffs_setcp

This API is not implemented, as the FatFS f_setcp function is not supported by the current configuration of the FatFS library used in MOS.

The purpose of f_setcp is to set the active code page for file paths, and this is not available as our FatFS configuration is restricted to a single code page. Adding this feature would greatly expand the size of FatFS, and consequently also MOS, which would almost certainly exceed the available flash space on the eZ80. As such it is highly unlikely that this API will be implemented in the future.

Returns:

  • A: 23 (Not implemented)

Status Codes

Many MOS API calls will return a status code in the A register. In general these follow a consistent set of result values, with a few exceptions which are documented against the individual API calls. Programs and commands will also return a status code when they complete. If you are using MOS 3, the status code value can be captured in a system variable if the command or program is run using the try command.

API calls that are documented above as returning an FRESULT value are returning a status code from the FatFS library. These directly equate to status codes 0-19 in the table below.

Status codes can be translated into a human-readable string using the mos_getError API call.

The possible status codes are as follows:

Code Error message Description
0 OK Call succeeded (NB this will not be displayed when running a program or star command)
1 Error accessing SD card An error has occurred when trying to access the SD card
2 Internal error An internal error has occurred. Generally, if possible, a more specific error will be used
3 SD card failure The SD card has failed
4 Could not find file The file could not be found
5 Could not find path The path could not be found
6 Invalid path name The path name is invalid
7 Access denied or directory full A file could not be saved to a directory either because of an access error or too many files in the directory
8 Access denied A file or directory cannot be accessed because it is not readable
9 Invalid file/directory object This is an internal filing system error
10 SD card is write protected The SD card cannot be written to as it is write protected
11 Logical drive number is invalid This is an internal filing system error, which should not occur
12 Volume has no work area This is an internal filing system error
13 No valid FAT volume The SD card does not contain a FAT format volume your Agon can understand
14 Error occurred during mkfs This is an internal filing system error
15 Volume timeout A problem has occured attempting to access your SD card
16 Volume locked The FAT volume cannot be written to
17 LFN working buffer could not be allocated This is an internal filing system error
18 Too many open files Occurs when too many separate files have been opened
19 Invalid parameter A parameter for the command or API is incorrect
20 Invalid command The command was not recognised or found on disc
21 Invalid executable An executable program does not have a valid header
22 Out of memory Either MOS has run out of internal memory, or a buffer provided to an API was not large enough
23 Not implemented The API call is not implemented in this version of MOS
24 Load overlaps system area File load prevented to stop overlapping system memory
25 Bad string A bad or incomplete string has been encountered
26 Too deep Too many nested commands have been detected
This is usually caused by a faulty alias definition including file load/run types

Please note that Quark MOS 1.04 will only return status codes 0-21. The Console8 MOS 2.x release series added status codes 22-25, and MOS 3.0 added status code 26.

System State Variables (SysVars)

The MOS API command mos_sysvars returns a pointer to the base of the MOS SysVars (system state variables) area in IXU as a 24-bit pointer. These are different from System Variables which can be used in commands and scripts, so these these internal MOS system state variables are often simply referred to as sysvars.

The following sysvars are available in mos_api.inc:

; System variable indexes for api_sysvars
; Index into _sysvars in globals.asm
;
sysvar_time:            EQU 00h ; 4: Clock timer in centiseconds (incremented by 2 every VBLANK)
sysvar_vpd_pflags:      EQU 04h ; 1: Flags to indicate completion of VDP commands
sysvar_keyascii:        EQU 05h ; 1: ASCII keycode, or 0 if no key is pressed
sysvar_keymods:         EQU 06h ; 1: Keycode modifiers
sysvar_cursorX:         EQU 07h ; 1: Cursor X position
sysvar_cursorY:         EQU 08h ; 1: Cursor Y position
sysvar_scrchar:         EQU 09h ; 1: Character read from screen
sysvar_scrpixel:        EQU 0Ah ; 3: Pixel data read from screen (R,B,G)
sysvar_audioChannel:    EQU 0Dh ; 1: Audio channel
sysvar_audioSuccess:    EQU 0Eh ; 1: Audio channel note queued (0 = no, 1 = yes)
sysvar_scrWidth:        EQU 0Fh ; 2: Screen width in pixels
sysvar_scrHeight:       EQU 11h ; 2: Screen height in pixels
sysvar_scrCols:         EQU 13h ; 1: Screen columns in characters
sysvar_scrRows:         EQU 14h ; 1: Screen rows in characters
sysvar_scrColours:      EQU 15h ; 1: Number of colours displayed
sysvar_scrpixelIndex:   EQU 16h ; 1: Index of pixel data read from screen
sysvar_vkeycode:        EQU 17h ; 1: Virtual key code from FabGL
sysvar_vkeydown         EQU 18h ; 1: Virtual key state from FabGL (0=up, 1=down)
sysvar_vkeycount:       EQU 19h ; 1: Incremented every time a key packet is received
sysvar_rtc:             EQU 1Ah ; 8: Real time clock data
sysvar_keydelay:        EQU 22h ; 2: Keyboard repeat delay
sysvar_keyrate:         EQU 24h ; 2: Keyboard repeat rate
sysvar_keyled:          EQU 26h ; 1: Keyboard LED status
sysvar_scrMode:         EQU 27h ; 1: Screen mode (from MOS 1.04)
sysvar_rtc_enable:      EQU 28h ; 1: RTC enable status (from Console8 MOS 2.0.0)
sysvar_mouseX:          EQU 29h ; 2: Mouse X position
sysvar_mouseY:          EQU 2Bh ; 2: Mouse Y position
sysvar_mouseButtons:    EQU 2Dh ; 1: Mouse left+right+middle buttons (bits 0-2, 0=up, 1=down)
sysvar_mouseWheel:      EQU 2Eh ; 1: Mouse wheel delta
sysvar_mouseXDelta:     EQU 2Fh ; 2: Mouse X delta
sysvar_mouseYDelta:     EQU 31h ; 2: Mouse Y delta

Example: Reading a virtual keycode in ADL mode (24-bit):

        MOSCALL mos_getkey
        LD  A, (IX + sysvar_vkeycode)   ; Load A with the virtual keycode from FabGL

Example: Reading a virtual keycode in Z80 mode (16-bit):

        MOSCALL mos_getkey
        LD.LIL  A, (IX + sysvar_vkeycode)   ; Load A with the virtual keycode from FabGL

For efficiency, the real-time clock data in the sysvars is stored in a packed format, using subsets of bits within the 8 bytes of the sysvar_rtc data. An API is provided from MOS 3 onwards to allow for this to be unpacked mos_unpackrtc into a buffer in a friendlier, more easy to use format. MOS uses the following C function to unpack the RTC data into a vdp_time_t object:

void rtc_unpack(UINT8 * sysvar_rtc, vdp_time_t * t) {
    UINT32  d = *(UINT32 *)sysvar_rtc;

    t->month =      (d & 0x0000000F);       // uint32_t month : 4;      00000000 00000000 00000000 0000xxxx : 00 00 00 0F >> 0
    t->day =        (d & 0x000001F0) >> 4;  // uint32_t day : 5;        00000000 00000000 0000000x xxxx0000 : 00 00 01 F0 >> 4
    t->dayOfWeek =  (d & 0x00000E00) >> 9;  // uint32_t dayOfWeek : 3;  00000000 00000000 0000xxx0 00000000 : 00 00 0E 00 >> 9
    t->dayOfYear =  (d & 0x001FF000) >> 12; // uint32_t dayOfYear : 9;  00000000 000xxxxx xxxx0000 00000000 : 00 1F F0 00 >> 12
    t->hour =       (d & 0x03E00000) >> 21; // uint32_t hour : 5;       000000xx xxx00000 00000000 00000000 : 03 E0 00 00 >> 21
    t->minute =     (d & 0xFC000000) >> 26; // uint32_t minute : 6;     xxxxxx00 00000000 00000000 00000000 : FC 00 00 00 >> 26

    t->second = sysvar_rtc[4];
    t->year = (char)sysvar_rtc[5] + 1980;
}