Routines of UniDOS

This chapter is dedicated to application developpers who wish to improve their software by adding some UniDOS specific support (sush as native directory browsing, physical drive selection, large file support…). It can be done easily with very little code adds, and unless you are using advanced UniDOS features you will be able to keep full AMSDOS compatibility; your program will run on both stock CPC and UniDOS equipped machine.

UniDOS is designed in a way that the programs created to run under AMSDOS and normally restricted to floppy discs can directly take advantage of new mass storage drives and directory handling without any modification. That said, legacy CAS indirections provided by UniDOS do implement new features that you can easily take advantage of. Moreover, if some programs whish to provide even more when they are ran under UniDOS, a new BIOS vector can be used with only a few additional code. Detection of this new CRTL-J vector is basically the right method to know if your program run under UniDOS or not, and then activate your dedicated code.

Note: the file “UniDOS.i” available in the source code archive contains all the commands definition and error codes you will need in your programs which are taking advantage of UniDOS features.

CAS indirections

Herafter is a description of all the new features which are available when using CAS indirections of UniDOS.

CAS_IN_OPEN

This vector behaves like the one from AMSDOS apart of the following cases:

  • If a directory name is provided at input, then you will have in return:
    • Carry = 0,
    • Zero = 1,
    • A = DSK_ERR_DIRECTORY_FOUND (with bit 7 set),
    • If the feature is not disabled (see cmd_disabled_directory) then the current logical drive will be assigned to the new directory.
  • If an explicit directory is provided at input (a path ending with “/”) and it matches a file instead of a directory, then you will have in return:
    • Carry = 0,
    • Zero = 1,
    • A =DSK_ERR_NOT_A_DIRECTORY
  • The 2 KiB buffer provided by DE will not be used when the file is eventually accessed through cmd_cas_in_read1).

CAS_IN_CLOSE

This vector behaves like the one from AMSDOS.

CAS_IN_ABANDON

This vector behaves like the one from AMSDOS.

CAS_IN_CHAR

This vector behaves like the one from AMSDOS.

CAS_IN_DIRECT

This vector behaves like the one from AMSDOS.

CAS_RETURN

This vector behaves like the one from AMSDOS.

CAS_TEST_EOF

This vector behaves like the one from AMSDOS.

CAS_OUT_OPEN

This vector behaves like the one from AMSDOS apart of the following cases:

  • If an explicit directory name is given at input (path ending with a “/”):
    • Carry = 0,
    • Zero = 1,
    • A = DSK_ERR_DIRECTORY_FOUND (with bit 7 set),
    • A directory of this name is created.

CAS_OUT_CLOSE

This vector behaves like the one from AMSDOS.

CAS_OUT_ABANDON

This vector behaves like the one from AMSDOS.

CAS_OUT_CHAR

This vector behaves like the one from AMSDOS.

CAS_OUT_DIRECT

This vector behaves like the one from AMSDOS.

CAS_CATALOG

This vector behaves like the one from AMSDOS apart of the following cases:

  • The free space size is given using a 32-bit value stored in BCDE (AMSDOS returns only a 16-bit value in DE).
  • In the buffer, the entry marker is also used to store the size of the files which are larger than 65535 KiB2).
    • If &00, then the end of the buffer was reached (like with AMSDOS).
    • If not null, then an entry is present (like with AMSDOS), but also, bits 0 to 5 contain the reverted 6 most significant bits of the file size expressed in 24-bit. For instance:
      • If &FF (like AMSDOS) then the file do have a size which fits in the legacy 16-bit (reverted bits 0 to 5 are then all zero).
      • If &FE then 65536 KiB (&010000, reverted bits 0 to 5 are equal to &01) must be added to the 16-bit legacy size to obtain the real file size.
  • In a buffer, if a file is both read-only3) and with a size of 0 bytes, then it is a directory.

BIOS vectors

UniDOS implements all AMSDOS standard vectors. Some of then are providing a full AMSDOS compatiblity, while others will be disabled when UniDOS is activated4).

CTRL-A

Identical to AMSDOS.

CTRL-B

No effect when UniDOS is active.

CTRL-C

No effect when UniDOS is active.

CTRL-D

No effect when UniDOS is active.

CTRL-E

No effect when UniDOS is active.

CTRL-F

No effect when UniDOS is active.

CTRL-G

Identical to AMSDOS.

CTRL-H

Identical to AMSDOS.

CTRL-I

Identical to AMSDOS.

CTRL-J (new)

In addition to BIOS vectors CTRL-A à CTRL-I provided by AMSDOS, UniDOS also implements a new BIOS vector CTRL-J. Any program which wants to take advantage of new features when UniDOS is available will just have to detect this vector; when missing, then it should simply fallback to the legacy AMSDOS code.

This new BIOS vector CTRL-J can be detected exactly like BIOS vectors of AMSDOS through a RSX find:

;
; Detect CTRL-J vector
; Input   - N/A
; Output  - If Carry = 1 then the vector was found and the associated "far call" is ready for calling
;           If Carry = 0 then the vector was not found
; Altered - AF,BC,DE,HL

IsUniDOS
        LD HL,RSX_BIOS_CTRL_J
        CALL KL_FIND_COMMAND
        RET NC
; Here HL = CTRL-J vector address
; and C = ROM slot where it is located
        LD (FARCALL_CTRL_J),HL
        LD A,C
        LD (FARCALL_CTRL_J+2),A
; We configure the "far call" associated
; That we could easily call
; avec un RST 3,FALCALL_CTRL_J
        RET
RSX_BIOS_CTRL_J
        DB &8A
FARCALL_CTRL_J
        DS 3

All the commands provided by this new vector do have the same semantic:

; Input   - C = command identifier
;            Value of the other registers depends on the command
; Ouput   - If Carry = 1 then the command could be executed
;               Value of other registers at output depends on the command
;           If Carry = 0 then the command is unknown or input is invalid
; Altered - Only ouput registers specific to the command

Hereafter is the list of the available commands.

cmd_cat_faked_parent (0)

;       Activate "parent" (/) entry in the catalog buffer
;           Input  - A = status, &FF=No (default), &00=Yes
;           Output - A = previous status

When activated, CAS_CATALOG will add an entry “/” in 1st position in the buffer pointed by DE, which is representing the parent directory.

Please note that this entry will not be added if there is no parent (basically when you are already at media root).

cmd_device_list (1)

;       Return the list of the physical drives
;             Input  - DE = address of a 64 bytes buffer where to store the list
;             Output - DE = address of the 64 bytes buffer where the list has been stored
;                              Each name is a string terminated by a character with bit 7 set.
;                              A 255 marks the end of the list

This command is useful to any program that want to provide a dynamic menu for the choice of the current device.

cmd_device_info (2)

;       Return detailled information about a physical drive
;           Input  - HL = pointer to the name of the physical drive (string terminated by a character with bit 7 set, stored in RAM)
;                    DE = address of a 64 bytes buffer to store the information
;           Sortie - DE = address of the 64 bytes buffers filled with information
;                            One byte with physical drive attributes
;                                Bit0 = 1 if a media is available in this drive
;                                Bit1 = 1 if the media handles directories
;                                Bit2 = 1 if the media is write protected
;                                Bit3 = 1 if the media is removable
;                                Bit4 = 1 if the media is astream (linear read/write only)
;                                Bit5 = 1 if the media can be accessed through the new UniDOS API
;                            One byte identifying the file system (always 255, not handled for now)
;                            One 32-bit word with the amount of free kilo-bytes
;                                &ffffffff if this information is not available for this drive
;                            One 32-bit word with the total capacity in kilo-bytes
;                                &ffffffff if this information is not available for this drive
;                            A description in the form of a string terminated by a character with bit 7 set
;       Disable symbolic link management in CAS IN OPEN
;           Input  - A = status, &FF=No (default), &00=Yes
;           Output - A = previous status

When links are disabled, they are handled like regular files during CAS_IN_OPEN and their contents can be analyzed.

Symbolic links are then shown as files of type 8.

cmd_emulate_soft_eof (4)

;       Activate emulation of software end of file tag like AMSDOS
;       (&1A value inside 128 bytes records)
;           Input  - A = status, &FF=No (default), &00=Yes
;           Output - A = previous status

AMSDOS is adding a byte &1A to tag the end of the files when it occurs in the middle on a 128 bytes record5). UniDOS do not require this tag because it always knows the real size of the files in bytes. By the way, in case this byte wouldbe useful for compatibility, activating this feature will make CAS_IN_CHAR and CAS_IN_DIRECT to add it on-the-fly at the ned of files (only when the end of the file occurs in the middle on a 128 bytes record, just like AMSDOS does).

cmd_cas_in_read (5)

;       Read on input stream
;       Only possible with drives which are compatible with the new UniDOS API
;       Cannot be used together with CAS IN DIRECT or CAS IN CHAR
;       The 2K buffer provided at CAS_IN_OPEN will never be used
;           Input  - HL = address where to store read data
;                     DE = number of bytes to read
;           Output - If Z then data were read
;                        DE = number of byte actually read
;                        A is undefined
;                    If NZ then an error occured
;                        A = error code

This command provides a modern access to files, without the constraints of CAS_IN_CHAR and CAS_IN_DIRECT.

cmd_cas_in_seek (6)

;       Change current position in the input stream
;       Only possible with drives which are compatible with the new UniDOS API
;       Cannot be used together with CAS IN DIRECT or CAS IN CHAR
;           Input  - DEHL = new position in the stream
;           Output - If Z then the new position was reached
;                        A is undefined
;                    If NZ then an error occured
;                        A = error code

This command provides a modern access to files, without the constraints of CAS_IN_CHAR and CAS_IN_DIRECT. Please note that it is not available for drives of type “stream” which are not able to freely navigate into files.

cmd_cas_out_write (7)

;       Write to output stream
;       Only possible with drives which are compatible with the new UniDOS API
;       Cannot be used together with CAS_OUT_DIRECT or CAS OUT CHAR
;       The 2K buffer provided at CAS_OUT_OPEN will never be used
;           Input  - HL = address where a located data to write
;                     DE = number of bytes to write
;           Output - If Z then data were written
;                        DE = number of bytes actually written
;                        A is undefined
;                    If NZ then an error occured
;                        A = error code

This command provides a modern access to files, without the constraints of CAS_OUT_CHAR and CAS_OUT_DIRECT.

cmd_cas_out_seek (8)

;       Change current position in the output stream
;       Only possible with drives which are compatible with the new UniDOS API
;       Cannot be used together with CAS OUT DIRECT or CAS OUT CHAR
;           Input  - DEHL = new position in the stream
;           Output - If Z then the new position was reached
;                        A is undefined
;                    If NZ then an error occured
;                        A = error code

This command provides a modern access to files, without the constraints of CAS_OUT_CHAR and CAS_OUT_DIRECT. Please note that it is not available for drives of type “stream” which are not able to freely navigate into files.

cmd_disabled_directory (9)

;       Disable directory handling in CAS IN OPEN
;           Input  - A = status, &FF=No (default), &00=Yes
;           Output - A = previous status

When the directory handling is disabled, CAS_IN_OPEN will not allow to enter directories anymore (no logical drive automatic assignation). It might be useful to detect a directory and do some specific treatment (with is the case of a copy software that will not do the same operation in the source is a file or a directory).

In anycase, the error DSK_ERR_DIRECTORY_FOUND is reported in case a directory name is provided to CAS_IN_OPEN.

cmd_enabled_sort_dir_first (10)

;       Activate directory sorting before files during CAS IN CATALOG
;           Input  - A = status, &FF=No (default), &00=Yes
;           Output - A = previous status

This command makes CAS IN CATALOG to first sort directories, then files.

cmd_is_active_dosnode (11)

;       Return activation status of a ROM containing a DOS node
;           Input  - A = slot number of the ROM
;           Output - If Z then the ROM is an active DOS node
;                    If NZ then the ROM is either an inactive DOS node or not a DOS node at all

cmd_examine (12)

;       Check that a file or a directory exists and return associated information
;           Input  - HL = name of the file or directory to examine
;                    B = length of the file or directory name to examine
;                    IX = buffer where to store last modification time and date on the entry (7 bytes)
;           Output - If HL pointed to a file name or an explicit  directory name (non empty name and not finished by a '/')
;
;                        If Z then the file or directory exists
;                           A = protection bits of the entry
;                               Bit 0 - Read only
;                               Bit 1 - Hidden
;                               Bit 2 - System
;                               Bit 4 = Directory
;                               Bit 5 = Archived
;                           BCDE = Size of the entry (undefined if the entry is a directory)
;                           IX = buffer where last modification time and date of the entry were stored
;                               One 16-bit word with year (1978..9999)
;                               One byte with number of month (1..12)
;                               One byte with number of day in the month (1..28,29,30 or 31)
;                               One byte with hours (0..23)
;                               One byte with minutes (0..59)
;                               One byte with seconds (0..59)
;                        If NZ then the file or directory could not be found
;                           A = error code
;
;                   If HL pointed to a explicit directory name (empty name or with a final '/')
;                        If Z the the directory is ready to be examined through ExamineNext
;                        If NZ then an error occurred
;                           A = error code

cmd_examine_next (13)

;       Retrieve the next entry in the directory being examined
;           Input  - HL = pointer to the memory where to store the normalized name of the entry (11 bytes)
;                    IX = buffer where to store last modification time and date of the entry (7 bytes)
;           Output - If Z then an entry was retrieved
;                        HL = pointer to the memory where the name of the entry was stored
;                        A = protection bits of the entry
;                            Bit 0 - Read only
;                            Bit 1 - Hidden
;                            Bit 2 - System
;                            Bit 4 = Directory
;                            Bit 5 = Archived
;                        BCDE = Size of the entry (undefined if the entry is a directory)
;                        IX = buffer where last modification time and date of the entry were stored
;                            One 16-bit word with year (1978..9999)
;                            One byte with number of month (1..12)
;                            One byte with number of day in the month (1..28,29,30 or 31)
;                            One byte with hours (0..23)
;                            One byte with minutes (0..59)
;                            One byte with seconds (0..59)
;                    If NZ then an error occurred
;                        A = error code (dsk_err_file_not_found indicates that all entries were retrieved)
1)
it is also not used in mode CAS_IN_DIRECT, like it was already the case with AMSDOS.
2)
the legacy 65535 KiB limit is due to the fact that AMSDOS stores the size using only 16-bit in the buffer
3)
bit 7 set in the first character of file extension
4)
in the case where UniDOS is disabled, AMSDOS BIOS vectors are all operating normally on floppy discs only
5)
AMSDOS is splitting files in 128 bytes records