From aca79b2a75c9a6106bc0047f767a475a2c3aaf8e Mon Sep 17 00:00:00 2001 From: spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> Date: Wed, 9 Feb 2022 22:59:16 +0100 Subject: Rename hwregs_a definitions, add hwregs_c, fix io/pads --- examples/io/pads/main.c | 57 +++++++++++++++------------ examples/io/pads/spi.c | 103 +++++++++++++++++++++--------------------------- examples/io/pads/spi.h | 15 +++++-- 3 files changed, 89 insertions(+), 86 deletions(-) (limited to 'examples/io') 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 @@ -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 #include #include +#include #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 #include -// 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 -- cgit v1.2.3 From 69a364049a3958396d2d083c660591dad9ec257d Mon Sep 17 00:00:00 2001 From: spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> Date: Sun, 27 Feb 2022 19:45:38 +0100 Subject: Rename some hwregs_c.h and hwregs.a definitions --- examples/graphics/rgb24/bunpattern.png | Bin 0 -> 59932 bytes examples/io/pads/spi.c | 6 +++--- examples/system/timer/main.c | 5 +++-- libpsn00b/include/hwregs_a.h | 22 +++++++++++----------- libpsn00b/include/hwregs_c.h | 10 +++++----- libpsn00b/psxgpu/clearotagr.s | 2 +- libpsn00b/psxgpu/drawotag.s | 4 ++-- libpsn00b/psxgpu/drawprim.s | 4 ++-- libpsn00b/psxgpu/drawsynccallback.s | 2 +- libpsn00b/psxgpu/loadimage.s | 14 +++++++------- libpsn00b/psxgpu/putdispenv.s | 8 ++++---- libpsn00b/psxgpu/putdispenvraw.s | 10 +++++----- libpsn00b/psxgpu/readgpustat.s | 4 ++-- libpsn00b/psxgpu/resetgraph.s | 28 ++++++++++++++-------------- libpsn00b/psxgpu/setdispmask.s | 4 ++-- libpsn00b/psxgpu/setvideomode.s | 2 +- libpsn00b/psxgpu/storeimage.s | 14 +++++++------- 17 files changed, 70 insertions(+), 69 deletions(-) create mode 100644 examples/graphics/rgb24/bunpattern.png (limited to 'examples/io') diff --git a/examples/graphics/rgb24/bunpattern.png b/examples/graphics/rgb24/bunpattern.png new file mode 100644 index 0000000..61524f8 Binary files /dev/null and b/examples/graphics/rgb24/bunpattern.png differ diff --git a/examples/io/pads/spi.c b/examples/io/pads/spi.c index 05a0e59..43b5bc3 100644 --- a/examples/io/pads/spi.c +++ b/examples/io/pads/spi.c @@ -179,12 +179,12 @@ SPI_Request *SPI_CreateRequest(void) { } void SPI_SetPollRate(uint32_t value) { - TIM_CTRL(2) = 0x0258; // CLK/8 input, IRQ on reload, disable one-shot IRQ + TIMER_CTRL(2) = 0x0258; // CLK/8 input, IRQ on reload, disable one-shot IRQ if (value < 65) - TIM_RELOAD(2) = 0xffff; + TIMER_RELOAD(2) = 0xffff; else - TIM_RELOAD(2) = (F_CPU / 8) / value; + TIMER_RELOAD(2) = (F_CPU / 8) / value; } void SPI_Init(SPI_Callback callback) { diff --git a/examples/system/timer/main.c b/examples/system/timer/main.c index 8153581..eb62712 100644 --- a/examples/system/timer/main.c +++ b/examples/system/timer/main.c @@ -3,6 +3,7 @@ #include #include #include +#include /* OT and Packet Buffer sizes */ #define OT_LEN 256 @@ -34,7 +35,7 @@ void display(); volatile int timer_calls = 0; -volatile short *timer2_ctrl = (short*)0x1F801124; + void timer_func() { timer_calls++; @@ -74,7 +75,7 @@ int main() { //counter = 5163000/560; SetRCnt(RCntCNT2, counter, RCntMdINTR); - *timer2_ctrl = 0x1E58; + TIMER_CTRL(2) = 0x1E58; InterruptCallback(6, timer_func); StartRCnt(RCntCNT2); ChangeClearRCnt(2, 0); diff --git a/libpsn00b/include/hwregs_a.h b/libpsn00b/include/hwregs_a.h index 4d0bade..8a504f5 100644 --- a/libpsn00b/include/hwregs_a.h +++ b/libpsn00b/include/hwregs_a.h @@ -8,8 +8,8 @@ ## GPU -.set GP0, 0x1810 # Also GPUREAD -.set GP1, 0x1814 # Also GPUSTAT +.set GPU_GP0, 0x1810 # Also GPUREAD +.set GPU_GP1, 0x1814 # Also GPUSTAT ## CD drive @@ -123,17 +123,17 @@ ## Timers -.set TIM0_VALUE, 0x1100 -.set TIM0_CTRL, 0x1104 -.set TIM0_RELOAD, 0x1108 +.set TIMER0_VALUE, 0x1100 +.set TIMER0_CTRL, 0x1104 +.set TIMER0_RELOAD, 0x1108 -.set TIM1_VALUE, 0x1110 -.set TIM1_CTRL, 0x1114 -.set TIM1_RELOAD, 0x1118 +.set TIMER1_VALUE, 0x1110 +.set TIMER1_CTRL, 0x1114 +.set TIMER1_RELOAD, 0x1118 -.set TIM2_VALUE, 0x1120 -.set TIM2_CTRL, 0x1124 -.set TIM2_RELOAD, 0x1128 +.set TIMER2_VALUE, 0x1120 +.set TIMER2_CTRL, 0x1124 +.set TIMER2_RELOAD, 0x1128 ## Memory control diff --git a/libpsn00b/include/hwregs_c.h b/libpsn00b/include/hwregs_c.h index 4222a22..e533c56 100644 --- a/libpsn00b/include/hwregs_c.h +++ b/libpsn00b/include/hwregs_c.h @@ -19,8 +19,8 @@ /* GPU */ -#define GP0 _MMIO32(0x1f801810) -#define GP1 _MMIO32(0x1f801814) +#define GPU_GP0 _MMIO32(0x1f801810) +#define GPU_GP1 _MMIO32(0x1f801814) /* CD drive */ @@ -109,9 +109,9 @@ /* 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)) +#define TIMER_VALUE(N) _MMIO32(0x1f801100 + 16 * (N)) +#define TIMER_CTRL(N) _MMIO32(0x1f801104 + 16 * (N)) +#define TIMER_RELOAD(N) _MMIO32(0x1f801108 + 16 * (N)) /* Memory control */ diff --git a/libpsn00b/psxgpu/clearotagr.s b/libpsn00b/psxgpu/clearotagr.s index 832e54c..562cad4 100644 --- a/libpsn00b/psxgpu/clearotagr.s +++ b/libpsn00b/psxgpu/clearotagr.s @@ -8,7 +8,7 @@ .global ClearOTagR .type ClearOTagR, @function ClearOTagR: - lui $a2, 0x1f80 + lui $a2, IOBASE addi $v0, $a1, -1 sll $v0, 2 addu $a0, $v0 diff --git a/libpsn00b/psxgpu/drawotag.s b/libpsn00b/psxgpu/drawotag.s index 595fcd5..3cb0db0 100644 --- a/libpsn00b/psxgpu/drawotag.s +++ b/libpsn00b/psxgpu/drawotag.s @@ -11,11 +11,11 @@ DrawOTag: addiu $sp, -4 sw $ra, 0($sp) - lui $a3, 0x1f80 # I/O segment base + lui $a3, IOBASE # I/O segment base lui $v0, 0x0400 # Set DMA direction to CPUtoGPU ori $v0, 0x2 - sw $v0, GP1($a3) + sw $v0, GPU_GP1($a3) .Lgpu_wait: # Wait for GPU to be ready for commands & DMA jal ReadGPUstat diff --git a/libpsn00b/psxgpu/drawprim.s b/libpsn00b/psxgpu/drawprim.s index de5afbd..d62c202 100644 --- a/libpsn00b/psxgpu/drawprim.s +++ b/libpsn00b/psxgpu/drawprim.s @@ -18,7 +18,7 @@ DrawPrim: lui $a3, IOBASE lui $v0, 0x0400 # Set transfer direction to off - sw $v0, GP1($a3) + sw $v0, GPU_GP1($a3) move $a0, $s0 lbu $a1, 3($a0) # Get length of primitive packet @@ -28,7 +28,7 @@ DrawPrim: .Ltransfer_loop: lw $v0, 0($a0) addiu $a0, 4 - sw $v0, GP0($a3) + sw $v0, GPU_GP0($a3) bgtz $a1, .Ltransfer_loop addiu $a1, -1 diff --git a/libpsn00b/psxgpu/drawsynccallback.s b/libpsn00b/psxgpu/drawsynccallback.s index 2b2c172..22cfb7d 100644 --- a/libpsn00b/psxgpu/drawsynccallback.s +++ b/libpsn00b/psxgpu/drawsynccallback.s @@ -84,7 +84,7 @@ _drawsync_handler: lw $v1, 0($v1) lui $v0, 0x0400 # Set DMA direction to off - sw $v0, GP1($a0) + sw $v0, GPU_GP1($a0) jalr $v1 nop diff --git a/libpsn00b/psxgpu/loadimage.s b/libpsn00b/psxgpu/loadimage.s index e2a5be5..45f152f 100644 --- a/libpsn00b/psxgpu/loadimage.s +++ b/libpsn00b/psxgpu/loadimage.s @@ -17,7 +17,7 @@ LoadImage: sw $ra, 0($sp) sw $s0, 4($sp) - lui $s0, 0x1f80 # Set I/O segment base address + lui $s0, IOBASE # Set I/O segment base address .Lgpu_wait: # Wait for GPU to be ready for commands and DMA jal ReadGPUstat @@ -31,21 +31,21 @@ LoadImage: nop lui $v0, 0x400 # Set DMA direction to off - sw $v0, GP1($s0) + sw $v0, GPU_GP1($s0) lui $v0, 0x0100 # Clear GPU cache - sw $v0, GP0($s0) + sw $v0, GPU_GP0($s0) lui $v1, 0xa000 # Load image to VRAM - sw $v1, GP0($s0) + sw $v1, GPU_GP0($s0) lw $v0, RECT_x($a0) # Set XY and dimensions of image lw $v1, RECT_w($a0) - sw $v0, GP0($s0) - sw $v1, GP0($s0) + sw $v0, GPU_GP0($s0) + sw $v1, GPU_GP0($s0) lui $v0, 0x400 # Set DMA direction to CPUtoVRAM ori $v0, 0x2 - sw $v0, GP1($s0) + sw $v0, GPU_GP1($s0) lhu $v0, RECT_w($a0) # Get rectangle size lhu $v1, RECT_h($a0) diff --git a/libpsn00b/psxgpu/putdispenv.s b/libpsn00b/psxgpu/putdispenv.s index 4baa20e..fc09454 100644 --- a/libpsn00b/psxgpu/putdispenv.s +++ b/libpsn00b/psxgpu/putdispenv.s @@ -102,7 +102,7 @@ PutDispEnv: or $a2, $v0 lui $v0, 0x0600 or $v0, $a2 - sw $v0, GP1($a3) + sw $v0, GPU_GP1($a3) # Vertical resolution @@ -127,7 +127,7 @@ PutDispEnv: or $v1, $a2 lui $v0, 0x0700 or $v1, $v0 - sw $v1, GP1($a3) + sw $v1, GPU_GP1($a3) # Video mode @@ -159,7 +159,7 @@ PutDispEnv: lui $v0, 0x800 # Apply mode or $a1, $v0 - sw $a1, GP1($a3) + sw $a1, GPU_GP1($a3) lhu $v0, DISP_dx($a0) # Set VRAM XY offset lhu $v1, DISP_dy($a0) @@ -171,4 +171,4 @@ PutDispEnv: or $v0, $v1 jr $ra - sw $v0, GP1($a3) + sw $v0, GPU_GP1($a3) diff --git a/libpsn00b/psxgpu/putdispenvraw.s b/libpsn00b/psxgpu/putdispenvraw.s index 157150d..747796f 100644 --- a/libpsn00b/psxgpu/putdispenvraw.s +++ b/libpsn00b/psxgpu/putdispenvraw.s @@ -19,7 +19,7 @@ PutDispEnvRaw: sw $ra, 0($sp) sw $s0, 4($sp) - lui $s0, 0x1f80 + lui $s0, IOBASE lh $at, DISP_vxpos($a0) # Set horizontal display range li $v0, 608 @@ -30,7 +30,7 @@ PutDispEnvRaw: or $v0, $v1 lui $v1, 0x600 or $v1, $v0 - sw $v1, GP1($s0) + sw $v1, GPU_GP1($s0) lh $at, DISP_vypos($a0) # Set vertical display range (for NTSC) li $v1, 120 # (values differet for PAL modes) @@ -47,12 +47,12 @@ PutDispEnvRaw: or $v0, $at lui $at, 0x700 or $v0, $at - sw $v0, GP1($s0) + sw $v0, GPU_GP1($s0) lw $v0, DISP_mode($a0) # Set video mode lui $at, 0x800 or $v0, $at - sw $v0, GP1($s0) + sw $v0, GPU_GP1($s0) lhu $v0, DISP_fbx($a0) # Set VRAM XY offset lhu $v1, DISP_fby($a0) @@ -62,7 +62,7 @@ PutDispEnvRaw: or $v0, $v1 lui $v1, 0x500 or $v0, $v1 - sw $v0, GP1($s0) + sw $v0, GPU_GP1($s0) lw $ra, 0($sp) lw $s0, 4($sp) diff --git a/libpsn00b/psxgpu/readgpustat.s b/libpsn00b/psxgpu/readgpustat.s index c587cfb..ffff4d7 100644 --- a/libpsn00b/psxgpu/readgpustat.s +++ b/libpsn00b/psxgpu/readgpustat.s @@ -8,7 +8,7 @@ .global ReadGPUstat .type ReadGPUstat, @function ReadGPUstat: - lui $v0, 0x1f80 - lw $v0, GP1($v0) + lui $v0, IOBASE + lw $v0, GPU_GP1($v0) jr $ra nop diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s index eae854c..6327f02 100644 --- a/libpsn00b/psxgpu/resetgraph.s +++ b/libpsn00b/psxgpu/resetgraph.s @@ -38,7 +38,7 @@ ResetGraph: nop # interrupts enabled when transferring # execution to the loaded program - lui $a3, 0x1f80 # Base address for I/O + lui $a3, IOBASE # Base address for I/O lui $v0, 0x3b33 # Enables DMA channel 6 (for ClearOTag) ori $v0, 0x3b33 # Enables DMA channel 2 @@ -84,9 +84,9 @@ ResetGraph: .Lskip_hook_init: - lui $a3, 0x1f80 + lui $a3, IOBASE - lw $v0, GP1($a3) # Get video standard + lw $v0, GPU_GP1($a3) # Get video standard lui $v1, 0x0010 and $v0, $v1 la $v1, _gpu_standard @@ -98,18 +98,18 @@ ResetGraph: lw $a0, 4($sp) # Get argument value - lui $a3, 0x1f80 # Set base I/O again (likely destroyed + lui $a3, IOBASE # Set base I/O again (likely destroyed # by previous calls) li $v0, 0x1d00 # Configure timer 1 as Hblank counter - sw $v0, TIM1_CTRL($a3) # Set timer 1 value + sw $v0, TIMER1_CTRL($a3) # Set timer 1 value beq $a0, 1, .Lgpu_init_1 nop beq $a0, 3, .Lgpu_init_3 nop - sw $0 , GP1($a3) # Reset the GPU + sw $0 , GPU_GP1($a3) # Reset the GPU b .Linit_done nop @@ -121,7 +121,7 @@ ResetGraph: .Lgpu_init_3: li $v0, 0x1 # Reset the command buffer - sw $v0, GP1($a3) + sw $v0, GPU_GP1($a3) .Linit_done: @@ -140,12 +140,12 @@ VSync: sw $s0, 4($sp) lui $a3, IOBASE # Get GPU status (for interlace sync) - lw $s0, GP1($a3) + lw $s0, GPU_GP1($a3) .Lhwait_loop: # Get Hblank time - lw $v0, TIM1_VALUE($a3) + lw $v0, TIMER1_VALUE($a3) nop - lw $v1, TIM1_VALUE($a3) + lw $v1, TIMER1_VALUE($a3) nop bne $v0, $v1, .Lhwait_loop nop @@ -189,14 +189,14 @@ VSync: lui $a3, IOBASE # Interlace wait logic - lw $v0, GP1($a3) + lw $v0, GPU_GP1($a3) nop xor $v0, $s0, $v0 bltz $v0, .Lhblank_exit lui $a0, 0x8000 .Linterlace_wait: - lw $v0, GP1($a3) + lw $v0, GPU_GP1($a3) nop xor $v0, $s0, $v0 and $v0, $a0 @@ -208,9 +208,9 @@ VSync: la $a2, _vsync_lasthblank .Lhwait2_loop: - lw $v0, TIM1_VALUE($a3) + lw $v0, TIMER1_VALUE($a3) nop - lw $v1, TIM1_VALUE($a3) + lw $v1, TIMER1_VALUE($a3) sw $v0, 0($a2) bne $v0, $v1, .Lhwait2_loop nop diff --git a/libpsn00b/psxgpu/setdispmask.s b/libpsn00b/psxgpu/setdispmask.s index 77ceb04..d79006c 100644 --- a/libpsn00b/psxgpu/setdispmask.s +++ b/libpsn00b/psxgpu/setdispmask.s @@ -8,12 +8,12 @@ .global SetDispMask .type SetDispMask, @function SetDispMask: - lui $v1, 0x1f80 + lui $v1, IOBASE andi $a0, 0x1 lui $v0, 0x300 ori $v0, 0x1 sub $v0, $a0 - sw $v0, GP1($v1) + sw $v0, GPU_GP1($v1) jr $ra nop diff --git a/libpsn00b/psxgpu/setvideomode.s b/libpsn00b/psxgpu/setvideomode.s index 4395f0a..b89b285 100644 --- a/libpsn00b/psxgpu/setvideomode.s +++ b/libpsn00b/psxgpu/setvideomode.s @@ -41,7 +41,7 @@ SetVideoMode: lui $v0, 0x800 # Apply new mode or $a1, $v0 lui $v0, IOBASE - sw $a1, GP1($v0) + sw $a1, GPU_GP1($v0) lw $ra, 0($sp) addiu $sp, 4 diff --git a/libpsn00b/psxgpu/storeimage.s b/libpsn00b/psxgpu/storeimage.s index 933b14c..554e83c 100644 --- a/libpsn00b/psxgpu/storeimage.s +++ b/libpsn00b/psxgpu/storeimage.s @@ -17,7 +17,7 @@ StoreImage: sw $ra, 0($sp) sw $s0, 4($sp) - lui $s0, 0x1f80 # Set I/O segment base address + lui $s0, IOBASE # Set I/O segment base address .Lgpu_wait: # Wait for GPU to be ready for commands and DMA jal ReadGPUstat @@ -29,21 +29,21 @@ StoreImage: nop lui $v0, 0x400 # Set DMA direction to off - sw $v0, GP1($s0) + sw $v0, GPU_GP1($s0) lui $v0, 0x0100 # Clear GPU cache - sw $v0, GP0($s0) + sw $v0, GPU_GP0($s0) lui $v1, 0xc000 # Store image from VRAM - sw $v1, GP0($s0) + sw $v1, GPU_GP0($s0) lw $v0, RECT_x($a0) # Set XY and dimensions of image lw $v1, RECT_w($a0) - sw $v0, GP0($s0) - sw $v1, GP0($s0) + sw $v0, GPU_GP0($s0) + sw $v1, GPU_GP0($s0) lui $v0, 0x400 # Set DMA direction to VRAMtoCPU ori $v0, 0x3 - sw $v0, GP1($s0) + sw $v0, GPU_GP1($s0) lhu $v0, RECT_w($a0) # Get rectangle size lhu $v1, RECT_h($a0) -- cgit v1.2.3 From 6174931fe58b1dc0fc64029dbe3abefc81aa67d5 Mon Sep 17 00:00:00 2001 From: spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> Date: Sun, 27 Feb 2022 23:54:39 +0100 Subject: Refactor io/system573, switch to MSVC for CI builds --- .github/workflows/build.yml | 6 +- CHANGELOG.md | 36 ++++++ CMakePresets.json | 2 +- cpack/setup.cmake | 2 +- examples/io/system573/iso.xml | 20 +++- examples/io/system573/k573io.c | 123 +++++++++++++++++++ examples/io/system573/k573io.h | 258 ++++++++++++++++++++++++++++++++++++++++ examples/io/system573/main.c | 264 ++++++++++------------------------------- tools/CMakeLists.txt | 2 +- 9 files changed, 503 insertions(+), 210 deletions(-) create mode 100644 examples/io/system573/k573io.c create mode 100644 examples/io/system573/k573io.h (limited to 'examples/io') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a2a5510..b2ca311 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -108,7 +108,7 @@ jobs: - name: Install prerequisites run: | - pacman -S --noconfirm mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc + pacman -S --noconfirm mingw-w64-x86_64-ninja - name: Fetch repo contents uses: actions/checkout@v2 @@ -118,7 +118,7 @@ jobs: - name: Build and package PSn00bSDK run: | - cmake --preset ci -S sdk -DPSN00BSDK_TC=${{ github.workspace }}\gcc\windows + cmake --preset ci -S sdk -G "Visual Studio 16 2019" -DPSN00BSDK_TC=${{ github.workspace }}\gcc\windows cmake --build build cmake --build build -t package @@ -162,7 +162,7 @@ jobs: - name: Build and package PSn00bSDK run: | - cmake --preset ci -S sdk -DPSN00BSDK_TC=${{ github.workspace }}/gcc/linux + cmake --preset ci -S sdk -G "Ninja" -DPSN00BSDK_TC=${{ github.workspace }}/gcc/linux cmake --build build cmake --build build -t package diff --git a/CHANGELOG.md b/CHANGELOG.md index 0203265..b8a57b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,42 @@ to ensure the changelog can be parsed correctly. ------------------------------------------------------------------------------- +## 2022-02-27: 0.19 + +spicyjpeg: + +- libpsn00b: Added `hwregs_c.h` header and renamed some registers in + `hwregs_a.h`. Added `assert()` as a proper macro. + +- psxpress: Added new MDEC library. + +- psxspu: Fixed critical bug in `SpuSetReverb()`. + +- psxetc: Fixed minor typos and bugs in `dlfcn.h`. Replaced `DL_CALL()` macro + with `DL_PRE_CALL()`. + +- psxapi: Rewritten all BIOS API stubs using a Python script and a JSON list, + both of which are included in the library's source directory. + +- examples: Updated `io/system573` with bugfixed I/O board code and separated + the APIs into a separate source file. Fixed timing bugs in `io/pads`. + +- mkpsxiso: Switched back to the master repository. The `dumpsxiso` command is + now included in PSn00bSDK installations. + +- Added `psn00bsdk_target_incbin()` and `psn00bsdk_target_incbin_a()` CMake + functions for quickly embedding binary files into executables and libraries. + The examples have been modified to use this function where applicable. + +- Added `LIBPSN00B_GENERATOR` CMake option to allow the host-side tools to be + compiled with MSVC or Xcode while still using Ninja or `make` to build the + libraries and examples. This is required as neither MSBuild nor Xcode support + custom toolchains. + +- Updated `LICENSE.md` with additional license information as well as a full + copy of the GPLv2 and GPLv3 (under which `mkpsxiso` and GCC are licensed + respectively). + ## 2022-01-17 Lameguy64: diff --git a/CMakePresets.json b/CMakePresets.json index 822d773..b103270 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -36,7 +36,7 @@ "cacheVariables": { "CMAKE_BUILD_TYPE": "Release", "BUNDLE_TOOLCHAIN": "ON", - "MKPSXISO_NO_LIBFLAC": "ON", + "LIBPSN00B_GENERATOR": "Ninja", "PSN00BSDK_TARGET": "$env{GCC_TARGET}", "PSN00BSDK_GIT_TAG": "$env{GITHUB_REF_NAME}", "PSN00BSDK_GIT_COMMIT": "$env{GITHUB_SHA}" diff --git a/cpack/setup.cmake b/cpack/setup.cmake index a5d71ff..a65055d 100644 --- a/cpack/setup.cmake +++ b/cpack/setup.cmake @@ -89,7 +89,7 @@ if(NOT DEFINED CPACK_GENERATOR) # TODO: add a macOS installer and related options set(CPACK_GENERATOR ZIP) elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(CPACK_GENERATOR ZIP DEB RPM) + set(CPACK_GENERATOR ZIP DEB) else() set(CPACK_GENERATOR ZIP) endif() diff --git a/examples/io/system573/iso.xml b/examples/io/system573/iso.xml index 09b4d85..0bb84d5 100644 --- a/examples/io/system573/iso.xml +++ b/examples/io/system573/iso.xml @@ -16,16 +16,26 @@ + + + + diff --git a/examples/io/system573/k573io.c b/examples/io/system573/k573io.c new file mode 100644 index 0000000..a8748d6 --- /dev/null +++ b/examples/io/system573/k573io.c @@ -0,0 +1,123 @@ +/* + * PSn00bSDK Konami System 573 example (I/O driver) + * (C) 2022 spicyjpeg - MPL licensed + * + * Note that this is far from being a complete driver. It currently lacks: + * - ATAPI driver + * - Flash erasing/writing APIs + * - JVS bus APIs + * - Functions for accessing the digital I/O board's MP3 decoder + */ + +#include +#include + +#include "k573io.h" + +K573_IOBoardType _board_type = IO_TYPE_ANALOG; + +/* I/O board light control */ + +static void _k573_set_lights_analog(uint32_t lights) { + uint32_t bits = 0xffffffff; + + bits ^= (lights & 0x01010101) << 7; // Lamp n*8+0 -> bit n*8+7 + bits ^= (lights & 0x02020202) << 5; // Lamp n*8+1 -> bit n*8+6 + bits ^= (lights & 0x04040404) >> 1; // Lamp n*8+2 -> bit n*8+1 + bits ^= (lights & 0x08080808) >> 3; // Lamp n*8+3 -> bit n*8+0 + bits ^= (lights & 0x10101010) << 1; // Lamp n*8+4 -> bit n*8+5 + bits ^= (lights & 0x20202020) >> 1; // Lamp n*8+5 -> bit n*8+4 + bits ^= (lights & 0x40404040) >> 3; // Lamp n*8+6 -> bit n*8+3 + bits ^= (lights & 0x80808080) >> 5; // Lamp n*8+7 -> bit n*8+2 + + K573_IO_BOARD[ANALOG_IO_REG_LIGHTS0] = (bits) & 0xff; + K573_IO_BOARD[ANALOG_IO_REG_LIGHTS1] = (bits >> 8) & 0xff; + K573_IO_BOARD[ANALOG_IO_REG_LIGHTS2] = (bits >> 16) & 0xff; + K573_IO_BOARD[ANALOG_IO_REG_LIGHTS3] = (bits >> 24) & 0xff; +} + +// This function controls light outputs on digital I/O boards (i.e. the ones +// that also include MP3 playback hardware, used by most Bemani games). +// TODO: test this on real hardware -- it might not work if lights are handled +// by the board's FPGA, which requires a binary blob... +static void _k573_set_lights_digital(uint32_t lights) { + uint32_t bits = 0xffffffff; + + bits ^= (lights & 0x11111111); // Lamp n*4+0 -> bit n*4+0 + bits ^= (lights & 0x22222222) << 1; // Lamp n*4+1 -> bit n*4+2 + bits ^= (lights & 0x44444444) << 1; // Lamp n*4+2 -> bit n*4+3 + bits ^= (lights & 0x88888888) >> 2; // Lamp n*4+3 -> bit n*4+1 + + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS0] = ((bits) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS1] = ((bits >> 4) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS2] = ((bits >> 8) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS3] = ((bits >> 12) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS4] = ((bits >> 16) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS5] = ((bits >> 20) & 0xf) << 12; + //K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS6] = ((bits >> 24) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS7] = ((bits >> 28) & 0xf) << 12; +} + +static const void (*_k573_set_lights[])(uint32_t) = { + &_k573_set_lights_analog, + &_k573_set_lights_digital +}; + +/* Public API */ + +uint32_t K573_GetJAMMAInputs(void) { + uint32_t inputs; + + inputs = K573_IO_CHIP[IO_REG_IN2]; + inputs |= ((K573_IO_CHIP[IO_REG_IN3_LOW] >> 8) & 0x0f) << 16; + inputs |= ((K573_IO_CHIP[IO_REG_IN3_HIGH] >> 8) & 0x0f) << 20; + inputs |= ((K573_IO_CHIP[IO_REG_IN1_HIGH] >> 8) & 0x1f) << 24; + inputs |= (K573_IO_CHIP[IO_REG_IN1_LOW] & 0x07) << 29; + + return inputs; +} + +void K573_SetLights(uint32_t lights) { + if (_board_type > IO_TYPE_DIGITAL) + return; + + _k573_set_lights[_board_type](lights); +} + +void K573_SetBoardType(K573_IOBoardType type) { + _k573_set_lights[_board_type](0); + _board_type = type; +} + +/*void K573_DDRStageCommand(uint32_t value, uint32_t length) { + uint32_t last_bit = 0; + uint32_t mask = 1; + + for (uint32_t i = 0; i < length; i++) { + uint32_t bit = DDR_LIGHT_P1_MUX_DATA | DDR_LIGHT_P2_MUX_DATA; + if (value & mask) + bit = 0; + + K573_SetLights(last_bit | DDR_LIGHT_P1_MUX_CLK | DDR_LIGHT_P2_MUX_CLK); + _k573_delay_hblanks(20); + K573_SetLights(bit | DDR_LIGHT_P1_MUX_CLK | DDR_LIGHT_P2_MUX_CLK); + _k573_delay_hblanks(20); + K573_SetLights(bit); + _k573_delay_hblanks(20); + + last_bit = bit; + mask <<= 1; + } + + K573_SetLights(0); +}*/ + +//K573_DDRStageCommand(0x000c90, 13); +//K573_DDRStageCommand(0x000001, 22); + +void K573_Init(void) { + EXP1_ADDR = 0x1f000000; + EXP1_CTRL = 0x24173f47; // 573 BIOS uses this value + + K573_RESET_WATCHDOG(); +} diff --git a/examples/io/system573/k573io.h b/examples/io/system573/k573io.h new file mode 100644 index 0000000..cf125e2 --- /dev/null +++ b/examples/io/system573/k573io.h @@ -0,0 +1,258 @@ +/* + * PSn00bSDK Konami System 573 example (I/O driver) + * (C) 2022 spicyjpeg - MPL licensed + */ + +#ifndef __K573IO_H +#define __K573IO_H + +#include + +/* Register definitions */ + +#define EXP1_ADDR *((volatile uint32_t *) 0x1f801000) +#define EXP1_CTRL *((volatile uint32_t *) 0x1f801008) + +#define K573_BANK_SWITCH *((volatile uint16_t *) 0x1f500000) +#define K573_IDE_RESET *((volatile uint16_t *) 0x1f560000) +#define K573_WATCHDOG *((volatile uint16_t *) 0x1f5c0000) +#define K573_EXT_OUT *((volatile uint16_t *) 0x1f600000) +#define K573_JVS_INPUT *((volatile uint16_t *) 0x1f680000) +#define K573_SECURITY_OUT *((volatile uint16_t *) 0x1f6a0000) + +#define K573_FLASH ((volatile uint16_t *) 0x1f000000) +#define K573_IO_CHIP ((volatile uint16_t *) 0x1f400000) +#define K573_IDE_CS0 ((volatile uint16_t *) 0x1f480000) +#define K573_IDE_CS1 ((volatile uint16_t *) 0x1f4c0000) +#define K573_RTC ((volatile uint16_t *) 0x1f620000) +#define K573_IO_BOARD ((volatile uint16_t *) 0x1f640000) + +typedef enum _K573_IOChipRegister { + IO_REG_IN0 = 0x0, + IO_REG_IN1_LOW = 0x2, + IO_REG_IN1_HIGH = 0x3, + IO_REG_IN2 = 0x4, + IO_REG_IN3_LOW = 0x6, + IO_REG_IN3_HIGH = 0x7 +} K573_IOChipRegister; + +typedef enum _K573_IOBoardRegister { + ANALOG_IO_REG_LIGHTS0 = 0x40, + ANALOG_IO_REG_LIGHTS1 = 0x44, + ANALOG_IO_REG_LIGHTS2 = 0x48, + ANALOG_IO_REG_LIGHTS3 = 0x4c, + + // The digital I/O board has a lot more registers than these, but there + // seems to be no DIGITAL_IO_LIGHTS6 register. WTF + DIGITAL_IO_REG_LIGHTS1 = 0x70, + DIGITAL_IO_REG_LIGHTS0 = 0x71, + DIGITAL_IO_REG_LIGHTS3 = 0x72, + DIGITAL_IO_REG_LIGHTS7 = 0x73, + DIGITAL_IO_REG_LIGHTS4 = 0x7d, + DIGITAL_IO_REG_LIGHTS5 = 0x7e, + DIGITAL_IO_REG_LIGHTS2 = 0x7f, + + FISHBAIT_IO_REG_UNKNOWN = 0x08, + FISHBAIT_IO_REG_MOTOR = 0x40, + FISHBAIT_IO_REG_BRAKE = 0x44, + FISHBAIT_IO_REG_ENCODER = 0x4c, + FISHBAIT_IO_REG_RESET_Y = 0x50 +} K573_IOBoardRegister; + +// The 573's real-time clock chip is an M48T58, which behaves like a standard +// 8 KB battery-backed SRAM with a bunch of special registers. Official games +// store highscores and settings in RTC RAM. +typedef enum _K573_RTCRegister { + RTC_REG_CTRL = 0x1ff8, + RTC_REG_SECONDS = 0x1ff9, + RTC_REG_MINUTES = 0x1ffa, + RTC_REG_HOURS = 0x1ffb, + RTC_REG_DAY_OF_WEEK = 0x1ffc, + RTC_REG_DAY_OF_MONTH = 0x1ffd, + RTC_REG_MONTH = 0x1ffe, + RTC_REG_YEAR = 0x1fff +} K573_RTCRegister; + +/* Inputs and lights bitfields */ + +typedef enum _K573_JAMMAInputs { + // IO_REG_IN2 bits 0-15 + JAMMA_P2_LEFT = 1 << 0, + JAMMA_P2_RIGHT = 1 << 1, + JAMMA_P2_UP = 1 << 2, + JAMMA_P2_DOWN = 1 << 3, + JAMMA_P2_BUTTON1 = 1 << 4, + JAMMA_P2_BUTTON2 = 1 << 5, + JAMMA_P2_BUTTON3 = 1 << 6, + JAMMA_P2_START = 1 << 7, + JAMMA_P1_LEFT = 1 << 8, + JAMMA_P1_RIGHT = 1 << 9, + JAMMA_P1_UP = 1 << 10, + JAMMA_P1_DOWN = 1 << 11, + JAMMA_P1_BUTTON1 = 1 << 12, + JAMMA_P1_BUTTON2 = 1 << 13, + JAMMA_P1_BUTTON3 = 1 << 14, + JAMMA_P1_START = 1 << 15, + + // IO_REG_IN3_LOW bits 8-11 + JAMMA_P1_BUTTON4 = 1 << 16, + JAMMA_P1_BUTTON5 = 1 << 17, + JAMMA_TEST = 1 << 18, + JAMMA_P1_BUTTON6 = 1 << 19, + + // IO_REG_IN3_HIGH bits 8-11 + JAMMA_P2_BUTTON4 = 1 << 20, + JAMMA_P2_BUTTON5 = 1 << 21, + JAMMA_UNKNOWN = 1 << 22, + JAMMA_P2_BUTTON6 = 1 << 23, + + // IO_REG_IN1_HIGH bits 8-12 + JAMMA_COIN1 = 1 << 24, + JAMMA_COIN2 = 1 << 25, + JAMMA_PCMCIA1 = 1 << 26, + JAMMA_PCMCIA2 = 1 << 27, + JAMMA_SERVICE = 1 << 28, + + // IO_REG_IN1_LOW bits 0-2 + JAMMA_DIP1 = 1 << 29, + JAMMA_DIP2 = 1 << 30, + JAMMA_DIP3 = 1 << 31 +} K573_JAMMAInputs; + +typedef enum _K573_Light { + // Dance Dance Revolution (2-player) + DDR_LIGHT_P1_UP = 1 << 0, + DDR_LIGHT_P1_LEFT = 1 << 1, + DDR_LIGHT_P1_RIGHT = 1 << 2, + DDR_LIGHT_P1_DOWN = 1 << 3, + DDR_LIGHT_P1_MUX_DATA = 1 << 4, // Used for stage commands + DDR_LIGHT_P1_MUX_CLK = 1 << 7, // Used for stage commands + DDR_LIGHT_P2_UP = 1 << 8, + DDR_LIGHT_P2_LEFT = 1 << 9, + DDR_LIGHT_P2_RIGHT = 1 << 10, + DDR_LIGHT_P2_DOWN = 1 << 11, + DDR_LIGHT_P2_MUX_DATA = 1 << 12, // Used for stage commands + DDR_LIGHT_P2_MUX_CLK = 1 << 15, // Used for stage commands + DDR_LIGHT_P1_BUTTONS = 1 << 17, + DDR_LIGHT_P2_BUTTONS = 1 << 18, + DDR_LIGHT_MARQUEE_BR = 1 << 20, + DDR_LIGHT_MARQUEE_BL = 1 << 21, + DDR_LIGHT_MARQUEE_TL = 1 << 22, + DDR_LIGHT_MARQUEE_TR = 1 << 23, + DDR_LIGHT_SPEAKER_DIGITAL = 1 << 28, // Speaker neon on digital I/O boards + DDR_LIGHT_SPEARKER_ANALOG = 1 << 30, // Speaker neon on analog I/O boards + + // Dance Dance Revolution Solo + DDRSOLO_LIGHT_EXTRA4 = 1 << 8, + DDRSOLO_LIGHT_EXTRA2 = 1 << 9, + DDRSOLO_LIGHT_EXTRA1 = 1 << 10, + DDRSOLO_LIGHT_EXTRA3 = 1 << 11, + DDRSOLO_LIGHT_SPEAKER = 1 << 16, + DDRSOLO_LIGHT_BUTTONS = 1 << 20, + DDRSOLO_LIGHT_BODY_CENTER = 1 << 21, + DDRSOLO_LIGHT_BODY_RIGHT = 1 << 22, + DDRSOLO_LIGHT_BODY_LEFT = 1 << 23, + + // DrumMania 1st Mix + DM_LIGHT_HIHAT = 1 << 16, + DM_LIGHT_HIGH_TOM = 1 << 17, + DM_LIGHT_LOW_TOM = 1 << 18, + DM_LIGHT_SNARE = 1 << 19, + DM_LIGHT_CYMBAL = 1 << 20, + DM_LIGHT_START_BUTTON = 1 << 21, + DM_LIGHT_SELECT_BUTTON = 1 << 22, + DM_LIGHT_NEON_BOTTOM = 1 << 27, + DM_LIGHT_SPOT = 1 << 30, + DM_LIGHT_NEON_TOP = 1 << 31, + + // DrumMania 2nd Mix and later + DM2_LIGHT_HIHAT = 1 << 0, + DM2_LIGHT_HIGH_TOM = 1 << 1, + DM2_LIGHT_LOW_TOM = 1 << 2, + DM2_LIGHT_SNARE = 1 << 3, + DM2_LIGHT_SPOT = 1 << 8, + DM2_LIGHT_NEON_TOP = 1 << 9, + DM2_LIGHT_NEON_BOTTOM = 1 << 11, + DM2_LIGHT_CYMBAL = 1 << 12, + DM2_LIGHT_START_BUTTON = 1 << 13, + DM2_LIGHT_SELECT_BUTTON = 1 << 14 +} K573_Light; + +/* System information structures */ + +typedef enum _K573_IOBoardType { + IO_TYPE_ANALOG = 0, // Light control board (early Bemani) + IO_TYPE_DIGITAL = 1, // Light control + MP3 playback board (late Bemani) + IO_TYPE_FISHBAIT = 2, // Fishing reel controls interface (Fisherman's Bait) + IO_TYPE_GUNMANIA = 3, // Gun control board (Gun Mania) + IO_TYPE_KARAOKE = 4, // Karaoke I/O + video mux board (DDR Karaoke Mix) + IO_TYPE_SERIAL = 5 // Serial port (debug?) board (Great Bishi Bashi Champ) + // TODO: does PunchMania have its own board? +} K573_IOBoardType; + +typedef enum _K573_DDRStageType { + DDR_TYPE_NONE = 0, + DDR_TYPE_2PLAYER = 1, + DDR_TYPE_SOLO = 2 +} K573_DDRStageType; + +/* Public API */ + +#define K573_RESET_WATCHDOG() { \ + K573_WATCHDOG = 0; \ +} + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Returns a bitfield containing the state of all JAMMA inputs and DIP + * switches. All bits are inverted as they represent the actual signal levels + * on the JAMMA pins (i.e. normally pulled up by resistors, shorted to ground + * when a button is pressed). + * + * @return Inverted logical OR of K573_JAMMAInputs flags + */ +uint32_t K573_GetJAMMAInputs(void); + +/** + * @brief Sets the 32 light outputs provided by the the analog and digital I/O + * boards to match the provided bitfield. K573_SetBoardType(IO_TYPE_ANALOG) or + * K573_SetBoardType(IO_TYPE_DIGITAL) must be called beforehand to set the I/O + * board type. + * + * @param lights Non-inverted logical OR of K573_Light flags + */ +void K573_SetLights(uint32_t lights); + +/** + * @brief Sets the installed I/O board type. Currently only IO_TYPE_ANALOG and + * IO_TYPE_DIGITAL are supported. + * + * @param type + */ +void K573_SetBoardType(K573_IOBoardType type); + +/** + * @brief Sends a command to the multiplexer PCB embedded into DDR stage units + * (if the system is a DDR cabinet) by bitbanging it through the light outputs. + * K573_SetBoardType(IO_TYPE_ANALOG) or K573_SetBoardType(IO_TYPE_DIGITAL) must + * be called beforehand to set the I/O board type. + * + * @param value + * @param length Number of bits to send (1-32) + */ +//void K573_DDRStageCommand(uint32_t value, uint32_t length); + +/** + * @brief Initializes the expansion port registers to enable System 573 I/O + * access. + */ +void K573_Init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/io/system573/main.c b/examples/io/system573/main.c index a06c4e5..64722d7 100644 --- a/examples/io/system573/main.c +++ b/examples/io/system573/main.c @@ -1,15 +1,14 @@ /* * PSn00bSDK Konami System 573 example - * (C) 2021 spicyjpeg - MPL licensed + * (C) 2022 spicyjpeg - MPL licensed * * This is a minimal example demonstrating how to target the Konami System 573 * using PSn00bSDK. The System 573 is a PS1-based arcade motherboard that * powered various Konami arcade games throughout the late 1990s, most notably * Dance Dance Revolution and other Bemani rhythm games. It came in several * configurations, with slightly different I/O connectors depending on the game - * and two optional add-on modules (known as the "analog I/O" and "digital I/O" - * boards respectively) providing light control outputs and, in the case of the - * digital I/O board, MP3 audio playback. + * and optional add-on boards providing extra features such as light control + * outputs or MP3 audio playback. * * Unlike other arcade systems based on PS1 hardware, the 573 is mostly * identical to a regular PS1, with almost all custom extensions mapped into @@ -62,60 +61,15 @@ #include #include #include -#include #include #include -#include - -/* Register definitions */ - -#define EXP1_ADDR *((volatile uint32_t *) 0x1f801000) -#define EXP1_CTRL *((volatile uint32_t *) 0x1f801008) - -#define K573_IN0 *((volatile uint16_t *) 0x1f400000) -#define K573_IN1_L *((volatile uint16_t *) 0x1f400004) -#define K573_IN1_H *((volatile uint16_t *) 0x1f400006) -#define K573_IN2 *((volatile uint16_t *) 0x1f400008) -#define K573_IN3_L *((volatile uint16_t *) 0x1f40000c) -#define K573_IN3_H *((volatile uint16_t *) 0x1f40000e) -#define K573_BANK *((volatile uint16_t *) 0x1f500000) -#define K573_WATCHDOG *((volatile uint16_t *) 0x1f5c0000) - -#define K573_IDE_CS0 ((volatile uint16_t *) 0x1f480000) -#define K573_IDE_CS1 ((volatile uint16_t *) 0x1f4c0000) -#define K573_RTC ((volatile uint16_t *) 0x1f620000) -#define K573_IO_BOARD ((volatile uint16_t *) 0x1f640000) - -typedef enum { - ANALOG_IO_LIGHTS0 = 0x20, - ANALOG_IO_LIGHTS1 = 0x22, - ANALOG_IO_LIGHTS2 = 0x24, - ANALOG_IO_LIGHTS3 = 0x26, - - // The digital I/O board has a lot more registers than these, but there - // seems to be no DIGITAL_IO_LIGHTS6 register. WTF - DIGITAL_IO_LIGHTS1 = 0x70, - DIGITAL_IO_LIGHTS0 = 0x71, - DIGITAL_IO_LIGHTS3 = 0x72, - DIGITAL_IO_LIGHTS7 = 0x73, - DIGITAL_IO_LIGHTS4 = 0x7d, - DIGITAL_IO_LIGHTS5 = 0x7e, - DIGITAL_IO_LIGHTS2 = 0x7f -} IO_BOARD_REG; - -// The 573's real-time clock chip is an M48T58, which behaves like a standard -// 8 KB battery-backed SRAM with a bunch of special registers. Official games -// store highscores and settings in RTC RAM. -typedef enum { - RTC_CTRL = 0x1ff8, - RTC_SECONDS = 0x1ff9, - RTC_MINUTES = 0x1ffa, - RTC_HOURS = 0x1ffb, - RTC_DAY_OF_WEEK = 0x1ffc, - RTC_DAY_OF_MONTH = 0x1ffd, - RTC_MONTH = 0x1ffe, - RTC_YEAR = 0x1fff -} RTC_REG; + +#include "k573io.h" + +const char *const IO_BOARD_TYPES[] = { + "ANALOG", + "DIGITAL" +}; #define btoi(x) ((((x) >> 4) & 0xf) * 10 + ((x) & 0xf)) @@ -179,89 +133,6 @@ void display(CONTEXT *ctx) { SetDispMask(1); } -/* Input polling utilities */ - -typedef struct { - uint8_t p1_joy, p1_btn; - uint8_t p2_joy, p2_btn; - uint8_t coin, dip_sw; -} JAMMAInputs; - -void get_jamma_inputs(JAMMAInputs *output) { - uint16_t in1l = K573_IN1_L; - uint16_t in1h = K573_IN1_H; - uint16_t in2 = K573_IN2; - uint16_t in3l = K573_IN3_L; - uint16_t in3h = K573_IN3_H; - uint8_t p1_btn, p2_btn, coin; - - // Rearrange the bits read from the input register into something that's - // easier to parse and display. Refer to MAME for information on what each - // bit in the IN* registers does. - p1_btn = ((in2 >> 15) & 0x0001); // Bit 0 = start button - p1_btn |= ((in2 >> 8) & 0x0007) << 1; // Bit 1-3 = buttons 1-3 - p1_btn |= ((in3l >> 8) & 0x0003) << 4; // Bit 4-5 = buttons 4-5 - p1_btn |= ((in3l >> 11) & 0x0001) << 6; // Bit 6 = button 6 - p2_btn = ((in2 >> 7) & 0x0001); // Bit 0 = start button - p2_btn |= ((in2 >> 4) & 0x0007) << 1; // Bit 1-3 = buttons 1-3 - p2_btn |= ((in3h >> 8) & 0x0003) << 4; // Bit 4-5 = buttons 4-5 - p2_btn |= ((in3h >> 11) & 0x0001) << 6; // Bit 6 = button 6 - coin = ((in1h >> 8) & 0x0003); // Bit 0-1 = coin switches - coin |= ((in1h >> 12) & 0x0001) << 2; // Bit 2 = service button - coin |= ((in3l >> 10) & 0x0001) << 3; // Bit 3 = test button - coin |= ((in1h >> 10) & 0x0003) << 4; // Bit 4-5 = PCMCIA cards - - output->p1_joy = (in2 >> 8) & 0x000f; - output->p1_btn = p1_btn; - output->p2_joy = in2 & 0x000f; - output->p2_btn = p2_btn; - output->coin = coin; - output->dip_sw = in1l & 0x000f; -} - -/* I/O board (light control) utilities */ - -// This function controls light outputs on analog I/O boards. -void set_lights_analog(uint32_t lights) { - uint32_t bits; - - bits = (lights & 0x01010101) << 7; // Lamp n*8+0 -> bit n*8+7 - bits |= (lights & 0x02020202) << 5; // Lamp n*8+1 -> bit n*8+6 - bits |= (lights & 0x04040404) >> 1; // Lamp n*8+2 -> bit n*8+1 - bits |= (lights & 0x08080808) >> 3; // Lamp n*8+3 -> bit n*8+0 - bits |= (lights & 0x10101010) << 1; // Lamp n*8+4 -> bit n*8+5 - bits |= (lights & 0x20202020) >> 1; // Lamp n*8+5 -> bit n*8+4 - bits |= (lights & 0x40404040) >> 3; // Lamp n*8+6 -> bit n*8+3 - bits |= (lights & 0x80808080) >> 5; // Lamp n*8+7 -> bit n*8+2 - - K573_IO_BOARD[ANALOG_IO_LIGHTS0] = (bits) & 0xff; - K573_IO_BOARD[ANALOG_IO_LIGHTS1] = (bits >> 8) & 0xff; - K573_IO_BOARD[ANALOG_IO_LIGHTS2] = (bits >> 16) & 0xff; - K573_IO_BOARD[ANALOG_IO_LIGHTS3] = (bits >> 24) & 0xff; -} - -// This function controls light outputs on digital I/O boards (i.e. the ones -// that include MP3 playback hardware in addition to the light control). -// TODO: test this on real hardware -- it might not work if lights are handled -// by the board's FPGA, which requires a binary blob... -void set_lights_digital(uint32_t lights) { - uint32_t bits; - - bits = (lights & 0x11111111); // Lamp n*4+0 -> bit n*4+0 - bits |= (lights & 0x22222222) << 1; // Lamp n*4+1 -> bit n*4+2 - bits |= (lights & 0x44444444) << 1; // Lamp n*4+2 -> bit n*4+3 - bits |= (lights & 0x88888888) >> 2; // Lamp n*4+3 -> bit n*4+1 - - K573_IO_BOARD[DIGITAL_IO_LIGHTS0] = ((bits) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS1] = ((bits >> 4) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS2] = ((bits >> 8) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS3] = ((bits >> 12) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS4] = ((bits >> 16) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS5] = ((bits >> 20) & 0xf) << 12; - //K573_IO_BOARD[DIGITAL_IO_LIGHTS6] = ((bits >> 24) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS7] = ((bits >> 28) & 0xf) << 12; -} - /* Main */ static CONTEXT ctx; @@ -270,101 +141,96 @@ static CONTEXT ctx; #define SHOW_ERROR(...) { SHOW_STATUS(__VA_ARGS__); while (1) __asm__("nop"); } int main(int argc, const char* argv[]) { - // Reinitialize the heap and relocate the stack to allow the 573's full 4 - // MB of RAM to be used. This isn't strictly required; executables designed - // for 2 MB of RAM will also run fine on the 573 (obviously). - // FIXME: this seems to be broken currently - //__asm__ volatile("li $sp, 0x803fffe0"); - //_mem_init(0x400000, 0x20000); - - EXP1_ADDR = 0x1f000000; - EXP1_CTRL = 0x24173f47; // 573 BIOS uses this value - K573_WATCHDOG = 0; - init_context(&ctx); + K573_Init(); - // Determine whether we are running on a 573 by fetching the version string - // from the BIOS. const char *const version = (const char *const) GetSystemInfo(0x02); //if (strncmp(version, "Konami OS", 9)) //SHOW_ERROR("ERROR: NOT RUNNING ON A SYSTEM 573!\n\n[%s]\n", version); uint32_t counter = 0; - uint8_t last_joystick = 0xff; - uint8_t last_buttons = 0xff; + uint32_t inputs = K573_GetJAMMAInputs(); + uint32_t last_inputs = 0xff; uint32_t current_light = 0; - uint32_t is_digital = 0; + + // DIP switch 1 is used to determine if an analog or digital I/O board is + // installed. + K573_IOBoardType io_type = (inputs & JAMMA_DIP1) + ? IO_TYPE_ANALOG + : IO_TYPE_DIGITAL; + + K573_SetBoardType(io_type); + K573_SetLights(1); while (1) { - FntPrint(-1, "COUNTER=%d\n", counter++); + inputs = K573_GetJAMMAInputs(); - JAMMAInputs inputs; - get_jamma_inputs(&inputs); + FntPrint(-1, "COUNTER=%d\n", counter++); FntPrint(-1, "\nJAMMA INPUTS:\n"); - FntPrint(-1, " P1 JOYSTICK =%04@\n", inputs.p1_joy); - FntPrint(-1, " P1 BUTTONS =%07@\n", inputs.p1_btn); - FntPrint(-1, " P2 JOYSTICK =%04@\n", inputs.p2_joy); - FntPrint(-1, " P2 BUTTONS =%07@\n", inputs.p2_btn); - FntPrint(-1, " COIN/SERVICE=%04@\n", inputs.coin & 0xf); - FntPrint(-1, " DIP SWITCHES=%04@\n", inputs.dip_sw); + FntPrint(-1, " IN2 =%016@\n", inputs & 0xffff); + FntPrint(-1, " IN3_L=%04@\n", (inputs >> 16) & 0x0f); + FntPrint(-1, " IN3_H=%04@\n", (inputs >> 20) & 0x0f); + FntPrint(-1, " IN1_H=%05@\n", (inputs >> 24) & 0x1f); FntPrint(-1, "\nCABINET LIGHTS:\n"); - FntPrint(-1, " BOARD=%s I/O\n", is_digital ? "DIGITAL" : "ANALOG"); - FntPrint(-1, " LIGHT=%d\n\n", current_light); - FntPrint(-1, " [START] CHANGE BOARD TYPE\n"); - FntPrint(-1, " [LEFT/RIGHT] SELECT LIGHT TO TEST\n"); + FntPrint(-1, " BOARD=%s\n", IO_BOARD_TYPES[io_type]); + FntPrint(-1, " LIGHT=%d\n", current_light); + FntPrint(-1, "\n [DIP SW1] CHANGE BOARD TYPE\n"); + FntPrint(-1, "\n [TEST SW] CHANGE ACTIVE LIGHT\n"); // Request the current date/time from the RTC and display it. - K573_RTC[RTC_CTRL] |= 0x40; + K573_RTC[RTC_REG_CTRL] |= 0x40; FntPrint(-1, "\nRTC:\n"); FntPrint( -1, " %02d-%02d-%02d %02d:%02d:%02d\n", - btoi(K573_RTC[RTC_YEAR]), - btoi(K573_RTC[RTC_MONTH]), - btoi(K573_RTC[RTC_DAY_OF_MONTH] & 0x3f), - btoi(K573_RTC[RTC_HOURS]), - btoi(K573_RTC[RTC_MINUTES]), - btoi(K573_RTC[RTC_SECONDS] & 0x7f) + btoi(K573_RTC[RTC_REG_YEAR]), + btoi(K573_RTC[RTC_REG_MONTH]), + btoi(K573_RTC[RTC_REG_DAY_OF_MONTH] & 0x3f), + btoi(K573_RTC[RTC_REG_HOURS]), + btoi(K573_RTC[RTC_REG_MINUTES]), + btoi(K573_RTC[RTC_REG_SECONDS] & 0x7f) ); FntPrint(-1, "\nSYSTEM:\n"); FntPrint(-1, " KERNEL=%s\n", version); - FntPrint(-1, " PCMCIA=%02@\n", inputs.coin >> 4); + FntPrint(-1, " DIP SW=%03@\n", inputs >> 29); + FntPrint(-1, " PCMCIA=%02@\n", (inputs >> 26) & 0x3); FntFlush(-1); display(&ctx); // Reset the watchdog. This must be done at least once per frame to // prevent the 573 from rebooting. - K573_WATCHDOG = 0; + K573_RESET_WATCHDOG(); - if (is_digital) - set_lights_digital(1 << current_light); - else - set_lights_analog(1 << current_light); - - // Handle inputs. - if ((last_joystick & 0x01) && !(inputs.p1_joy & 0x01)) // Left - current_light--; - if ((last_joystick & 0x02) && !(inputs.p1_joy & 0x02)) // Right - current_light++; - if ((last_buttons & 0x02) && !(inputs.p1_btn & 0x02)) // Button 1 - current_light--; - if ((last_buttons & 0x04) && !(inputs.p1_btn & 0x04)) // Button 2 + // Change the currently active light if the test button on the 573's + // front panel is pressed. DDR non-light outputs are skipped. + if ((last_inputs & JAMMA_TEST) && !(inputs & JAMMA_TEST)) { current_light++; - if ((last_buttons & 0x01) && !(inputs.p1_btn & 0x01)) { // Start - is_digital = !is_digital; - if (is_digital) - set_lights_analog(0); - else - set_lights_digital(0); + if ( + (current_light == 4) || // DDR_LIGHT_P1_MUX_DATA + (current_light == 7) || // DDR_LIGHT_P1_MUX_CLK + (current_light == 12) || // DDR_LIGHT_P2_MUX_DATA + (current_light == 15) // DDR_LIGHT_P2_MUX_CLK + ) current_light++; + + current_light %= 32; + K573_SetLights(1 << current_light); + } + + // if DIP switch 1 is toggled, change the I/O board type. + if ((last_inputs & JAMMA_DIP1) != (inputs & JAMMA_DIP1)) { + io_type = (inputs & JAMMA_DIP1) + ? IO_TYPE_ANALOG + : IO_TYPE_DIGITAL; + + K573_SetBoardType(io_type); + K573_SetLights(1 << current_light); } - current_light %= 32; - last_joystick = inputs.p1_joy; - last_buttons = inputs.p1_btn; + last_inputs = inputs; } return 0; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index af99046..6f604d5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -14,7 +14,7 @@ include(GNUInstallDirs) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") set(CMAKE_C_STANDARD 11) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) ## Dependencies -- cgit v1.2.3 From 93f0a6d23ebed50833f565f949f351c2b80853ac Mon Sep 17 00:00:00 2001 From: spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> Date: Mon, 7 Mar 2022 22:17:50 +0100 Subject: Fix critical ldscript bug and CI, add BIOS setjmp --- .github/workflows/build.yml | 28 ++++++------------ examples/io/system573/k573io.c | 5 ++-- examples/io/system573/k573io.h | 3 -- libpsn00b/include/psxapi.h | 12 ++++++++ libpsn00b/ldscripts/dll.ld | 1 + libpsn00b/ldscripts/exe.ld | 11 +++---- libpsn00b/psxapi/stubs.json | 12 ++++++++ libpsn00b/psxapi/sys.s | 18 +++++++++++- libpsn00b/readme.txt | 67 +++++++++++++++++++++--------------------- 9 files changed, 94 insertions(+), 63 deletions(-) (limited to 'examples/io') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b2ca311..6f42e41 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,9 @@ env: jobs: # This is based on doc/toolchain.md, no surprises here other than the cache. + # Since actions/cache@v2 has bugs when restoring on Windows caches created on + # Linux, v1 is used instead. + # https://github.com/actions/cache/issues/576 build-gcc: name: Build GCC toolchain runs-on: ubuntu-latest @@ -23,7 +26,7 @@ jobs: steps: - name: Initialize toolchain cache id: _cache - uses: actions/cache@v2 + uses: actions/cache@v1 with: key: gcc-${{ env.GCC_TARGET }}-${{ env.GCC_VERSION }} path: gcc @@ -83,25 +86,19 @@ jobs: # No surprises here either. The GitHub Actions VMs even come with most of the # dependencies required to build PSn00bSDK preinstalled. - # NOTE: the workaround to allow the toolchain cache to be loaded (see below) - # doesn't seem to work on Windows Server 2022 currently. build-sdk-windows: name: Build PSn00bSDK on Windows - runs-on: windows-2019 + runs-on: windows-2022 needs: build-gcc steps: - # Due to a bug in the cache action (and in order to use Ninja and pacman) - # the directories MSys2 stores binaries in must be added to PATH. For - # some reason they are not present in PATH by default. - # https://github.com/actions/cache/issues/576 - name: Add MSys2 to PATH run: | echo "C:\msys64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Initialize toolchain cache - uses: actions/cache@v2 + uses: actions/cache@v1 with: key: gcc-${{ env.GCC_TARGET }}-${{ env.GCC_VERSION }} path: gcc @@ -118,7 +115,7 @@ jobs: - name: Build and package PSn00bSDK run: | - cmake --preset ci -S sdk -G "Visual Studio 16 2019" -DPSN00BSDK_TC=${{ github.workspace }}\gcc\windows + cmake --preset ci -S sdk -G "Visual Studio 17 2022" -DPSN00BSDK_TC=${{ github.workspace }}\gcc\windows cmake --build build cmake --build build -t package @@ -144,7 +141,7 @@ jobs: steps: - name: Initialize toolchain cache - uses: actions/cache@v2 + uses: actions/cache@v1 with: key: gcc-${{ env.GCC_TARGET }}-${{ env.GCC_VERSION }} path: gcc @@ -178,12 +175,6 @@ jobs: name: psn00bsdk-linux-deb path: build/packages/*.deb - - name: Upload build artifacts (RPM) - uses: actions/upload-artifact@v2 - with: - name: psn00bsdk-linux-rpm - path: build/packages/*.rpm - # This job takes care of creating a new release and upload the build # artifacts if the last commit is associated to a tag. create-release: @@ -194,7 +185,7 @@ jobs: steps: - name: Initialize toolchain cache if: ${{ github.ref_type == 'tag' }} - uses: actions/cache@v2 + uses: actions/cache@v1 with: key: gcc-${{ env.GCC_TARGET }}-${{ env.GCC_VERSION }} path: gcc @@ -236,4 +227,3 @@ jobs: psn00bsdk-windows-nsis/* psn00bsdk-linux/* psn00bsdk-linux-deb/* - psn00bsdk-linux-rpm/* diff --git a/examples/io/system573/k573io.c b/examples/io/system573/k573io.c index a8748d6..bc13852 100644 --- a/examples/io/system573/k573io.c +++ b/examples/io/system573/k573io.c @@ -11,6 +11,7 @@ #include #include +#include #include "k573io.h" @@ -116,8 +117,8 @@ void K573_SetBoardType(K573_IOBoardType type) { //K573_DDRStageCommand(0x000001, 22); void K573_Init(void) { - EXP1_ADDR = 0x1f000000; - EXP1_CTRL = 0x24173f47; // 573 BIOS uses this value + EXP1_ADDR = 0x1f000000; + EXP1_DELAY_SIZE = 0x24173f47; // 573 BIOS uses this value K573_RESET_WATCHDOG(); } diff --git a/examples/io/system573/k573io.h b/examples/io/system573/k573io.h index cf125e2..7095a7c 100644 --- a/examples/io/system573/k573io.h +++ b/examples/io/system573/k573io.h @@ -10,9 +10,6 @@ /* Register definitions */ -#define EXP1_ADDR *((volatile uint32_t *) 0x1f801000) -#define EXP1_CTRL *((volatile uint32_t *) 0x1f801008) - #define K573_BANK_SWITCH *((volatile uint16_t *) 0x1f500000) #define K573_IDE_RESET *((volatile uint16_t *) 0x1f560000) #define K573_WATCHDOG *((volatile uint16_t *) 0x1f5c0000) diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h index e7c2e1e..1298d29 100644 --- a/libpsn00b/include/psxapi.h +++ b/libpsn00b/include/psxapi.h @@ -121,6 +121,12 @@ struct EXEC { unsigned int sp,fp,rp,ret,base; }; +struct JMP_BUF { + unsigned int ra, sp, fp; + unsigned int s0, s1, s2, s3, s4, s5, s6, s7; + unsigned int gp; +}; + // Not recommended to use these functions to install IRQ handlers typedef struct { @@ -211,6 +217,12 @@ void ChangeClearRCnt(int t, int m); int Exec(struct EXEC *exec, int argc, char **argv); void FlushCache(void); +// BIOS setjmp functions +void b_setjmp(struct JMP_BUF *buf); +void b_longjmp(struct JMP_BUF *buf, int param); +void SetDefaultExitFromException(void); +void SetCustomExitFromException(struct JMP_BUF *buf); + // Misc functions int GetSystemInfo(int index); void *GetB0Table(void); diff --git a/libpsn00b/ldscripts/dll.ld b/libpsn00b/ldscripts/dll.ld index a03a504..15158e4 100644 --- a/libpsn00b/ldscripts/dll.ld +++ b/libpsn00b/ldscripts/dll.ld @@ -86,6 +86,7 @@ SECTIONS { * as we don't have to worry about managing .bss separately from the * main DLL blob. */ + . = ALIGN((. != 0) ? 4 : 1); __bss_start = .; *(.bss .bss.* .gnu.linkonce.b.*) diff --git a/libpsn00b/ldscripts/exe.ld b/libpsn00b/ldscripts/exe.ld index c6b9f29..583d76a 100644 --- a/libpsn00b/ldscripts/exe.ld +++ b/libpsn00b/ldscripts/exe.ld @@ -82,6 +82,11 @@ SECTIONS { /* BSS sections, i.e. uninitialized variables */ + /* + * Align all BSS sections to 4 bytes to ensure _start() doesn't perform + * unaligned memory accesses when clearing them. + */ + . = ALIGN((. != 0) ? 4 : 1); __bss_start = .; .sbss (NOLOAD) : { @@ -91,13 +96,9 @@ SECTIONS { .bss (NOLOAD) : { *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) - - /* - * This crap was in the stock GCC linker script. - */ - . = ALIGN((. != 0) ? 4 : 1); } > APP_RAM + . = ALIGN((. != 0) ? 4 : 1); _end = .; /* Dummy section */ diff --git a/libpsn00b/psxapi/stubs.json b/libpsn00b/psxapi/stubs.json index 14ef935..9198b06 100644 --- a/libpsn00b/psxapi/stubs.json +++ b/libpsn00b/psxapi/stubs.json @@ -47,6 +47,18 @@ "name": "putc", "file": "stdio.s" }, + { + "type": "a", + "id": 19, + "name": "b_setjmp", + "file": "sys.s" + }, + { + "type": "a", + "id": 20, + "name": "b_longjmp", + "file": "sys.s" + }, { "type": "a", "id": 57, diff --git a/libpsn00b/psxapi/sys.s b/libpsn00b/psxapi/sys.s index ef57124..e54bd98 100644 --- a/libpsn00b/psxapi/sys.s +++ b/libpsn00b/psxapi/sys.s @@ -6,7 +6,23 @@ .set noreorder -## A0 table functions (5) +## A0 table functions (7) + +.section .text.b_setjmp +.global b_setjmp +.type b_setjmp, @function +b_setjmp: + li $t2, 0xa0 + jr $t2 + li $t1, 0x13 + +.section .text.b_longjmp +.global b_longjmp +.type b_longjmp, @function +b_longjmp: + li $t2, 0xa0 + jr $t2 + li $t1, 0x14 .section .text.b_InitHeap .global b_InitHeap diff --git a/libpsn00b/readme.txt b/libpsn00b/readme.txt index cfff733..6a6be5a 100644 --- a/libpsn00b/readme.txt +++ b/libpsn00b/readme.txt @@ -18,33 +18,39 @@ recommended version as that is what LibPSn00b is most tested most on. Brief summary of libraries: - libc - Standard C library. Covers only a small subset of the full - standard C library such as basic string and memory manipulation - functions. Should include libgcc to avoid libc/libgcc linker - hell (endless cross referencing). - - psxgpu - GPU library for video, graphics control, and interrupt service - subsystem that other libraries that uses interrupts depend on. - - psxgte - GTE library for hardware accelerated vector transformations - that are integral for high performance 3D graphics on the PS1 - (it is a Geometry Transformation Engine, NOT Transfer Engine). - - psxapi - Provides function calls for using functions provided by the PS1 - BIOS. - - psxetc - Provides some miscellaneous features used by the other libraries - as well as a dynamic linker for loading DLLs at runtime. - - psxspu - SPU library (work in progress). Currently supports hardware - init, sample data upload via DMA and playing sound samples. - Lacks support for reverb and a sequenced music subsystem. - - psxcd - CD-ROM library for loading files, parsing directories - (PSn00bSDK addition), CD Audio/XA playback with provisions for - data streaming. Also supports multi-session discs (must be - selected manually). - + libc - Standard C library. Covers only a small subset of the full + standard C library such as basic string and memory manipulation + functions. Should include libgcc to avoid libc/libgcc linker + hell (endless cross referencing). + + psxgpu - GPU library for video, graphics control, and interrupt service + subsystem that other libraries that uses interrupts depend on. + + psxgte - GTE library for hardware accelerated vector transformations + that are integral for high performance 3D graphics on the PS1 + (it is a Geometry Transformation Engine, NOT Transfer Engine). + + psxapi - Provides function calls for using functions provided by the PS1 + BIOS. + + psxetc - Provides some miscellaneous features used by the other libraries + as well as a dynamic linker for loading DLLs at runtime. + + psxspu - SPU library (work in progress). Currently supports hardware + init, sample data upload via DMA and playing sound samples. + Lacks support for reverb and a sequenced music subsystem. + + psxcd - CD-ROM library for loading files, parsing directories + (PSn00bSDK addition), CD Audio/XA playback with provisions for + data streaming. Also supports multi-session discs (must be + selected manually). + + psxpress - Experimental MDEC library. Currently provides APIs to feed data + to the MDEC and retrieve decoded images, as well as a + decompressor for the Huffman encoding used in FMVs encoded using + Sony tools. A custom decompressor based on arithmetic coding + might be implemented in the future. + Each library has its own readme file that contains a todo list, credits and some additional details of the library. Changes of all the libraries must be covered in the changelog.txt file. @@ -52,7 +58,7 @@ Brief summary of libraries: Compiling: - Refer to INSTALL.md in the parent directory for up-to-date installation + Refer to installation.md in the doc directory for up-to-date installation instructions. --- THE SECTION BELOW IS OUTDATED AND ONLY KEPT FOR REFERENCE --- @@ -144,11 +150,6 @@ LibPSn00b Library to-do list: psxmcrd - Better and faster memory card library with provisions for low-level card access. The psxpad library would provide communication routines for the card library. - - psxpress - MDEC and data decompression library. May use DEFLATE or LZ77 - for compressing MDEC data instead of Huffman as used in the - official libraries. It may yield better compression which may - potentially result in higher quality FMVs. psxexp - Support library for various devices connected to the serial or expansion port, including both official ones (e.g. PCMCIA cards -- cgit v1.2.3 From 8c68b4b8a5bf7757b8e4d6bc2f68f10584b0deb1 Mon Sep 17 00:00:00 2001 From: spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> Date: Sat, 12 Mar 2022 14:28:11 +0100 Subject: Minor fixes, add C++ placement new, n00bdemo 573 support --- examples/demos/n00bdemo/main.c | 46 ++++++++++++++++++++++++++++---- examples/io/system573/CMakeLists.txt | 2 +- examples/lowlevel/cartrom/CMakeLists.txt | 2 +- examples/sound/spustream/main.c | 4 +++ libpsn00b/include/elf.h | 2 +- libpsn00b/libc/abort.c | 14 ++++++++++ libpsn00b/libc/c++-support.cxx | 39 ++++++++++++++++----------- libpsn00b/libc/putchar.s | 10 ------- 8 files changed, 85 insertions(+), 34 deletions(-) delete mode 100644 libpsn00b/libc/putchar.s (limited to 'examples/io') diff --git a/examples/demos/n00bdemo/main.c b/examples/demos/n00bdemo/main.c index d2fe317..cb64c42 100644 --- a/examples/demos/n00bdemo/main.c +++ b/examples/demos/n00bdemo/main.c @@ -11,14 +11,19 @@ * * Changelog: * + * Mar 12, 2022 - Added Konami System 573 support. + * * May 10, 2021 - Variable types updated for psxgpu.h changes. * * Apr 4, 2019 - Some code clean-up and added more comments. * - * Mar 20, 2019 - Initial completed version. + * Mar 20, 2019 - Initial completed version. * */ - + +// Comment to disable 573 support +#define SYSTEM_573_SUPPORT + #include #include #include @@ -27,7 +32,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -64,6 +71,34 @@ SPRT psn00b_sprite; void sort_overlay(int showlotl); void lightdemo(); +#ifdef SYSTEM_573_SUPPORT +#define K573_WATCHDOG *((volatile uint16_t *) 0x1f5c0000) +#define K573_EXP1_CFG 0x24173f47 + +/* + The only thing required to support the 573 is to periodically reset the + watchdog. Hooking the vblank IRQ (through VSyncCallback) is the "right" way + to do it, however using a hardware timer running at a higher rate (100 Hz) + seems to improve stability. +*/ +void reset573Watchdog() { + K573_WATCHDOG = 0; +} + +void system573Setup() { + EnterCriticalSection(); + + EXP1_ADDR = 0x1f000000; + EXP1_DELAY_SIZE = K573_EXP1_CFG; + TIMER_CTRL(2) = 0x0258; // CLK/8 input, IRQ on reload + TIMER_RELOAD(2) = (F_CPU / 8) / 100; // 100 Hz + + // Configure timer 2 IRQ + ChangeClearRCnt(2, 0); + InterruptCallback(6, &reset573Watchdog); + ExitCriticalSection(); +} +#endif void UploadTIM(TIM_IMAGE *tim) { @@ -197,9 +232,10 @@ void unpackModels() { } void init() { - - int i; - +#ifdef SYSTEM_573_SUPPORT + system573Setup(); +#endif + // Init display initDisplay(); diff --git a/examples/io/system573/CMakeLists.txt b/examples/io/system573/CMakeLists.txt index 1c74347..2a362e8 100644 --- a/examples/io/system573/CMakeLists.txt +++ b/examples/io/system573/CMakeLists.txt @@ -1,7 +1,7 @@ # PSn00bSDK example CMake script # (C) 2021 spicyjpeg - MPL licensed -cmake_minimum_required(VERSION 3.21) +cmake_minimum_required(VERSION 3.20) project( system573 diff --git a/examples/lowlevel/cartrom/CMakeLists.txt b/examples/lowlevel/cartrom/CMakeLists.txt index 107cc3d..7d5e86e 100644 --- a/examples/lowlevel/cartrom/CMakeLists.txt +++ b/examples/lowlevel/cartrom/CMakeLists.txt @@ -1,7 +1,7 @@ # PSn00bSDK example CMake script # (C) 2021 spicyjpeg - MPL licensed -cmake_minimum_required(VERSION 3.21) +cmake_minimum_required(VERSION 3.20) project( cartrom diff --git a/examples/sound/spustream/main.c b/examples/sound/spustream/main.c index 6284c6d..6b9db93 100644 --- a/examples/sound/spustream/main.c +++ b/examples/sound/spustream/main.c @@ -308,6 +308,10 @@ void init_stream(CdlFILE *file) { CdReadyCallback(&cd_event_handler); ExitCriticalSection(); + // Configure the CD drive to read 2048-byte sectors at 2x speed. + uint8_t mode = CdlModeSpeed; + CdControl(CdlSetmode, (const uint8_t *) &mode, 0); + // Set the initial LBA of the stream file, which is going to be incremented // as the stream is played. str_ctx.lba = CdPosToInt(&(file->pos)); diff --git a/libpsn00b/include/elf.h b/libpsn00b/include/elf.h index b4c4408..abfb3d5 100644 --- a/libpsn00b/include/elf.h +++ b/libpsn00b/include/elf.h @@ -12,7 +12,7 @@ #ifndef __ELF_H #define __ELF_H -#include +#include typedef enum { DT_NULL = 0, /* Marks end of dynamic section */ diff --git a/libpsn00b/libc/abort.c b/libpsn00b/libc/abort.c index 1d07037..de4323d 100644 --- a/libpsn00b/libc/abort.c +++ b/libpsn00b/libc/abort.c @@ -1,5 +1,8 @@ + #include +/* Standard abort */ + void abort() { printf("abort()\n"); @@ -7,9 +10,20 @@ void abort() { __asm__ volatile(""); } +/* Internal function used by assert() macro */ + void _assert_abort(const char *file, int line, const char *expr) { printf("%s:%d: assert(%s)\n", file, line, expr); for (;;) __asm__ volatile(""); } + +/* Pure virtual function call (C++) */ + +void __cxa_pure_virtual(void) { + printf("__cxa_pure_virtual()\n"); + + for (;;) + __asm__ volatile(""); +} diff --git a/libpsn00b/libc/c++-support.cxx b/libpsn00b/libc/c++-support.cxx index d0c0f3a..38354dd 100644 --- a/libpsn00b/libc/c++-support.cxx +++ b/libpsn00b/libc/c++-support.cxx @@ -1,39 +1,46 @@ + #include #include #include -extern "C" void __cxa_pure_virtual(void) { - printf("__cxa_pure_virtual()\n"); - - for (;;) - __asm__ volatile(""); -} +/* Default new/delete operators */ -void* operator new(size_t size) { +void *operator new(size_t size) noexcept { return malloc(size); } -void* operator new[](size_t size) { +void *operator new[](size_t size) noexcept { return malloc(size); } -void operator delete(void* ptr) { +void operator delete(void *ptr) noexcept { free(ptr); } -void operator delete[](void* ptr) { +void operator delete[](void *ptr) noexcept { free(ptr); } -/*- - * +/* + * https://en.cppreference.com/w/cpp/memory/new/operator_delete * * Called if a user-defined replacement is provided, except that it's * unspecified whether other overloads or this overload is called when deleting - * objects of incomplete type and arrays of non-class and trivially-destructible - * class types. + * objects of incomplete type and arrays of non-class and trivially + * destructible class types. * - * A memory allocator can use the given size to be more efficient */ -void operator delete(void* ptr, unsigned int) { + * A memory allocator can use the given size to be more efficient. + */ +void operator delete(void *ptr, size_t size) noexcept { free(ptr); } + +/* Placement new operators */ + +void *operator new(size_t size, void *ptr) noexcept { + return ptr; +} + +void *operator new[](size_t size, void *ptr) noexcept { + return ptr; +} diff --git a/libpsn00b/libc/putchar.s b/libpsn00b/libc/putchar.s deleted file mode 100644 index a3f6c57..0000000 --- a/libpsn00b/libc/putchar.s +++ /dev/null @@ -1,10 +0,0 @@ -.set noreorder -.section .text - -.global putchar -.type putchar, @function -putchar: - addiu $t2, $0, 0xa0 - jr $t2 - addiu $t1, $0, 0x3c - \ No newline at end of file -- cgit v1.2.3 From 4bbfe640a8c357137524e797a8d2bd0a94d3abfa Mon Sep 17 00:00:00 2001 From: spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> Date: Sun, 20 Mar 2022 10:56:23 +0100 Subject: Remove stdint.h, fix n00bdemo crashing --- examples/demos/n00bdemo/logo.c | 4 +++- examples/demos/n00bdemo/main.c | 5 ++--- examples/io/pads/spi.c | 1 + examples/io/pads/spi.h | 1 + libpsn00b/include/stdint.h | 16 ---------------- libpsn00b/include/stdlib.h | 2 +- libpsn00b/libc/start.c | 23 ++++++++++++----------- 7 files changed, 20 insertions(+), 32 deletions(-) delete mode 100644 libpsn00b/include/stdint.h (limited to 'examples/io') diff --git a/examples/demos/n00bdemo/logo.c b/examples/demos/n00bdemo/logo.c index 40160e7..784c9e1 100644 --- a/examples/demos/n00bdemo/logo.c +++ b/examples/demos/n00bdemo/logo.c @@ -51,9 +51,11 @@ typedef struct { int size; } NODE; +extern NODE _end[]; + void DumpHeap() { - NODE *n = (NODE*)GetBSSend(); + NODE *n = _end; printf( "--\n" ); diff --git a/examples/demos/n00bdemo/main.c b/examples/demos/n00bdemo/main.c index cb64c42..439bccc 100644 --- a/examples/demos/n00bdemo/main.c +++ b/examples/demos/n00bdemo/main.c @@ -232,12 +232,11 @@ void unpackModels() { } void init() { + // Init display + initDisplay(); #ifdef SYSTEM_573_SUPPORT system573Setup(); #endif - - // Init display - initDisplay(); FntLoad( 960, 0 ); diff --git a/examples/io/pads/spi.c b/examples/io/pads/spi.c index 43b5bc3..133782c 100644 --- a/examples/io/pads/spi.c +++ b/examples/io/pads/spi.c @@ -27,6 +27,7 @@ */ #include +#include #include #include #include diff --git a/examples/io/pads/spi.h b/examples/io/pads/spi.h index 7d4d75b..8c17df3 100644 --- a/examples/io/pads/spi.h +++ b/examples/io/pads/spi.h @@ -7,6 +7,7 @@ #define __SPI_H #include +#include #include // Maximum request/response length (34 bytes for pads, 140 for memory cards). diff --git a/libpsn00b/include/stdint.h b/libpsn00b/include/stdint.h deleted file mode 100644 index 83acb00..0000000 --- a/libpsn00b/include/stdint.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _STDINT_H -#define _STDINT_H - -typedef unsigned int size_t; - -typedef char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long long int64_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; - -#endif // _STDINT_H \ No newline at end of file diff --git a/libpsn00b/include/stdlib.h b/libpsn00b/include/stdlib.h index b187a6f..4c4fcd3 100644 --- a/libpsn00b/include/stdlib.h +++ b/libpsn00b/include/stdlib.h @@ -44,7 +44,7 @@ double strtod(const char *nptr, char **endptr); float strtof(const char *nptr, char **endptr); // Memory allocation functions -unsigned int *GetBSSend(); +void _mem_init(int ram_size, int stack_max_size); void InitHeap(unsigned int *addr, int size); int SetHeapSize(int size); void *malloc(int size); diff --git a/libpsn00b/libc/start.c b/libpsn00b/libc/start.c index f190794..fd6fe33 100644 --- a/libpsn00b/libc/start.c +++ b/libpsn00b/libc/start.c @@ -6,19 +6,20 @@ #include #include #include +#include -#define KERNEL_ARG_STRING ((const char *) 0x80000180) -#define KERNEL_RETURN_VALUE ((volatile int *) 0x8000dffc) +#define KERNEL_ARG_STRING ((const char *) 0x80000180) +#define KERNEL_RETURN_VALUE ((volatile int *) 0x8000dffc) /* Argument parsing */ -int32_t __argc; -const char **__argv; +int __argc; +const char **__argv; #define ARGC_MAX 16 -static const char *_argv_buffer[ARGC_MAX]; -static char _arg_string_buffer[132]; +static const char *_argv_buffer[ARGC_MAX]; +static char _arg_string_buffer[132]; static void _parse_kernel_args() { // Copy the argument string from kernel memory into a private buffer (which @@ -61,10 +62,10 @@ extern uint8_t _end[]; // useful though to change the stack size and/or reinitialize the heap on // systems that have more than 2 MB of RAM (e.g. emulators, devkits, PS1-based // arcade boards). -void _mem_init(size_t ram_size, size_t stack_max_size) { - void *exe_end = _end + 4; - size_t exe_size = (size_t) exe_end - (size_t) __text_start; - size_t ram_used = (0x10000 + exe_size + stack_max_size) & 0xfffffffc; +void _mem_init(int ram_size, int stack_max_size) { + void *exe_end = _end + 4; + int exe_size = (int) exe_end - (int) __text_start; + int ram_used = (0x10000 + exe_size + stack_max_size) & 0xfffffffc; InitHeap(exe_end, ram_size - ram_used); } @@ -74,7 +75,7 @@ void _mem_init(size_t ram_size, size_t stack_max_size) { extern void (*__CTOR_LIST__[])(void); extern void (*__DTOR_LIST__[])(void); -extern int32_t main(int32_t 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 -- cgit v1.2.3