diff options
| author | spicyjpeg <thatspicyjpeg@gmail.com> | 2022-11-17 22:20:38 +0100 |
|---|---|---|
| committer | spicyjpeg <thatspicyjpeg@gmail.com> | 2022-11-17 22:20:38 +0100 |
| commit | fc021dc6d6f06f8eff7edc72929faddd1e1f0d1b (patch) | |
| tree | c088d292c6cc974854c2e7d3a4024c4951ef3602 /libpsn00b/include | |
| parent | 85d765f30595fe7f27c1b065c5a1934c3d389cef (diff) | |
| download | psn00bsdk-fc021dc6d6f06f8eff7edc72929faddd1e1f0d1b.tar.gz | |
Refactor libpsxcd, add new CD-ROM APIs, fix SPU DMA read
Diffstat (limited to 'libpsn00b/include')
| -rw-r--r-- | libpsn00b/include/psxcd.h | 1004 |
1 files changed, 628 insertions, 376 deletions
diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h index 8150703..503bc83 100644 --- a/libpsn00b/include/psxcd.h +++ b/libpsn00b/include/psxcd.h @@ -1,6 +1,6 @@ /* - * PSn00bSDK CD-ROM drive library - * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed + * PSn00bSDK CD-ROM library + * (C) 2020-2022 Lameguy64, spicyjpeg - MPL licensed */ /** @@ -54,7 +54,9 @@ typedef enum _CdlCommand { CdlTest = 0x19, CdlGetID = 0x1a, CdlReadS = 0x1b, - CdlReset = 0x1c + CdlReset = 0x1c, + CdlGetQ = 0x1d, + CdlReadTOC = 0x1e } CdlCommand; typedef enum _CdlStatFlag { @@ -90,6 +92,15 @@ typedef enum _CdlIntrResult { CdlDiskError = 5 } CdlIntrResult; +typedef enum _CdlRegionCode { + CdlRegionUnknown = 0, + CdlRegionSCEI = 1, // Japan + CdlRegionSCEA = 2, // North America + CdlRegionSCEE = 3, // Europe + CdlRegionSCEW = 4, // Wordwide (Net Yaroze) + CdlRegionDebug = 5 // DebuggingStation or test console +} CdlRegionCode; + typedef enum _CdlIsoError { CdlIsoOkay = 0, CdlIsoSeekError = 1, @@ -99,51 +110,48 @@ typedef enum _CdlIsoError { } CdlIsoError; /** - * @brief Translates a BCD format value to decimal + * @brief Translates a BCD value to decimal. * - * @details Translates a specified value in BCD format (ie. 32/0x20 = 20) into - * a decimal integer, as the CD-ROM controller returns integer values only in - * BCD format. + * @details Translates the specified value in BCD format (in 0-99 range) into + * a decimal integer. */ -#define btoi(b) ((b)/16*10+(b)%16) +#define btoi(b) (((b) / 16 * 10) + ((b) % 16)) /** - * @brief Translates a decimal value to BCD + * @brief Translates a decimal value to BCD. * - * @details Translates a decimal integer into a BCD format value (ie. - * 20 = 32/0x20), as the CD-ROM controller only accepts values in BCD format. + * @details Translates a decimal integer in 0-99 range into a BCD format value. */ -#define itob(i) ((i)/10*16+(i)%10) +#define itob(i) (((i) / 10 * 16) | ((i) % 10)) /* Structure and type definitions */ /** - * @brief CD-ROM positional coordinates + * @brief CD-ROM MSF positional coordinates. + * + * @details This structure is used to specify CD-ROM coordinates in + * minutes/seconds/frames format for some commands (see CdControl()). It can + * be converted from/to a logical logical sector number using CdIntToPos() and + * CdPosToInt() respectively. * - * @details This structure is used to specify CD-ROM positional coordinates for - * CdlSetloc, CdlReadN and CdlReadS CD-ROM commands. Use CdIntToPos() to set - * parameters from a logical sector number. + * NOTE: the minute, second and sector fields are in BCD format. The track + * field is only returned by CdGetToc() and otherwise ignored by all commands. * - * @see CdIntToPos(), CdControl() + * @see CdIntToPos(), CdPosToInt(), CdControl() */ typedef struct _CdlLOC { uint8_t minute; // Minutes (BCD) uint8_t second; // Seconds (BCD) uint8_t sector; // Sector or frame (BCD) - uint8_t track; // Track number (not used) + uint8_t track; // Track number } CdlLOC; /** - * @brief CD-ROM attenuation parameters - * - * @details This structure specifies parameters for the CD-ROM attenuation. - * Values must be of range 0 to 127. + * @brief CD-ROM volume mixing matrix. * - * The CD-ROM attenuation can be used to set the CD-ROM audio output to mono - * (0x40, 0x40, 0x40, 0x40) or reversed stereo (0x00, 0x80, 0x00, 0x80). It can - * also be used to play one of two stereo channels to both speakers. - * - * The CD-ROM attenuation affects CD-DA and CD-XA audio. + * @details This structure is used to change the CD-ROM drive's volume levels + * using CdMix(). Each field represents a volume level as a value in 0-255 + * range, with 128 being 100% and values above 128 distorting the output. * * @see CdMix() */ @@ -155,27 +163,73 @@ typedef struct _CdlATV { } CdlATV; /** - * @brief File entry structure + * @brief File entry structure. * - * @details Used to store basic information of a file such as logical block - * location and size. Currently, CdSearchFile() is the only function that uses - * this struct but it will be used in directory listing functions that may be - * implemented in the future. + * @details This structure is used to store basic metadata of a file such as + * its position and size. Currently, CdSearchFile() is the only function that + * uses this structure. * * @see CdSearchFile() */ typedef struct _CdlFILE { - CdlLOC pos; // CD-ROM position coordinates of file - uint32_t size; // Size of file in bytes - char name[16]; // File name + CdlLOC pos; // CD-ROM position coordinates of file + int size; // Size of file in bytes + char name[16]; // File name } CdlFILE; /** - * @brief Structure used to set CD-ROM XA filter + * @brief Current logical location information structure. + * + * @details This structure is returned by the CdlGetlocL command and contains + * information about the last data sector read by the drive head, including its + * location as well as mode and XA attributes if any. + * + * CdlGetlocL can only be issued while reading data sectors, as CD-DA data has + * no headers. Use CdlGetlocP instead to obtain the current drive position when + * playing CD-DA. + * + * @see CdControl() + */ +typedef struct _CdlLOCINFOL { + uint8_t minute; // Minutes (BCD) + uint8_t second; // Seconds (BCD) + uint8_t sector; // Sector or frame (BCD) + uint8_t mode; // Sector mode (usually 2) + uint8_t file; // XA file number (usually 0 or 1) + uint8_t chan; // XA channel number (0-31) + uint8_t submode; // XA submode + uint8_t coding_info; // XA coding information (ADPCM sectors only) +} CdlLOCINFOL; + +/** + * @brief Current physical location information structure. + * + * @details This structure is returned by the CdlGetlocP command and contains + * information about the current location of the drive head relative to the + * entire CD as well as to the beginning of the track being played or read. + * + * This information is obtained by reading subchannel Q, so CdlGetlocP works on + * both data and CD-DA tracks (albeit with slightly lower precision on data + * tracks). + * + * @see CdControl() + */ +typedef struct _CdlLOCINFOP { + uint8_t track; // Track number (BCD) + uint8_t index; // Index number (BCD, usually 1) + uint8_t track_minute; // Minutes relative to beginning of track (BCD) + uint8_t track_second; // Seconds relative to beginning of track (BCD) + uint8_t track_sector; // Sector or frame relative to beginning of track (BCD) + uint8_t minute; // Minutes (BCD) + uint8_t second; // Seconds (BCD) + uint8_t sector; // Sector or frame (BCD) +} CdlLOCINFOP; + +/** + * @brief CD-ROM XA filter structure. * - * @details This structure is used to specify stream filter parameters for - * CD-ROM XA audio streaming using the CdlSetfilter command. This only affects - * CD-ROM XA audio streaming. + * @details This structure is used with the CdlSetfilter command to specify + * sector filter parameters for XA-ADPCM audio playback. * * CD-ROM XA audio is normally comprised of up to 8 or more ADPCM compressed * audio streams interleaved into one continuous stream of data. The data @@ -191,13 +245,13 @@ typedef struct _CdlFILE { * @see CdControl() */ typedef struct _CdlFILTER { - uint8_t file; // File number to fetch (usually 1) - uint8_t chan; // Channel number (0 through 7) - uint16_t pad; // Padding + uint8_t file; // XA file number (usually 1) + uint8_t chan; // XA channel number (0-31) + uint16_t pad; } CdlFILTER; /** - * @brief CD-ROM directory query context handle + * @brief CD-ROM directory query context handle. * * @details Used to store a directory context created by CdOpenDir(). An open * context can then be used with CdReadDir() and closed with CdCloseDir(). @@ -206,7 +260,7 @@ typedef struct _CdlFILTER { */ typedef void *CdlDIR; -typedef void (*CdlCB)(int, uint8_t *); +typedef void (*CdlCB)(CdlIntrResult, uint8_t *); /* Public API */ @@ -215,190 +269,230 @@ extern "C" { #endif /** - * @brief Initializes the CD-ROM library + * @brief Initializes the CD-ROM library. * * @details Initializes the CD-ROM subsystem which includes hooking the * required IRQ handler, sets up internal variables of the CD-ROM library and * attempts to initialize the CD-ROM controller. The mode parameter does * nothing but may be used in future updates of this library. * - * This function must be called after ResetGraph and before any other CD-ROM - * library function that interfaces with the CD-ROM controller. This function - * may not be called twice as it may cause instability or would just crash. + * This function shall only be called once after ResetGraph() or + * ResetCallback(), and shall not be called on systems which are known not to + * be equipped with a CD drive such as most PS1-based arcade boards. * - * @return Always 1. May change in the future. + * @return 1 if the drive is ready or 0 if an error occurred */ int CdInit(void); /** - * @brief Translates a logical sector number to CD-ROM positional coordinates + * @brief Translates an LBA to MSF coordinates. * - * @details This function translates the logical sector number from i to CD-ROM - * positional coordinates stored to a CdlLOC struct specified by p. The - * translation takes the lead-in offset into account so the first logical - * sector begins at 0 and the result will be offset by 150 sectors. + * @details Translates the provided logical sector number to CD-ROM positional + * coordinates in minutes/seconds/frames format, which are stored into the + * provided CdlLOC structure. The translation takes the lead-in offset into + * account, so LBA 0 is correctly translated to 00:02:00 rather than 00:00:00. * - * @param i Logical sector number + * @param i Logical sector number minus the 150-sector lead-in * @param p Pointer to a CdlLOC structure - * @return Pointer to the specified CdlLOC struct plus 150 sectors. + * @return Pointer to the specified CdlLOC structure */ CdlLOC* CdIntToPos(int i, CdlLOC *p); /** - * @brief Translates CD-ROM positional coordinates to a logical sector number + * @brief Translates MSF coordinates to an LBA. * - * @details Translates the CD-ROM position parameters from a CdlLOC struct - * specified by p to a logical sector number. The translation takes the lead-in - * offset of 150 sectors into account so the logical sector number returned - * would begin at zero. + * @details Translates the CD-ROM positional coordinates in + * minutes/seconds/frames format from the provided CdlLOC structure to a + * logical sector number. The translation takes the lead-in offset into account + * so 00:02:00 is correctly translated to LBA 0 rather than 150. * - * @param p Pointer to a CdlLOC struct - * @return Logical sector number minus the 150 sector lead-in. + * @param p Pointer to a CdlLOC structure + * @return Logical sector number minus the 150-sector lead-in */ int CdPosToInt(const CdlLOC *p); /** - * @brief Gets CD-ROM TOC information + * @brief Issues a command to the CD-ROM controller. * - * @details Retrieves the track entries from a CD's table of contents (TOC). The - * function can return up to 99 track entries, which is the maximum number of - * audio tracks the CD standard supports. + * @details Sends a CD-ROM command specified by com to the CD-ROM controller, + * waits for an acknowledge interrupt (very fast) then returns. It will also + * issue parameters from param to the CD-ROM controller if the command accepts + * parameters. Any response from the controller is stored into the provided + * buffer asynchronously. + * + * Some commands (marked as blocking in the table below) will keep running in + * the background after being acknowledged. Use CdSync() to wait for these + * commands to finish, or CdSyncCallback() to register a callback to be + * executed once the drive is idle. + * + * This function requires interrupts to be enabled and cannot be used in a + * critical section or IRQ callback. Use CdControlF() in callbacks instead. + * + * The following commands are available: + * + * | Command | Value | Parameter | Blocking | Description | + * | :------------ | ----: | :--------- | :------- | :---------------------------------------------------------------------------------------------------------------- | + * | CdlNop | 0x01 | | No | Updates the current CD-ROM status and resets the CdlStatShellOpen flag, without doing anything else. | + * | CdlSetloc | 0x02 | CdlLOC | No | Sets the seek target location, but does not seek. Actual seeking begins upon issuing a seek or read command. | + * | CdlPlay | 0x03 | (uint8_t) | No | Begins CD-DA playback. Parameter specifies an optional track number to play (some emulators do not support it). | + * | CdlForward | 0x04 | | No | Starts fast-forwarding (CD-DA only). Issue CdlPlay to stop fast forwarding. | + * | CdlBackward | 0x05 | | No | Starts rewinding (CD-DA only). Issue CdlPlay to stop rewinding. | + * | CdlReadN | 0x06 | (CdlLOC) | No | Begins reading data sectors with automatic retry. Used in conjunction with CdReadyCallback(). | + * | CdlStandby | 0x07 | | Yes | Starts the spindle motor if it was previously stopped. | + * | CdlStop | 0x08 | | Yes | Stops playback or data reading and shuts down the spindle motor. | + * | CdlPause | 0x09 | | Yes | Stops playback or data reading without stopping the spindle motor. | + * | CdlInit | 0x0a | | Yes | Initializes the CD-ROM controller and aborts any ongoing command. | + * | CdlMute | 0x0b | | No | Mutes the drive's audio output (both CD-DA and XA). | + * | CdlDemute | 0x0c | | No | Unmutes the drive's audio output (both CD-DA and XA). | + * | CdlSetfilter | 0x0d | CdlFILTER | No | Configures the XA ADPCM sector filter. | + * | CdlSetmode | 0x0e | uint8_t | No | Sets the CD-ROM mode. | + * | CdlGetparam | 0x0f | | No | Returns current CD-ROM mode and file/channel filter settings. | + * | CdlGetlocL | 0x10 | | No | Returns current logical CD position, mode and XA filter parameters. | + * | CdlGetlocP | 0x11 | | No | Returns current physical CD position (using SubQ location data). | + * | CdlSetsession | 0x12 | uint8_t | Yes | Attempts to seek to the specified session on a multi-session disc. | + * | CdlGetTN | 0x13 | | No | Returns the number of tracks on the disc. | + * | CdlGetTD | 0x14 | uint8_t | No | Returns the starting location of the specified track number. | + * | CdlSeekL | 0x15 | (CdlLOC) | Yes | Logical seek (using data sector headers) to target position, set by last CdlSetloc command. | + * | CdlSeekP | 0x16 | (CdlLOC) | Yes | Physical seek (using subchannel Q) to target position, set by last CdlSetloc command. | + * | CdlTest | 0x19 | (varies) | Yes | Executes a test subcommand (see nocash documentation). Shall be issued using CdCommand() rather than CdControl(). | + * | CdlGetID | 0x1a | | Yes | Identifies the disc type and returns its license string if any. | + * | CdlReadS | 0x1b | (CdlLOC) | No | Begins reading data sectors in real-time (without retry) mode. Intended for playing XA ADPCM or .STR files. | + * | CdlReset | 0x1c | | No | Resets the CD-ROM controller (similar behavior to manually opening and closing the door). | + * | CdlGetQ | 0x1d | uint8_t[2] | Yes | Reads up to 10 raw bytes of subchannel Q data directly from the table of contents. | + * | CdlReadTOC | 0x1e | | Yes | Forces reinitialization of the disc's table of contents. | + * + * Most commands return the current CD-ROM status as result (which is + * automatically saved by the library and can be retrieved at any time using + * CdStatus()). The following commands also return additional data: + * + * | Command | Return values | + * | :---------- | :-------------------------------------- | + * | CdlGetparam | uint8_t status, mode, _pad, file, chan | + * | CdlGetlocL | CdlLOCINFOL info | + * | CdlGetlocP | CdlLOCINFOP info | + * | CdlGetTN | uint8_t status, first_track, last_track | + * | CdlGetTD | uint8_t status, minutes, seconds | + * + * NOTE: Values are in BCD format. For some commands (CdlReadN, CdlReadS, + * CdlSeekL, CdlSeekP), if a CdlLOC parameter is passed, it will be sent to the + * controller as a separate CdlSetloc command. + * + * @param cmd + * @param param Pointer to command parameters + * @param result Optional pointer to buffer to store result into + * @return 1 if the command was issued successfully, 0 if a previously issued + * command has not yet finished processing or -1 if a parameter is required but + * was not specified + * + * @see CdSync(), CdControlF(), CdCommand() + */ +int CdControl(CdlCommand cmd, const void *param, uint8_t *result); + +/** + * @brief Issues a command to the CD-ROM controller and waits for it to + * complete. * - * This function only retrieve the minutes and seconds of an audio track's - * position as the CD-ROM controller only returns the minutes and seconds of a - * track, which may result in the end of the previous track being played - * instead of the intended track to be played. This can be remedied by having a - * 2 second pregap on each audio track on your disc. + * @details Equivalent to CdControl() followed by CdSync(). If a blocking + * command is issued, this function blocks until said command has completed. * - * @param toc Pointer to an array of CdlLOC entries - * @return Number of tracks on the disc, zero on error. + * This function requires interrupts to be enabled and cannot be used in a + * critical section or IRQ callback. Use CdControlF() in callbacks instead. * - * @see CdControl() + * @param cmd + * @param param Pointer to command parameters + * @param result Optional pointer to buffer to store result into + * @return 1 if the command was issued successfully, 0 if a previously issued + * command has not yet finished processing or -1 if a parameter is required but + * was not specified + * + * @see CdControl(), CdControlF() */ -int CdGetToc(CdlLOC *toc); +int CdControlB(CdlCommand cmd, const void *param, uint8_t *result); /** - * @brief Issues a control command to the CD-ROM controller + * @brief Issues a command to the CD-ROM controller (asynchronous). * - * @details Sends a CD-ROM command specified by com to the CD-ROM controller, - * waits for an acknowledge interrupt (very fast) then returns. It will also - * issue parameters from param to the CD-ROM controller if the command accepts - * parameters. Response data from the CD-ROM controller is stored to result on - * commands that produce response data. - * - * Because this function waits for an acknowledge interrupt from the CD-ROM - * controller, this function should not be used in a callback. Instead, use - * CdControlF(). - * - * Commands that are blocking require the use of CdSync() to wait for the - * command to fully complete. - * - * CD-ROM control commands: - * - * | Command | Value | Parameter | Blocking | Description | - * | :------------ | ----: | :-------- | :------- | :----------------------------------------------------------------------------------------------------------------- | - * | CdlNop | 0x01 | | No | Also known as Getstat. Normally used to query the CD-ROM status, which is retrieved using CdStatus(). | - * | CdlSetloc | 0x02 | CdlLOC | No | Sets the seek target location, but does not seek. Actual seeking begins upon issuing a seek or read command. | - * | CdlPlay | 0x03 | uint8_t | No | Begins CD Audio playback. Parameter specifies an optional track number to play (some emulators do not support it). | - * | CdlForward | 0x04 | | No | Fast forward (CD Audio only), issue CdlPlay to stop fast forward. | - * | CdlBackward | 0x05 | | No | Rewind (CD Audio only), issue CdlPlay to stop rewind. | - * | CdlReadN | 0x06 | CdlLOC | No | Begin reading data sectors. Used in conjunction with CdReadCallback(). | - * | CdlStandby | 0x07 | | Yes | Also known as MotorOn, starts CD motor and remains idle. | - * | CdlStop | 0x08 | | Yes | Stops playback and the disc itself. | - * | CdlPause | 0x09 | | Yes | Stops playback or data reading, but leaves the disc on standby. | - * | CdlInit | 0x0A | | Yes | Initialize the CD-ROM controller. | - * | CdlMute | 0x0B | | No | Mutes CD audio (both DA and XA). | - * | CdlDemute | 0x0C | | No | Unmutes CD audio (both DA and XA). | - * | CdlSetfilter | 0x0D | CdlFILTER | No | Set XA audio filter. | - * | CdlSetmode | 0x0E | uint8_t | No | Set CD-ROM mode. | - * | CdlGetparam | 0x0F | | No | Returns current CD-ROM mode and file/channel filter settings. | - * | CdlGetlocL | 0x10 | | No | Returns current logical CD position, mode and XA filter parameters. | - * | CdlGetlocP | 0x11 | | No | Returns current physical CD position (using SubQ location data). | - * | CdlSetsession | 0x12 | uint8_t | Yes | Seek to specified session on a multi-session disc. | - * | CdlGetTN | 0x13 | | No | Get CD-ROM track count. | - * | CdlGetTD | 0x14 | uint8_t | No | Get specified track position. | - * | CdlSeekL | 0x15 | | Yes | Logical seek to target position, set by last CdlSetloc command. | - * | CdlSeekP | 0x16 | | Yes | Physical seek to target position, set by last CdlSetloc command. | - * | CdlTest | 0x19 | (varies) | Yes | Special test command not disclosed to official developers (see nocash documents for more info). | - * | CdlReadS | 0x1B | CdlLOC | No | Begin reading data sectors without pausing for error correction. | - * - * CD-ROM return values: - * - * | Command | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | - * | :---------- | :---- | :---- | :----- | :--- | :------ | :------ | :--- | :----- | - * | CdlGetparam | stat | mode | 0 | file | channel | | | | - * | CdlGetlocL | amin | asec | aframe | mode | file | channel | sm | ci | - * | CdlGetlocP | track | index | min | sec | frame | amin | asec | aframe | - * | CdlGetTN | stat | first | last | | | | | | - * | CdlGetTD | stat | min | sec | | | | | | - * - * NOTE: Values are in BCD format. - * - * @param com Command value - * @param param Command parameters - * @param result Pointer of buffer to store result - * @return 1 if the command was issued successfully. Otherwise 0 if a - * previously issued command has not yet finished processing. - * - * @see CdSync(), CdControlF() - */ -int CdControl(uint8_t com, const void *param, uint8_t *result); - -/** - * @brief Issues a CD-ROM command to the CD-ROM controller (blocking) - * - * @details This function works just like CdControl(), but blocks on blocking - * commands until said blocking command has completed. - * - * Because this function waits for an acknowledge interrupt from the CD-ROM - * controller, this function should not be used in a callback. Use CdControlF() - * instead. - * - * @param com Command value - * @param param Command parameters - * @param result Pointer of buffer to store result - * @return 1 if the command was issued successfully. Otherwise 0 if a - * previously issued command has not yet finished processing. + * @details This function works similarly to CdControl() but does not block for + * the acknowledge interrupt from the CD-ROM controller, making it suitable for + * usage in an IRQ handler or callback function. Use CdSync() (outside of a + * callback) to wait for a command to finish, or CdSyncCallback() to register a + * callback to be executed once the drive is idle. * - * @see CdControl(), CdControlF() + * A maximum of two commands can be issued at once and only the first command + * can have parameters, as the parameter buffer is not cleared until the last + * command is acknowledged by the controller. + * + * NOTE: as with CdControl(), some commands (CdlReadN, CdlReadS, CdlSeekL, + * CdlSeekP) are sent as two separate commands if a CdlLOC parameter is passed. + * In some cases this may overflow the controller's two-command buffer. + * + * @param cmd + * @param param Pointer to command parameters + * @return -1 if a parameter is required but was not specified, otherwise 1 + * (even if sending the command failed) + * + * @see CdControl(), CdCommand() */ -int CdControlB(uint8_t com, const void *param, uint8_t *result); +int CdControlF(CdlCommand cmd, const void *param); /** - * @brief Issues a CD-ROM command to the CD-ROM controller (does not block) + * @brief Issues a custom packet to the CD-ROM controller. * - * @details This function works more or less the same as CdControl() but it - * does not block even for the acknowledge interrupt from the CD-ROM - * controller. Since this function is non-blocking it can be used in a callback - * function. + * @details This is a more advanced variant of CdControl() that allows sending + * commands with an arbitrary number of parameters, such as CdlTest commands, + * and does not issue any additional CdlSetloc commands automatically. The + * number of parameter bytes must be specified manually. * - * When using this function in a callback, a maximum of two commands can be - * issued at once and only the first command can have parameters. This is - * because the CD-ROM controller can only queue up to two commands and the - * parameter FIFO is not cleared until the last command is acknowledged. But - * waiting for acknowledgment in a callback is not possible. + * As with CdControl(), this function waits for the drive to acknowledge the + * command. Any response from the controller is stored into the provided buffer + * asynchronously. * - * @param com Command value - * @param param Command parameters - * @return 1 if the command was issued successfully. Otherwise 0 if a - * previously issued command has not yet finished processing. + * This function requires interrupts to be enabled and cannot be used in a + * critical section or IRQ callback. Use CdCommandF() in callbacks instead. * - * @see CdControl() + * @param cmd + * @param param Pointer to command parameters if any + * @param length Number of parameter bytes expected by the command + * @param result Optional pointer to buffer to store result into + * @return 1 if the command was issued successfully or 0 if a previously issued + * command has not yet finished processing + * + * @see CdSync(), CdCommandF(), CdControl() */ -int CdControlF(uint8_t com, const void *param); +int CdCommand(CdlCommand cmd, const void *param, int length, uint8_t *result); /** - * @brief Waits for blocking command or blocking status + * @brief Issues a custom packet to the CD-ROM controller (asynchronous). * - * @details If mode is zero the function blocks if a blocking command was - * issued earlier until the command has finished. If mode is non-zero the - * function returns a command status value. + * @details This function works similarly to CdCommand() but does not block for + * the acknowledge interrupt from the CD-ROM controller, making it suitable for + * usage in an IRQ handler or callback function. Use CdSync() (outside of a + * callback) to wait for a command to finish, or CdSyncCallback() to register a + * callback to be executed once the drive is idle. + * + * A maximum of two commands can be issued at once and only the first command + * can have parameters, as the parameter buffer is not cleared until the last + * command is acknowledged by the controller. + * + * @param cmd + * @param param Pointer to command parameters + * @param length Number of parameter bytes expected by the command + * @return Always 1 (even if sending the command failed) + * + * @see CdCommand(), CdControlF() + */ +int CdCommandF(CdlCommand cmd, const void *param, int length); + +/** + * @brief Waits for a blocking command or returns the current status. * - * A buffer specified by result will be set with the most recent CD-ROM status - * value from the last command issued. + * @details Waits for the controller to finish processing any blocking command + * (if mode = 0) or returns the current command status (if mode = 1). The + * buffer specified by result will be populated with the most recent CD-ROM + * status value from the last command issued. * - * @param mode Mode - * @param result Pointer to store most recent CD-ROM status + * @param mode + * @param result Optional pointer to buffer to store result into * @return Command status is returned as one of the following definitions: * * | Definition | Description | @@ -409,332 +503,489 @@ int CdControlF(uint8_t com, const void *param); * * @see CdControl() */ -int CdSync(int mode, uint8_t *result); +CdlIntrResult CdSync(int mode, uint8_t *result); /** - * @brief Sets a callback function + * @brief Sets a callback for blocking commands. * - * @details Sets a callback with the specified function func. The callback is - * executed whenever a blocking command has completed. + * @details Registers a function to be called whenever a blocking command has + * completed. The callback will get the interrupt status (CdlComplete or + * CdlDiskError) and the pointer to any result buffer previously passed to + * CdControl() as arguments. * - * status is the CD-ROM status from the command that has completed processing. - * *result corresponds to the *result parameter on CdControl()/CdControlB() and - * returns the pointer to the buffer last set with that function. + * The callback will run in the exception handler's context, so it should be as + * fast as possible and shall not call any function that relies on interrupts + * being enabled. * - * @param func Callback function - * @return Pointer to last callback function set, or NULL if none was set. + * @param func + * @return Previously set callback or NULL * - * @see CdControl, CdControlB, CdSync + * @see CdControl(), CdControlB(), CdSync() */ -uint32_t CdSyncCallback(CdlCB func); +CdlCB CdSyncCallback(CdlCB func); /** - * @brief Sets a callback function + * @brief Sets a callback for incoming sector or report data. + * + * @details Registers a function to be called whenever a data sector or report + * packet is available to be read from the drive, or in case of an error. The + * callback will get the interrupt status (CdlDataReady or CdlDiskError) and + * the pointer to any result buffer previously passed to CdControl() as + * arguments. * - * @details Sets a callback with the specified function func. The callback is - * executed whenever there's an incoming data sector from the CD-ROM controller - * during CdlReadN or CdlReadS. The pending sector data can be retrieved using - * CdGetSector(). + * Note that the actual sector data is not retrieved automatically and must + * instead be read into memory using CdGetSector() or CdGetSector2() before the + * drive overwrites its internal sector buffer. * - * status is the CD-ROM status code from the last CD command that has finished - * processing. *result corresponds to the result pointer that was passed by the - * last CdControl()/CdControlB() call. + * The callback will run in the exception handler's context, so it should be as + * fast as possible and shall not call any function that relies on interrupts + * being enabled. * - * This callback cannot be used in conjunction with CdRead() because it also - * uses this callback hook for its own internal use. The previously set - * callback is restored after read completion however. + * NOTE: when using CdRead() or CdReadRetry(), any callback set using + * CdReadyCallback() is temporarily disabled in order to let the library handle + * read sectors internally. * - * @param func Callback function - * @return Pointer to last callback function set, or NULL if none was set. + * @param func + * @return Previously set callback or NULL * * @see CdControl(), CdControlB(), CdGetSector() */ -int CdReadyCallback(CdlCB func); +CdlCB CdReadyCallback(CdlCB func); + +/** + * @brief Sets a callback for the end of a track. + * + * @details Registers a function to be called whenever the drive encounters and + * pauses at the end of a track (if the CdlModeAP bit is set in the CD-ROM + * mode), or whether the end of the disc is reached during data reading or + * audio playback. The callback will get the interrupt status (CdlDataEnd) and + * the pointer to any result buffer previously passed to CdControl() as + * arguments. + * + * Such a callback can be used along with the CdlModeAP flag to detect when + * playback of a CD-DA track ends and automatically loop it or start playing + * another track, with no manual polling required. + * + * @param func + * @return Previously set callback or NULL + * + * @see CdControl() + */ +CdlCB CdAutoPauseCallback(CdlCB func); /** - * @brief Gets data from the CD-ROM sector buffered + * @brief Transfers data from the CD-ROM sector buffer. * * @details Reads sector data that is pending in the CD-ROM sector buffer and - * stores it to *madr. Uses DMA to transfer the sector data and blocks very - * briefly until said transfer completes. + * stores it into the provided buffer (which must be 32-bit aligned). Blocks + * until the transfer has finished. * * This function is intended to be called within a callback routine set using * CdReadyCallback() to fetch read data sectors from the CD-ROM sector buffer. - * - * @param madr Pointer to memory buffer to store sector data - * @param size Number of 32-bit words to retrieve - * @return Always 1. + * + * @param madr + * @param size Number of 32-bit words to read (usually 512 for a 2048-byte + * sector) + * @return Always 1 * * @see CdReadyCallback() */ int CdGetSector(void *madr, int size); /** - * @brief Gets data from the CD-ROM sector buffered (non-blocking) + * @brief Transfers data from the CD-ROM sector buffer (non-blocking). * * @details Reads sector data that is pending in the CD-ROM sector buffer and - * stores it to *madr. Uses DMA to transfer the sector data in the background - * while keeping the CPU running (one word is transferred every 16 CPU cycles). - * Note this is much slower than the blocking transfer performed by - * CdGetSector(). + * stores it into the provided buffer (which must be 32-bit aligned). The + * transfer runs in the background while keeping the CPU running; about one + * word is transferred every 16 CPU cycles. Note this is slower than the + * blocking transfer performed by CdGetSector(). * * This function is intended to be called within a callback routine set using * CdReadyCallback() to fetch read data sectors from the CD-ROM sector buffer. * Since the transfer is asynchronous, CdDataSync() should be used to wait * until the whole sector has been read. - * - * @param madr Pointer to memory buffer to store sector data - * @param size Number of 32-bit words to retrieve - * @return Always 1. + * + * @param madr + * @param size Number of 32-bit words to read (usually 512 for a 2048-byte + * sector) + * @return Always 1 * * @see CdReadyCallback(), CdDataSync() */ int CdGetSector2(void *madr, int size); /** - * @brief Waits for sector transfer to finish + * @brief Waits for a sector buffer transfer to finish. * - * @details If mode is zero the function blocks until any sector DMA transfer - * initiated by calling CdGetSector2() has finished. If mode is non-zero the - * function returns a boolean value representing whether a transfer is - * currently in progress. + * @details Blocks until any sector DMA transfer initiated using CdGetSector2() + * has finished (if mode = 0) or returns whether a transfer is currently in + * progress (if mode = 1). * - * @param mode Mode + * @param mode * @return 0 if the transfer has finished, 1 if it is still in progress or -1 - * in case of a timeout. + * in case of a timeout * * @see CdGetSector2() */ int CdDataSync(int mode); /** - * @brief Locates a file in the CD-ROM file system + * @brief Reads one or more sectors into a buffer. * - * @details Searches a file specified by filename by path and name in the - * CD-ROM file system and returns information of the file if found. The file - * information acquired will be stored to loc. + * @details Starts reading the specified number of sectors, starting from the + * location set by the last CdlSetloc command issued, and stores them + * contiguously into the provided buffer. The given mode is applied using a + * CdlSetmode command prior to starting the read. * - * Directories can be separated with slashes (/) or backslashes (\), a leading - * slash or backslash is optional but paths must be absolute. File version - * identifier (;1) at the end of the file name is also optional. File and - * directory names are case insensitive. + * Each sector read is 2340 bytes long if the CdlModeSize bit is set in the + * mode, 2048 bytes long otherwise. Ideally, the CdlModeSpeed bit shall be set + * to enable double speed mode. * - * The ISO9660 file system routines of libpsxcd do not support long file names - * currently. Only MS-DOS style 8.3 file names are supported; extensions such - * as Joliet and Rock Ridge are ignored. + * Reading is done asynchronously. Use CdReadSync() to block until all data has + * been read, or CdReadCallback() to register a callback to be executed on + * completion or error. In case of errors, reading is aborted immediately and + * CdReadSync() will return -1. * - * Upon calling this function for the first time, the ISO descriptor of the - * disc is read and the whole path table is cached into memory. Next the - * directory descriptor of the particular directory specified is loaded and - * cached to locate the file specified. The directory descriptor is kept in - * memory as long as the consecutive files to be searched are stored in the - * same directory until a file in another directory is to be searched. On which - * the directory descriptor is unloaded and a new directory descriptor is read - * from the disc and cached. Therefore, locating files in the same directory is - * faster as the relevant directory descriptor is already in memory and no disc - * reads are issued. + * This function requires interrupts to be enabled and cannot be used in a + * critical section or IRQ callback. Any callback set using CdReadyCallback() + * is temporarily disabled and restored once the read operation completes. * - * As of Revision 66 of PSn00bSDK, media change is detected by checking the - * CD-ROM lid open status bit and attempting to acknowledge it with a CdlNop - * command, to discriminate the status from an open lid or changed disc. + * @param sectors + * @param buf + * @param mode CD-ROM mode to apply prior to reading using CdlSetmode + * @return 1 if the read operation started successfully or 0 in case of errors * - * @param loc Pointer to a CdlFILE struct to store file information - * @param filename Path and name of file to locate - * @return Pointer to the specified CdlFILE struct. Otherwise NULL is returned - * when the file is not found. + * @see CdReadRetry(), CdReadSync(), CdReadCallback() */ -CdlFILE* CdSearchFile(CdlFILE *loc, const char *filename); +int CdRead(int sectors, uint32_t *buf, int mode); /** - * @brief Reads sectors from the CD-ROM + * @brief Reads one or more sectors into a buffer (performs multiple attempts). * - * @details Reads a number sectors specified by sectors from the location set - * by the last CdlSetloc command, the read sectors are then stored to a buffer - * specified by buf. mode specifies the CD-ROM mode to use for the read - * operation. + * @details This function works similarly to CdRead(), but retries reading in + * case of errors. If reading fails, up to the specified number of attempts + * will be done before an error is returned by CdReadSync(). * - * The size of the sector varies depending on the sector read mode specified by - * mode. For standard data sectors it is multiples of 2048 bytes. If - * CdlModeSize0 is specified the sector size is 2328 bytes which includes the - * whole sector minus sync, adress, mode and sub header bytes. CdlModeSize1 - * makes the sector size 2340 which is the entire sector minus sync bytes. - * Ideally, CdlModeSpeed must be specified to read data sectors at double - * CD-ROM speed. + * This function requires interrupts to be enabled and cannot be used in a + * critical section or IRQ callback. Any callback set using CdReadyCallback() + * is temporarily disabled and restored once the read operation completes. * - * This function blocks very briefly to issue the necessary commands to start - * CD-ROM reading. To determine if reading has completed use CdReadSync or - * CdReadCallback. + * IMPORTANT: in order for retries to be correctly processed, CdReadSync(0) + * (blocking) shall be called immediately after starting the read, or + * CdReadSync(1) (non-blocking) shall be called frequently (e.g. once per + * frame) until reading has finished. * - * @param sectors Number of sectors to read - * @param buf Pointer to buffer to store sectors read - * @param mode CD-ROM mode for reading - * @return Always returns 0 even on errors. This may change in future versions. + * @param sectors + * @param buf + * @param mode CD-ROM mode to apply prior to reading using CdlSetmode + * @param attempts Maximum number of attempts (>= 1) + * @return 1 if the read operation started successfully or 0 in case of errors * - * @see CdReadSync(), CdReadCallback() + * @see CdRead(), CdReadSync(), CdReadCallback() */ -int CdRead(int sectors, uint32_t *buf, int mode); +int CdReadRetry(int sectors, uint32_t *buf, int mode, int attempts); /** - * @brief Waits for CD-ROM read completion or returns read status + * @brief Cancels reading initiated by CdRead(). * - * @details This function works more or less like CdSync() but for CdRead(). If - * mode is zero the function blocks if CdRead() was issued earlier until - * reading has completed. If mode is non-zero the function completes - * immediately and returns number of sectors remaining. + * @details Aborts any ongoing read operation that was previously started by + * calling CdRead() or CdReadRetry(). After aborting, CdReadSync() will return + * -2 and any callback registered using CdReadCallback() *not* be called. * - * A buffer specified by result will be set with the most recent CD-ROM status - * value from the last read issued. + * NOTE: the CD-ROM controller may take several hundred milliseconds to + * actually stop reading. CdReadSync() should be used to make sure the drive is + * idle before sending a command or starting another read. * - * @param mode Mode - * @param result Pointer to store most recent CD-ROM status - * @return Number of sectors remaining. If reading is completed, 0 is returned. - * On error, -1 is returned. + * @see CdReadSync() + */ +void CdReadBreak(void); + +/** + * @brief Waits for reading initiated by CdRead() to finish or returns status. + * + * @details Waits for any ongoing read operation previously started using + * CdRead() or CdReadRetry() to finish (if mode = 0) or returns the number of + * sectors pending (if mode = 1). The buffer specified by result will be + * populated with the most recent CD-ROM status value from the last command + * issued. + * + * When using CdReadRetry(), this function also handles starting a new read + * attempt if the previous one failed. As such, it needs to be called once (if + * mode = 0) or periodically (if mode = 1) in order to poll the drive for + * failures, even if the return value is ignored. * - * @see CdRead() + * @param mode + * @param result Buffer to store most recent CD-ROM status into + * @return Number of sectors remaining, -1 in case of errors or -2 if the read + * was aborted + * + * @see CdRead(), CdReadCallback() */ int CdReadSync(int mode, uint8_t *result); /** - * @brief Sets a callback function for read completion + * @brief Sets a callback for read operations started by CdRead(). + * + * @details Registers a function to be called whenever a read started using + * CdRead() or CdReadRetry() has completed. The callback will get the interrupt + * status (CdlComplete or CdlDiskError) and the pointer to a result buffer + * internal to the library. + * + * The callback will run in the exception handler's context, so it should be as + * fast as possible and shall not call any function that relies on interrupts + * being enabled. + * + * @param func + * @return Previously set callback or NULL * - * @details Works much the same as CdSyncCallback() but for CdRead(). Sets a - * callback with the specified function func. The callback is executed whenever - * a read operation initiated by CdRead() has completed. + * @see CdRead(), CdReadSync() + */ +CdlCB CdReadCallback(CdlCB func); + +/** + * @brief Returns the last command issued. * - * status is the CD-ROM status from the command that has completed processing. - * *result points to a read result buffer. + * @details Returns the index of the last command sent to the CD-ROM controller + * using CdCommand(), CdControl() or any of its variants. The value is stored + * in an internal variable, so this function returns instantly and can be used + * in an IRQ callback. * - * @param func Callback function - * @return Pointer to last callback function set, or NULL if none was set. + * @return Last command issued * - * @see CdRead() + * @see CdControl() */ -uint32_t CdReadCallback(CdlCB func); +CdlCommand CdLastCom(void); /** - * @brief Gets the most recent CD-ROM status + * @brief Returns the last CD-ROM position set. * - * @details Returns the CD-ROM status since the last command issued. The status - * value is updated by most CD-ROM commands. + * @details Returns the last seek location set using the CdlSetloc command (or + * any of the commands that are processed by sending CdlSetloc internally, such + * as CdlReadN, CdlReadS, CdlSeekL or CdlSeekP). The value is stored in an + * internal variable, so this function returns instantly and can be used in an + * IRQ callback. * - * To get the current CD-ROM status you can issue CdlNop commands at regular - * intervals to update the CD-ROM status this function returns. + * Note that if CdlReadN, CdlReadS or CdlPlay were issued, this will be the + * location the read was started from and *not* the current position of the + * drive head, which can instead be retrieved using CdlGetlocL or CdlGetlocP. * - * @return CD-ROM status from last comand issued. + * @return Pointer to an internal CdlLOC structure containing the last position * * @see CdControl() */ -int CdStatus(void); +const CdlLOC *CdLastPos(void); /** - * @brief Gets the last CD-ROM mode + * @brief Returns the last CD-ROM mode set. * - * @details Returns the CD-ROM mode last set when issuing a CdlSetmode command. - * The function returns instantly as it merely returns a value stored in an - * internal variable. + * @details Returns the CD-ROM mode last set using the CdlSetmode command. + * The value is stored in an internal variable, so this function returns + * instantly and can be used in an IRQ callback. * - * Since the value is simply a copy of what was specified from the last - * CdlSetmode command, the mode value may become inaccurate if CdlInit or other - * commands that affect the CD-ROM mode have been issued previously. + * WARNING: upon receiving some commands, such as CdlInit, the CD-ROM drive may + * change its mode automatically. The value returned by CdMode() will not + * reflect those changes; use CdlGetparam instead. * - * @return Last CD-ROM mode value. + * @return Last CD-ROM mode value set + * + * @see CdControl() */ int CdMode(void); /** - * @brief Sets CD-ROM mixer or attenuation + * @brief Returns the most recent CD-ROM status. + * + * @details Returns the CD-ROM status since the last command issued. The value + * is stored in an internal variable, so this function returns instantly and + * can be used in an IRQ callback. + * + * The status value is updated by most CD-ROM commands, with the exception of + * CdlTest, CdlGetlocL and CdlGetlocP; it can also be updated manually by + * issuing the CdlNop command. + * + * @return CD-ROM status returned by last comand issued + * + * @see CdControl() + */ +int CdStatus(void); + +/** + * @brief Retrieves the disc's table of contents. + * + * @details Retrieves the track entries from a CD's table of contents (TOC). The + * function can return up to 99 track entries, which is the maximum number of + * tracks on a CD. This function shall only be called while the drive is idle + * and cannot be used in an IRQ callback or critical section. + * + * NOTE: the CD-ROM controller only returns the minutes and seconds of each + * track's location. This makes it impossible to start playing a track from its + * *exact* beginning, and may result in the end of the previous track being + * played if there are no silent gaps between tracks. The CD specification + * recommends adding a 2-second pregap to each track for this reason. + * + * @param toc Pointer to an array of CdlLOC entries + * @return Number of tracks on the disc, or 0 in case of error + * + * @see CdControl() + */ +int CdGetToc(CdlLOC *toc); + +/** + * @brief Returns the CD-ROM controller's region code. + * + * @details Attempts to fetch region information from the drive using a CdlTest + * command. This can be used to reliably determine the system's region without + * having to resort to workarounds like probing the BIOS ROM. * - * @details Sets the CD-ROM attenuation parameters from a CdlATV struct - * specified by vol. The CD-ROM attenuation settings are different from the SPU - * CD-ROM volume. + * This function may return incorrect results on emulators or consoles equipped + * with CD-ROM drive emulation devices such as the PSIO. It is not affected by + * modchips. * - * Normally used to configure CD and XA audio playback for mono or reverse - * stereo output, though this was rarely used in practice. + * @return Region code or 0 if the region cannot be determined + */ +CdlRegionCode CdGetRegion(void); + +/** + * @brief Sets the CD-ROM volume mixing matrix. + * + * @details Sets the volume levels of the CD-ROM drive's audio output (used for + * both CD-DA and XA playback) to match the values in the provided CdlATV + * structure. + * + * The default setting is { 128, 0, 128, 0 }, i.e. send the left channel to the + * left output only and the right channel to the right output only. The output + * can be downmixed to mono by setting the values to { 64, 64, 64, 64 }, or the + * left and right channels can be swapped using { 0, 128, 0, 128 }. + * + * NOTE: the SPU has an additional volume control for CD audio. Both must be + * set in order for audio output to work. * * @param vol CD-ROM attenuation parameters - * @return Always 1. + * @return Always 1 */ int CdMix(const CdlATV *vol); /** - * @brief Opens a directory on the CD-ROM file system + * @brief Locates a file in the CD-ROM file system. + * + * @details Searches the CD-ROM's ISO9660 file system for the specified file + * and populates the given CdlFILE structure with information about the file if + * found. This function uses dynamic memory allocation. + * + * Directories can be separated with slashes (/) or backslashes (\), a leading + * slash or backslash is optional but paths must be absolute. The device prefix + * (cdrom:) must be omitted. A file version identifier (;1) at the end of the + * name is also optional. File and directory names are case insensitive; long + * names and ISO9660 extensions such as Joliet are currently not supported. + * + * This function is blocking and may take several seconds to load and + * subsequently parse the path table and directory records if none of the file + * system functions have yet been called. + * + * Upon calling this function for the first time, the ISO descriptor of the + * disc is read and the whole path table is cached into memory. Next the + * directory descriptor of the particular directory specified is loaded and + * cached to locate the file specified. The directory descriptor is kept in + * memory as long as the consecutive files to be searched are stored in the + * same directory until a file in another directory is to be searched. On which + * the directory descriptor is unloaded and a new directory descriptor is read + * from the disc and cached. Therefore, locating files in the same directory is + * faster as the relevant directory descriptor is already in memory and no disc + * reads are issued. + * + * Since file system access is slow, it is recommended to only use + * CdSearchFile() sparingly to e.g. find the location of a custom archive file, + * and then use the archive's internal table of contents to locate entries + * within the archive. + * + * @param loc Pointer to a CdlFILE structure + * @param filename + * @return Pointer to the specified CdlFILE structure, or a null pointer if the + * file cannot be found or another error occurred; the return value of + * CdIsoError() is also updated + * + * @see CdOpenDir() + */ +CdlFILE* CdSearchFile(CdlFILE *loc, const char *filename); + +/** + * @brief Opens a directory on the CD-ROM file system. * - * @details Opens a directory on the CD-ROM file system to read the contents of - * a directory. + * @details Opens a directory on the CD-ROM's ISO9660 file system and reads its + * contents, returning a newly allocated CdlDIR structure. This function uses + * dynamic memory allocation. * - * A path name can use a slash (/) or backslash character (\) as the directory - * name separator. The path must be absolute and should begin with a slash or - * backslash. It should also not be prefixed with a device name (ie. - * \MYDIR1\MYDIR2 will work but not cdrom:\MYDIR1\MYDIR2). The file system - * routines in libpsxcd can query directory paths of up to 128 characters. + * Directories can be separated with slashes (/) or backslashes (\), a leading + * slash or backslash is optional but paths must be absolute. The device prefix + * (cdrom:) must be omitted. Directory names are case insensitive; long names + * and ISO9660 extensions such as Joliet are currently not supported. * - * The ISO9660 file system routines of libpsxcd do not support long file names - * currently. Only MS-DOS style 8.3 file names are supported; extensions such - * as Joliet and Rock Ridge are ignored. + * This function is blocking and may take several seconds to load and + * subsequently parse the path table and directory records if none of the file + * system functions have yet been called. * - * @param path Directory path to open - * @return Pointer of a CdlDIR context, NULL if an error occurred. + * @param path + * @return Pointer of a CdlDIR context or a null pointer if an error occurred; + * the return value of CdIsoError() is also updated * * @see CdReadDir(), CdCloseDir() */ -CdlDIR* CdOpenDir(const char* path); +CdlDIR *CdOpenDir(const char *path); /** - * @brief Reads a directory entry from an open directory context + * @brief Obtains information about the next file in the directory. * - * @details Retrieves a file entry from an open directory context and stores it - * to a CdlFILE struct specified by file. Repeated calls of this function - * retrieves the next directory entry available until there are no more - * directory entries that follow. + * @details Retrieves a file entry from an open directory context and stores + * information about the file into the provided CdlFILE structure. This + * function is meant to be called repeatedly until no more files are available + * in the directory, in which case it returns 0. * - * @param dir Open directory context (from CdOpenDir()) - * @param file Pointer to a CdlFILE struct - * @return 1 if there are proceeding directory entries that follow, otherwise 0. + * @param dir + * @param file Pointer to a CdlFILE structure + * @return 1 if there are proceeding directory entries that follow, 0 otherwise * * @see CdOpenDir() */ -int CdReadDir(CdlDIR* dir, CdlFILE* file); +int CdReadDir(CdlDIR *dir, CdlFILE *file); /** - * @brief Closes a directory context created by CdOpenDir() + * @brief Closes a directory opened by CdOpenDir(). * - * @details Closes a directory query context created by CdOpenDir(). Behavior - * is undefined when closing a previously closed directory context. + * @details Closes and deallocates directory query context returned by + * CdOpenDir(). Behavior is undefined when closing a previously closed + * directory context. * - * @param dir Directory context + * @param dir * * @see CdOpenDir() */ -void CdCloseDir(CdlDIR* dir); - -int CdGetVolumeLabel(char* label); +void CdCloseDir(CdlDIR *dir); /** - * @brief Sets a callback function for auto pause - * - * @details The callback function specified in *func is executed when an auto - * pause interrupt occurs when the current CD-ROM mode is set with CdlModeAP. - * Auto pause interrupt occurs when CD Audio playback reaches the end of the - * audio track. Specifying 0 disables the callback. + * @brief Retrieves the volume label of the CD-ROM file system. * - * This can be used to easily loop CD audio automatically without requiring any - * intervention in your software loop. + * @details Reads the volume identifier of the disc's ISO9660 file system and + * stores it into the provided string buffer. The volume label can be up to 32 + * characters long. * - * @param func Callback function - * @return Pointer to the last callback function set. Zero if no callback was - * set previously. + * This function is blocking and may take several seconds to load and + * subsequently parse the path table and directory records if none of the file + * system functions have yet been called. * - * @see CdControl() + * @param label + * @return Length of the volume label (excluding the null terminator) or -1 in + * case of an error; the return value of CdIsoError() is also updated */ -int* CdAutoPauseCallback(void(*func)()); +int CdGetVolumeLabel(char *label); /** - * @brief Retrieves CD-ROM ISO9660 parser status + * @brief Retrieves CD-ROM ISO9660 parser status. * * @details Returns the status of the file system parser from the last call of - * a file system related function, such as CdSearchFile(), CdGetVolumeLabel() - * and CdOpenDir(). Use this function to retrieve the exact error occurred when - * either of those functions fail. + * a file system related function, such as CdSearchFile(), CdGetVolumeLabel(), + * CdOpenDir() and CdLoadSession(). Use this function to retrieve the exact + * error occurred when any of those functions fail. * * @return CD-ROM ISO9660 parser error code, as listed below: * @@ -745,11 +996,13 @@ int* CdAutoPauseCallback(void(*func)()); * | CdlIsoReadError | Read error occurred while reading the CD-ROM file system descriptor. | * | CdlIsoInvalidFs | Disc does not contain a standard ISO9660 file system. | * | CdlIsoLidOpen | Lid is open when attempting to parse the CD-ROM file system. | + * + * @see CdSearchFile(), CdOpenDir() */ int CdIsoError(void); /** - * @brief Locates and parses the specified disc session + * @brief Locates and loads the specified disc session. * * @details Loads a session specified by session on a multi-session disc. Uses * CdlSetsession to seek to the specified disc session, then scans the @@ -778,16 +1031,15 @@ int CdIsoError(void); * with the swap trick however, so a chipped or unlockable console is desired * for reading multi-session discs. * - * NOTE: When the lid has been opened, the current CD-ROM session is reset to + * NOTE: when the lid has been opened, the current CD-ROM session is reset to * the first session on the disc. The console may produce an audible click * sound when executing this function. This is normal, and the click sound is * no different to the click heard on disc spin-up in older models of the * console. * * @param session Session number (1 = first session) - * @return 0 on success. On failure due to open lid, bad session number or no - * volume descriptor found in specified session, returns -1 and return value of - * CdIsoError() is updated. + * @return 0 on success or -1 in case of errors; the return value of + * CdIsoError() is also updated */ int CdLoadSession(int session); |
