diff options
| author | spicyjpeg <thatspicyjpeg@gmail.com> | 2022-10-30 17:19:56 +0100 |
|---|---|---|
| committer | spicyjpeg <thatspicyjpeg@gmail.com> | 2022-10-30 17:19:56 +0100 |
| commit | 37d963f724113e45d15aa9b8ee86baa9c4362b8f (patch) | |
| tree | d4d3374afd5e36e8580cc424ab2c63ee9e7d357c /libpsn00b/include | |
| parent | 68daf6d338aba6e32e687d4151eaddc8735227b3 (diff) | |
| download | psn00bsdk-37d963f724113e45d15aa9b8ee86baa9c4362b8f.tar.gz | |
Add inline docs to psxcd.h, psxetc.h, psxgte.h
Diffstat (limited to 'libpsn00b/include')
| -rw-r--r-- | libpsn00b/include/inline_c.h | 173 | ||||
| -rw-r--r-- | libpsn00b/include/psxcd.h | 824 | ||||
| -rw-r--r-- | libpsn00b/include/psxetc.h | 152 | ||||
| -rw-r--r-- | libpsn00b/include/psxgte.h | 205 | ||||
| -rw-r--r-- | libpsn00b/include/psxpress.h | 158 | ||||
| -rw-r--r-- | libpsn00b/include/psxsio.h | 99 |
6 files changed, 1432 insertions, 179 deletions
diff --git a/libpsn00b/include/inline_c.h b/libpsn00b/include/inline_c.h index c5eaa59..5facc1c 100644 --- a/libpsn00b/include/inline_c.h +++ b/libpsn00b/include/inline_c.h @@ -3,9 +3,17 @@ * (C) 2019 Lameguy64 * (C) 2021-2022 Soapy (tweaked by spicyjpeg) * - * This header is basically identical to Nugget's inline_n.h. All GTE commands - * can be used right away without having to run DMPSX or any other tool on - * object files. + * This header is basically identical to Nugget's inline_n.h. + */ + +/** + * @file inline_c.h + * @brief Inline GTE macro header + * + * @details This header provides a set of macros for making use of GTE commands + * and registers from C or C++ code. Unlike the official SDK, all commands can + * be used right away without having to run any other post-processing tool on + * compiled object files. */ #ifndef _INLINE_C_H @@ -13,7 +21,11 @@ /* GTE load macros */ -/* Load a SVECTOR (passed as a pointer) to GTE V0 +/** + * @brief Loads a single SVECTOR to GTE vector register V0 + * + * @details Loads values from an SVECTOR struct to GTE data registers C2_VXY0 + * and C2_VZ0. */ #define gte_ldv0( r0 ) __asm__ volatile ( \ "lwc2 $0, 0( %0 );" \ @@ -22,7 +34,11 @@ : "r"( r0 ) \ : "$t0" ) -/* Load a SVECTOR (passed as a pointer) to GTE V1 +/** + * @brief Loads a single SVECTOR to GTE vector register V1 + * + * @details Loads values from an SVECTOR struct to GTE data registers C2_VXY1 + * and C2_VZ1. */ #define gte_ldv1( r0 ) __asm__ volatile ( \ "lwc2 $2, 0( %0 );" \ @@ -31,7 +47,11 @@ : "r"( r0 ) \ : "$t0" ) -/* Load a SVECTOR (passed as a pointer) to GTE V2 +/** + * @brief Loads a single SVECTOR to GTE vector register V2 + * + * @details Loads values from an SVECTOR struct to GTE data registers C2_VXY2 + * and C2_VZ2. */ #define gte_ldv2( r0 ) __asm__ volatile ( \ "lwc2 $4, 0( %0 );" \ @@ -40,7 +60,11 @@ : "r"( r0 ) \ : "$t0" ) -/* Load three SVECTORs (passed as a pointer) to the GTE at once +/** + * @brief Load three SVECTORs to GTE vector registers at once + * + * @details Loads values from three SVECTOR structs to GTE data registers + * C2_VXY0 and C2_VZ0, C2_VXY1 and C2_VZ1, C2_VXY2 and C2_VZ2 at once. */ #define gte_ldv3( r0, r1, r2 ) __asm__ volatile ( \ "lwc2 $0, 0( %0 );" \ @@ -88,6 +112,14 @@ : \ : "r"( r0 ) ) +/** + * @brief Load a CVECTOR to GTE register C2_RGBC + * + * @details Loads a CVECTOR value to GTE data register C2_RGBC. The primitive + * code (the last byte of a CVECTOR) is passed to the color FIFO registers when + * performing lighting compute operations, so it can be stored to the RGBC + * field of a primitive directly without any additional operation required. + */ #define gte_ldrgb( r0 ) __asm__ volatile ( \ "lwc2 $6 , 0( %0 );" \ : \ @@ -224,6 +256,12 @@ : "r"( r0 ) \ : "$12", "$13", "$14" ) +/** + * @brief Loads values to GTE registers C2_IR1-3 + * + * @details Loads three 32-bit values to GTE data registers C2_IR1, C2_IR2 and + * C2_IR3. + */ #define gte_ldopv2( r0 ) __asm__ volatile ( \ "lwc2 $11, 8( %0 );" \ "lwc2 $9 , 0( %0 );" \ @@ -253,6 +291,14 @@ : \ : "r"( r0 ), "r"( r1 ), "r"( r2 ) ) +/** + * @brief Sets an RGB color value to the GTE + * + * @details Sets the specified RGB value to GTE control registers C2_RBK, + * C2_GBK and C2_BBK. This specifies the color value to use when a normal faces + * away from the direction of the light source. This can be considered as the + * ambient light color. + */ #define gte_SetBackColor( r0, r1, r2 ) __asm__ volatile ( \ "sll $t0, %0, 4;" \ "sll $t1, %1, 4;" \ @@ -282,6 +328,13 @@ : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ : "$12", "$13", "$14" ) +/** + * @brief Sets the GTE screen offset + * + * @details Sets the values of the GTE screen offset which is applied to 2D + * projected coordinates when performing perspective transformation. The values + * are set to GTE control registers C2_OFX and C2_OFY. + */ #define gte_SetGeomOffset( r0, r1 ) __asm__ volatile ( \ "sll $t0, %0, 16;" \ "sll $t1, %1, 16;" \ @@ -291,6 +344,13 @@ : "r"( r0 ), "r"( r1 ) \ : "$t0", "$t1" ) +/** + * @brief Sets the distance of the projection plane + * + * @details Sets the specified value to GTE control register C2_H which + * determines the projection plane distance, otherwise known as the field of + * view. + */ #define gte_SetGeomScreen( r0 ) __asm__ volatile ( \ "ctc2 %0, $26;" \ : \ @@ -305,6 +365,12 @@ : "r"( r0 ) \ : "$12", "$13" ) +/** + * @brief Sets a 3x3 rotation matrix portion from a MATRIX to the GTE + * + * @details Sets the 3x3 rotation matrix coordinates from a MATRIX struct to + * GTE control registers C2_R11R12, C2_R13R21, C2_R22R23, C2_R31R32 and C2_R33. + */ #define gte_SetRotMatrix( r0 ) __asm__ volatile ( \ "lw $t0, 0( %0 );" \ "lw $t1, 4( %0 );" \ @@ -329,6 +395,17 @@ : "r"( r0 ) \ : "$12", "$13" ) +/** + * @brief Sets a 3x3 lighting matrix from a MATRIX to the GTE + * + * @details Sets the 3x3 lighting matrix coordinates from a MATRIX struct to + * GTE control registers C2_L11L12, C2_L13L21, C2_L22L23, C2_L31L32 and C2_L33. + * + * The lighting matrix is essentially a triplet of three light direction + * vectors. L11, L12 and L13 represents the X, Y and Z coordinates of light + * source 0 for example. Coordinates must be normalized to ensure correct + * results. + */ #define gte_SetLightMatrix( r0 ) __asm__ volatile ( \ "lw $t0, 0( %0 );" \ "lw $t1, 4( %0 );" \ @@ -353,6 +430,17 @@ : "r"( r0 ) \ : "$12", "$13" ) +/** + * @brief Sets a 3x3 color matrix from a MATRIX to the GTE + * + * @details Sets the 3x3 color matrix values from a MATRIX struct to GTE + * control registers C2_LR1LR2, C2_LR3LG1, C2_LG2LG3, C2_LB1LB2 and C2_LB3. + * + * The light color matrix is essentially a triplet of three RGB colors for each + * of the three light sources. LR1, LG1 and LB1 represents the R, G and B color + * values for light source 0 for example. Values are of range 0 to 4095, higher + * values will be saturated. + */ #define gte_SetColorMatrix( r0 ) __asm__ volatile ( \ "lw $t0, 0( %0 );" \ "lw $t1, 4( %0 );" \ @@ -368,6 +456,12 @@ : "r"( r0 ) \ : "$t2" ) +/** + * @brief Sets the translation portion of a MATRIX to the GTE + * + * @details Sets the translation coordinates from a MATRIX struct to GTE + * control registers C2_TRX, C2_TRY and C2_TRZ respectively. + */ #define gte_SetTransMatrix( r0 ) __asm__ volatile ( \ "lw $t0, 20( %0 );" \ "lw $t1, 24( %0 );" \ @@ -1044,11 +1138,39 @@ /* GTE operation macros */ +/** + * @brief Rotate, Translate and Perspective Single (15 cycles) + * + * @details Performs rotation, translation and perspective calculation of a + * single vertex. Divide overflows are simply saturated allowing for crude Z + * clipping. Check C2_FLAG to determine which overflow error has occurred + * during calculation. + * + * The following equation is performed when executing this GTE command: + * + * IR1 = MAC1 = (TRX*4096 + R11*VX0 + R12*VY0 + R13*VZ0) / 4096 + * IR2 = MAC2 = (TRY*4096 + R21*VX0 + R22*VY0 + R23*VZ0) / 4096 + * IR3 = MAC3 = (TRZ*4096 + R31*VX0 + R32*VY0 + R33*VZ0) / 4096 + * SZ3 = MAC3 + * + * MAC0 = (((H*131072/SZ3)+1)/2) * IR1 + OFX, SX2 = MAC0 / 65536 + * MAC0 = (((H*131072/SZ3)+1)/2) * IR2 + OFY, SY2 = MAC0 / 65536 + * MAC0 = (((H*131072/SZ3)+1)/2) * DQA + DQB, IR0 = MAC0 / 4096 + */ #define gte_rtps() __asm__ volatile ( \ "nop;" \ "nop;" \ "cop2 0x0180001;" ) +/** + * @brief Rotate, Translate and Perspective Triple (23 cycles) + * + * @details Performs rotation, translation and perspective calculation of three + * vertices at once. The equation performed is the same as gte_rtps() only + * repeated three times for each vertex. The result of the first vertex is + * stored in GTE data register C2_SXY0, the second vector in C2_SXY1 then + * C2_SXY2. + */ #define gte_rtpt() __asm__ volatile ( \ "nop;" \ "nop;" \ @@ -1325,16 +1447,53 @@ "nop;" \ "cop2 0x0138041C;" ) +/** + * @brief Normal clipping (8 cycles) + * + * @details Computes the sign of three screen coordinates (C2_SXY0-3) used for + * backface culling. If the value of C2_MAC0 is negative, the coordinates are + * inverted and thus the triangle is back facing. + * + * The following equation is performed when executing this GTE command: + * + * MAC0 = SX0*SY1 + SX1*SY2 + SX2*SY0 - SX0*SY2 - SX1*SY0 - SX2*SY1 + */ #define gte_nclip() __asm__ volatile ( \ "nop;" \ "nop;" \ "cop2 0x01400006;" ) +/** + * @brief Average screen Z result (5 cycles) + * + * @details Averages the values of GTE registers C2_SZ1, C2_SZ2 and C2_SZ3, + * multiplies it by C2_ZSF3 and divides the result by 0x1000 before storing to + * C2_OTZ. Used to compute the ordering table depth level for a three-vertex + * primitive. + * + * The following equation is performed when executing this GTE command: + * + * MAC0 = ZSF3 * (SZ1+SZ2+SZ3) + * OTZ = MAC0 / 4096 + */ #define gte_avsz3() __asm__ volatile ( \ "nop;" \ "nop;" \ "cop2 0x0158002D;" ) +/** + * @brief Average screen Z result (6 cycles) + * + * @details Averages the values of GTE registers C2_SZ1, C2_SZ2, C2_SZ3 and + * C2_SZ4, multiplies it by C2_ZSF4 and divides the result by 0x1000 before + * storing to C2_OTZ. Used to compute the ordering table depth level for a + * four-vertex primitive. + * + * The following equation is performed when executing this GTE command: + * + * MAC0 = ZSF4 * (SZ1+SZ2+SZ3+SZ4) + * OTZ = MAC0 / 4096 + */ #define gte_avsz4() __asm__ volatile ( \ "nop;" \ "nop;" \ diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h index bd89f53..8150703 100644 --- a/libpsn00b/include/psxcd.h +++ b/libpsn00b/include/psxcd.h @@ -3,174 +3,792 @@ * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed */ +/** + * @file psxcd.h + * @brief CD-ROM library header + * + * @details The PSn00bSDK CD-ROM library provides facilities for using the + * CD-ROM hardware of the PS1. Unlike the CD-ROM library of the official SDK, + * psxcd is immune to the 30 file and directory limit and is capable of parsing + * directories containing as many files as the ISO9660 file system can support, + * unless the records are too large to be loaded into memory. However, to + * maintain compatibility with the PS1 BIOS, the root directory must not exceed + * the 30 file limit and the entire disc should contain no more than 45 + * directories total. + * + * Whilst psxcd is not constrained by the 30 file per directory limit, it does + * not support Joliet CD-ROM extensions to support long file names. However, a + * library extension is considered for future development. + */ + #ifndef __PSXCD_H #define __PSXCD_H #include <stdint.h> -/* - * CD-ROM control commands - */ -#define CdlNop 0x01 /* a.k.a. Getstat */ -#define CdlSetloc 0x02 -#define CdlPlay 0x03 -#define CdlForward 0x04 -#define CdlBackward 0x05 -#define CdlReadN 0x06 -#define CdlStandby 0x07 /* a.k.a. MotorOn */ -#define CdlStop 0x08 -#define CdlPause 0x09 -#define CdlInit 0x0A -#define CdlMute 0x0B -#define CdlDemute 0x0C -#define CdlSetfilter 0x0D -#define CdlSetmode 0x0E -#define CdlGetparam 0x0F -#define CdlGetlocL 0x10 -#define CdlGetlocP 0x11 -#define CdlSetsession 0x12 /* ORIGINAL CODE */ -#define CdlGetTN 0x13 -#define CdlGetTD 0x14 -#define CdlSeekL 0x15 -#define CdlSeekP 0x16 -#define CdlTest 0x19 /* ORIGINAL CODE */ -#define CdlReadS 0x1B +/* Enum definitions */ -/* - * CD-ROM status bits - */ -#define CdlStatError 0x01 -#define CdlStatStandby 0x02 -#define CdlStatSeekError 0x04 -#define CdlStatIdError 0x08 /* ORIGINAL CODE */ -#define CdlStatShellOpen 0x10 -#define CdlStatRead 0x20 -#define CdlStatSeek 0x40 -#define CdlStatPlay 0x80 +typedef enum _CdlCommand { + CdlNop = 0x01, + CdlSetloc = 0x02, + CdlPlay = 0x03, + CdlForward = 0x04, + CdlBackward = 0x05, + CdlReadN = 0x06, + CdlStandby = 0x07, + CdlStop = 0x08, + CdlPause = 0x09, + CdlInit = 0x0a, + CdlMute = 0x0b, + CdlDemute = 0x0c, + CdlSetfilter = 0x0d, + CdlSetmode = 0x0e, + CdlGetparam = 0x0f, + CdlGetlocL = 0x10, + CdlGetlocP = 0x11, + CdlSetsession = 0x12, + CdlGetTN = 0x13, + CdlGetTD = 0x14, + CdlSeekL = 0x15, + CdlSeekP = 0x16, + CdlTest = 0x19, + CdlGetID = 0x1a, + CdlReadS = 0x1b, + CdlReset = 0x1c +} CdlCommand; -/* - * CD-ROM mode bits - */ -#define CdlModeDA 0x01 -#define CdlModeAP 0x02 -#define CdlModeRept 0x04 -#define CdlModeSF 0x08 -//#define CdlModeSize0 0x10 -//#define CdlModeSize1 0x20 -#define CdlModeIgnore 0x10 -#define CdlModeSize 0x20 -#define CdlModeRT 0x40 -#define CdlModeSpeed 0x80 +typedef enum _CdlStatFlag { + CdlStatError = 1 << 0, + CdlStatStandby = 1 << 1, + CdlStatSeekError = 1 << 2, + CdlStatIdError = 1 << 3, + CdlStatShellOpen = 1 << 4, + CdlStatRead = 1 << 5, + CdlStatSeek = 1 << 6, + CdlStatPlay = 1 << 7 +} CdlStatFlag; -/* - * CD-ROM interrupt result values +typedef enum _CdlModeFlag { + CdlModeDA = 1 << 0, + CdlModeAP = 1 << 1, + CdlModeRept = 1 << 2, + CdlModeSF = 1 << 3, + //CdlModeSize0 = 1 << 4, + //CdlModeSize1 = 1 << 5, + CdlModeIgnore = 1 << 4, + CdlModeSize = 1 << 5, + CdlModeRT = 1 << 6, + CdlModeSpeed = 1 << 7 +} CdlModeFlag; + +typedef enum _CdlIntrResult { + CdlNoIntr = 0, + CdlDataReady = 1, + CdlComplete = 2, + CdlAcknowledge = 3, + CdlDataEnd = 4, + CdlDiskError = 5 +} CdlIntrResult; + +typedef enum _CdlIsoError { + CdlIsoOkay = 0, + CdlIsoSeekError = 1, + CdlIsoReadError = 2, + CdlIsoInvalidFs = 3, + CdlIsoLidOpen = 4 +} CdlIsoError; + +/** + * @brief Translates a BCD format 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. */ -#define CdlNoIntr 0x00 -#define CdlDataReady 0x01 -#define CdlComplete 0x02 -#define CdlAcknowledge 0x03 -#define CdlDataEnd 0x04 -#define CdlDiskError 0x05 +#define btoi(b) ((b)/16*10+(b)%16) -/* - * CD-ROM file system error codes (original) +/** + * @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. */ -#define CdlIsoOkay 0x00 -#define CdlIsoSeekError 0x01 -#define CdlIsoReadError 0x02 -#define CdlIsoInvalidFs 0x03 -#define CdlIsoLidOpen 0x04 +#define itob(i) ((i)/10*16+(i)%10) -#define btoi(b) ((b)/16*10+(b)%16) /* Convert BCD value to integer */ -#define itob(i) ((i)/10*16+(i)%10) /* Convert integer to BCD value */ +/* Structure and type definitions */ -/* - * CD-ROM disc location struct - */ -typedef struct _CdlLOC -{ - uint8_t minute; - uint8_t second; - uint8_t sector; - uint8_t track; +/** + * @brief CD-ROM positional coordinates + * + * @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. + * + * @see CdIntToPos(), 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) } CdlLOC; -/* - * CD-ROM audio attenuation struct (volume) - */ -typedef struct _CdlATV -{ - uint8_t val0; /* L -> SPU L */ - uint8_t val1; /* L -> SPU R */ - uint8_t val2; /* R -> SPU R */ - uint8_t val3; /* R -> SPU L */ +/** + * @brief CD-ROM attenuation parameters + * + * @details This structure specifies parameters for the CD-ROM attenuation. + * Values must be of range 0 to 127. + * + * 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. + * + * @see CdMix() + */ +typedef struct _CdlATV { + uint8_t val0; // CD to SPU L-to-L volume + uint8_t val1; // CD to SPU L-to-R volume + uint8_t val2; // CD to SPU R-to-R volume + uint8_t val3; // CD to SPU R-to-L volume } CdlATV; -/* - * CD-ROM file information struct +/** + * @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. + * + * @see CdSearchFile() */ -typedef struct _CdlFILE -{ - CdlLOC pos; - uint32_t size; - char name[16]; +typedef struct _CdlFILE { + CdlLOC pos; // CD-ROM position coordinates of file + uint32_t size; // Size of file in bytes + char name[16]; // File name } CdlFILE; -typedef struct _CdlFILTER -{ - uint8_t file; - uint8_t chan; - uint16_t pad; +/** + * @brief Structure used to set CD-ROM XA filter + * + * @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. + * + * 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 + * stream is normally read at 2x speed but only one of eight XA audio streams + * can be played at a time. The XA stream to play is specified by the + * CdlSetfilter command and this struct. + * + * The CD-ROM XA filter can be changed during CD-ROM XA audio playback with + * zero audio interruption. This can be used to achieve dynamic music effects + * by switching to alternate versions of a theme to fit specific scenes + * seamlessly. + * + * @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 } CdlFILTER; -/* Directory query context */ -typedef void* CdlDIR; +/** + * @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(). + * + * @see CdOpenDir() + */ +typedef void *CdlDIR; -/* Data callback */ typedef void (*CdlCB)(int, uint8_t *); +/* Public API */ + #ifdef __cplusplus extern "C" { #endif +/** + * @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. + * + * @return Always 1. May change in the future. + */ int CdInit(void); +/** + * @brief Translates a logical sector number to CD-ROM positional 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. + * + * @param i Logical sector number + * @param p Pointer to a CdlLOC structure + * @return Pointer to the specified CdlLOC struct plus 150 sectors. + */ CdlLOC* CdIntToPos(int i, CdlLOC *p); + +/** + * @brief Translates CD-ROM positional coordinates to a logical sector number + * + * @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. + * + * @param p Pointer to a CdlLOC struct + * @return Logical sector number minus the 150 sector lead-in. + */ int CdPosToInt(const CdlLOC *p); + +/** + * @brief Gets CD-ROM TOC information + * + * @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. + * + * 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. + * + * @param toc Pointer to an array of CdlLOC entries + * @return Number of tracks on the disc, zero on error. + * + * @see CdControl() + */ int CdGetToc(CdlLOC *toc); +/** + * @brief Issues a control command to the CD-ROM controller + * + * @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. + * + * @see CdControl(), CdControlF() + */ int CdControlB(uint8_t com, const void *param, uint8_t *result); + +/** + * @brief Issues a CD-ROM command to the CD-ROM controller (does not block) + * + * @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. + * + * 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. + * + * @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. + * + * @see CdControl() + */ int CdControlF(uint8_t com, const void *param); + +/** + * @brief Waits for blocking command or blocking status + * + * @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. + * + * A buffer specified by result will be set 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 + * @return Command status is returned as one of the following definitions: + * + * | Definition | Description | + * | :----------- | :-------------------------- | + * | CdlComplete | Command completed. | + * | CdlNoIntr | No interrupt, command busy. | + * | CdlDiskError | CD-ROM error occurred. | + * + * @see CdControl() + */ int CdSync(int mode, uint8_t *result); + +/** + * @brief Sets a callback function + * + * @details Sets a callback with the specified function func. The callback is + * executed whenever a blocking command has completed. + * + * 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. + * + * @param func Callback function + * @return Pointer to last callback function set, or NULL if none was set. + * + * @see CdControl, CdControlB, CdSync + */ uint32_t CdSyncCallback(CdlCB func); +/** + * @brief Sets a callback function + * + * @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(). + * + * 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. + * + * 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. + * + * @param func Callback function + * @return Pointer to last callback function set, or NULL if none was set. + * + * @see CdControl(), CdControlB(), CdGetSector() + */ int CdReadyCallback(CdlCB func); + +/** + * @brief Gets data from the CD-ROM sector buffered + * + * @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. + * + * 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. + * + * @see CdReadyCallback() + */ int CdGetSector(void *madr, int size); + +/** + * @brief Gets data from the CD-ROM sector buffered (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(). + * + * 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. + * + * @see CdReadyCallback(), CdDataSync() + */ int CdGetSector2(void *madr, int size); + +/** + * @brief Waits for sector 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. + * + * @param mode Mode + * @return 0 if the transfer has finished, 1 if it is still in progress or -1 + * in case of a timeout. + * + * @see CdGetSector2() + */ int CdDataSync(int mode); +/** + * @brief Locates a file in the CD-ROM file system + * + * @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. + * + * 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. + * + * 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. + * + * 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. + * + * 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 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. + */ CdlFILE* CdSearchFile(CdlFILE *loc, const char *filename); +/** + * @brief Reads sectors from the CD-ROM + * + * @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. + * + * 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 blocks very briefly to issue the necessary commands to start + * CD-ROM reading. To determine if reading has completed use CdReadSync or + * CdReadCallback. + * + * @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. + * + * @see CdReadSync(), CdReadCallback() + */ int CdRead(int sectors, uint32_t *buf, int mode); + +/** + * @brief Waits for CD-ROM read completion or returns read status + * + * @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. + * + * A buffer specified by result will be set with the most recent CD-ROM status + * value from the last read issued. + * + * @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 CdRead() + */ int CdReadSync(int mode, uint8_t *result); + +/** + * @brief Sets a callback function for read completion + * + * @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. + * + * status is the CD-ROM status from the command that has completed processing. + * *result points to a read result buffer. + * + * @param func Callback function + * @return Pointer to last callback function set, or NULL if none was set. + * + * @see CdRead() + */ uint32_t CdReadCallback(CdlCB func); +/** + * @brief Gets the most recent CD-ROM status + * + * @details Returns the CD-ROM status since the last command issued. The status + * value is updated by most CD-ROM commands. + * + * To get the current CD-ROM status you can issue CdlNop commands at regular + * intervals to update the CD-ROM status this function returns. + * + * @return CD-ROM status from last comand issued. + * + * @see CdControl() + */ int CdStatus(void); + +/** + * @brief Gets the last CD-ROM mode + * + * @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. + * + * 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. + * + * @return Last CD-ROM mode value. + */ int CdMode(void); +/** + * @brief Sets CD-ROM mixer or attenuation + * + * @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. + * + * Normally used to configure CD and XA audio playback for mono or reverse + * stereo output, though this was rarely used in practice. + * + * @param vol CD-ROM attenuation parameters + * @return Always 1. + */ int CdMix(const CdlATV *vol); -/* ORIGINAL CODE */ +/** + * @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. + * + * 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. + * + * 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. + * + * @param path Directory path to open + * @return Pointer of a CdlDIR context, NULL if an error occurred. + * + * @see CdReadDir(), CdCloseDir() + */ CdlDIR* CdOpenDir(const char* path); + +/** + * @brief Reads a directory entry from an open directory context + * + * @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. + * + * @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. + * + * @see CdOpenDir() + */ int CdReadDir(CdlDIR* dir, CdlFILE* file); + +/** + * @brief Closes a directory context created by CdOpenDir() + * + * @details Closes a directory query context created by CdOpenDir(). Behavior + * is undefined when closing a previously closed directory context. + * + * @param dir Directory context + * + * @see CdOpenDir() + */ void CdCloseDir(CdlDIR* dir); int CdGetVolumeLabel(char* label); +/** + * @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. + * + * This can be used to easily loop CD audio automatically without requiring any + * intervention in your software loop. + * + * @param func Callback function + * @return Pointer to the last callback function set. Zero if no callback was + * set previously. + * + * @see CdControl() + */ int* CdAutoPauseCallback(void(*func)()); -int CdIsoError(); +/** + * @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. + * + * @return CD-ROM ISO9660 parser error code, as listed below: + * + * | Value | Description | + * | :-------------- | :-------------------------------------------------------------------------------------------------- | + * | CdlIsoOkay | File system parser okay. | + * | CdlIsoSeekError | Logical seek error occurred. May occur when attempting to query the filesystem on an audio-only CD. | + * | 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. | + */ +int CdIsoError(void); + +/** + * @brief Locates and parses 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 + * following 512 sectors for an ISO volume descriptor. If a volume descriptor + * is found the file system of that session is parsed and files inside the new + * session can be accessed using regular CD-ROM file and directory querying + * functions (CdSearchFile(), CdOpenDir(), CdReadDir(), CdCloseDir()). No + * special consideration is required when reading files from a new session. + * + * Loading a session takes 5-10 seconds to complete depending on the distance + * between the beginning of the disc and the start of the specified session. If + * the session specified does not exist, the disc will stop and would take + * 15-20 seconds to restart. The function does not support loading the most + * recent session of a disc automatically due to limitations of the CD-ROM + * hardware, so the user must be prompted to specify which session to load and + * to keep a record of the number of sessions that have been written to the + * disc. + * + * This function can also be used to update the Table of Contents (TOC) and + * reparse the file system regardless of the media change status by simply + * loading the first session. This is most useful for accessing files or audio + * tracks on a disc that was inserted using the swap trick method (it is + * recommended to stop the disc using CdlStop then restart it with CdlStandby + * after a button prompt for convenience, if you wish to implement this + * capability). Seeking to sessions other than the first session does not work + * 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 + * 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. + */ int CdLoadSession(int session); #ifdef __cplusplus diff --git a/libpsn00b/include/psxetc.h b/libpsn00b/include/psxetc.h index 3b18784..ae4611e 100644 --- a/libpsn00b/include/psxetc.h +++ b/libpsn00b/include/psxetc.h @@ -3,6 +3,16 @@ * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed */ +/** + * @file psxetc.h + * @brief Interrupt management library header + * + * @details This library provides basic facilities (such as interrupt handling) + * used by all other PSn00bSDK libraries, as well as some additional + * functionality including a dynamic linker (whose API is however defined in a + * separate header). + */ + #ifndef __PSXETC_H #define __PSXETC_H @@ -39,13 +49,155 @@ typedef enum _DMA_Channel { extern "C" { #endif +/** + * @brief Sets a callback for an interrupt. + * + * @details Registers a function to be called whenever the specified interrupt + * is fired. A previously registered callback can be removed by passing a null + * pointer instead. The IRQ controller is automatically configured to only + * enable interrupts for which a callback is registered. + * + * 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. Each interrupt is acknowledged automatically before the + * callback is invoked. + * + * The following interrupt channels are available (the ones already used + * internally by libraries shall not be overridden to avoid conflicts): + * + * | ID | Channel | Used by | + * | --: | :--------------- | :-------------------------------------- | + * | 0 | IRQ_VBLANK | psxgpu (use VSyncCallback() instead) | + * | 1 | IRQ_GPU | | + * | 2 | IRQ_CD | psxcd (use CdReadyCallback() instead) | + * | 3 | IRQ_DMA | psxetc (use DMACallback() instead) | + * | 4 | IRQ_TIMER0 | | + * | 5 | IRQ_TIMER1 | | + * | 6 | IRQ_TIMER2 | | + * | 7 | IRQ_SIO0 | | + * | 8 | IRQ_SIO1 | psxsio (use SIO_ReadCallback() instead) | + * | 9 | IRQ_SPU | | + * | 10 | IRQ_GUN, IRQ_PIO | | + * + * WARNING: even though interrupts are acknowledged automatically at the IRQ + * controller side, most IRQ channels (1, 2, 3, 7, 8, 9) additionally require + * acknowledging at the device side, which must be done by the callback. The + * exact way to acknowledge interrupts varies for each device, however it + * usually involves setting or clearing a bit in a register. See the nocash + * documentation for more details. + * + * @param irq + * @param func + * @return Previously set callback for the channel or NULL + */ void *InterruptCallback(IRQ_Channel irq, void (*func)(void)); + +/** + * @brief Gets the callback for an interrupt. + * + * @details Returns a pointer to the callback currently registered to handle + * the specified interrupt, or a null pointer if none is set. + * + * @param irq + * @return Currently set callback for the channel or NULL + * + * @see InterruptCallback() + */ void *GetInterruptCallback(IRQ_Channel irq); + +/** + * @brief Sets a callback for a DMA interrupt. + * + * @details Registers a function to be called whenever the specified DMA + * channel goes from busy to idle, i.e. when a transfer is completed. A + * previously registered callback can be removed by passing a null pointer + * instead. The DMA controller is automatically configured to only enable DMA + * interrupts for which a callback is registered. + * + * This function uses InterruptCallback() to register a "master handler" for + * DMA interrupts, which then dispatches the IRQ to depending on the channel + * that triggered it. + * + * 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. Each interrupt is acknowledged automatically before the + * callback is invoked. + * + * The following DMA channels are available (the ones already used internally + * by libraries shall not be overridden to avoid conflicts): + * + * | ID | Channel | Used by | + * | --: | :----------- | :-------------------------------------- | + * | 0 | DMA_MDEC_IN | | + * | 1 | DMA_MDEC_OUT | | + * | 2 | DMA_GPU | psxgpu (use DrawSyncCallback() instead) | + * | 3 | DMA_CD | | + * | 4 | DMA_SPU | | + * | 5 | DMA_PIO | | + * | 6 | DMA_OTC | | + * + * @param dma + * @param func + * @return Previously set callback for the channel or NULL + */ void *DMACallback(DMA_Channel dma, void (*func)(void)); + +/** + * @brief Gets the callback for a DMA interrupt. + * + * @details Returns a pointer to the callback currently registered to handle + * the specified DMA interrupt, or a null pointer if none is set. + * + * @param dma + * @return Currently set callback for the channel or NULL + * + * @see DMACallback() + */ void *GetDMACallback(DMA_Channel dma); +/** + * @brief Initializes the interrupt dispatcher. + * + * @details Sets up the interrupt handling system, hooks the BIOS to dispatch + * interrupts to the library and clears all registered callbacks. This function + * must be called once at the beginning of the program, prior to registering + * any IRQ or DMA callbacks. + * + * ResetCallback() is called by psxgpu's ResetGraph(), so invoking it manually + * is usually not required. Calling ResetCallback() after ResetGraph() will + * actually result in improper initialization, as ResetGraph() registers + * several callbacks used internally by psxgpu. + * + * @return 0 or -1 if the was already initialized + */ int ResetCallback(void); + +/** + * @brief Restores the interrupt dispatcher. + * + * @details Restores the IRQ and DMA controller state saved by StopCallback() + * and reinstalls BIOS hooks for interrupt dispatching. All callbacks + * previously set before StopCallback() was called are preserved. + * + * @see StopCallback() + */ void RestartCallback(void); + +/** + * @brief Temporarily disables the interrupt dispatcher. + * + * @details Saves the state of the IRQ and DMA controllers, then disables them + * and removes BIOS hooks. This function must be called prior to launching a + * new executable or DLL that calls ResetCallback() or ResetGraph(), or an + * executable not built with PSn00bSDK that uses its own interrupt handling + * subsystem (such as a retail game). The saved state can be restored after the + * executable returns using RestartCallback(). + * + * Note that interrupts are (obviously) disabled until RestartCallback() is + * called. + * + * @see RestartCallback() + */ void StopCallback(void); #ifdef __cplusplus diff --git a/libpsn00b/include/psxgte.h b/libpsn00b/include/psxgte.h index ddc988d..3c1d5a4 100644 --- a/libpsn00b/include/psxgte.h +++ b/libpsn00b/include/psxgte.h @@ -3,6 +3,17 @@ * (C) 2019-2022 Lameguy64 - MPL licensed */ +/** + * @file psxgte.h + * @brief GTE library header + * + * @details The Geometry Transformation Engine, often referred to as the GTE, + * is most responsible for providing 3D capabilities to the PS1. This is + * effectively an all-integer math co-processor connected directly to the CPU, + * as it is accessed using COP2 and related MIPS instructions to access + * registers and issue commands to the GTE. + */ + #ifndef __PSXGTE_H #define __PSXGTE_H @@ -35,50 +46,216 @@ typedef struct _DVECTOR { /* Public API */ +#define csin(a) isin(a) +#define ccos(a) icos(a) +#define rsin(a) isin(a) +#define rcos(a) icos(a) + #ifdef __cplusplus extern "C" { #endif -void InitGeom(void); - -// Integer SIN/COS functions (4096 = 360 degrees) -// Does not use tables! +/** + * @brief Gets sine of angle (fixed-point, high precision version) + * + * @details Returns the sine of angle a. + * + * @param a Angle in fixed-point format (131072 = 360 degrees) + * @return Sine value in 20.12 fixed-point format (4096 = 1.0). + */ int isin(int a); + +/** + * @brief Gets cosine of angle (fixed-point, high precision version) + * + * @details Returns the cosine of angle a. + * + * @param a Angle in fixed-point format (131072 = 360 degrees) + * @return Cosine value in 20.12 fixed-point format (4096 = 1.0). + */ int icos(int a); -// Higher precision integer sin/cos functions (131072 = 360 degrees) -// Does not use tables! +/** + * @brief Gets sine of angle (fixed-point) + * + * @details Returns the sine of angle a. + * + * @param a Angle in fixed-point format (131072 = 360 degrees) + * @return Sine value in 20.12 fixed-point format (4096 = 1.0). + */ int hisin(int a); + +/** + * @brief Gets cosine of angle (fixed-point) + * + * @details Returns the cosine of angle a. + * + * @param a Angle in fixed-point format (131072 = 360 degrees) + * @return Cosine value in 20.12 fixed-point format (4096 = 1.0). + */ int hicos(int a); +/** + * @brief Initializes the GTE + * + * @details Resets, enables and initializes the GTE. Must be called prior to + * using any GTE function or macro. + */ +void InitGeom(void); + +/** + * @brief Gets square root (fixed-point) + * + * @details Returns the square root of value v. + * + * @param v Value in 20.12 fixed-point format (4096 = 1.0) + * @return Square root in 20.12 fixed-point format (4096 = 1.0). + */ +int SquareRoot12(int v); + +/** + * @brief Gets square root (integer) + * + * @details Returns the square root of value v. + * + * @param v Value in integer format + * @return Square root in integer format. + */ +int SquareRoot0(int v); + +/** + * @brief Pushes the current GTE matrix to the matrix stack + * + * @details Pushes the current GTE rotation matrix and translation vector to + * the internal matrix stack. Only one matrix stack level is currently + * supported. + */ void PushMatrix(void); + +/** + * @brief Pops the last matrix pushed into the matrix stack back to the GTE + * + * @details Pops the last inserted matrix in the internal matrix stack back to + * the GTE. Only one matrix stack level is currently supported. + */ void PopMatrix(void); +/** + * @brief Defines the rotation matrix of a MATRIX + * + * @details Defines the rotation matrix of m from rotation coordinates of r. + * The matrix is computed as follows: + * + * [ 1 0 0 ] [ cy 0 sy] [ cz -sz 0 ] + * [ 0 cx -sx] * [ 0 1 0 ] * [ sz cz 0 ] + * [ 0 sx cx] [-sy 0 cy] [ 0 0 1 ] + * + * where: + * + * sx = sin(r.x) sy = sin(r.y) sz = sin(r.z) + * cx = cos(r.x) cy = cos(r.y) cz = cos(r.z) + * + * @param r Rotation vector (input) + * @param m Matrix (output) + * @return Pointer to m. + * + * @see TransMatrix(), CompMatrixLV() + */ MATRIX *RotMatrix(SVECTOR *r, MATRIX *m); + +/** + * @brief Defines the rotation matrix of a MATRIX (high precision version) + * + * @details Defines the rotation matrix of m from rotation coordinates of r. + * This function is a variant of RotMatrix() that uses hisin()/hicos() instead + * of isin()/icos(). + * + * See RotMatrix() for more details. + * + * @param r Rotation vector (input) + * @param m Matrix (output) + * @return Pointer to m. + * + * @see RotMatrix() + */ MATRIX *HiRotMatrix(VECTOR *r, MATRIX *m); +/** + * @brief Defines the translation vector of a MATRIX + * + * @details Simply sets the translation vector of MATRIX m. To perform + * accumulative translation operations, see CompMatrixLV(). + * + * @param m Translation vector (input) + * @param r Matrix (output) + * @return Pointer to m. + * + * @see RotMatrix(), CompMatrixLV() + */ MATRIX *TransMatrix(MATRIX *m, VECTOR *r); + MATRIX *ScaleMatrix(MATRIX *m, VECTOR *s); MATRIX *ScaleMatrixL(MATRIX *m, VECTOR *s); MATRIX *MulMatrix(MATRIX *m0, MATRIX *m1); MATRIX *MulMatrix0(MATRIX *m0, MATRIX *m1, MATRIX *m2); +/** + * @brief Composite coordinate matrix transform + * + * @details Performs vector multiply by matrix with vector addition from v0 to + * the translation vector of v1. Then, multiples the rotation matrix of v0 by + * the rotation matrix of v1. The result of both operations is then stored in + * v2. Replaces the current GTE rotation matrix and translation vector with v0. + * + * Often used to adjust the matrix (includes rotation and translation) of an + * object relative to a world matrix, so the object would render relative to + * the world matrix. + * + * @param v0 Input matrix A + * @param v1 Input matrix B + * @param v2 Output matrix + * @return Pointer to v2. + */ MATRIX *CompMatrixLV(MATRIX *v0, MATRIX *v1, MATRIX *v2); + +/** + * @brief Multiplies a vector by a matrix + * + * @details Multiplies vector v0 with matrix m, result is stored to v1. + * Replaces the current GTE rotation matrix and translation vector with m. + * + * Often used to calculate a translation vector in relation to the rotation + * matrix for first person or vector camera perspectives. + * + * @param m Input matrix + * @param v0 Input vector + * @param v1 Output vector + * @return Pointer to v1. + */ VECTOR *ApplyMatrixLV(MATRIX *m, VECTOR *v0, VECTOR *v1); +/** + * @brief Normalizes a VECTOR into SVECTOR format + * + * Normalizes a 32-bit vector into a 16-bit vector in 4.12 fixed-point format + * (4096 = 1.0, 2048 = 0.5). + * + * @param v0 Input (raw) 32-bit vector + * @param v1 Output (normalized) 16-bit vector + */ void VectorNormalS(VECTOR *v0, SVECTOR *v1); +/** + * @brief Calculates the square of a VECTOR + * + * @details Calculates the square of vector v0 and stores the result to v1. + * + * @param v0 Input vector + * @param v1 Output vector + */ void Square0(VECTOR *v0, VECTOR *v1); -int SquareRoot12(int v); -int SquareRoot0(int v); - -#define csin(a) isin(a) -#define ccos(a) icos(a) -#define rsin(a) isin(a) -#define rcos(a) icos(a) - #ifdef __cplusplus } #endif diff --git a/libpsn00b/include/psxpress.h b/libpsn00b/include/psxpress.h index 2106a53..dc1d52c 100644 --- a/libpsn00b/include/psxpress.h +++ b/libpsn00b/include/psxpress.h @@ -3,6 +3,23 @@ * (C) 2022 spicyjpeg - MPL licensed */ +/** + * @file psxpress.h + * @brief MDEC library header + * + * @details This is a fully original reimplementation of the official SDK's + * "data compression" library. This library is made up of two parts, the MDEC + * API and functions to decompress Huffman-encoded bitstreams (.BS files, or + * frames in .STR files) into data to be fed to the MDEC. Two different + * implementations of the latter are provided, one using the GTE and scratchpad + * region and an older one using a large lookup table in main RAM. + * + * FMV playback is not part of this library per se, but can implemented using + * the APIs defined here alongside some code to stream data from the CD drive. + * + * Currently only version 1 and 2 .BS files are supported. + */ + #ifndef __PSXPRESS_H #define __PSXPRESS_H @@ -70,7 +87,9 @@ extern "C" { #endif /** - * @brief Resets the MDEC and aborts any MDEC DMA transfers. If mode = 0, the + * @brief Resets and optionally initializes the MDEC. + * + * @details Resets the MDEC and aborts any MDEC DMA transfers. If mode = 0, the * default IDCT matrix and quantization tables are also loaded and the MDEC is * put into color output mode, discarding any custom environment previously set * with DecDCTPutEnv(). @@ -78,15 +97,19 @@ extern "C" { * DecDCTReset(0) must be called at least once prior to using the MDEC. * * @param mode + * + * @see DecDCTPutEnv() */ void DecDCTReset(int mode); /** - * @brief Uploads the specified decoding environment's quantization tables and - * IDCT matrix to the MDEC, or restores the default tables if a null pointer is - * passed. Calling this function is normally not required as DecDCTReset(0) - * initializes the MDEC with the default tables, but it may be useful for e.g. - * decoding JPEG or a format with custom quantization tables. + * @brief Loads default or custom quantization and IDCT tables into the MDEC. + * + * @details Uploads the specified decoding environment's quantization tables + * and IDCT matrix to the MDEC, or restores the default tables if a null + * pointer is passed. Calling this function is normally not required as + * DecDCTReset(0) initializes the MDEC with the default tables, but it may be + * useful for e.g. decoding JPEG or a format with custom quantization tables. * * The second argument, not present in the official SDK, specifies whether the * MDEC shall be put into color (0) or monochrome (1) output mode. In @@ -103,12 +126,16 @@ void DecDCTReset(int mode); void DecDCTPutEnv(const DECDCTENV *env, int mono); /** - * @brief Sets up the MDEC to start fetching and decoding the given buffer. - * This function is meant to be used with buffers generated by DecDCTvlc(): the - * first 32-bit word of the buffer is initially copied to the MDEC0 register, - * then all subsequent data is read in 128-byte (32-word) chunks. The length of - * the stream (in 32-bit units, minus the first word) is encoded by DecDCTvlc() - * in the lower 16 bits of the first word. + * @brief Feeds the MDEC with a run-length code buffer from the specified + * location. + * + * @details Sets up the MDEC to start fetching and decoding the given buffer. + * This function is meant to be used with buffers generated by DecDCTvlc(), + * DecDCTvlc2() or their variants: the first 32-bit word of the buffer is + * initially copied to the MDEC0 register, then all subsequent data is read in + * 128-byte (32-word) chunks. The length of the stream (in 32-bit units, minus + * the first word) is encoded by DecDCTvlc() in the lower 16 bits of the first + * word. * * The mode argument optionally specifies the output color depth (0 for 16bpp, * 1 for 24bpp) if not already set in the first word. Passing -1 will result in @@ -117,11 +144,15 @@ void DecDCTPutEnv(const DECDCTENV *env, int mono); * * @param data * @param mode DECDCT_MODE_* or -1 + * + * @see DecDCTinRaw(), DecDCTinSync() */ void DecDCTin(const uint32_t *data, int mode); /** - * @brief Configures the MDEC to automatically fetch data (the input stream, + * @brief Feeds the MDEC with raw data from the specified location. + * + * @details Configures the MDEC to automatically fetch data (the input stream, * IDCT matrix or quantization tables) in 128-byte (32-word) chunks from the * specified address in main RAM. The transfer is stopped, and any callback * registered with DMACallback(0) is fired, once a certain number of 32-bit @@ -135,13 +166,17 @@ void DecDCTin(const uint32_t *data, int mode); * * @param data * @param length Number of 32-bit words to read (must be multiple of 32) + * + * @see DecDCTin(), DecDCTinSync() */ void DecDCTinRaw(const uint32_t *data, size_t length); /** - * @brief Waits for the MDEC to finish decoding the input stream (if mode = 0) - * or returns whether it is busy (if mode = 1). MDEC commands can be issued - * only when the MDEC isn't busy. + * @brief Waits for an MDEC input transfer to finish or returns its status. + * + * @details Waits for the MDEC to finish decoding the input stream (if + * mode = 0) or returns whether it is busy (if mode = 1). MDEC commands can be + * issued only when the MDEC isn't busy. * * WARNING: DecDCTinSync(0) might time out and return -1 if the MDEC can't * output decoded data, e.g. if the length passed DecDCTout() was too small and @@ -155,7 +190,9 @@ void DecDCTinRaw(const uint32_t *data, size_t length); int DecDCTinSync(int mode); /** - * @brief Configures the MDEC to automatically transfer decoded image data in + * @brief Writes image data decoded by the MDEC to the specified location. + * + * @details Configures the MDEC to automatically transfer decoded image data in * 128-byte (32-word) chunks to the specified address in main RAM. MDEC * operation is paused once a certain number of 32-bit words have been output * and can be resumed by calling DecDCTout() again: the MDEC will continue @@ -168,12 +205,16 @@ int DecDCTinSync(int mode); * * @param data * @param length Number of 32-bit words to output (must be multiple of 32) + * + * @see DecDCToutSync() */ void DecDCTout(uint32_t *data, size_t length); /** - * @brief Waits until the transfer set up by DecDCTout() finishes (if mode = 0) - * or returns whether it is still in progress (if mode = 1). + * @brief Waits for an MDEC output transfer to finish or returns its status. + * + * @details Waits until the transfer set up by DecDCTout() finishes (if + * mode = 0) or returns whether it is still in progress (if mode = 1). * * WARNING: DecDCToutSync(0) might time out and return -1 if the MDEC is unable * to consume enough input data in order to produce the desired amount of data. @@ -186,7 +227,9 @@ void DecDCTout(uint32_t *data, size_t length); int DecDCToutSync(int mode); /** - * @brief Begins decompressing the contents of a .BS file (or of a single .STR + * @brief Decompresses or begins decompressing a .BS file into MDEC codes. + * + * @details Begins decompressing the contents of a .BS file (or of a single STR * frame) into a buffer that can be passed to DecDCTin(). This function uses a * small (<1 KB) lookup table combined with the GTE to accelerate the process; * performance is roughly on par with DecDCTvlcStart2() if the lookup table @@ -212,11 +255,15 @@ int DecDCToutSync(int mode); * @param max_size Maximum number of 32-bit words to output * @param bs * @return 0, 1 if more data needs to be output or -1 in case of failure + * + * @see DecDCTvlcContinue(), DecDCTvlcCopyTable() */ int DecDCTvlcStart(VLC_Context *ctx, uint32_t *buf, size_t max_size, const uint32_t *bs); /** - * @brief Resumes the decompression process started by DecDCTvlcStart(). The + * @brief Resumes or finishes decompressing a .BS file into MDEC codes. + * + * @details Resumes the decompression process started by DecDCTvlcStart(). The * state of the decompressor is contained entirely in the VLC_Context structure * so an arbitrary number of bitstreams can be decoded concurrently (although * the limited CPU power makes it impractical to do so) by keeping a separate @@ -236,14 +283,18 @@ int DecDCTvlcStart(VLC_Context *ctx, uint32_t *buf, size_t max_size, const uint3 * @param buf * @param max_size Maximum number of 32-bit words to output * @return 0, 1 if more data needs to be output or -1 in case of failure + * + * @see DecDCTvlcStart() */ int DecDCTvlcContinue(VLC_Context *ctx, uint32_t *buf, size_t max_size); /** - * A wrapper around DecDCTvlcStart() and DecDCTvlcContinue() for compatibility - * with the official SDK. This function uses an internal context; additionally, - * the maximum output buffer size is not passed as an argument but is instead - * set by calling DecDCTvlcSize(). + * @brief Decompresses a .BS file into MDEC codes. + * + * @details A wrapper around DecDCTvlcStart() and DecDCTvlcContinue() for + * compatibility with the official SDK. This function uses an internal context; + * additionally, the maximum output buffer size is not passed as an argument + * but is instead set by calling DecDCTvlcSize(). * * This function behaves identically to DecDCTvlcContinue() if bs = 0 and * DecDCTvlcStart() otherwise. @@ -257,21 +308,34 @@ int DecDCTvlcContinue(VLC_Context *ctx, uint32_t *buf, size_t max_size); * @param bs Pointer to bitstream data or 0 to resume decoding * @param buf * @return 0, 1 if more data needs to be output or -1 in case of failure + * + * @see DecDCTvlcSize(), DecDCTvlcCopyTable() */ int DecDCTvlc(const uint32_t *bs, uint32_t *buf); /** - * @brief Sets the maximum number of 32-bit words that a single call to + * @brief Sets the maximum amount of data to be decompressed. + * + * @details Sets the maximum number of 32-bit words that a single call to * DecDCTvlc() will output. If size = 0, the entire frame will always be * decoded in one shot. * + * Note that DecDCTvlcStart() and DecDCTvlcContinue() do not use the value set + * by this function and instead expect the maximum size to be passed as an + * argument. + * * @param size Maximum number of 32-bit words to output - * @return Previously set value + * @return Previously set value + * + * @see DecDCTvlc() */ size_t DecDCTvlcSize(size_t size); /** - * @brief Copies the small (<1 KB) lookup table used by DecDCTvlcContinue(), + * @brief Moves the lookup table used by the .BS decompressor to the scratchpad + * region. + * + * @details Copies the small (<1 KB) lookup table used by DecDCTvlcContinue(), * DecDCTvlcStart() and DecDCTvlc() (a DECDCTTAB structure) to the specified * address. A copy of this table is always present in main RAM, however this * function can be used to copy it to the scratchpad region to boost @@ -287,7 +351,10 @@ size_t DecDCTvlcSize(size_t size); void DecDCTvlcCopyTable(DECDCTTAB *addr); /** - * @brief Begins decompressing the contents of a .BS file (or of a single .STR + * @brief Decompresses or begins decompressing a .BS file into MDEC codes + * (alternate implementation). + * + * @details Begins decompressing the contents of a .BS file (or of a single STR * frame) into a buffer that can be passed to DecDCTin(). This function uses a * large (34 KB) lookup table that must be loaded into main RAM beforehand by * calling DecDCTvlcBuild(), but does not use the GTE nor the scratchpad. @@ -311,11 +378,16 @@ void DecDCTvlcCopyTable(DECDCTTAB *addr); * @param max_size Maximum number of 32-bit words to output * @param bs * @return 0, 1 if more data needs to be output or -1 in case of failure + * + * @see DecDCTvlcContinue2(), DecDCTvlcBuild() */ int DecDCTvlcStart2(VLC_Context *ctx, uint32_t *buf, size_t max_size, const uint32_t *bs); /** - * @brief Resumes the decompression process started by DecDCTvlcStart2(). The + * @brief Resumes or finishes decompressing a .BS file into MDEC codes + * (alternate implementation). + * + * @details Resumes the decompression process started by DecDCTvlcStart2(). The * state of the decompressor is contained entirely in the VLC_Context structure * so an arbitrary number of bitstreams can be decoded concurrently (although * the limited CPU power makes it impractical to do so) by keeping a separate @@ -333,11 +405,15 @@ int DecDCTvlcStart2(VLC_Context *ctx, uint32_t *buf, size_t max_size, const uint * @param buf * @param max_size Maximum number of 32-bit words to output * @return 0, 1 if more data needs to be output or -1 in case of failure + * + * @see DecDCTvlcStart2() */ int DecDCTvlcContinue2(VLC_Context *ctx, uint32_t *buf, size_t max_size); /** - * A wrapper around DecDCTvlcStart2() and DecDCTvlcContinue2() for + * @brief Decompresses a .BS file into MDEC codes (alternate implementation). + * + * @details A wrapper around DecDCTvlcStart2() and DecDCTvlcContinue2() for * compatibility with the official SDK. This function uses an internal context; * additionally, the maximum output buffer size is not passed as an argument * but is instead set by calling DecDCTvlcSize2(). @@ -353,21 +429,35 @@ int DecDCTvlcContinue2(VLC_Context *ctx, uint32_t *buf, size_t max_size); * @param buf * @param table Pointer to decompressed table or 0 to use last table used * @return 0, 1 if more data needs to be output or -1 in case of failure + * + * @see DecDCTvlcSize2(), DecDCTvlcBuild() */ int DecDCTvlc2(const uint32_t *bs, uint32_t *buf, DECDCTTAB2 *table); /** - * @brief Sets the maximum number of 32-bit words that a single call to + * @brief Sets the maximum amount of data to be decompressed (alternate + * implementation). + * + * @details Sets the maximum number of 32-bit words that a single call to * DecDCTvlc2() will output. If size = 0, the entire frame will always be * decoded in one shot. * + * Note that DecDCTvlcStart2() and DecDCTvlcContinue2() do not use the value + * set by this function and instead expect the maximum size to be passed as an + * argument. + * * @param size Maximum number of 32-bit words to output - * @return Previously set value + * @return Previously set value + * + * @see DecDCTvlc2() */ size_t DecDCTvlcSize2(size_t size); /** - * @brief Generates the lookup table required by DecDCTvlcStart2(), + * @brief Generates the lookup table used by the alternate implementation of + * the .BS decompressor. + * + * @details Generates the lookup table required by DecDCTvlcStart2(), * DecDCTvlcContinue2() and DecDCTvlc2() (a DECDCTTAB2 structure) into the * specified buffer. Since the table is relatively large (34 KB), it is * recommended to only generate it in a dynamically-allocated buffer when diff --git a/libpsn00b/include/psxsio.h b/libpsn00b/include/psxsio.h index d5f7d9a..449e43a 100644 --- a/libpsn00b/include/psxsio.h +++ b/libpsn00b/include/psxsio.h @@ -3,12 +3,27 @@ * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed */ +/** + * @file psxsio.h + * @brief Serial port library header + * + * @details This library provides a custom API to access the PS1's serial port. + * Sending and receiving data is done fully asynchronously using a pair of + * 128-byte FIFOs kept in main RAM, with optional hardware flow control. More + * advanced use cases such as custom callbacks for each byte received are also + * supported. + * + * A BIOS TTY driver to redirect stdin/stdout (including BIOS messages as well + * as PSn00bSDK's own debug logging) to the serial port is also provided for + * debugging purposes. + */ + #ifndef __PSXSIO_H #define __PSXSIO_H #include <stdint.h> -/* Register definitions (used internally) */ +/* Enum and register definitions */ typedef enum _SIO_StatusRegFlag { SR_TXRDY = 1 << 0, @@ -67,7 +82,9 @@ extern "C" { #endif /** - * @brief Resets the serial port, initializes the library's internal ring + * @brief Initializes the serial port driver. + * + * @details Resets the serial port, initializes the library's internal ring * buffers and installs a serial IRQ handler. The given mode value (normally * MR_CHLEN_8|MR_SB_01 for 8 data bits, 1 stop bit and no parity) is copied to * the SIO_MODE register. Flow control is disabled by default (see @@ -79,18 +96,28 @@ extern "C" { * * @param baud Baud rate in bits per second * @param mode Binary OR of SIO_ModeRegFlag enum members + * + * @see SIO_Quit() */ void SIO_Init(int baud, uint16_t mode); /** - * @brief Resets the serial port and removes the IRQ callback added by - * SIO_Init(), restoring any previously installed handler. + * @brief Uninstalls the serial port driver. + * + * @details Resets the serial port and removes the IRQ callback added by + * SIO_Init(), restoring any previously installed handler if any. If SIO_Init() + * was previously invoked, calling SIO_Quit() before accessing serial port + * registers manually is highly recommended. + * + * @see SIO_Init() */ void SIO_Quit(void); /** - * @brief Changes the serial port's flow control mode. The following modes are - * available: + * @brief Sets the flow control mode. + * + * @details Changes the serial port's flow control mode. The following modes + * are available: * * - SIO_FC_NONE (default): do not assert RTS or DTR automatically and ignore * DSR. Note that the hardware will still wait for CTS to be asserted before @@ -106,7 +133,9 @@ void SIO_Quit(void); void SIO_SetFlowControl(SIO_FlowControl mode); /** - * @brief Reads a byte from the RX buffer. If the buffer is empty, blocks + * @brief Reads a byte from the RX buffer (blocking). + * + * @details Reads a byte from the RX buffer. If the buffer is empty, blocks * indefinitely until a byte is received. * * WARNING: this function shall not be used in a critical section or IRQ @@ -115,21 +144,29 @@ void SIO_SetFlowControl(SIO_FlowControl mode); * or SIO_ReadSync(1) and implementing a timeout instead. * * @return Received byte + * + * @see SIO_ReadByte2(), SIO_ReadSync() */ int SIO_ReadByte(void); /** - * @brief Non-blocking variant of SIO_ReadByte(). Reads a byte from the RX + * @brief Reads a byte from the RX buffer (non-blocking). + * + * @details Non-blocking variant of SIO_ReadByte(). Reads a byte from the RX * buffer or returns -1 if the buffer is empty. Unlike SIO_ReadByte() this * function is safe to use in a critical section (although no data will be * received while interrupts are disabled). * * @return Received byte, -1 if no data is available + * + * @see SIO_ReadByte() */ int SIO_ReadByte2(void); /** - * @brief Waits for at least one byte to be available in the RX buffer (if + * @brief Waits for a byte to be received or returns the RX buffer's length. + * + * @details Waits for at least one byte to be available in the RX buffer (if * mode = 0) or returns the length of the RX buffer (if mode = 1). * * WARNING: this function shall not be used in a critical section or IRQ @@ -144,7 +181,9 @@ int SIO_ReadByte2(void); int SIO_ReadSync(int mode); /** - * @brief Registers a function to be called whenever a byte is received. The + * @brief Sets a callback for received bytes. + * + * @details Registers a function to be called whenever a byte is received. The * received byte is passed as an argument to the callback, which shall then * return a zero value to also store the byte in the RX buffer or a non-zero * value to drop it. This can be used to e.g. filter or validate incoming data, @@ -160,7 +199,9 @@ int SIO_ReadSync(int mode); void *SIO_ReadCallback(int (*func)(uint8_t)); /** - * @brief Sends the given byte, or appends it to the TX buffer if the serial + * @brief Writes a byte to the TX buffer (blocking). + * + * @details Sends the given byte, or appends it to the TX buffer if the serial * port is busy. If the buffer is full, blocks until the byte can be stored in * the buffer (with a timeout). * @@ -169,11 +210,15 @@ void *SIO_ReadCallback(int (*func)(uint8_t)); * * @param value * @return Number of TX bytes previously pending, -1 in case of a timeout + * + * @see SIO_WriteByte2(), SIO_WriteSync() */ int SIO_WriteByte(uint8_t value); /** - * @brief Non-blocking variant of SIO_WriteByte(). Sends the given byte, or + * @brief Writes a byte to the TX buffer (non-blocking). + * + * @details Non-blocking variant of SIO_WriteByte(). Sends the given byte, or * appends it to the TX buffer if the serial port is busy. If the buffer is * full, returns -1 without actually sending the byte. Unlike SIO_WriteByte() * this function is safe to use in a critical section (although no data will be @@ -181,12 +226,16 @@ int SIO_WriteByte(uint8_t value); * * @param value * @return Number of TX bytes previously pending, -1 in case of failure + * + * @see SIO_WriteByte() */ int SIO_WriteByte2(uint8_t value); /** - * @brief Waits for all bytes pending in the TX buffer to be sent (if mode = 0) - * or returns the length of the TX buffer (if mode = 1). + * @brief Waits for all bytes to be sent or returns the TX buffer's length. + * + * @details Waits for all bytes pending in the TX buffer to be sent (if + * mode = 0) or returns the length of the TX buffer (if mode = 1). * * WARNING: this function shall not be used in a critical section or IRQ * callback as no data is sent or received while interrupts are disabled. @@ -197,10 +246,11 @@ int SIO_WriteByte2(uint8_t value); int SIO_WriteSync(int mode); /** - * @brief Installs a BIOS file driver to redirect TTY stdin/stdout (including - * BIOS messages as well as PSn00bSDK's own debug logging) to the serial port. - * Uses SIO_Init() internally. The port is configured for 8 data bits, 1 stop - * bit and no parity. + * @brief Installs the serial port TTY driver. + * + * @details Installs a BIOS file driver to redirect TTY stdin/stdout to the + * serial port. Uses SIO_Init() internally. The port is configured for 8 data + * bits, 1 stop bit and no parity. * * This function shall only be used for debugging purposes. Picking a high baud * rate is recommended as all TTY writes are blocking and bypass the TX buffer. @@ -210,13 +260,20 @@ int SIO_WriteSync(int mode); * built-in TTY functionality of these loaders. * * @param baud Baud rate in bits per second + * + * @see DelSIO() */ void AddSIO(int baud); /** - * @brief Uninstalls the BIOS driver installed by AddSIO() and attempts to - * restore a "dummy" TTY driver. Calling this function is not recommended as - * any further TTY usage may crash the system. + * @brief Removes the serial port TTY driver. + * + * @details Uninstalls the BIOS driver installed by AddSIO() and attempts to + * restore the default "dummy" TTY driver. Uses SIO_Quit() internally. Calling + * this function is not recommended as any further TTY usage may crash the + * system. + * + * @see AddSIO() */ void DelSIO(void); |
