diff options
| author | spicyjpeg <thatspicyjpeg@gmail.com> | 2024-01-08 18:33:11 +0100 |
|---|---|---|
| committer | spicyjpeg <thatspicyjpeg@gmail.com> | 2024-01-08 18:33:11 +0100 |
| commit | dd85f9f993427ae69ab905486f8ef372d3960664 (patch) | |
| tree | 605e6aec308795ee466fa12b090067c6517ea2d7 | |
| parent | 06e65bea3a778b2dae5af77a7935ae3868ddd4d3 (diff) | |
Fix bugs in libc, psxgpu, psxpress, clean up headers
| -rw-r--r-- | libpsn00b/include/hwregs_c.h | 6 | ||||
| -rw-r--r-- | libpsn00b/include/psxcd.h | 387 | ||||
| -rw-r--r-- | libpsn00b/include/psxgpu.h | 34 | ||||
| -rw-r--r-- | libpsn00b/include/psxpress.h | 33 | ||||
| -rw-r--r-- | libpsn00b/include/psxsn.h | 13 | ||||
| -rw-r--r-- | libpsn00b/libc/malloc.c | 2 | ||||
| -rw-r--r-- | libpsn00b/libc/start.c | 17 | ||||
| -rw-r--r-- | libpsn00b/psxcd/isofs.c | 14 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/drawing.c | 4 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/image.c | 18 | ||||
| -rw-r--r-- | libpsn00b/psxpress/vlc.s | 14 |
11 files changed, 311 insertions, 231 deletions
diff --git a/libpsn00b/include/hwregs_c.h b/libpsn00b/include/hwregs_c.h index ec198cd..6f3943a 100644 --- a/libpsn00b/include/hwregs_c.h +++ b/libpsn00b/include/hwregs_c.h @@ -114,9 +114,9 @@ /* Timers */ -#define TIMER_VALUE(N) _MMIO32((IOBASE | 0x1100) + (16 * (N))) -#define TIMER_CTRL(N) _MMIO32((IOBASE | 0x1104) + (16 * (N))) -#define TIMER_RELOAD(N) _MMIO32((IOBASE | 0x1108) + (16 * (N))) +#define TIMER_VALUE(N) _MMIO16((IOBASE | 0x1100) + (16 * (N))) +#define TIMER_CTRL(N) _MMIO16((IOBASE | 0x1104) + (16 * (N))) +#define TIMER_RELOAD(N) _MMIO16((IOBASE | 0x1108) + (16 * (N))) /* Memory/bus control */ diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h index fc9c391..2e256f4 100644 --- a/libpsn00b/include/psxcd.h +++ b/libpsn00b/include/psxcd.h @@ -1,6 +1,6 @@ /* * PSn00bSDK CD-ROM library - * (C) 2020-2022 Lameguy64, spicyjpeg - MPL licensed + * (C) 2020-2023 Lameguy64, spicyjpeg - MPL licensed */ /** @@ -27,85 +27,151 @@ /* Enum definitions */ -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, - CdlGetQ = 0x1d, - CdlReadTOC = 0x1e +/** + * @brief CD-ROM controller command definitions. + * + * @details This enum defines all commands supported by the CD-ROM drive, + * including ones that are not documented in the official SDK. + * + * Most commands are non-blocking: they can be issued using CdControl() or + * CdCommand() and will quickly return an "acknowledge" response, usually + * consisting of the current status flags and optionally other data. Some + * non-blocking commands, such as CdlReadN, CdlReadS or CdlPlay, will return an + * acknowledge response immediately but start reading data or playing audio + * asynchronously in the background. + * + * Other commands are blocking: they will still return an empty acknowledge + * response immediately, but will then proceed to execute asynchronously and + * return a second "complete" response once done. Any values returned by + * blocking commands will be received as part of the complete response. The + * acknowledge response is handled internally by libpsxcd and is not exposed to + * any user-provided callbacks. + * + * The following commands are supported: + * + * | ID | Command | Parameters | Return values | Blocking | Notes | + * | ---: | :------------ | :--------------- | :----------------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------- | + * | 0x01 | CdlNop | | uint8_t status | No | This command will clear the CdlStatShellOpen status flag if it was previously set but the lid has since been closed. | + * | 0x02 | CdlSetloc | CdlLOC pos | uint8_t status | No | Only the first 3 fields of the CdlLOC structure are used. The track number is ignored. | + * | 0x03 | CdlPlay | uint8_t track | uint8_t status | No | The parameter is optional. When not passed, playback will start from the last location set using CdlSetloc. | + * | 0x04 | CdlForward | | uint8_t status | No | | + * | 0x05 | CdlBackward | | uint8_t status | No | | + * | 0x06 | CdlReadN | (see note) | uint8_t status | No | CdControl() (but not CdCommand()) allows passing a CdlLOC as parameter, which will be sent as a separate CdlSetloc command. | + * | 0x07 | CdlStandby | | uint8_t status | Yes | | + * | 0x08 | CdlStop | | uint8_t status | Yes | | + * | 0x09 | CdlPause | | uint8_t status | Yes | | + * | 0x0a | CdlInit | | uint8_t status | Yes | | + * | 0x0b | CdlMute | | uint8_t status | No | | + * | 0x0c | CdlDemute | | uint8_t status | No | | + * | 0x0d | CdlSetfilter | CdlFILTER filter | uint8_t status | No | | + * | 0x0e | CdlSetmode | uint8_t mode | uint8_t status | No | See CdlModeFlag for a list of mode flags. | + * | 0x0f | CdlGetparam | | CdlPARAMINFO info | No | | + * | 0x10 | CdlGetlocL | | CdlLOCINFOL info | No | As no status is provided in the response, the status flags returned by CdStatus() will not be updated. | + * | 0x11 | CdlGetlocP | | CdlLOCINFOP info | No | As no status is provided in the response, the status flags returned by CdStatus() will not be updated. | + * | 0x12 | CdlSetsession | uint8_t session | uint8_t status | Yes | | + * | 0x13 | CdlGetTN | | uint8_t status, first, last | No | | + * | 0x14 | CdlGetTD | uint8_t track | uint8_t status, minute, second | No | | + * | 0x15 | CdlSeekL | (see note) | uint8_t status | Yes | CdControl() (but not CdCommand()) allows passing a CdlLOC as parameter, which will be sent as a separate CdlSetloc command. | + * | 0x16 | CdlSeekP | (see note) | uint8_t status | Yes | CdControl() (but not CdCommand()) allows passing a CdlLOC as parameter, which will be sent as a separate CdlSetloc command. | + * | 0x19 | CdlTest | (varies) | (varies) | No | See the nocash documentation for more information on test subcommands and their parameters. | + * | 0x1a | CdlGetID | | CdlIDINFO info | Yes | | + * | 0x1b | CdlReadS | (see note) | uint8_t status | No | CdControl() (but not CdCommand()) allows passing a CdlLOC as parameter, which will be sent as a separate CdlSetloc command. | + * | 0x1c | CdlReset | | uint8_t status | No | After issuing a CdlReset command, no further commands shall be sent for about 150ms. | + * | 0x1d | CdlGetQ | uint8_t adr, p | uint8_t data[10], peak_low | Yes | Not supported on some older console models, should not be used. | + * | 0x1e | CdlReadTOC | | uint8_t status | Yes | Not supported on some older console models, should not be used. | + * + * NOTE: all parameters and return values, such as track numbers, are in BCD + * format unless otherwise specified. The btoi() and itob() macros can be used + * to convert between decimal and BCD. Drive unlock commands are not listed in + * this enum, but can be issued by calling CdGetRegion() and CdUnlock(). + * + * @see CdControl(), CdCommand(), CdlStatFlag + */ +typedef enum { + CdlNop = 0x01, // Updates the current CD-ROM status and resets the CdlStatShellOpen flag, without doing anything else. + CdlSetloc = 0x02, // Sets the seek target location, but does not seek. Actual seeking begins upon issuing a seek or read command. + CdlPlay = 0x03, // Begins CD-DA playback. Parameter specifies an optional track number to play (some emulators do not support it). + CdlForward = 0x04, // Starts fast-forwarding (CD-DA only). Issue CdlPlay to stop fast-forwarding. + CdlBackward = 0x05, // Starts rewinding (CD-DA only). Issue CdlPlay to stop rewinding. + CdlReadN = 0x06, // Begins reading data sectors and/or playing XA-ADPCM with automatic retry. Used in conjunction with CdReadyCallback(). + CdlStandby = 0x07, // Starts the spindle motor if it was previously stopped. + CdlStop = 0x08, // Stops playback or data reading and shuts down the spindle motor. + CdlPause = 0x09, // Stops playback or data reading without stopping the spindle motor. + CdlInit = 0x0a, // Initializes the CD-ROM controller and aborts any ongoing command. + CdlMute = 0x0b, // Mutes the drive's audio output (both CD-DA and XA-ADPCM). + CdlDemute = 0x0c, // Unmutes the drive's audio output (both CD-DA and XA-ADPCM). + CdlSetfilter = 0x0d, // Configures the XA-ADPCM sector filter. + CdlSetmode = 0x0e, // Sets the CD-ROM mode flags (see CdlModeFlags). + CdlGetparam = 0x0f, // Returns the current CD-ROM mode flags and XA-ADPCM filter settings. + CdlGetlocL = 0x10, // Returns the location, mode and XA subheader of the current data sector. Does not work on CD-DA sectors. + CdlGetlocP = 0x11, // Returns the current physical CD location (using subchannel Q data). + CdlSetsession = 0x12, // Attempts to seek to the specified session on a multi-session disc. Used by CdLoadSession(). + CdlGetTN = 0x13, // Returns the total number of tracks on the disc. + CdlGetTD = 0x14, // Returns the starting location of the specified track number. + CdlSeekL = 0x15, // Seeks (using data sector headers) to the position set by the last CdlSetloc command. Does not work on CD-DA sectors. + CdlSeekP = 0x16, // Seeks (using subchannel Q data) to the position set by the last CdlSetloc command. + CdlTest = 0x19, // Executes a test subcommand. Shall be issued using CdCommand() rather than CdControl(). + CdlGetID = 0x1a, // Identifies the disc type and returns its license string if any. + CdlReadS = 0x1b, // Begins reading data sectors and/or playing XA-ADPCM in real-time (without automatic retry) mode. + CdlReset = 0x1c, // Resets the CD-ROM controller (similar behavior to manually opening and closing the lid). + CdlGetQ = 0x1d, // Reads up to 10 raw bytes of subchannel Q data directly from the disc's table of contents. + CdlReadTOC = 0x1e // Forces reading of the disc's table of contents. } CdlCommand; -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 +typedef enum { + CdlStatError = 1 << 0, // A command error has occurred. Set when an invalid command or parameters are sent. + CdlStatStandby = 1 << 1, // Set whenever the spindle motor is powered on or spinning up. + CdlStatSeekError = 1 << 2, // A seek error has occurred. + CdlStatIdError = 1 << 3, // Disc has been rejected due to being unlicensed (on consoles without a modchip installed). + CdlStatShellOpen = 1 << 4, // Lid is open or has been opened before. This flag is cleared by sending a CdlNop command. + CdlStatRead = 1 << 5, // Drive is currently reading data and/or playing XA-ADPCM. + CdlStatSeek = 1 << 6, // Drive is currently seeking. + CdlStatPlay = 1 << 7 // Drive is currently playing a CD-DA track. } CdlStatFlag; -typedef enum _CdlModeFlag { - CdlModeDA = 1 << 0, - CdlModeAP = 1 << 1, - CdlModeRept = 1 << 2, - CdlModeSF = 1 << 3, +typedef enum { + CdlModeDA = 1 << 0, // Enable CD-DA playback. + CdlModeAP = 1 << 1, // Automatically pause CD-DA playback and invoke any callback set by CdAutoPauseCallback() when the end of a track is reached. + CdlModeRept = 1 << 2, // Automatically send report packets containing the current drive status and position during CD-DA playback. + CdlModeSF = 1 << 3, // Enable XA sector filter. When set, only XA-ADPCM sectors that match the file and channel numbers set using CdlSetloc will be played. //CdlModeSize0 = 1 << 4, //CdlModeSize1 = 1 << 5, - CdlModeIgnore = 1 << 4, - CdlModeSize = 1 << 5, - CdlModeRT = 1 << 6, - CdlModeSpeed = 1 << 7 + CdlModeIgnore = 1 << 4, // Ignore any previously set sector size (CdlModeSize flag) and location set using CdlSetloc. + CdlModeSize = 1 << 5, // Return 2340 bytes instead of 2048 for each data sector read. The data returned is a full 2352-byte CD sector minus the sync bytes at the beginning. + CdlModeRT = 1 << 6, // Enable XA-ADPCM playback. When not set, XA-ADPCM sectors will be read as normal data. + CdlModeSpeed = 1 << 7 // Read sectors at 2x speed instead of the default 1x. Should be cleared for CD-DA playback. } CdlModeFlag; -typedef enum _CdlIntrResult { - CdlNoIntr = 0, - CdlDataReady = 1, - CdlComplete = 2, - CdlAcknowledge = 3, - CdlDataEnd = 4, - CdlDiskError = 5 +typedef enum { + CdlIDFlagAudio = 1 << 4, // Disc only contains CD-DA tracks. + CdlIDFlagNoDisc = 1 << 6, // No disc present. + CdlIDFlagDenied = 1 << 7 // Disc has an invalid license string and has been rejected. +} CdlIDFlag; + +typedef enum { + CdlNoIntr = 0, // No pending interrupt + CdlDataReady = 1, // INT1 (new sector or CD-DA report packet available) + CdlComplete = 2, // INT2 ("complete" response received, blocking command has finished) + CdlAcknowledge = 3, // INT3 ("acknowledge" response received, non-blocking command has finished or blocking command has started) + CdlDataEnd = 4, // INT4 (end of track or end of disc reached) + CdlDiskError = 5 // INT5 (command error, read error or lid opened) } CdlIntrResult; -typedef enum _CdlRegionCode { +typedef enum { CdlRegionUnknown = 0, CdlRegionSCEI = 1, // Japan CdlRegionSCEA = 2, // North America CdlRegionSCEE = 3, // Europe - CdlRegionSCEW = 4, // Wordwide (Net Yaroze) - CdlRegionDebug = 5 // DebuggingStation or test console + CdlRegionSCEW = 4, // World (Net Yaroze) + CdlRegionDebug = 5 // Debugging unit (DTL-Hxxxx) } CdlRegionCode; -typedef enum _CdlIsoError { - CdlIsoOkay = 0, - CdlIsoSeekError = 1, - CdlIsoReadError = 2, - CdlIsoInvalidFs = 3, - CdlIsoLidOpen = 4 +typedef enum { + CdlIsoOkay = 0, // File system parser okay. + CdlIsoSeekError = 1, // Logical seek error occurred. May occur when attempting to query the filesystem on an audio-only CD. + CdlIsoReadError = 2, // Read error occurred while reading the CD-ROM file system descriptor. + CdlIsoInvalidFs = 3, // Disc does not contain a standard ISO9660 file system. + CdlIsoLidOpen = 4 // Lid is open when attempting to parse the CD-ROM file system. } CdlIsoError; /** @@ -136,9 +202,9 @@ typedef enum _CdlIsoError { * 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(), CdPosToInt(), CdControl() + * @see CdIntToPos(), CdPosToInt(), CdControl(), CdlCommand */ -typedef struct _CdlLOC { +typedef struct { uint8_t minute; // Minutes (BCD) uint8_t second; // Seconds (BCD) uint8_t sector; // Sector or frame (BCD) @@ -154,7 +220,7 @@ typedef struct _CdlLOC { * * @see CdMix() */ -typedef struct _CdlATV { +typedef struct { 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 @@ -170,13 +236,32 @@ typedef struct _CdlATV { * * @see CdSearchFile() */ -typedef struct _CdlFILE { +typedef struct { CdlLOC pos; // CD-ROM position coordinates of file int size; // Size of file in bytes char name[16]; // File name } CdlFILE; /** + * @brief Current CD-ROM settings structure. + * + * @details This structure represents the parameters returned by the CD-ROM + * controller after issuing a CdlGetparam command. Mode flags can be set using + * the CdlSetmode command, while XA-ADPCM sector filter parameters can be set + * by sending a CdlSetfilter command. + * + * @see CdControl(), CdlCommand, CdlFILTER + */ +typedef struct { + uint8_t status; // Current CD-ROM status flags + uint8_t mode; // Current CD-ROM mode flags + uint8_t pad; + uint8_t file; // Current XA-ADPCM filter file number (0-255) + uint8_t chan; // Current XA-ADPCM filter channel number (0-31) + uint8_t pad2[3]; +} CdlPARAMINFO; + +/** * @brief Current logical location information structure. * * @details This structure is returned by the CdlGetlocL command and contains @@ -189,7 +274,7 @@ typedef struct _CdlFILE { * * @see CdControl() */ -typedef struct _CdlLOCINFOL { +typedef struct { uint8_t minute; // Minutes (BCD) uint8_t second; // Seconds (BCD) uint8_t sector; // Sector or frame (BCD) @@ -213,7 +298,7 @@ typedef struct _CdlLOCINFOL { * * @see CdControl() */ -typedef struct _CdlLOCINFOP { +typedef struct { 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) @@ -225,7 +310,26 @@ typedef struct _CdlLOCINFOP { } CdlLOCINFOP; /** - * @brief CD-ROM XA filter structure. + * @brief CD-ROM type and license information structure. + * + * @details This structure is returned by the CdlGetID command and contains + * information about the currently inserted disc, including whether or not it + * has passed the license check and its region string (if any). Note that the + * data returned may not be accurate on consoles equipped with modchips or + * optical drive emulation devices. + * + * @see CdControl(), CdlCommand, CdlIDFlag + */ +typedef struct { + uint8_t status; // Current CD-ROM status flags + uint8_t flags; // Disc flags (see CdlIDFlag) + uint8_t type; // Disc type from CD table of contents + uint8_t atip; // ATIP value from CD table of contents (usually 0) + char license[4]; // License string +} CdlIDINFO; + +/** + * @brief CD-ROM XA-ADPCM sector filter structure. * * @details This structure is used with the CdlSetfilter command to specify * sector filter parameters for XA-ADPCM audio playback. @@ -241,10 +345,10 @@ typedef struct _CdlLOCINFOP { * by switching to alternate versions of a theme to fit specific scenes * seamlessly. * - * @see CdControl() + * @see CdControl(), CdlCommand */ -typedef struct _CdlFILTER { - uint8_t file; // XA file number (usually 1) +typedef struct { + uint8_t file; // XA file number (0-255) uint8_t chan; // XA channel number (0-31) uint16_t pad; } CdlFILTER; @@ -259,6 +363,26 @@ typedef struct _CdlFILTER { */ typedef void *CdlDIR; +/** + * @brief Callback function for CD-ROM events. + * + * @details This prototype is used for all user-defined CD-ROM callback + * functions. The first argument passed to the callback represents the type of + * the event that occurred (see CdlIntrResult) while the second argument is an + * optional pointer to the buffer the CD-ROM controller's response was stored + * into, if such a buffer was provided to CdControl() or CdCommand() when + * initially issuing the command. + * + * Most commands will return the current status flags as the first byte of the + * response. When processing the response to a command that returns status + * flags, libpsxcd will automatically fetch the first byte and store it in an + * internal variable even if no actual response buffer was provided. In such + * cases, the latest status flags can be retrieved using CdStatus() even when + * the second argument is a null pointer. + * + * @see CdSyncCallback(), CdReadyCallback(), CdAutoPauseCallback(), + * CdReadyCallback() + */ typedef void (*CdlCB)(CdlIntrResult, uint8_t *); /* Public API */ @@ -291,11 +415,11 @@ int CdInit(void); * 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 minus the 150-sector lead-in - * @param p Pointer to a CdlLOC structure + * @param i + * @param p * @return Pointer to the specified CdlLOC structure */ -CdlLOC* CdIntToPos(int i, CdlLOC *p); +CdlLOC *CdIntToPos(int i, CdlLOC *p); /** * @brief Translates MSF coordinates to an LBA. @@ -305,7 +429,7 @@ CdlLOC* CdIntToPos(int i, CdlLOC *p); * 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 structure + * @param p * @return Logical sector number minus the 150-sector lead-in */ int CdPosToInt(const CdlLOC *p); @@ -313,68 +437,24 @@ int CdPosToInt(const CdlLOC *p); /** * @brief Issues a 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. Any response from the controller is stored into the provided - * buffer asynchronously. + * @details Sends a command, alongside any required parameters, to the CD-ROM + * controller and waits for an acknowledge interrupt (very fast). Any response + * from the controller is stored into the provided buffer asynchronously. See + * the CdlCommand enum for details on supported commands, their parameters and + * responses. * - * 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. + * Some commands (see CdlCommand) are blocking and 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. + * NOTE: all parameters and return values are in BCD format unless otherwise + * specified. 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 @@ -383,7 +463,7 @@ int CdPosToInt(const CdlLOC *p); * command has not yet finished processing or -1 if a parameter is required but * was not specified * - * @see CdSync(), CdControlF(), CdCommand() + * @see CdlCommand, CdSync(), CdControlF(), CdCommand() */ int CdControl(CdlCommand cmd, const void *param, uint8_t *result); @@ -404,7 +484,7 @@ int CdControl(CdlCommand cmd, const void *param, uint8_t *result); * command has not yet finished processing or -1 if a parameter is required but * was not specified * - * @see CdControl(), CdControlF() + * @see CdlCommand, CdControl(), CdControlF() */ int CdControlB(CdlCommand cmd, const void *param, uint8_t *result); @@ -430,7 +510,7 @@ int CdControlB(CdlCommand cmd, const void *param, uint8_t *result); * @return -1 if a parameter is required but was not specified, otherwise 1 * (even if sending the command failed) * - * @see CdControl(), CdCommand() + * @see CdlCommand, CdControl(), CdCommand() */ int CdControlF(CdlCommand cmd, const void *param); @@ -440,7 +520,8 @@ int CdControlF(CdlCommand cmd, const void *param); * @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. + * number of parameter bytes must be specified manually. See the CdlCommand + * enum for details on supported commands, their parameters and responses. * * As with CdControl(), this function waits for the drive to acknowledge the * command. Any response from the controller is stored into the provided buffer @@ -456,7 +537,7 @@ int CdControlF(CdlCommand cmd, const void *param); * @return 1 if the command was issued successfully or 0 if a previously issued * command has not yet finished processing * - * @see CdSync(), CdCommandF(), CdControl() + * @see CdlCommand, CdSync(), CdCommandF(), CdControl() */ int CdCommand(CdlCommand cmd, const void *param, int length, uint8_t *result); @@ -478,7 +559,7 @@ int CdCommand(CdlCommand cmd, const void *param, int length, uint8_t *result); * @param length Number of parameter bytes expected by the command * @return Always 1 (even if sending the command failed) * - * @see CdCommand(), CdControlF() + * @see CdlCommand, CdCommand(), CdControlF() */ int CdCommandF(CdlCommand cmd, const void *param, int length); @@ -664,16 +745,16 @@ int CdRead(int sectors, uint32_t *buf, int mode); * * @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(). + * will be made before an error is returned by CdReadSync(). * * 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. * - * IMPORTANT: in order for retries to be correctly processed, CdReadSync(0) + * IMPORTANT: in order for retries to be handled correctly, 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. + * frame) until reading has finished or an error occurs. * * @param sectors * @param buf @@ -690,7 +771,7 @@ int CdReadRetry(int sectors, uint32_t *buf, int mode, int attempts); * * @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. + * -2 and any callback registered using CdReadCallback() will *not* be called. * * NOTE: the CD-ROM controller may take several hundred milliseconds to * actually stop reading. CdReadSync() should be used to make sure the drive is @@ -865,7 +946,7 @@ int CdUnlock(CdlRegionCode region); * 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 + * @param toc Pointer to an array of 99 CdlLOC entries * @return Number of tracks on the disc, or 0 in case of error * * @see CdControl() @@ -1013,19 +1094,11 @@ int CdGetVolumeLabel(char *label); * 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: - * - * | 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. | + * @return CD-ROM ISO9660 parser error code (see CdlIsoError) * - * @see CdSearchFile(), CdOpenDir() + * @see CdlIsoError, CdSearchFile(), CdOpenDir() */ -int CdIsoError(void); +CdlIsoError CdIsoError(void); /** * @brief Locates and loads the specified disc session. diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index f1e5de8..d562420 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -27,7 +27,7 @@ /* Definitions */ -typedef enum _GPU_DispFlags { +typedef enum { DISP_WIDTH_256 = 0, DISP_WIDTH_320 = 1, DISP_WIDTH_512 = 2, @@ -39,12 +39,12 @@ typedef enum _GPU_DispFlags { DISP_WIDTH_384 = 1 << 6 } GPU_DispFlags; -typedef enum _GPU_VideoMode { +typedef enum { MODE_NTSC = 0, MODE_PAL = 1 } GPU_VideoMode; -typedef enum _GPU_DrawOpType { +typedef enum { DRAWOP_TYPE_DMA = 1, DRAWOP_TYPE_GPU_IRQ = 2 } GPU_DrawOpType; @@ -273,19 +273,19 @@ typedef enum _GPU_DrawOpType { /* Primitive structure definitions */ -typedef struct _P_TAG_T { +typedef struct { uint32_t color:24; uint32_t code:8; } P_TAG_T; -typedef struct _P_TAG { +typedef struct { uint32_t addr:24; uint32_t len:8; uint32_t color:24; uint32_t code:8; } P_TAG; -typedef struct _P_COLOR { +typedef struct { uint32_t color:24; uint32_t pad:8; } P_COLOR; @@ -293,11 +293,11 @@ typedef struct _P_COLOR { // These macros are used to define two variants of each primitive, a regular one // and a "tagless" one (_T suffix) without the OT/display list header. #define _DEF_PRIM(name, ...) \ - typedef struct _##name##_T { __VA_ARGS__ } name##_T; \ - typedef struct _##name { uint32_t tag; __VA_ARGS__ } name; + typedef struct { __VA_ARGS__ } name##_T; \ + typedef struct { uint32_t tag; __VA_ARGS__ } name; #define _DEF_ALIAS(name, target) \ - typedef struct _##target##_T name##_T; \ - typedef struct _##target name; + typedef target##_T name##_T; \ + typedef target name; _DEF_PRIM(POLY_F3, uint8_t r0, g0, b0, code; @@ -524,23 +524,23 @@ _DEF_PRIM(DR_ENV, /* Structure definitions */ -typedef struct _RECT { +typedef struct { int16_t x, y, w, h; } RECT; -typedef struct _DISPENV_RAW { +typedef struct { uint32_t vid_mode; int16_t vid_xpos, vid_ypos; int16_t fb_x, fb_y; } DISPENV_RAW; -typedef struct _DISPENV { +typedef struct { RECT disp, screen; uint8_t isinter, isrgb24, reverse; uint8_t _reserved; } DISPENV; -typedef struct _DRAWENV { +typedef struct { RECT clip; // Drawing area int16_t ofs[2]; // GPU draw offset (relative to draw area) RECT tw; // Texture window @@ -552,7 +552,7 @@ typedef struct _DRAWENV { DR_ENV dr_env; // GPU primitive cache area (used internally) } DRAWENV; -typedef struct _TIM_IMAGE { +typedef struct { uint32_t mode; RECT *crect; uint32_t *caddr; @@ -560,7 +560,7 @@ typedef struct _TIM_IMAGE { uint32_t *paddr; } TIM_IMAGE; -typedef struct _GsIMAGE { +typedef struct { uint32_t pmode; int16_t px, py, pw, ph; uint32_t *pixel; @@ -615,7 +615,7 @@ int DrawBuffer(const uint32_t *buf, size_t length); int DrawBufferIRQ(const uint32_t *buf, size_t length); void DrawBuffer2(const uint32_t *buf, size_t length); void DrawBufferIRQ2(const uint32_t *buf, size_t length); -void DrawPrim(const uint32_t *pri); +void DrawPrim(const void *pri); void AddPrim(uint32_t *ot, const void *pri); diff --git a/libpsn00b/include/psxpress.h b/libpsn00b/include/psxpress.h index f26e030..4d32171 100644 --- a/libpsn00b/include/psxpress.h +++ b/libpsn00b/include/psxpress.h @@ -29,20 +29,20 @@ /* Structure definitions */ -typedef struct _DECDCTENV { +typedef struct { uint8_t iq_y[64]; // Luma quantization table, stored in zigzag order uint8_t iq_c[64]; // Chroma quantization table, stored in zigzag order int16_t dct[64]; // Inverse DCT matrix (2.14 fixed-point) } DECDCTENV; -typedef struct _VLC_TableV2 { +typedef struct { uint16_t ac0[2]; uint32_t ac2[8], ac3[64]; uint16_t ac4[8], ac5[8], ac7[16], ac8[32]; uint16_t ac9[32], ac10[32], ac11[32], ac12[32]; } VLC_TableV2; -typedef struct _VLC_TableV3 { +typedef struct { uint16_t ac0[2]; uint32_t ac2[8], ac3[64]; uint16_t ac4[8], ac5[8], ac7[16], ac8[32]; @@ -51,18 +51,18 @@ typedef struct _VLC_TableV3 { uint8_t _reserved[3]; } VLC_TableV3; -typedef struct _DECDCTTAB { +typedef struct { uint32_t ac[8192], ac00[512]; } DECDCTTAB; -typedef enum _DECDCTMODE { +typedef enum { DECDCT_MODE_24BPP = 1, DECDCT_MODE_16BPP = 0, DECDCT_MODE_16BPP_BIT15 = 2, DECDCT_MODE_RAW = -1 } DECDCTMODE; -typedef struct _VLC_Context { +typedef struct { const uint32_t *input; uint32_t window, next_window, remaining; int8_t is_v3, bit_offset, block_index, coeff_index; @@ -70,10 +70,6 @@ typedef struct _VLC_Context { int16_t last_y, last_cr, last_cb; } VLC_Context; -// Despite what some docs claim, the "number of 32-byte blocks" and "always -// 0x3800" fields are actually a single 32-bit field which is copied over to -// the output buffer, then parsed by DecDCTin() and written to the MDEC0 -// register. typedef struct { uint32_t mdec0_header; uint16_t quant_scale; @@ -179,10 +175,10 @@ void DecDCTinRaw(const uint32_t *data, size_t length); * 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 - * no callback is registered to set up further transfers. DecDCTinSync(0) shall - * only be used alongside DMACallback(1) or if the entirety of the decoded - * stream (usually a whole frame) is being written to main RAM. + * output decoded data, e.g. if the length passed to DecDCTout() was too small + * and no callback is registered to set up further transfers. DecDCTinSync(0) + * shall only be used alongside DMACallback(1) or if the entirety of the + * decoded stream (usually a whole frame) is being written to main RAM. * * @param mode * @return 0 or -1 in case of a timeout (mode = 0), MDEC busy flag (mode = 1) @@ -219,7 +215,8 @@ void DecDCTout(uint32_t *data, size_t length); * 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. * If the input stream isn't contiguous in memory, DMACallback(0) shall be used - * to register a callback that calls DecDCTin() to feed the MDEC. + * to register a callback that calls DecDCTin() or DecDCTinRaw() to feed the + * MDEC. * * @param mode * @return 0 or -1 in case of a timeout (mode = 0), DMA busy flag (mode = 1) @@ -249,7 +246,7 @@ int DecDCToutSync(int mode); * first time. Attempting to call this function with the GTE disabled will * result in a crash. * - * @param ctx Pointer to VLC_Context structure (which will be initialized) + * @param ctx Pointer to new VLC_Context structure * @param buf * @param max_size Maximum number of 32-bit words to output * @param bs @@ -456,8 +453,8 @@ int DecDCTvlcContinue2(VLC_Context *ctx, uint32_t *buf, size_t max_size); * additionally, the maximum output buffer size is not passed as an argument * but is instead set by calling DecDCTvlcSize2(). * - * This function behaves identically to DecDCTvlcContinue() if bs = 0 and - * DecDCTvlcStart() otherwise. The table argument can optionally be passed to + * This function behaves identically to DecDCTvlcContinue2() if bs = 0 and + * DecDCTvlcStart2() otherwise. The table argument can optionally be passed to * use a custom lookup table. If zero, the last pointer passed to * DecDCTvlcBuild() will be used. * diff --git a/libpsn00b/include/psxsn.h b/libpsn00b/include/psxsn.h index 1acbc18..f14db12 100644 --- a/libpsn00b/include/psxsn.h +++ b/libpsn00b/include/psxsn.h @@ -11,24 +11,29 @@ * write access to a directory on the host's filesystem when the executable is * running on an emulator or through a debugger that supports the PCDRV * protocol, such as Unirom or pcsx-redux. These functions are completely - * separate and independent from the BIOS file API and do not register any - * device drivers. + * separate and independent from the file APIs provided by the BIOS and do not + * register any device drivers. * * Note that in the official SDK these functions are provided by libsn, while * in PSn00bSDK they are part of libpsxapi. + * + * IMPORTANT: as these function rely on break instructions internally, calling + * them on real hardware without a PCDRV handler installed or on an emulator + * that does not support the API will result in an uncaught break exception, + * which will cause the BIOS to get stuck in an infinite loop. */ #pragma once #include <stddef.h> -typedef enum _PCDRV_OpenMode { +typedef enum { PCDRV_MODE_READ = 0, PCDRV_MODE_WRITE = 1, PCDRV_MODE_READ_WRITE = 2 } PCDRV_OpenMode; -typedef enum _PCDRV_SeekMode { +typedef enum { PCDRV_SEEK_SET = 0, PCDRV_SEEK_CUR = 1, PCDRV_SEEK_END = 2 diff --git a/libpsn00b/libc/malloc.c b/libpsn00b/libc/malloc.c index e9fd6f4..d3425d0 100644 --- a/libpsn00b/libc/malloc.c +++ b/libpsn00b/libc/malloc.c @@ -224,7 +224,7 @@ __attribute__((weak)) void *realloc(void *ptr, size_t size) { } // No luck. - void *new = malloc(_size); + void *new = malloc(size); if (!new) return 0; diff --git a/libpsn00b/libc/start.c b/libpsn00b/libc/start.c index dcbad2d..fe6dedd 100644 --- a/libpsn00b/libc/start.c +++ b/libpsn00b/libc/start.c @@ -65,17 +65,13 @@ extern uint8_t _end[]; extern void (*__CTOR_LIST__[])(void); extern void (*__DTOR_LIST__[])(void); -extern int main(int argc, const char* argv[]); +extern int main(int argc, const char **argv); // Even though _start() usually takes no arguments, this implementation allows // parent executables to pass args directly to child executables without having // to overwrite the arg strings in kernel RAM. -void _start_inner(int argc, const char **argv) { - //__asm__ volatile("la $gp, _gp;"); - - // BSS is always aligned to 4 bytes by the linker script. - for (uint32_t *i = (uint32_t *) __bss_start; i < (uint32_t *) _end; i++) - *i = 0; +int _start_inner(int argc, const char **argv) { + __builtin_memset(__bss_start, 0, (void *) _end - (void *) __bss_start); // Initialize the heap and place it after the executable, assuming 2 MB of // RAM. Note that InitHeap() can be called again in main(). @@ -91,11 +87,12 @@ void _start_inner(int argc, const char **argv) { for (int i = (int) __CTOR_LIST__[0]; i >= 1; i--) __CTOR_LIST__[i](); - // Store main()'s return value into the kernel return value area (for child - // executables). - *KERNEL_RETURN_VALUE = main(__argc, __argv); + int value = main(argc, argv); // Call global destructors (in forward order). for (int i = 0; i < (int) __DTOR_LIST__[0]; i++) __DTOR_LIST__[i + 1](); + + //*KERNEL_RETURN_VALUE = value; + return value; } diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c index 31ed00c..3410e82 100644 --- a/libpsn00b/psxcd/isofs.c +++ b/libpsn00b/psxcd/isofs.c @@ -25,12 +25,12 @@ typedef struct _CdlDIR_INT extern volatile int _cd_media_changed; -static int _cd_iso_last_dir_lba; -static uint8_t _cd_iso_descriptor_buff[2048]; -static uint8_t *_cd_iso_pathtable_buff=NULL; -static uint8_t *_cd_iso_directory_buff=NULL; -static int _cd_iso_directory_len; -static int _cd_iso_error=0; +static int _cd_iso_last_dir_lba; +static uint8_t _cd_iso_descriptor_buff[2048]; +static uint8_t *_cd_iso_pathtable_buff=NULL; +static uint8_t *_cd_iso_directory_buff=NULL; +static int _cd_iso_directory_len; +static CdlIsoError _cd_iso_error=CdlIsoOkay; static int _CdReadIsoDescriptor(int session_offs) { @@ -721,7 +721,7 @@ void CdCloseDir(CdlDIR *dir) free( d_dir ); } -int CdIsoError() +CdlIsoError CdIsoError() { return _cd_iso_error; } diff --git a/libpsn00b/psxgpu/drawing.c b/libpsn00b/psxgpu/drawing.c index 161b2f7..85bf6a8 100644 --- a/libpsn00b/psxgpu/drawing.c +++ b/libpsn00b/psxgpu/drawing.c @@ -108,11 +108,11 @@ void DrawBufferIRQ2(const uint32_t *buf, size_t length) { _send_buffer(DRAWOP_TYPE_GPU_IRQ, buf, length); } -void DrawPrim(const uint32_t *pri) { +void DrawPrim(const void *pri) { _sdk_validate_args_void(pri); DrawSync(0); - DrawBuffer2(&pri[1], getlen(pri)); + DrawBuffer2(((const uint32_t *) pri) + 1, getlen(pri)); } /* Helper functions */ diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c index e02c3c2..3a2bb8f 100644 --- a/libpsn00b/psxgpu/image.c +++ b/libpsn00b/psxgpu/image.c @@ -45,16 +45,24 @@ static void _dma_transfer(const RECT *rect, uint32_t *data, int write) { GPU_GP1 = 0x04000000; // Disable DMA request GPU_GP0 = 0x01000000; // Flush cache - GPU_GP0 = write ? 0xa0000000 : 0xc0000000; + uint32_t dreq_mode, status_mask; + if (write) { + GPU_GP0 = 0xa0000000; // Begin VRAM write + dreq_mode = 0x04000002; // Enable DMA request, route to GP0 + status_mask = 1 << 28; + } else { + GPU_GP0 = 0xc0000000; // Begin VRAM read + dreq_mode = 0x04000003; // Enable DMA request, route to GPU_READ + status_mask = 1 << 27; + } + //GPU_GP0 = rect->x | (rect->y << 16); GPU_GP0 = *((const uint32_t *) &(rect->x)); //GPU_GP0 = rect->w | (rect->h << 16); GPU_GP0 = *((const uint32_t *) &(rect->w)); + GPU_GP1 = dreq_mode; - // Enable DMA request, route to GP0 (2) or from GPU_READ (3) - GPU_GP1 = 0x04000002 | (write ^ 1); - - while ((DMA_CHCR(DMA_GPU) & (1 << 24)) || !(GPU_GP1 & (1 << 28))) + while ((DMA_CHCR(DMA_GPU) & (1 << 24)) || !(GPU_GP1 & status_mask)) __asm__ volatile(""); DMA_MADR(DMA_GPU) = (uint32_t) data; diff --git a/libpsn00b/psxpress/vlc.s b/libpsn00b/psxpress/vlc.s index 2b059c1..546d427 100644 --- a/libpsn00b/psxpress/vlc.s +++ b/libpsn00b/psxpress/vlc.s @@ -229,12 +229,12 @@ _vlc_skip_context_load: srlv temp, temp, $at subu value, temp .Ldc_cr_positive: + sll value, 2 # last_cr = (last_cr + (value << 2)) & 0x3ff addu last_cr, value andi last_cr, 0x3ff .Ldc_cr_zero: - sll temp, last_cr, 2 # *output = (last_cr << 2) | quant_scale - or temp, quant_scale + or temp, last_cr, quant_scale # *output = last_cr | quant_scale b .Lupdate_window_dc # update_window(dc_length) sh temp, 0(output) @@ -259,14 +259,14 @@ _vlc_skip_context_load: srlv temp, temp, $at subu value, temp .Ldc_cb_positive: + sll value, 2 # last_cb = (last_cb + (value << 2)) & 0x3ff addu last_cb, value andi last_cb, 0x3ff .Ldc_cb_zero: - sll value, last_cb, 2 # *output = (last_cb << 2) | quant_scale - or value, quant_scale + or temp, last_cb, quant_scale # *output = last_cb | quant_scale b .Lupdate_window_dc # update_window(dc_length) - sh value, 0(output) + sh temp, 0(output) .Ldc_block_y: # if (block_index < Cb) nop @@ -293,12 +293,12 @@ _vlc_skip_context_load: srlv temp, temp, $at subu value, temp .Ldc_y_positive: + sll value, 2 # last_y = (last_y + (value << 2)) & 0x3ff addu last_y, value andi last_y, 0x3ff .Ldc_y_zero: - sll temp, last_y, 2 # *output = (last_y << 2) | quant_scale - or temp, quant_scale + or temp, last_y, quant_scale # *output = last_y | quant_scale b .Lupdate_window_dc # update_window(dc_length) sh temp, 0(output) |
