BIOS File I/O
I/O management service for the CD-ROM, Memory Card and console devices.
| Open files | 16, of which 2 are standard I/O |
|---|---|
| Devices | cdrom, bu, tty |
This is an old revision of this page, as edited by RemmyLee at 02:45, 23 October 2026. Edit this revision | Latest revision
Overview
The PlayStation supports low-level access to files and logical devices through the I/O management service, and all file control on the PlayStation is performed with it.12 Each file system is reached through a device driver, which allows several file systems to coexist.3 The structures used for input and output are defined in sys/file.h.1
A file name starts with the device name. Examples are cdrom:PSX.EXE;1 and bu00:ABCD12345.1 Each device has a data access unit called its block size, and all data access is done in multiples of the block size. If a size given to read() or write() has a fraction, the fraction is discarded.1
Devices
The kernel supports the following devices.14
| Device name | Contents | Block size | Example of file designation |
|---|---|---|---|
| cdrom | CD-ROM file system | 2048 bytes | cdrom:PSX.EXE;1 |
| bu | Memory Card file system | 128 bytes | bu00:ABCD12345 |
| tty | Console (DUART or dummy) | 1 byte | tty00: |
Device names are lowercase and case-sensitive. A hexadecimal port number may follow the name, so "bu00:" selects the first Memory Card slot and "cdrom:" is short for "cdrom0:".56 Because a trailing hex digit is read as the port number, a device name must not end in a hex digit.5
CD-ROM File System
The CD-ROM file system conforms to the level 1 format of ISO 9660.1 Its rules are shown below.
| Item | Rule |
|---|---|
| Device name | cdrom |
| File format | basename.extension;version, with an 8-letter base name and an extension of up to 3 letters |
| Characters | English capital letters, numbers and underscore |
| Directory name format | Base name of 8 letters |
| Directory hierarchy | At most 8 levels, no root name |
| File arrangement | All sectors of a file are physically contiguous |
| Block size | 2048 bytes |
The file and directory lists are supported only as far as they fit in one 2048-byte sector. With standard 8.3 names this allows up to 45 directories and 30 files per directory, and shorter names allow more.1 A program can avoid the limits by keeping track of its own files and not using CdSearchFile().1
The PlayStation Operating System manual states a different rule: subdirectories cannot be created, all files are in the root directory, and the number of files there has no limit.7
cd() changes the default directory of a device. Only the directory is remembered, so every file name must still include the device name. The function does not check that the directory exists, and for the CD-ROM it reads the path table from the disc on every call.89 The kernel has no function for playing CD audio tracks or for setting the XA-ADPCM filter, so these require direct access to the CD-ROM ports.6
Memory Card File System
The Memory Card file system manages the files on the removable Memory Card used for saving game data. Mounting and initialization are performed by libcard BIOS calls.10
| Item | Rule |
|---|---|
| Device name | buXY, with X the port (0 for A, 1 for B) and Y the extension connector number (1 and up) or 0 |
| File format | ASCII base name of up to 20 bytes, with no extension |
| Directory structure | None |
| Block size | 128 bytes |
Before the file functions are used on a Memory Card, a program calls InitCARD2(), StartCARD2() and then _bu_init().11 The file size is fixed when the file is created: it must be a multiple of 0x2000 bytes (one block), up to 0x1E000 bytes for all 15 blocks, and is given in bits 16 to 31 of the access mode. The BIOS does not allow the size to change afterward.11 Reads and writes must be multiples of 0x80 bytes at positions aligned to 0x80 bytes, but they may cross block boundaries.11 The first 0x100 to 0x200 bytes of a file must hold its title and icon.11
The BIOS accesses only one sector per frame, and each slot only on every second frame. Consequently Memory Card access through the BIOS runs at about 0.5 sectors per frame.11 The device names bu01 to bu03 and bu11 to bu13 select extra cards on a Multi Tap. However, the BIOS keeps directory and broken sector buffers for only two cards, and using more cards may corrupt data.11 The Memory Card file system format page describes the data on the card.
Standard I/O Stream
The standard I/O stream reserves file descriptors 0 and 1.10 The PlayStation Operating System manual assigns standard output to descriptor 0 and standard input to descriptor 1, on RS232C channel 0 (tty00) with 8-bit characters, one stop bit and no parity under hardware flow control.12 On the game unit the stream is assigned to a NULL device, and in the development environment standard output goes to Debug Message Window #0.10
Several BIOS functions print status and error messages with printf(). Closing descriptors 0 and 1 therefore makes those functions unstable.13
Open Modes
open() opens a device for low-level input and output and returns a descriptor. The values of the open mode depend on the device.14
| Macro | Open mode |
|---|---|
| O_RDONLY | Read only |
| O_WRONLY | Write only |
| O_RDWR | Both read and write |
| O_CREAT | Create new file |
| O_NOBUF | Non-buffer mode |
| O_NOWAIT | Asynchronous mode |
The bits of the access mode word as the BIOS reads them are shown below.9
| Bit | Meaning |
|---|---|
| 0 | Read |
| 1 | Write |
| 2 | Return without waiting when the TTY buffer is empty |
| 9 | Create a new file (Memory Card only) |
| 15 | Asynchronous mode (Memory Card only) |
| 16 to 31 | Number of blocks for a new Memory Card file |
The BIOS ignores bits 0 and 1. However, at least one bit of the word must be set, or the open fails.9 Up to 16 files may be open at once. Two descriptors are reserved for standard I/O, and cd(), testdevice(), erase(), undelete(), format(), firstfile2() and rename() each borrow one internally. Consequently erase() fails when a game has more than 13 files open.9
File Functions
| Function | BIOS | Explanation |
|---|---|---|
| open(devname, flag) | A(00h), B(32h) | Opens a file and returns its descriptor, or -114 |
| lseek(fd, offset, flag) | A(01h), B(33h) | Moves the file pointer from SEEK_SET or SEEK_CUR15 |
| read(fd, buf, n) | A(02h), B(34h) | Reads n bytes and returns the number read, or -116 |
| write(fd, buf, n) | A(03h), B(35h) | Writes n bytes and returns the number written, or -117 |
| close(fd) | A(04h), B(36h) | Closes the file and returns fd, or -118 |
| ioctl(fd, com, arg) | A(05h), B(37h) | Executes a device control command19 |
| cd(path) | B(40h) | Changes the default directory8 |
| format(fs) | B(41h) | Initializes a writeable file system20 |
| firstfile(name, dir) | B(42h) | Finds the first file matching a name pattern21 |
| nextfile(dir) | B(43h) | Finds the next file matching the same pattern22 |
| rename(src, dest) | B(44h) | Changes a file name; both names include the device23 |
| erase(name) | B(45h) | Deletes a file (formerly called delete)24 |
| undelete(name) | B(46h) | Resurrects a deleted file25 |
| _get_errno() | B(54h) | Returns the latest I/O error code26 |
| _get_error(fd) | B(55h) | Returns the error code of one descriptor27 |
The BIOS function at B(42h) is named firstfile2 by psx-spx.28 lseek() from the end of a file (seek type 2) does not work in the BIOS, and movement past the end of a file is not checked.9 Sony notes that lseek() does not apply to a PC communication link.15 A read on the bu device proceeds in 0x80-byte units and on the cdrom device in 0x800-byte units, and a write to the cdrom device returns 0.9
Directory Entries
firstfile() and nextfile() store information about a file in a DIRENTRY structure. The wildcards "?" (any one character) and "" (any string) may be used in the name, and characters after "" are ignored.2129
struct DIRENTRY {
char name[20]; /* filename */
long attr; /* attributes (dependent on file system) */
long size; /* file size (in bytes) */
struct DIRENTRY *next; /* pointer to next file entry (for user) */
char system[8]; /* reserved by system */
};
| Offset | Size | Contents |
|---|---|---|
| 0x00 | 0x14 | File name, ended by 0x00 |
| 0x14 | 4 | Attribute (0 for CD-ROM; 0x50 normal or 0xA0 deleted for a Memory Card) |
| 0x18 | 4 | File size |
| 0x1C | 4 | Pointer to the next entry (not used by the BIOS) |
| 0x20 | 4 | First sector number |
| 0x24 | 4 | Reserved |
The offsets and attribute values are from psx-spx.9 nextfile() fails and reports that no file is found if the CD-ROM shell cover has been opened since the previous firstfile().22 set_card_find_mode(1) makes firstfile2() and nextfile() find deleted Memory Card files.11
Error Codes
_get_errno() returns the latest error code from all file descriptors, and the codes are defined in sys/errno.h.26 The code is not cleared by functions that succeed, so it is meaningful only after an error.9
| Code | Meaning |
|---|---|
| 0x00 | No error |
| 0x02 | File not found |
| 0x06 | Bad device port number (tty2 and up) |
| 0x09 | Invalid or unused file handle |
| 0x10 | General error (I/O error, unformatted card, disc changed) |
| 0x11 | File already exists (create, undelete, rename) |
| 0x12 | Rename across devices |
| 0x13 | Unknown device name |
| 0x16 | Sector alignment error, position past the end, unknown seek type or ioctl command |
| 0x18 | Not enough free file handles |
| 0x1C | Not enough free Memory Card blocks |
The codes are from psx-spx.9
CD-ROM Functions
The normal file functions read the CD-ROM synchronously and wait until all data is transferred. A file can be read asynchronously instead by finding its first sector with CdGetLbn() and reading with CdAsyncSeekL() and CdAsyncReadSector(). This works because CD-ROM files are never fragmented.6 Before the boot executable starts, the BIOS calls _96_init(), so a game can use the CD-ROM file functions without initialization.6
| Function | BIOS | Explanation |
|---|---|---|
| _96_init() | A(54h), A(71h) | Installs the ISO 9660 file system driver30 |
| _96_remove() | A(56h), A(72h) | Removes the ISO 9660 file system driver31 |
| CdGetLbn(filename) | A(A4h) | Returns the first sector of a file |
| CdReadSector(count, sector, buffer) | A(A5h) | Reads count 2048-byte sectors at double speed and waits |
| CdGetStatus() | A(A6h) | Returns the drive status byte |
| CdAsyncSeekL(src) | A(78h) | Issues Setloc and SeekL to a BCD MM:SS:FF position |
| CdAsyncGetStatus(dst) | A(7Ch) | Issues GetStat and stores the status byte |
| CdAsyncReadSector(count, dst, mode) | A(7Eh) | Issues SetMode and ReadN, or ReadS when mode bit 8 is set |
| CdAsyncSetMode(mode) | A(81h) | Issues SetMode only |
The asynchronous functions return 1 when the command is accepted and 0 on failure. Completion is reported by an event with class 0xF0000003 and type 0x20, 0x80, or 0x8000.6 The sector size of CdAsyncReadSector() follows the mode: 0x918 bytes when bit 4 is set, 0x924 bytes when only bit 5 is set, and 0x800 bytes otherwise.6
CdGetLbn() returns -1 for the first entry of a directory, and garbage when the file is not found.6 CdAsyncGetStatus() clears the door open flag but does not reload the path table. After a disc change a program should therefore call cd() or another function that reloads the path table.6 _96_remove() does not work in the retail BIOS, because SysDeqIntRP() cannot remove the CD-ROM interrupt handlers.6
Memory Card Functions
The Memory Card functions below the file system work on single 128-byte sectors.11
| Function | BIOS | Explanation |
|---|---|---|
| InitCARD2(pad_enable) | B(4Ah) | Initializes the card driver and selects whether pads are read with it |
| StartCARD2() | B(4Bh) | Starts the card driver |
| StopCARD2() | B(4Ch) | Stops the card driver |
| _bu_init() | A(55h), A(70h) | Initializes the Memory Card file system |
| _card_read(port, sector, dst) | B(4Fh) | Starts reading one sector |
| _card_write(port, sector, src) | B(4Eh) | Starts writing one sector |
| _card_status(slot) | B(5Ch) | Returns the status of the last command |
| _card_wait(slot) | B(5Dh) | Waits until the last command is not busy |
| _card_info(port) | A(ABh) | Checks a card with a dummy read |
| _card_load(port) | A(ACh) | Reads the directory asynchronously |
| _card_auto(flag) | A(ADh) | Turns automatic formatting on or off |
| card_write_test(port) | A(AFh) | Clears the card change flag with a dummy write |
| _new_card() | B(50h) | Ignores the card change flag on the next access |
_card_read() and _card_write() take sector numbers 0 to 0x3FF and access the sector directly. They do not use the broken sector replacement list. They return 1 when the command starts and 0 for an invalid sector.11 A write error is reported only when the next sector command completes, so _card_info() is used to verify the last sector written.11
| Value | Status |
|---|---|
| 0x01 | Ready |
| 0x02 | Busy, reading |
| 0x04 | Busy, writing |
| 0x08 | Busy, info |
| 0x11 | Failed, timeout (no card) |
| 0x21 | Failed, general error |
The file read() and write() functions run asynchronously when the file is opened with access mode bit 15. Completion is then reported by one of several events, which the game must open and test.11 The events page lists these events. Automatic formatting formats a card whenever the "MC" identifier in sector 0 cannot be read. psx-spx warns that a dirty or loose card can cause such a read error, and _bu_init() leaves automatic formatting off.11
Control Blocks
The kernel keeps 16 file control blocks of 0x2C bytes and 10 device control blocks of 0x50 bytes at fixed addresses in its variables.4 A file descriptor converts to its FCB as [0x140] + fd * 0x2C.32
| Offset | Contents |
|---|---|
| 0x00 | Status (0 free, otherwise the access mode) |
| 0x04 | Disc ID (CD-ROM) or port number (Memory Card) |
| 0x08 | Transfer address |
| 0x0C | Transfer length |
| 0x10 | Current file position |
| 0x14 | Device flags (copy of DCB 0x04) |
| 0x18 | Error code (returned by _get_error) |
| 0x1C | Pointer to the DCB |
| 0x20 | File size |
| 0x24 | First logical block number |
| 0x28 | FCB number (0 to 15) |
| Offset | Contents |
|---|---|
| 0x00 | Pointer to the lowercase name (cdrom, bu, tty), or 0 when free |
| 0x04 | Device flags (cdrom 0x14, bu 0x14, dummy tty 1, DUART tty 3) |
| 0x08 | Sector size (cdrom 0x800, bu 0x80, tty 1) |
| 0x0C | Pointer to the long name (CD-ROM, MEMORY CARD, CONSOLE) |
| 0x10 to 0x4C | Pointers to the init, open, in_out, close, ioctl, read, write, erase, undelete, firstfile, nextfile, format, cd, rename, remove and testdevice functions |
The control block layouts are from psx-spx.4
References
-
^ a b c d e f g h Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-15, Table 2-17, Table 2-18.
-
^ Sony Computer Entertainment Inc. PlayStation Operating System. August 1998. Page 3-3.
-
^ Sony Computer Entertainment Inc. PlayStation Operating System. August 1998. Page 1-4.
-
^ a b c psx-spx. Kernel (BIOS), BIOS Control Blocks. https://psx-spx.consoledev.net/kernelbios/
-
^ a b psx-spx. Kernel (BIOS), BIOS More Internal Functions, Device Names. https://psx-spx.consoledev.net/kernelbios/
-
^ a b c d e f g h i psx-spx. Kernel (BIOS), BIOS CDROM Functions. https://psx-spx.consoledev.net/kernelbios/
-
^ Sony Computer Entertainment Inc. PlayStation Operating System. August 1998. Page 2-4.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-11, cd.
-
^ a b c d e f g h i psx-spx. Kernel (BIOS), BIOS File Functions. https://psx-spx.consoledev.net/kernelbios/
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-16, Table 2-19.
-
^ a b c d e f g h i j k l psx-spx. Kernel (BIOS), BIOS Memory Card Functions. https://psx-spx.consoledev.net/kernelbios/
-
^ Sony Computer Entertainment Inc. PlayStation Operating System. August 1998. Page 4-5.
-
^ psx-spx. Kernel (BIOS), BIOS TTY Console (std_io). https://psx-spx.consoledev.net/kernelbios/
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-53, open, Table 1-3.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-49, lseek.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-56, read.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-77, write.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-14, close.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-43, ioctl.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-29, format.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-27, firstfile.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-52, nextfile.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-59, rename.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-23, erase.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-74, undelete.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-81, _get_errno.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-82, _get_error.
-
^ psx-spx. Kernel (BIOS), BIOS Function Summary. https://psx-spx.consoledev.net/kernelbios/
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-3, DIRENTRY.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-78, _96_init.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-79, _96_remove.
-
^ psx-spx. Kernel (BIOS), Table of Tables. https://psx-spx.consoledev.net/kernelbios/