diff options
| author | spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> | 2022-02-09 22:59:16 +0100 |
|---|---|---|
| committer | spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> | 2022-02-09 22:59:16 +0100 |
| commit | aca79b2a75c9a6106bc0047f767a475a2c3aaf8e (patch) | |
| tree | a9536efe30ce2d3a40414948494a0eda3e45dbbd | |
| parent | c083d3f18ecf80297b45eeda2abdf2fd6719cd7b (diff) | |
| download | psn00bsdk-aca79b2a75c9a6106bc0047f767a475a2c3aaf8e.tar.gz | |
Rename hwregs_a definitions, add hwregs_c, fix io/pads
25 files changed, 426 insertions, 294 deletions
diff --git a/examples/io/pads/main.c b/examples/io/pads/main.c index d100482..17bf331 100644 --- a/examples/io/pads/main.c +++ b/examples/io/pads/main.c @@ -15,12 +15,12 @@ * but the code in spi.c can be used to read/write sectors on a memory card and * combined with a higher-level filesystem driver for full support. * - * IMPORTANT: this example hasn't yet been tested on real hardware and/or with - * unofficial controllers, which might behave differently at higher poll rates. - * Also keep in mind that many emulators emulate controllers and memory cards - * inaccurately. It is thus recommended to test controller I/O code extensively - * and handle as many edge cases as possible (e.g. partial but valid responses, - * zerofilled responses, slow replies) for maximum compatibility. + * IMPORTANT: some controller models seem to be unable to respond to config + * mode commands reliably, even though simple high-speed polling usually works + * without issues. Also keep in mind that many emulators emulate controllers + * and memory cards inaccurately. It is thus recommended to test controller I/O + * code extensively and handle as many edge cases as possible (e.g. partial but + * valid responses, zerofilled responses, slow replies) for best compatibility. */ #include <stdint.h> @@ -116,7 +116,7 @@ void display(CONTEXT *ctx) { static volatile uint8_t pad_buff[2][34]; static volatile size_t pad_buff_len[2]; -static volatile uint32_t pad_digital_only[2] = { 0, 0 }; +static volatile uint32_t pad_config_attempt[2] = { 0, 0 }; // Just a wrapper around SPI_CreateRequest(). This does not send the command // immediately but adds it to the driver's request queue. @@ -148,7 +148,8 @@ void send_pad_cmd( // This callback determines whether a pad that identified as digital is // actually a DualShock in digital mode by checking if it started identifying -// as CONFIG_MODE after receiving a configuration command. +// as CONFIG_MODE after receiving a configuration command. Calls to printf() +// had to be commented out due to them being too slow. void dualshock_init_cb(uint32_t port, const volatile uint8_t *buff, size_t rx_len) { PadResponse *pad = (PadResponse *) buff; @@ -157,13 +158,13 @@ void dualshock_init_cb(uint32_t port, const volatile uint8_t *buff, size_t rx_le (pad->prefix != 0x5a) || (pad->type != PAD_ID_CONFIG_MODE) ) { - printf("no, pad is digital-only (len = %d)\n", rx_len); + //printf("no, pad is digital-only (len = %d)\n", rx_len); - pad_digital_only[port] = 1; + pad_config_attempt[port]++; return; } - printf("yes, forcing analog mode (len = %d)\n", rx_len); + //printf("yes, forcing analog mode (len = %d)\n", rx_len); // Issue further commands to force analog mode on, unlock rumble (not used // in this example) and enable longer responses containing button pressure @@ -171,6 +172,7 @@ void dualshock_init_cb(uint32_t port, const volatile uint8_t *buff, size_t rx_le // TODO: find out if passing 0x03 instead of 0x02 in PAD_CMD_SET_ANALOG // locks the analog button, as emulated by DuckStation... // https://gist.github.com/scanlime/5042071 + send_pad_cmd(port, PAD_CMD_CONFIG_MODE, 0x01, 0x00, 0); send_pad_cmd(port, PAD_CMD_SET_ANALOG, 0x01, 0x02, 0); send_pad_cmd(port, PAD_CMD_INIT_PRESSURE, 0x00, 0x00, 0); // Ignored by DualShock 1 send_pad_cmd(port, PAD_CMD_REQUEST_CONFIG, 0x00, 0x01, 0); @@ -189,29 +191,37 @@ void poll_cb(uint32_t port, const volatile uint8_t *buff, size_t rx_len) { PadResponse *pad = (PadResponse *) buff; - // If this pad identifies as a digital pad and hasn't been flagged as a - // digital-only pad already, attempt to put it into analog mode by entering - // configuration mode. It this fails, it will be flagged as digital-only. - // The digital-only flag is reset when the controller is unplugged or stops + // If this pad identifies as a digital pad, attempt to put it into analog + // mode up to 3 times by entering configuration mode. Once the attempt + // counter exceeds the threshold, it will be treated as digital-only. The + // attempt counter is reset when the controller is unplugged or stops // returning digital pad responses. + // NOTE: according to nocash docs, there is a hardware bug in DualShock + // controllers that causes the prefix byte (normally 0x5a) to turn into + // 0x00 if the analog button is pressed after config commands have been + // used. if ( rx_len && - (pad->prefix == 0x5a) && + ((pad->prefix == 0x5a) || !(pad->prefix)) && (pad->type == PAD_ID_DIGITAL) ) { - if (!pad_digital_only[port]) { - printf("Detecting if pad %d supports config mode... ", port + 1); + if (pad_config_attempt[port] < 3) { + /*printf( + "Detecting if pad %d supports config mode: attempt %d... ", + port + 1, + pad_config_attempt[port] + 1 + );*/ // The pad only identifies as CONFIG_MODE after at least another // command is sent. send_pad_cmd(port, PAD_CMD_CONFIG_MODE, 0x01, 0x00, 0); - send_pad_cmd(port, PAD_CMD_CONFIG_MODE, 0x01, 0x00, &dualshock_init_cb); + send_pad_cmd(port, PAD_CMD_READ, 0x00, 0x00, &dualshock_init_cb); } } else { - //printf("Clearing digital-only flag for pad %d\n", port + 1); + //printf("Clearing attempt counter for pad %d\n", port + 1); - pad_digital_only[port] = 0; + pad_config_attempt[port] = 0; } } @@ -240,11 +250,6 @@ int main(int argc, const char* argv[]) { PadResponse *pad = (PadResponse *) pad_buff[port]; - // According to nocash docs, there is a hardware bug in DualShock - // controllers that causes the prefix byte (normally 0x5a) to turn - // into 0x00 if the analog button is pressed after configuration - // commands have been used. Thus making sure the prefix is 0x5a - // isn't enough to reliably detect pads. /*if ((pad->prefix != 0x5a) && (pad->type != PAD_ID_ANALOG)) { FntPrint(-1, "\n\nPORT %d: INVALID RESPONSE\n", port + 1); if ((counter % 64) < 32) diff --git a/examples/io/pads/spi.c b/examples/io/pads/spi.c index ef75ffc..05a0e59 100644 --- a/examples/io/pads/spi.c +++ b/examples/io/pads/spi.c @@ -32,43 +32,27 @@ #include <psxetc.h> #include <psxapi.h> #include <psxpad.h> +#include <hwregs_c.h> #include "spi.h" -/* Register definitions */ - -#define F_CPU 33868800UL - -#define TIM_VALUE(N) *((volatile uint32_t *) 0x1f801100 + 4 * (N)) -#define TIM_CTRL(N) *((volatile uint32_t *) 0x1f801104 + 4 * (N)) -#define TIM_RELOAD(N) *((volatile uint32_t *) 0x1f801108 + 4 * (N)) - -// IMPORTANT: even though JOY_TXRX is a 32-bit register, it should only be -// accessed as 8-bit. Reading it as 16 or 32-bit works fine on real hardware, -// but leads to problems in some emulators. -#define JOY_TXRX *((volatile uint8_t *) 0x1f801040) -#define JOY_STAT *((volatile uint16_t *) 0x1f801044) -#define JOY_MODE *((volatile uint16_t *) 0x1f801048) -#define JOY_CTRL *((volatile uint16_t *) 0x1f80104a) -#define JOY_BAUD *((volatile uint16_t *) 0x1f80104e) - /* Internal structures and globals */ -typedef struct _SPI_CONTEXT { +typedef struct _SPI_Context { uint8_t tx_buff[SPI_BUFF_LEN]; uint8_t rx_buff[SPI_BUFF_LEN]; uint32_t tx_len, rx_len, port; SPI_Callback callback; } SPI_Context; -static volatile SPI_Context ctx; -static volatile SPI_Request volatile *current_req; -static SPI_Callback default_cb; +static volatile SPI_Context _context; +static volatile SPI_Request volatile *_current_req; +static volatile SPI_Callback _default_cb; /* Request queue management */ static void _spi_create_poll_req(void) { - PadRequest *req = (PadRequest *) ctx.tx_buff; + PadRequest *req = (PadRequest *) _context.tx_buff; req->addr = 0x01; req->cmd = PAD_CMD_READ; @@ -76,27 +60,31 @@ static void _spi_create_poll_req(void) { req->motor_l = 0x00; req->motor_r = 0x00; - ctx.tx_len = 4; - ctx.rx_len = 0; - ctx.port ^= 1; - ctx.callback = default_cb; + _context.tx_len = 4; + _context.rx_len = 0; + _context.port ^= 1; + _context.callback = _default_cb; } static void _spi_next_req(void) { // Copy the contents of the first request in the queue into the TX buffer. - memcpy((void *) ctx.tx_buff, (void *) current_req->data, current_req->len); + memcpy( + (void *) _context.tx_buff, + (void *) _current_req->data, + _current_req->len + ); - ctx.tx_len = current_req->len; - ctx.rx_len = 0; - ctx.port = current_req->port; - ctx.callback = current_req->callback; + _context.tx_len = _current_req->len; + _context.rx_len = 0; + _context.port = _current_req->port; + _context.callback = _current_req->callback; // Pop the first request from the queue by deallocating it and adjusting // the pointer to the first queue item. - SPI_Request *next = current_req->next; + SPI_Request *next = _current_req->next; - free((void *) current_req); - current_req = next; + free((void *) _current_req); + _current_req = next; } /* Interrupt handlers */ @@ -105,13 +93,13 @@ static void _spi_poll_irq_handler(void) { // Fetch the last response byte, which wasn't followed by a pulse on /ACK, // from the RX FIFO. if (JOY_STAT & 0x0002) - ctx.rx_buff[ctx.rx_len - 1] = (uint8_t) JOY_TXRX; + _context.rx_buff[_context.rx_len - 1] = (uint8_t) JOY_TXRX; - if (ctx.callback) - ctx.callback(ctx.port, ctx.rx_buff, ctx.rx_len); + if (_context.callback) + _context.callback(_context.port, _context.rx_buff, _context.rx_len); // If the request queue is empty, create a pad polling request. - if (current_req) + if (_current_req) _spi_next_req(); else _spi_create_poll_req(); @@ -119,17 +107,18 @@ static void _spi_poll_irq_handler(void) { // Prepare the SPI port by clearing any pending IRQ, pulling /CS high and // enabling the /ACK IRQ. In order to communicate with controllers, /CS has // to be driven low again for about 20 us before sending the first byte. + // TODO: these delays can be probably tweaked for better performance JOY_CTRL = 0x0010; - for (uint32_t i = 0; i < 50; i++) - __asm__("nop"); + for (uint32_t i = 0; i < 1000; i++) + __asm__ volatile(""); - JOY_CTRL = 0x1003 | (ctx.port << 13); - for (uint32_t i = 0; i < 500; i++) - __asm__("nop"); + JOY_CTRL = 0x1003 | (_context.port << 13); + for (uint32_t i = 0; i < 2000; i++) + __asm__ volatile(""); // Send the first byte indicating which device to address. If the matching // device is connected, it will reply by triggering the /ACK IRQ. - JOY_TXRX = ctx.tx_buff[0]; + JOY_TXRX = _context.tx_buff[0]; } static void _spi_ack_irq_handler(void) { @@ -137,29 +126,29 @@ static void _spi_ack_irq_handler(void) { // byte. According to nocash docs, this has to be done before resetting the // IRQ. while (JOY_STAT & 0x0080) - __asm__("nop"); + __asm__ volatile(""); // Keep /CS pulled low and acknowledge the IRQ (bit 4) to ensure it can be // triggered again. - JOY_CTRL = 0x1013 | (ctx.port << 13); + JOY_CTRL = 0x1013 | (_context.port << 13); - if (!ctx.rx_len) { + if (!_context.rx_len) { // We just sent the first address byte. Obviously the response we // received was read from an open bus, so the SPI port's internal FIFO // must be flushed (by performing dummy reads) to ensure we are only // going to read valid data from now on. JOY_TXRX; - } else if (ctx.rx_len <= SPI_BUFF_LEN) { + } else if (_context.rx_len <= SPI_BUFF_LEN) { // If this is not the first byte, put it in the RX buffer. - ctx.rx_buff[ctx.rx_len - 1] = (uint8_t) JOY_TXRX; + _context.rx_buff[_context.rx_len - 1] = (uint8_t) JOY_TXRX; } // Send the next byte, or a null byte if there is no more data to send and // we're just reading a response. - ctx.rx_len++; - if (ctx.rx_len < ctx.tx_len) - JOY_TXRX = (uint32_t) ctx.tx_buff[ctx.rx_len]; + _context.rx_len++; + if (_context.rx_len < _context.tx_len) + JOY_TXRX = (uint32_t) _context.tx_buff[_context.rx_len]; else JOY_TXRX = 0x00; } @@ -176,10 +165,10 @@ SPI_Request *SPI_CreateRequest(void) { // Find the last queued request by traversing the linked list and append a // pointer to the new request. - if (!current_req) { - current_req = req; + if (!_current_req) { + _current_req = req; } else { - volatile SPI_Request *volatile last = current_req; + volatile SPI_Request *volatile last = _current_req; while (last->next) last = last->next; @@ -213,6 +202,6 @@ void SPI_Init(SPI_Callback callback) { JOY_BAUD = 0x0088; // 250000 bps SPI_SetPollRate(250); - current_req = 0; - default_cb = callback; + _current_req = 0; + _default_cb = callback; } diff --git a/examples/io/pads/spi.h b/examples/io/pads/spi.h index c50e065..7d4d75b 100644 --- a/examples/io/pads/spi.h +++ b/examples/io/pads/spi.h @@ -9,8 +9,9 @@ #include <stdint.h> #include <psxpad.h> -// Maximum request/response length (34 bytes for pads, 140 for memory cards) -//#define SPI_BUFF_LEN 34 +// Maximum request/response length (34 bytes for pads, 140 for memory cards). +// Must be a multiple of 4 to avoid memory alignment issues. +//#define SPI_BUFF_LEN 36 #define SPI_BUFF_LEN 140 /* Request structures */ @@ -30,6 +31,10 @@ typedef struct _SPI_Request { /* Public API */ +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief Allocates a new request object and adds it to the request queue. The * object must be populated afterwards by setting the length, callback and @@ -49,7 +54,7 @@ void SPI_SetPollRate(uint32_t value); /** * @brief Installs the SPI and timer 2 interrupt handlers and starts the poll * timer. By default the polling rate is set to 250 Hz (125 Hz per port), - * however it can be changed at any time by calling spi_set_poll_rate(). + * however it can be changed at any time by calling SPI_SetPollRate(). * * The provided callback (if any) is called to report the result of poll * requests, which are issued automatically when no other request is in the @@ -59,4 +64,8 @@ void SPI_SetPollRate(uint32_t value); */ void SPI_Init(SPI_Callback callback); +#ifdef __cplusplus +} +#endif + #endif diff --git a/examples/sound/spustream/main.c b/examples/sound/spustream/main.c index be095cb..6284c6d 100644 --- a/examples/sound/spustream/main.c +++ b/examples/sound/spustream/main.c @@ -11,8 +11,8 @@ * SPU ADPCM data (one for each channel, so a stereo stream would have 2 * buffers per chunk). All buffers in a chunk are played simultaneously using * multiple SPU channels; each buffer has the loop flag set at the end, so each - * channel will jump to its loop address (SPU_CHANNELS[n].loop_addr) once the - * chunk is played. + * channel will jump to its loop address (SPU_CH_LOOP_ADDR(n)) once the chunk + * is played. * * Since the loop point doesn't necessarily have to be within the chunk itself, * we can abuse it to "queue" another set of buffers to be played immediately @@ -94,6 +94,7 @@ #include <psxpad.h> #include <psxspu.h> #include <psxcd.h> +#include <hwregs_c.h> // To maximize STREAM.BIN packing efficiency and get rid of padding between // chunks, buffer size should be a multiple of sector size (2048 bytes). Buffer @@ -105,27 +106,6 @@ #define NUM_CHANNELS 2 #define CHANNEL_MASK 0x03 -/* Register definitions */ - -// For some reason SpuVoiceRaw doesn't actually match the layout of SPU -// registers, so here we go. -typedef struct { - uint16_t vol_left; - uint16_t vol_right; - uint16_t freq; - uint16_t addr; - uint32_t adsr_param; - uint16_t _reserved; - uint16_t loop_addr; -} SPUChannel; - -#define SPU_CTRL *((volatile uint16_t *) 0x1f801daa) -#define SPU_IRQ_ADDR *((volatile uint16_t *) 0x1f801da4) -#define SPU_KEY_ON *((volatile uint32_t *) 0x1f801d88) -#define SPU_KEY_OFF *((volatile uint32_t *) 0x1f801d8c) - -// SPU RAM is addressed in 8-byte units, using 16-bit pointers. -#define SPU_CHANNELS ((volatile SPUChannel *) 0x1f801c00) #define SPU_RAM_ADDR(x) ((uint16_t) (((uint32_t) (x)) >> 3)) /* Display/GPU context utilities */ @@ -252,7 +232,7 @@ void spu_irq_handler(void) { SPU_IRQ_ADDR = SPU_RAM_ADDR(str_ctx.spu_addr); for (uint32_t i = 0; i < NUM_CHANNELS; i++) - SPU_CHANNELS[i].loop_addr = SPU_RAM_ADDR(str_ctx.spu_addr + BUFFER_SIZE * i); + SPU_CH_LOOP_ADDR(i) = SPU_RAM_ADDR(str_ctx.spu_addr + BUFFER_SIZE * i); // Start loading the next chunk. cd_event_handler() will be called // repeatedly for each sector until the entire chunk is read. @@ -317,7 +297,7 @@ void init_spu_channels(void) { SPU_KEY_OFF = 0x00ffffff; for (uint32_t i = 0; i < 24; i++) - SPU_CHANNELS[i].addr = SPU_RAM_ADDR(DUMMY_BLOCK_ADDR); + SPU_CH_ADDR(i) = SPU_RAM_ADDR(DUMMY_BLOCK_ADDR); SPU_KEY_ON = 0x00ffffff; } @@ -347,18 +327,18 @@ void start_stream(void) { SPU_KEY_OFF = CHANNEL_MASK; for (uint32_t i = 0; i < NUM_CHANNELS; i++) { - SPU_CHANNELS[i].addr = SPU_RAM_ADDR(BUFFER_START_ADDR + BUFFER_SIZE * i); - SPU_CHANNELS[i].freq = SAMPLE_RATE; - SPU_CHANNELS[i].adsr_param = 0x1fee80ff; // or 0x9fc080ff, 0xdff18087 + SPU_CH_ADDR(i) = SPU_RAM_ADDR(BUFFER_START_ADDR + BUFFER_SIZE * i); + SPU_CH_FREQ(i) = SAMPLE_RATE; + SPU_CH_ADSR(i) = 0x1fee80ff; // or 0x9fc080ff, 0xdff18087 } // Unmute the channels and route them for stereo output. You'll want to // edit this if you are using more than 2 channels, and/or if you want to // provide an option to output mono audio instead of stereo. - SPU_CHANNELS[0].vol_left = 0x3fff; - SPU_CHANNELS[0].vol_right = 0x0000; - SPU_CHANNELS[1].vol_left = 0x0000; - SPU_CHANNELS[1].vol_right = 0x3fff; + SPU_CH_VOL_L(0) = 0x3fff; + SPU_CH_VOL_R(0) = 0x0000; + SPU_CH_VOL_L(1) = 0x0000; + SPU_CH_VOL_R(1) = 0x3fff; SPU_KEY_ON = CHANNEL_MASK; spu_irq_handler(); @@ -446,7 +426,7 @@ int main(int argc, const char* argv[]) { // Only set the sample rate registers if necessary. if (pad->btn != 0xffff) { for (uint32_t i = 0; i < NUM_CHANNELS; i++) - SPU_CHANNELS[i].freq = sample_rate; + SPU_CH_FREQ(i) = sample_rate; } last_buttons = pad->btn; diff --git a/libpsn00b/include/hwregs_a.h b/libpsn00b/include/hwregs_a.h index 0680679..4d0bade 100644 --- a/libpsn00b/include/hwregs_a.h +++ b/libpsn00b/include/hwregs_a.h @@ -6,11 +6,13 @@ .set IOBASE, 0x1f80 # IO segment base -# GPU +## GPU + .set GP0, 0x1810 # Also GPUREAD .set GP1, 0x1814 # Also GPUSTAT -# CD +## CD drive + .set CD_STAT, 0x1800 .set CD_CMD, 0x1801 # Also response FIFO .set CD_DATA, 0x1802 # Also parameters @@ -21,14 +23,14 @@ .set CD_REG2, 0x1802 .set CD_REG3, 0x1803 -.set SBUS_5, 0x1018 -.set COM_DELAY, 0x1020 +## SPU -# SPU (must be used with 16-bit load/store instructions) .set SPU_VOICE_BASE, 0x1c00 -.set SPU_MASTER_VOL, 0x1d80 -.set SPU_REVERB_VOL, 0x1d84 +.set SPU_MASTER_VOL_L, 0x1d80 +.set SPU_MASTER_VOL_R, 0x1d82 +.set SPU_REVERB_VOL_L, 0x1d84 +.set SPU_REVERB_VOL_R, 0x1d86 .set SPU_KEY_ON, 0x1d88 .set SPU_KEY_OFF, 0x1d8c .set SPU_FM_MODE, 0x1d90 @@ -41,81 +43,107 @@ .set SPU_ADDR, 0x1da6 .set SPU_DATA, 0x1da8 -.set SPUCNT, 0x1daa -.set SPUDTCNT, 0x1dac -.set SPUSTAT, 0x1dae +.set SPU_CTRL, 0x1daa +.set SPU_DMA_CTRL, 0x1dac +.set SPU_STAT, 0x1dae -.set SPU_CD_VOL, 0x1db0 -.set SPU_EXT_VOL, 0x1db4 -.set SPU_CURRENT_VOL, 0x1db8 +.set SPU_CD_VOL_L, 0x1db0 +.set SPU_CD_VOL_R, 0x1db2 +.set SPU_EXT_VOL_L, 0x1db4 +.set SPU_EXT_VOL_R, 0x1db6 +.set SPU_CURRENT_VOL_L, 0x1db8 +.set SPU_CURRENT_VOL_R, 0x1dba .set SPU_VOICE_VOL_L, 0x00 .set SPU_VOICE_VOL_R, 0x02 .set SPU_VOICE_FREQ, 0x04 .set SPU_VOICE_ADDR, 0x06 .set SPU_VOICE_ADSR_L, 0x08 -.set SPU_VOICE_ADSR_H, 0x0a +.set SPU_VOICE_ADSR_H, 0x0a .set SPU_VOICE_LOOP, 0x0e -# MDEC +## MDEC + .set MDEC0, 0x1820 .set MDEC1, 0x1824 -# Pads -.set JOY_TXRX, 0x1040 -.set JOY_STAT, 0x1044 -.set JOY_MODE, 0x1048 -.set JOY_CTRL, 0x104A -.set JOY_BAUD, 0x104E - -# Serial -.set SIO_TXRX, 0x1050 -.set SIO_STAT, 0x1054 -.set SIO_MODE, 0x1058 -.set SIO_CTRL, 0x105a -.set SIO_BAUD, 0x105e - -# IRQ -.set ISTAT, 0x1070 -.set IMASK, 0x1074 - -# DMA -.set DPCR, 0x10f0 -.set DICR, 0x10f4 - -.set D0_MADR, 0x1080 -.set D0_BCR, 0x1084 -.set D0_CHCR, 0x1088 - -.set D1_MADR, 0x1090 -.set D1_BCR, 0x1094 -.set D1_CHCR, 0x1098 - -.set D2_MADR, 0x10a0 -.set D2_BCR, 0x10a4 -.set D2_CHCR, 0x10a8 - -.set D3_MADR, 0x10b0 -.set D3_BCR, 0x10b4 -.set D3_CHCR, 0x10b8 - -.set D4_MADR, 0x10c0 -.set D4_BCR, 0x10c4 -.set D4_CHCR, 0x10c8 - -.set D6_MADR, 0x10e0 -.set D6_BCR, 0x10e4 -.set D6_CHCR, 0x10e8 - -# Timers -.set T0_CNT, 0x1100 -.set T0_MODE, 0x1104 -.set T0_TGT, 0x1108 - -.set T1_CNT, 0x1110 -.set T1_MODE, 0x1114 -.set T1_TGT, 0x1118 - -.set T2_CNT, 0x1120 -.set T2_MODE, 0x1124 -.set T2_TGT, 0x1128 +## SPI controller port + +.set JOY_TXRX, 0x1040 +.set JOY_STAT, 0x1044 +.set JOY_MODE, 0x1048 +.set JOY_CTRL, 0x104a +.set JOY_BAUD, 0x104e + +## Serial port + +.set SIO_TXRX, 0x1050 +.set SIO_STAT, 0x1054 +.set SIO_MODE, 0x1058 +.set SIO_CTRL, 0x105a +.set SIO_BAUD, 0x105e + +## IRQ controller + +.set IRQ_STAT, 0x1070 +.set IRQ_MASK, 0x1074 + +## DMA + +.set DMA_DPCR, 0x10f0 +.set DMA_DICR, 0x10f4 + +.set DMA0_MADR, 0x1080 +.set DMA0_BCR, 0x1084 +.set DMA0_CHCR, 0x1088 + +.set DMA1_MADR, 0x1090 +.set DMA1_BCR, 0x1094 +.set DMA1_CHCR, 0x1098 + +.set DMA2_MADR, 0x10a0 +.set DMA2_BCR, 0x10a4 +.set DMA2_CHCR, 0x10a8 + +.set DMA3_MADR, 0x10b0 +.set DMA3_BCR, 0x10b4 +.set DMA3_CHCR, 0x10b8 + +.set DMA4_MADR, 0x10c0 +.set DMA4_BCR, 0x10c4 +.set DMA4_CHCR, 0x10c8 + +.set DMA5_MADR, 0x10d0 +.set DMA5_BCR, 0x10d4 +.set DMA5_CHCR, 0x10d8 + +.set DMA6_MADR, 0x10e0 +.set DMA6_BCR, 0x10e4 +.set DMA6_CHCR, 0x10e8 + +## Timers + +.set TIM0_VALUE, 0x1100 +.set TIM0_CTRL, 0x1104 +.set TIM0_RELOAD, 0x1108 + +.set TIM1_VALUE, 0x1110 +.set TIM1_CTRL, 0x1114 +.set TIM1_RELOAD, 0x1118 + +.set TIM2_VALUE, 0x1120 +.set TIM2_CTRL, 0x1124 +.set TIM2_RELOAD, 0x1128 + +## Memory control + +.set EXP1_ADDR, 0x1000 +.set EXP2_ADDR, 0x1004 +.set EXP1_DELAY_SIZE, 0x1008 +.set EXP3_DELAY_SIZE, 0x100c +.set BIOS_DELAY_SIZE, 0x1010 +.set SPU_DELAY_SIZE, 0x1014 +.set CD_DELAY_SIZE, 0x1018 +.set EXP2_DELAY_SIZE, 0x101c +.set COM_DELAY_CFG, 0x1020 +.set RAM_SIZE_CFG, 0x1060 diff --git a/libpsn00b/include/hwregs_c.h b/libpsn00b/include/hwregs_c.h new file mode 100644 index 0000000..4222a22 --- /dev/null +++ b/libpsn00b/include/hwregs_c.h @@ -0,0 +1,129 @@ +/* + * PSn00bSDK hardware registers definitions + * (C) 2022 spicyjpeg - MPL licensed + */ + +#ifndef __HWREGS_C_H +#define __HWREGS_C_H + +#include <stdint.h> + +#define _MMIO8(addr) *((volatile uint8_t *) (addr)) +#define _MMIO16(addr) *((volatile uint16_t *) (addr)) +#define _MMIO32(addr) *((volatile uint32_t *) (addr)) + +/* Constants */ + +#define F_CPU 33868800UL +#define F_GPU 53222400UL + +/* GPU */ + +#define GP0 _MMIO32(0x1f801810) +#define GP1 _MMIO32(0x1f801814) + +/* CD drive */ + +#define CD_STAT _MMIO8(0x1f801800) +#define CD_CMD _MMIO8(0x1f801801) +#define CD_DATA _MMIO8(0x1f801802) +#define CD_IRQ _MMIO8(0x1f801803) + +#define CD_REG(N) _MMIO8(0x1f801800 + (N)) + +/* SPU */ + +#define SPU_MASTER_VOL_L _MMIO16(0x1f801d80) +#define SPU_MASTER_VOL_R _MMIO16(0x1f801d82) +#define SPU_REVERB_VOL_L _MMIO16(0x1f801d84) +#define SPU_REVERB_VOL_R _MMIO16(0x1f801d86) +#define SPU_KEY_ON _MMIO32(0x1f801d88) +#define SPU_KEY_OFF _MMIO32(0x1f801d8c) +#define SPU_FM_MODE _MMIO32(0x1f801d90) +#define SPU_NOISE_MODE _MMIO32(0x1f801d94) +#define SPU_REVERB_ON _MMIO32(0x1f801d98) +#define SPU_CHAN_STATUS _MMIO32(0x1f801d9c) + +#define SPU_REVERB_ADDR _MMIO16(0x1f801da2) +#define SPU_IRQ_ADDR _MMIO16(0x1f801da4) +#define SPU_ADDR _MMIO16(0x1f801da6) +#define SPU_DATA _MMIO16(0x1f801da8) + +#define SPU_CTRL _MMIO16(0x1f801daa) +#define SPU_DMA_CTRL _MMIO16(0x1f801dac) +#define SPU_STAT _MMIO16(0x1f801dae) + +#define SPU_CD_VOL_L _MMIO16(0x1f801db0) +#define SPU_CD_VOL_R _MMIO16(0x1f801db2) +#define SPU_EXT_VOL_L _MMIO16(0x1f801db4) +#define SPU_EXT_VOL_R _MMIO16(0x1f801db6) +#define SPU_CURRENT_VOL_L _MMIO16(0x1f801db8) +#define SPU_CURRENT_VOL_R _MMIO16(0x1f801dba) + +// These are not named SPU_VOICE_* to avoid name clashes with SPU attribute +// flags defined in psxspu.h. +#define SPU_CH_VOL_L(N) _MMIO16(0x1f801c00 + 16 * (N)) +#define SPU_CH_VOL_R(N) _MMIO16(0x1f801c02 + 16 * (N)) +#define SPU_CH_FREQ(N) _MMIO16(0x1f801c04 + 16 * (N)) +#define SPU_CH_ADDR(N) _MMIO16(0x1f801c06 + 16 * (N)) +#define SPU_CH_ADSR(N) _MMIO32(0x1f801c08 + 16 * (N)) +#define SPU_CH_LOOP_ADDR(N) _MMIO16(0x1f801c0e + 16 * (N)) + +/* MDEC */ + +#define MDEC0 _MMIO32(0x1f801820) +#define MDEC1 _MMIO32(0x1f801824) + +/* SPI controller port */ + +// IMPORTANT: even though JOY_TXRX is a 32-bit register, it should only be +// accessed as 8-bit. Reading it as 16 or 32-bit works fine on real hardware, +// but leads to problems in some emulators. +#define JOY_TXRX _MMIO8(0x1f801040) +#define JOY_STAT _MMIO16(0x1f801044) +#define JOY_MODE _MMIO16(0x1f801048) +#define JOY_CTRL _MMIO16(0x1f80104a) +#define JOY_BAUD _MMIO16(0x1f80104e) + +/* Serial port */ + +#define SIO_TXRX _MMIO8(0x1f801050) +#define SIO_STAT _MMIO16(0x1f801054) +#define SIO_MODE _MMIO16(0x1f801058) +#define SIO_CTRL _MMIO16(0x1f80105a) +#define SIO_BAUD _MMIO16(0x1f80105e) + +/* IRQ controller */ + +#define IRQ_STAT _MMIO32(0x1f801070) +#define IRQ_MASK _MMIO32(0x1f801074) + +/* DMA */ + +#define DMA_DPCR _MMIO32(0x1f8010f0) +#define DMA_DICR _MMIO32(0x1f8010f4) + +#define DMA_MADR(N) _MMIO32(0x1f801080 + 16 * (N)) +#define DMA_BCR(N) _MMIO32(0x1f801084 + 16 * (N)) +#define DMA_CHCR(N) _MMIO32(0x1f801088 + 16 * (N)) + +/* Timers */ + +#define TIM_VALUE(N) _MMIO32(0x1f801100 + 16 * (N)) +#define TIM_CTRL(N) _MMIO32(0x1f801104 + 16 * (N)) +#define TIM_RELOAD(N) _MMIO32(0x1f801108 + 16 * (N)) + +/* Memory control */ + +#define EXP1_ADDR _MMIO32(0x1f801000) +#define EXP2_ADDR _MMIO32(0x1f801004) +#define EXP1_DELAY_SIZE _MMIO32(0x1f801008) +#define EXP3_DELAY_SIZE _MMIO32(0x1f80100c) +#define BIOS_DELAY_SIZE _MMIO32(0x1f801010) +#define SPU_DELAY_SIZE _MMIO32(0x1f801014) +#define CD_DELAY_SIZE _MMIO32(0x1f801018) +#define EXP2_DELAY_SIZE _MMIO32(0x1f80101c) +#define COM_DELAY_CFG _MMIO32(0x1f801020) +#define RAM_SIZE_CFG _MMIO32(0x1f801060) + +#endif diff --git a/libpsn00b/psxapi/_initcd.s b/libpsn00b/psxapi/_initcd.s index decf2bd..c3a2861 100644 --- a/libpsn00b/psxapi/_initcd.s +++ b/libpsn00b/psxapi/_initcd.s @@ -11,7 +11,7 @@ _InitCd: lui $a0, IOBASE # Load IOBASE value - lw $v0, DPCR($a0) # Get current DMA settings + lw $v0, DMA_DPCR($a0) # Get current DMA settings nop sw $v0, 4($sp) # Save to stack @@ -21,14 +21,14 @@ _InitCd: lui $a0, IOBASE # Load IOBASE again lw $v0, 4($sp) # Get old DMA control settings - lw $v1, DPCR($a0) # Get DMA settings by _96_init() + lw $v1, DMA_DPCR($a0) # Get DMA settings by _96_init() lui $a1, 0xffff # Mask out settings for CD DMA ori $a1, 0x0f00 and $v0, $a1 or $v0, $v1 # Merge and set new DMA settings - sw $v0, DPCR($a0) + sw $v0, DMA_DPCR($a0) lw $ra, 0($sp) addiu $sp, 8 diff --git a/libpsn00b/psxcd/cdgetsector.s b/libpsn00b/psxcd/cdgetsector.s index dbe95cb..9f38e7a 100644 --- a/libpsn00b/psxcd/cdgetsector.s +++ b/libpsn00b/psxcd/cdgetsector.s @@ -21,16 +21,16 @@ CdGetSector: # srl $a1, 2 # (the official implementation expects $a1/size # to be in 32-bit words rather than bytes) or $v0, $a1 - sw $a0, D3_MADR($a2) # Set DMA base address and transfer length - sw $v0, D3_BCR($a2) + sw $a0, DMA3_MADR($a2) # Set DMA base address and transfer length + sw $v0, DMA3_BCR($a2) lui $v0, 0x1100 # Start DMA transfer - sw $v0, D3_CHCR($a2) + sw $v0, DMA3_CHCR($a2) nop nop .Ldma_wait: # Ensure DMA transfer has completed - lw $v0, D3_CHCR($a2) + lw $v0, DMA3_CHCR($a2) nop srl $v0, 24 andi $v0, 0x1 diff --git a/libpsn00b/psxcd/psxcd_asm.s b/libpsn00b/psxcd/psxcd_asm.s index 1dbf542..129bc89 100644 --- a/libpsn00b/psxcd/psxcd_asm.s +++ b/libpsn00b/psxcd/psxcd_asm.s @@ -17,9 +17,9 @@ _cd_init: lui $a3, IOBASE # Acknowledge all CD IRQs li $v0, 0x20943 # Set CD-ROM Delay/Size and common delay - sw $v0, SBUS_5($a3) + sw $v0, CD_DELAY_SIZE($a3) li $v0, 0x1325 - sw $v0, COM_DELAY($a3) + sw $v0, COM_DELAY_CFG($a3) li $v0, 1 sb $v0, CD_REG0($a3) @@ -71,10 +71,10 @@ _cd_init: la $v0, _cd_read_cb sw $0 , 0($v0) - lw $v0, DPCR($a3) + lw $v0, DMA_DPCR($a3) li $v1, 0xB000 or $v0, $v1 - sw $v0, DPCR($a3) + sw $v0, DMA_DPCR($a3) jal ExitCriticalSection nop diff --git a/libpsn00b/psxetc/dmacallback.s b/libpsn00b/psxetc/dmacallback.s index b2f86cf..8ea8ec0 100644 --- a/libpsn00b/psxetc/dmacallback.s +++ b/libpsn00b/psxetc/dmacallback.s @@ -46,13 +46,13 @@ DMACallback: lui $a2, IOBASE - lw $v0, DICR($a2) # Enable DMA interrupt + lw $v0, DMA_DICR($a2) # Enable DMA interrupt lui $v1, 0x1 sll $v1, $a0 or $v0, $v1 lui $v1, 0x80 or $v0, $v1 - sw $v0, DICR($a2) + sw $v0, DMA_DICR($a2) b .Lskip_remove nop @@ -67,7 +67,7 @@ DMACallback: sw $v1, 4($sp) lui $a2, IOBASE # Disable DMA interrupt - lw $v0, DICR($a2) + lw $v0, DMA_DICR($a2) lui $v1, 0x1 sll $v1, $a0 .set noat @@ -78,13 +78,13 @@ DMACallback: xor $v1, $at and $v0, $v1 .set at - sw $v0, DICR($a2) + sw $v0, DMA_DICR($a2) jal _dma_has_cb # Check if callbacks are present nop bnez $v0, .Lskip_remove nop - sw $0 , DICR($a2) + sw $0 , DMA_DICR($a2) jal GetInterruptCallback # Check if callback is the DMA handler li $a0, 3 @@ -143,7 +143,7 @@ _dma_handler: .Lhandler_loop: lui $a0, IOBASE - lw $v0, DICR($a0) + lw $v0, DMA_DICR($a0) li $v1, 24 addu $v1, $s0 srl $v0, $v1 @@ -166,9 +166,9 @@ _dma_handler: addi $s0, 1 lui $a0, IOBASE - lw $v0, DICR($a0) + lw $v0, DMA_DICR($a0) nop - sw $v0, DICR($a0) + sw $v0, DMA_DICR($a0) lw $ra, 0($sp) lw $s0, 4($sp) diff --git a/libpsn00b/psxetc/interruptcallback.s b/libpsn00b/psxetc/interruptcallback.s index 8e912d8..78e5e6e 100644 --- a/libpsn00b/psxetc/interruptcallback.s +++ b/libpsn00b/psxetc/interruptcallback.s @@ -16,25 +16,25 @@ InterruptCallback: beqz $a1, .Ldisable_irq nop - lw $v0, IMASK($a2) # Enable interrupt mask + lw $v0, IRQ_MASK($a2) # Enable interrupt mask li $v1, 1 sll $v1, $a0 or $v0, $v1 b .Lcont - sw $v0, IMASK($a2) + sw $v0, IRQ_MASK($a2) .Ldisable_irq: .set noat - lw $v0, IMASK($a2) # Disable interrupt mask + lw $v0, IRQ_MASK($a2) # Disable interrupt mask li $v1, 1 sll $v1, $a0 addiu $at, $0 , -1 xor $v1, $at .set at and $v0, $v1 - sw $v0, IMASK($a2) + sw $v0, IRQ_MASK($a2) .Lcont: diff --git a/libpsn00b/psxetc/isr.s b/libpsn00b/psxetc/isr.s index 00428a4..440be50 100644 --- a/libpsn00b/psxetc/isr.s +++ b/libpsn00b/psxetc/isr.s @@ -20,7 +20,7 @@ _global_isr: # changed elsewhere sometimes lui $a0, IOBASE # Get IRQ status - lw $v0, IMASK($a0) + lw $v0, IRQ_MASK($a0) nop srl $v0, $s1 # Check IRQ mask bit if set @@ -29,7 +29,7 @@ _global_isr: beqz $v0, .Lno_irq # Don't execute callback if IRQ not enabled nop - lw $v0, ISTAT($a0) + lw $v0, IRQ_STAT($a0) nop srl $v0, $s1 # Check IRQ status bit if set andi $v0, 0x1 @@ -39,12 +39,12 @@ _global_isr: lw $v1, 0($s0) # Load IRQ callback function nop - lw $v0, ISTAT($a0) # Acknowledge the IRQ (by writing a 0 bit) + lw $v0, IRQ_STAT($a0) # Acknowledge the IRQ (by writing a 0 bit) li $a1, 1 sll $a1, $s1 addiu $a2, $0 , -1 xor $a1, $a2 - sw $a1, ISTAT($a0) + sw $a1, IRQ_STAT($a0) beqz $v1, .Lno_irq # Don't execute if callback is not set nop diff --git a/libpsn00b/psxetc/restartcallback.s b/libpsn00b/psxetc/restartcallback.s index 151d78e..036a5a0 100644 --- a/libpsn00b/psxetc/restartcallback.s +++ b/libpsn00b/psxetc/restartcallback.s @@ -44,8 +44,8 @@ RestartCallback: addiu $a1, 1 lui $a0, IOBASE - sw $0 , ISTAT($a0) - sw $v0, IMASK($a0) + sw $0 , IRQ_STAT($a0) + sw $v0, IRQ_MASK($a0) lw $ra, 0($sp) addiu $sp, 4 diff --git a/libpsn00b/psxgpu/clearotagr.s b/libpsn00b/psxgpu/clearotagr.s index 3e888f1..832e54c 100644 --- a/libpsn00b/psxgpu/clearotagr.s +++ b/libpsn00b/psxgpu/clearotagr.s @@ -12,10 +12,10 @@ ClearOTagR: addi $v0, $a1, -1 sll $v0, 2 addu $a0, $v0 - sw $a0, D6_MADR($a2) + sw $a0, DMA6_MADR($a2) andi $a1, 0xffff - sw $a1, D6_BCR($a2) + sw $a1, DMA6_BCR($a2) lui $v0, 0x1100 addiu $v0, 2 jr $ra - sw $v0, D6_CHCR($a2) + sw $v0, DMA6_CHCR($a2) diff --git a/libpsn00b/psxgpu/drawotag.s b/libpsn00b/psxgpu/drawotag.s index ba771fc..595fcd5 100644 --- a/libpsn00b/psxgpu/drawotag.s +++ b/libpsn00b/psxgpu/drawotag.s @@ -25,12 +25,12 @@ DrawOTag: beqz $v0, .Lgpu_wait nop - sw $a0, D2_MADR($a3) # Set DMA base address to specified OT - sw $0 , D2_BCR($a3) + sw $a0, DMA2_MADR($a3) # Set DMA base address to specified OT + sw $0 , DMA2_BCR($a3) lui $v0, 0x0100 # Begin OT transfer! ori $v0, 0x0401 - sw $v0, D2_CHCR($a3) + sw $v0, DMA2_CHCR($a3) lw $ra, 0($sp) addiu $sp, 4 diff --git a/libpsn00b/psxgpu/drawsync.s b/libpsn00b/psxgpu/drawsync.s index 2e29381..b671b03 100644 --- a/libpsn00b/psxgpu/drawsync.s +++ b/libpsn00b/psxgpu/drawsync.s @@ -24,7 +24,7 @@ DrawSync: nop .Ldma_wait: - lw $v0, D2_CHCR($a0) + lw $v0, DMA2_CHCR($a0) nop srl $v0, 24 andi $v0, 0x1 @@ -59,7 +59,7 @@ DrawSync: .Lgetwords: - lw $v0, D2_BCR($a0) + lw $v0, DMA2_BCR($a0) nop jr $ra diff --git a/libpsn00b/psxgpu/drawsynccallback.s b/libpsn00b/psxgpu/drawsynccallback.s index 37c0375..2b2c172 100644 --- a/libpsn00b/psxgpu/drawsynccallback.s +++ b/libpsn00b/psxgpu/drawsynccallback.s @@ -64,7 +64,7 @@ _drawsync_handler: addiu $sp, -4 sw $ra, 0($sp) - lw $v0, D2_CHCR($a0) + lw $v0, DMA2_CHCR($a0) nop srl $v0, 24 andi $v0, 0x1 diff --git a/libpsn00b/psxgpu/loadimage.s b/libpsn00b/psxgpu/loadimage.s index 4a3b4e0..e2a5be5 100644 --- a/libpsn00b/psxgpu/loadimage.s +++ b/libpsn00b/psxgpu/loadimage.s @@ -56,12 +56,12 @@ LoadImage: sll $v1, 0x10 ori $v1, 0x8 - sw $a1, D2_MADR($s0) # Set DMA base address and transfer length - sw $v1, D2_BCR($s0) + sw $a1, DMA2_MADR($s0) # Set DMA base address and transfer length + sw $v1, DMA2_BCR($s0) lui $v0, 0x100 # Start DMA transfer ori $v0, 0x201 - sw $v0, D2_CHCR($s0) + sw $v0, DMA2_CHCR($s0) lw $ra, 0($sp) lw $s0, 4($sp) diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s index f469fbe..eae854c 100644 --- a/libpsn00b/psxgpu/resetgraph.s +++ b/libpsn00b/psxgpu/resetgraph.s @@ -42,10 +42,10 @@ ResetGraph: lui $v0, 0x3b33 # Enables DMA channel 6 (for ClearOTag) ori $v0, 0x3b33 # Enables DMA channel 2 - sw $v0, DPCR($a3) - sw $0 , DICR($a3) # Clear DICR (not needed) + sw $v0, DMA_DPCR($a3) + sw $0 , DMA_DICR($a3) # Clear DICR (not needed) - sw $0 , IMASK($a3) # Clear IRQ settings + sw $0 , IRQ_MASK($a3) # Clear IRQ settings la $v0, _hooks_installed # Set installed flag li $v1, 0x1 @@ -102,7 +102,7 @@ ResetGraph: # by previous calls) li $v0, 0x1d00 # Configure timer 1 as Hblank counter - sw $v0, T1_MODE($a3) # Set timer 1 value + sw $v0, TIM1_CTRL($a3) # Set timer 1 value beq $a0, 1, .Lgpu_init_1 nop @@ -116,7 +116,7 @@ ResetGraph: .Lgpu_init_1: - sw $0 , D2_CHCR($a3) # Stop any DMA + sw $0 , DMA2_CHCR($a3) # Stop any DMA .Lgpu_init_3: @@ -143,9 +143,9 @@ VSync: lw $s0, GP1($a3) .Lhwait_loop: # Get Hblank time - lw $v0, T1_CNT($a3) + lw $v0, TIM1_VALUE($a3) nop - lw $v1, T1_CNT($a3) + lw $v1, TIM1_VALUE($a3) nop bne $v0, $v1, .Lhwait_loop nop @@ -208,9 +208,9 @@ VSync: la $a2, _vsync_lasthblank .Lhwait2_loop: - lw $v0, T1_CNT($a3) + lw $v0, TIM1_VALUE($a3) nop - lw $v1, T1_CNT($a3) + lw $v1, TIM1_VALUE($a3) sw $v0, 0($a2) bne $v0, $v1, .Lhwait2_loop nop diff --git a/libpsn00b/psxgpu/storeimage.s b/libpsn00b/psxgpu/storeimage.s index 5d4c793..933b14c 100644 --- a/libpsn00b/psxgpu/storeimage.s +++ b/libpsn00b/psxgpu/storeimage.s @@ -54,8 +54,8 @@ StoreImage: sll $v1, 0x10 ori $v1, 0x8 - sw $a1, D2_MADR($s0) # Set DMA base address and transfer length - sw $v1, D2_BCR($s0) + sw $a1, DMA2_MADR($s0) # Set DMA base address and transfer length + sw $v1, DMA2_BCR($s0) .Lgpu_wait_2: # Wait for GPU to be ready for commands and DMA jal ReadGPUstat @@ -67,7 +67,7 @@ StoreImage: lui $v0, 0x100 # Start DMA transfer ori $v0, 0x200 - sw $v0, D2_CHCR($s0) + sw $v0, DMA2_CHCR($s0) lw $ra, 0($sp) lw $s0, 4($sp) diff --git a/libpsn00b/psxspu/spuinit.s b/libpsn00b/psxspu/spuinit.s index 42f302a..6966213 100644 --- a/libpsn00b/psxspu/spuinit.s +++ b/libpsn00b/psxspu/spuinit.s @@ -17,30 +17,25 @@ SpuInit: # Stop and mute everything - sh $0 , SPUCNT($v1) # Clear control settings + sh $0 , SPU_CTRL($v1) # Clear control settings jal SpuCtrlSync move $a0, $0 - sh $0 , SPU_MASTER_VOL($v1) # Clear master volume - sh $0 , SPU_MASTER_VOL+2($v1) + sh $0 , SPU_MASTER_VOL_L($v1) # Clear master volume + sh $0 , SPU_MASTER_VOL_R($v1) - sh $0 , SPU_REVERB_VOL($v1) # Clear reverb volume - sh $0 , SPU_REVERB_VOL+2($v1) + sh $0 , SPU_REVERB_VOL_L($v1) # Clear reverb volume + sh $0 , SPU_REVERB_VOL_R($v1) - sh $0 , SPU_CD_VOL($v1) # Clear CD volume - sh $0 , SPU_CD_VOL+2($v1) + sh $0 , SPU_CD_VOL_L($v1) # Clear CD volume + sh $0 , SPU_CD_VOL_R($v1) - sh $0 , SPU_EXT_VOL($v1) # Clear external audio volume - sh $0 , SPU_EXT_VOL+2($v1) + sh $0 , SPU_EXT_VOL_L($v1) # Clear external audio volume + sh $0 , SPU_EXT_VOL_R($v1) - sh $0 , SPU_FM_MODE($v1) # Turn off FM modes - sh $0 , SPU_FM_MODE+2($v1) - - sh $0 , SPU_NOISE_MODE($v1) # Turn off noise modes - sh $0 , SPU_NOISE_MODE+2($v1) - - sh $0 , SPU_REVERB_ON($v1) # Turn off reverb modes - sh $0 , SPU_REVERB_ON+2($v1) + sw $0 , SPU_FM_MODE($v1) # Turn off FM modes + sw $0 , SPU_NOISE_MODE($v1) # Turn off noise modes + sw $0 , SPU_REVERB_ON($v1) # Turn off reverb modes li $v0, 0xfffe sh $v0, SPU_REVERB_ADDR($v1) @@ -65,32 +60,28 @@ SpuInit: bgez $a2, .Lclear_voices nop - li $v0, 0xffff # Set all keys to off - sh $v0, SPU_KEY_OFF($v1) - sh $v0, SPU_KEY_OFF+2($v1) + addiu $v0, $0, -1 # Set all keys to off + sw $v0, SPU_KEY_OFF($v1) li $v0, 0x4 # Set SPU data transfer control - sh $v0, SPUDTCNT($v1) # (usually always 0x4) + sh $v0, SPU_DMA_CTRL($v1) # (usually always 0x4) - lw $v0, DPCR($v1) # Enable DMA channel 4 (SPU DMA) + lw $v0, DMA_DPCR($v1) # Enable DMA channel 4 (SPU DMA) lui $at, 0xb or $v0, $at - sw $v0, DPCR($v1) + sw $v0, DMA_DPCR($v1) li $v0, 0xC001 # Enable SPU - sh $v0, SPUCNT($v1) + sh $v0, SPU_CTRL($v1) jal SpuCtrlSync move $a0, $v0 li $v0, 0x3fff # Activate master volume - sh $v0, SPU_MASTER_VOL($v1) - sh $v0, SPU_MASTER_VOL+2($v1) - - sh $v0, SPU_CD_VOL($v1) # Activate CD volume - sh $v0, SPU_CD_VOL+2($v1) + sh $v0, SPU_MASTER_VOL_L($v1) + sh $v0, SPU_MASTER_VOL_R($v1) - sh $v0, SPU_CD_VOL($v1) # Activate CD volume - sh $v0, SPU_CD_VOL+2($v1) + sh $v0, SPU_CD_VOL_L($v1) # Activate CD volume + sh $v0, SPU_CD_VOL_R($v1) lw $ra, 0($sp) addiu $sp, 4 @@ -108,7 +99,7 @@ SpuCtrlSync: lui $v1, IOBASE andi $a0, 0x3f .Lctrl_wait: - lhu $v0, SPUSTAT($v1) # Get SPUSTAT value + lhu $v0, SPU_STAT($v1) # Get SPUSTAT value nop andi $v0, 0x3f bne $v0, $a0, .Lctrl_wait # Wait until SPUCNT and SPUSTAT are equal @@ -123,7 +114,7 @@ SpuCtrlSync: .type SpuWait, @function SpuWait: lui $v0, IOBASE - lhu $v0, SPUSTAT($v0) + lhu $v0, SPU_STAT($v0) nop andi $v0, 0x400 bnez $v0, SpuWait diff --git a/libpsn00b/psxspu/spureverbon.s b/libpsn00b/psxspu/spureverbon.s index 852bff3..635fac3 100644 --- a/libpsn00b/psxspu/spureverbon.s +++ b/libpsn00b/psxspu/spureverbon.s @@ -11,6 +11,6 @@ SpuReverbOn: lui $v1, IOBASE li $v0, 1 sll $v0, $a0 - sh $v0, SPU_REVERB_ON($v1) + sw $v0, SPU_REVERB_ON($v1) jr $ra nop
\ No newline at end of file diff --git a/libpsn00b/psxspu/spusetreverb.s b/libpsn00b/psxspu/spusetreverb.s index 993b166..8257812 100644 --- a/libpsn00b/psxspu/spusetreverb.s +++ b/libpsn00b/psxspu/spusetreverb.s @@ -10,11 +10,12 @@ SpuSetReverb: addiu $sp, -4 sw $ra, 0($sp) - - lhu $v0, SPUCNT($v1) + + lui $v1, IOBASE + lhu $v0, SPU_CTRL($v1) nop ori $v0, 0x80 # Enable reverb - sh $v0, SPUCNT($v1) + sh $v0, SPU_CTRL($v1) jal SpuCtrlSync move $a0, $v0 diff --git a/libpsn00b/psxspu/spusetreverbaddr.s b/libpsn00b/psxspu/spusetreverbaddr.s index 6ddbf44..089a91a 100644 --- a/libpsn00b/psxspu/spusetreverbaddr.s +++ b/libpsn00b/psxspu/spusetreverbaddr.s @@ -8,7 +8,7 @@ .global SpuSetReverbAddr .type SpuSetReverbAddr, @function SpuSetReverbAddr: - lui $a3, 0x1f80 + lui $a3, IOBASE srl $a0, 3 sh $a0, SPU_REVERB_ADDR($a3) jr $ra @@ -18,8 +18,8 @@ SpuSetReverbAddr: .global SpuSetReverbVolume .type SpuSetReverbVolume, @function SpuSetReverbVolume: - lui $a3, 0x1f80 - sh $a0, SPU_REVERB_VOL($a3) - sh $a1, SPU_REVERB_VOL+2($a3) + lui $a3, IOBASE + sh $a0, SPU_REVERB_VOL_L($a3) + sh $a1, SPU_REVERB_VOL_R($a3) jr $ra nop
\ No newline at end of file diff --git a/libpsn00b/psxspu/transfer.s b/libpsn00b/psxspu/transfer.s index 5b62c28..adcdb33 100644 --- a/libpsn00b/psxspu/transfer.s +++ b/libpsn00b/psxspu/transfer.s @@ -46,10 +46,10 @@ SpuWrite: lui $a3, IOBASE - lhu $v0, SPUCNT($a3) # Set transfer mode to Stop + lhu $v0, SPU_CTRL($a3) # Set transfer mode to Stop nop andi $v0, 0xffcf - sh $v0, SPUCNT($a3) + sh $v0, SPU_CTRL($a3) jal SpuCtrlSync move $a0, $v0 @@ -58,10 +58,10 @@ SpuWrite: nop sh $v1, SPU_ADDR($a3) - lhu $v0, SPUCNT($a3) # Set transfer mode to DMA write + lhu $v0, SPU_CTRL($a3) # Set transfer mode to DMA write nop ori $v0, 0x20 - sh $v0, SPUCNT($a3) + sh $v0, SPU_CTRL($a3) #jal SpuCtrlSync # Locks up on most emulators (bit 5 in #move $a0, $v0 # SPUSTAT likely not updating, seems to # be okay to not wait for it on real HW) @@ -69,13 +69,13 @@ SpuWrite: lw $a0, 4($sp) .Ldma_wait: # Wait for SPU to be ready for DMA - lhu $v0, SPUSTAT($a3) + lhu $v0, SPU_STAT($a3) nop andi $v0, 0x400 # Bit 8 in SPUSTAT never changes to 1 on bnez $v0, .Ldma_wait # emulators so use bit 10 instead nop - sw $a0, D4_MADR($a3) # Set DMA source address + sw $a0, DMA4_MADR($a3) # Set DMA source address li $v0, 0x10 # 16 words per block (64 bytes) addiu $a1, 63 # Add by 63 to ensure all bytes get sent @@ -83,11 +83,11 @@ SpuWrite: andi $a1, 0xffff sll $a1, 16 or $v0, $a1 - sw $v0, D4_BCR($a3) + sw $v0, DMA4_BCR($a3) lui $v0, 0x0100 # Commence transfer ori $v0, 0x0201 - sw $v0, D4_CHCR($a3) + sw $v0, DMA4_CHCR($a3) lw $ra, 0($sp) addiu $sp, 8 |
