shithub: psxe

Download patch

ref: 41fb845c7cc25d7508851aeced8114fd8c0f4c8d
parent: 59dc0947be593d508695aa81c11b5ce477c27129
author: allkern <lisandroaalarcon@gmail.com>
date: Wed May 8 20:43:29 EDT 2024

Input fixes

Fixes Silent Hill, Harvest Moon, Chrono Cross, Capcom vs. SNK, US Racer, Army Men - Air Attack, Alone in the Dark - The New Nightmare, and more

--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -304,6 +304,7 @@
             int m = PFIFO_POP;
 
             if (!(VALID_BCD(m) && VALID_BCD(s) && VALID_BCD(f) && (f < 0x75))) {
+                printf("setloc: invalid msf\n");
                 cdrom->irq_delay = DELAY_1MS;
                 cdrom->delayed_command = CDL_ERROR;
                 cdrom->state = CD_STATE_ERROR;
@@ -323,11 +324,11 @@
 
             cdrom->seek_pending = 1;
 
-            log_fatal("setloc: %02x:%02x:%02x",
-                cdrom->seek_msf.m,
-                cdrom->seek_msf.s,
-                cdrom->seek_msf.f
-            );
+            // printf("setloc: %02x:%02x:%02x\n",
+            //     cdrom->seek_msf.m,
+            //     cdrom->seek_msf.s,
+            //     cdrom->seek_msf.f
+            // );
 
             cdrom->irq_delay = DELAY_1MS;
             cdrom->delayed_command = CDL_SETLOC;
@@ -336,7 +337,7 @@
 
         case CD_STATE_SEND_RESP1: {
             SET_BITS(ifr, IFR_INT, IFR_INT3);
-            RESP_PUSH(GETSTAT_MOTOR);
+            RESP_PUSH(GETSTAT_MOTOR | GETSTAT_SEEK);
 
             if (cdrom->ongoing_read_command) {
                 // printf("command=%02x\n", cdrom->ongoing_read_command);
@@ -881,24 +882,24 @@
 
         case CD_STATE_SEND_RESP1: {
             SET_BITS(ifr, IFR_INT, IFR_INT3);
-            RESP_PUSH(cdrom->dfifo[0x13]);
-            RESP_PUSH(cdrom->dfifo[0x12]);
-            RESP_PUSH(cdrom->dfifo[0x11]);
-            RESP_PUSH(cdrom->dfifo[0x10]);
-            RESP_PUSH(cdrom->dfifo[0x0f]);
-            RESP_PUSH(cdrom->dfifo[0x0e]);
-            RESP_PUSH(cdrom->dfifo[0x0d]);
-            RESP_PUSH(cdrom->dfifo[0x0c]);
+            RESP_PUSH(cdrom->xa_sector_buf[0x13]);
+            RESP_PUSH(cdrom->xa_sector_buf[0x12]);
+            RESP_PUSH(cdrom->xa_sector_buf[0x11]);
+            RESP_PUSH(cdrom->xa_sector_buf[0x10]);
+            RESP_PUSH(cdrom->xa_sector_buf[0x0f]);
+            RESP_PUSH(cdrom->xa_sector_buf[0x0e]);
+            RESP_PUSH(cdrom->xa_sector_buf[0x0d]);
+            RESP_PUSH(cdrom->xa_sector_buf[0x0c]);
 
-            // if (cdrom->ongoing_read_command) {
-            //     // printf("command=%02x\n", cdrom->ongoing_read_command);
-            //     cdrom->state = CD_STATE_SEND_RESP2;
-            //     cdrom->delayed_command = cdrom->ongoing_read_command;
-            //     cdrom->irq_delay = DELAY_1MS;
-            // } else {
+            if (cdrom->ongoing_read_command) {
+                // printf("command=%02x\n", cdrom->ongoing_read_command);
+                cdrom->state = CD_STATE_SEND_RESP2;
+                cdrom->delayed_command = cdrom->ongoing_read_command;
+                cdrom->irq_delay = DELAY_1MS;
+            } else {
                 cdrom->delayed_command = CDL_NONE;
                 cdrom->state = CD_STATE_RECV_CMD;
-            // }
+            }
         } break;
     }
 }
@@ -1564,6 +1565,9 @@
 }
 
 uint8_t cdrom_read_rfifo(psx_cdrom_t* cdrom) {
+    if (cdrom->rfifo_index < 0)
+        return 0;
+
     uint8_t data = cdrom->rfifo[--cdrom->rfifo_index];
 
     if (cdrom->rfifo_index == 0)
@@ -1608,17 +1612,17 @@
 }
 
 void cdrom_write_cmd(psx_cdrom_t* cdrom, uint8_t value) {
-    // printf("%s(%02x) %u params=[%02x, %02x, %02x, %02x, %02x, %02x]\n",
-    //     g_psx_cdrom_command_names[value],
-    //     value,
-    //     cdrom->pfifo_index,
-    //     cdrom->pfifo[0],
-    //     cdrom->pfifo[1],
-    //     cdrom->pfifo[2],
-    //     cdrom->pfifo[3],
-    //     cdrom->pfifo[4],
-    //     cdrom->pfifo[5]
-    // );
+    printf("%s(%02x) %u params=[%02x, %02x, %02x, %02x, %02x, %02x]\n",
+        g_psx_cdrom_command_names[value],
+        value,
+        cdrom->pfifo_index,
+        cdrom->pfifo[0],
+        cdrom->pfifo[1],
+        cdrom->pfifo[2],
+        cdrom->pfifo[3],
+        cdrom->pfifo[4],
+        cdrom->pfifo[5]
+    );
 
     cdrom->command = value;
     cdrom->state = CD_STATE_RECV_CMD;
--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -239,7 +239,9 @@
     uint32_t size = hdr >> 24;
     uint32_t addr = dma->gpu.madr;
 
-    while (true) {
+    int timeout = 16384;
+
+    while (timeout--) {
         while (size--) {
             addr = (addr + (CHCR_STEP(gpu) ? -4 : 4)) & 0x1ffffc;
 
--- a/psx/dev/mcd.c
+++ b/psx/dev/mcd.c
@@ -12,6 +12,7 @@
     mcd->flag = 0x08;
     mcd->path = path;
     mcd->buf = malloc(MCD_MEMORY_SIZE);
+    mcd->tx_data_ready = 0;
 
     memset(mcd->buf, 0, MCD_MEMORY_SIZE);
 
@@ -33,8 +34,6 @@
 }
 
 uint8_t psx_mcd_read(psx_mcd_t* mcd) {
-    return 0xff;
-
     switch (mcd->state) {
         case MCD_STATE_TX_HIZ: mcd->tx_data = 0xff; break;
         case MCD_STATE_TX_FLG: mcd->tx_data = mcd->flag; mcd->flag = 0x00; break;
@@ -49,6 +48,8 @@
                 case 'S': mcd->state = MCD_S_STATE_TX_ACK1; break;
             }
 
+            // printf("mcd read %02x\n", mcd->tx_data);
+
             // log_set_quiet(0);
             // log_fatal("mcd read %02x", mcd->tx_data);
             // log_set_quiet(1);
@@ -77,6 +78,8 @@
                 break;
             }
 
+            // printf("mcd read %02x\n", data);
+
             // log_set_quiet(0);
             // log_fatal("mcd read %02x", data);
             // log_set_quiet(1);
@@ -92,6 +95,8 @@
             // log_fatal("mcd read %02x", 'G');
             // log_set_quiet(1);
 
+            // printf("mcd read %02x\n", 'G');
+
             return 'G';
         } break;
 
@@ -110,6 +115,8 @@
                 break;
             }
 
+            // printf("mcd read %02x\n", mcd->rx_data);
+
             // log_set_quiet(0);
             // log_fatal("mcd read %02x", mcd->rx_data);
             // log_set_quiet(1);
@@ -127,6 +134,8 @@
             // log_fatal("mcd read %02x", 'G');
             // log_set_quiet(1);
 
+            // printf("mcd read %02x\n", 'G');
+
             return 'G';
         } break;
     }
@@ -138,15 +147,17 @@
     // log_fatal("mcd read %02x", mcd->tx_data);
     // log_set_quiet(1);
 
+    // printf("mcd read %02x\n", mcd->tx_data);
+
     return mcd->tx_data;
 }
 
 void psx_mcd_write(psx_mcd_t* mcd, uint8_t data) {
-    return;
-
     // log_set_quiet(0);
     // log_fatal("mcd write %02x", data);
     // log_set_quiet(1);
+
+    // printf("mcd write %02x\n", data);
 
     switch (mcd->state) {
         case MCD_STATE_TX_FLG: mcd->mode = data; break;
--- a/psx/dev/pad.c
+++ b/psx/dev/pad.c
@@ -5,6 +5,8 @@
 #include "pad.h"
 #include "../log.h"
 
+#define JOY_IRQ_DELAY 512
+
 uint32_t pad_read_rx(psx_pad_t* pad) {
     int slot = (pad->ctrl >> 13) & 1;
 
@@ -34,10 +36,6 @@
         } break;
 
         case DEST_MCD: {
-            pad->dest[slot] = 0;
-
-            return 0xff;
-
             if (!mcd) {
                 pad->dest[slot] = 0;
 
@@ -58,7 +56,6 @@
 
 void pad_write_tx(psx_pad_t* pad, uint16_t data) {
     int slot = (pad->ctrl >> 13) & 1;
-    // printf("slot=%u dest=%02x write tx data=%02x ", slot, pad->dest[slot], data);
 
     psx_input_t* joy = pad->joy_slot[slot];
     psx_mcd_t* mcd = pad->mcd_slot[slot];
@@ -66,20 +63,18 @@
     if (!(pad->ctrl & CTRL_TXEN))
         return;
 
-    // if (slot == 0)
-    //     printf("slot %u (%02x) write %08x\n", slot, pad->dest[slot], data);
-
     if (!pad->dest[slot]) {
         if ((data == DEST_JOY) || (data == DEST_MCD)) {
             pad->dest[slot] = data;
 
-            // printf("  slot=%u dest=%02x\n", slot, data);
+            if ((data == DEST_JOY) && !joy)
+                return;
 
-            // if (slot == 0)
-            //     printf("dest=%02x\n", data);
+            if ((data == DEST_MCD) && !mcd)
+                return;
 
             if (pad->ctrl & CTRL_ACIE)
-                pad->cycles_until_irq = 1500;
+                pad->cycles_until_irq = JOY_IRQ_DELAY;
         }
     } else {
         switch (pad->dest[slot]) {
@@ -97,10 +92,6 @@
             } break;
 
             case DEST_MCD: {
-                pad->dest[slot] = 0;
-
-                return;
-
                 if (!mcd) {
                     pad->dest[slot] = 0;
 
@@ -114,34 +105,34 @@
             } break;
         }
 
-        if (pad->ctrl & CTRL_ACIE)
-            pad->cycles_until_irq = 1500;
+        if (pad->ctrl & CTRL_ACIE) {
+            pad->irq_bit = 1;
+            pad->cycles_until_irq = JOY_IRQ_DELAY;
+        }
     }
 }
 
 uint32_t pad_handle_stat_read(psx_pad_t* pad) {
-    // // log_set_quiet(0);
-    // printf("pad stat read\n");
-    // // log_set_quiet(1);
-    // return 0x07;
-    psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
-
-    if (!joy)
-        return 0xff;
-
-    return 0x7;
+    return pad->stat | 7;
 }
 
 void pad_handle_ctrl_write(psx_pad_t* pad, uint32_t value) {
+    int slot = pad->ctrl & CTRL_SLOT;
+
     pad->ctrl = value;
 
     if (!(pad->ctrl & CTRL_JOUT)) {
-        // pad->dest[0] = 0;
-        // pad->dest[1] = 0;
         pad->ctrl &= ~CTRL_SLOT;
 
-        psx_mcd_reset(pad->mcd_slot[(pad->ctrl >> 13) & 1]);
+        if (pad->mcd_slot[slot >> 13])
+            psx_mcd_reset(pad->mcd_slot[slot >> 13]);
     }
+
+    // Reset STAT bits 3, 4, 5, 9
+    if (pad->ctrl & CTRL_ACKN) {
+        pad->stat &= 0xfdc7;
+        pad->ctrl &= ~CTRL_ACKN;
+    }
 }
 
 psx_pad_t* psx_pad_create() {
@@ -155,31 +146,40 @@
 
     pad->io_base = PSX_PAD_BEGIN;
     pad->io_size = PSX_PAD_SIZE;
+
+    pad->joy_slot[0] = NULL;
+    pad->joy_slot[1] = NULL;
+    pad->mcd_slot[0] = NULL;
+    pad->mcd_slot[1] = NULL;
 }
 
 uint32_t psx_pad_read32(psx_pad_t* pad, uint32_t offset) {
+    uint32_t v = 0;
+
     switch (offset) {
-        case 0: return pad_read_rx(pad);
-        case 4: return pad_handle_stat_read(pad);
-        case 8: return pad->mode;
-        case 10: return pad->ctrl;
-        case 14: return pad->baud;
+        case 0: v = pad_read_rx(pad); break;
+        case 4: v = pad_handle_stat_read(pad); break;
+        case 8: v = pad->mode; break;
+        case 10: v = pad->ctrl; break;
+        case 14: v = pad->baud; break;
     }
 
-    printf("Unhandled 32-bit PAD read at offset %08x", offset);
-
-    return 0x0;
+    return v;
 }
 
 uint16_t psx_pad_read16(psx_pad_t* pad, uint32_t offset) {
+    uint32_t v = 0;
+
     switch (offset) {
-        case 0: return pad_read_rx(pad) & 0xffff;
-        case 4: return pad_handle_stat_read(pad) & 0xffff;
-        case 8: return pad->mode;
-        case 10: return pad->ctrl & 0xffff;
-        case 14: return pad->baud;
+        case 0: v = pad_read_rx(pad) & 0xffff; break;
+        case 4: v = pad_handle_stat_read(pad) & 0xffff; break;
+        case 8: v = pad->mode; break;
+        case 10: v = pad->ctrl & 0xffff; break;
+        case 14: v = pad->baud; break;
     }
 
+    return v;
+
     printf("Unhandled 16-bit PAD read at offset %08x", offset);
 
     return 0x0;
@@ -186,17 +186,25 @@
 }
 
 uint8_t psx_pad_read8(psx_pad_t* pad, uint32_t offset) {
+    uint32_t v = 0;
+
     switch (offset) {
-        case 0: return pad_read_rx(pad) & 0xff;
-        case 4: return pad_handle_stat_read(pad) & 0xff;
-        case 8: return pad->mode & 0xff;
-        case 10: return pad->ctrl & 0xff;
-        case 14: return pad->baud & 0xff;
+        case 0: v = pad_read_rx(pad) & 0xff; break;
+        case 4: v = pad_handle_stat_read(pad) & 0xff; break;
+        case 8: v = pad->mode; break;
+        case 10: v = pad->ctrl & 0xff; break;
+        case 14: v = pad->baud; break;
     }
 
-    printf("Unhandled 8-bit PAD read at offset %08x", offset);
+    // if (offset <= 0xa)
+    // printf("slot=%d dest=%02x pad_read8(%02x)   -> %02x\n",
+    //     (pad->ctrl & CTRL_SLOT) >> 13,
+    //     pad->dest[(pad->ctrl & CTRL_SLOT) >> 13],
+    //     offset,
+    //     v
+    // );
 
-    return 0x0;
+    return v;
 }
 
 void psx_pad_write32(psx_pad_t* pad, uint32_t offset, uint32_t value) {
@@ -222,6 +230,14 @@
 }
 
 void psx_pad_write8(psx_pad_t* pad, uint32_t offset, uint8_t value) {
+    // if (offset <= 0xa)
+    // printf("slot=%d dest=%02x pad_write8(%02x)  -> %02x\n",
+    //     (pad->ctrl & CTRL_SLOT) >> 13,
+    //     pad->dest[(pad->ctrl & CTRL_SLOT) >> 13],
+    //     offset,
+    //     value
+    // );
+
     switch (offset) {
         case 0: pad_write_tx(pad, value); return;
         case 8: pad->mode = value; return;
@@ -270,6 +286,10 @@
 }
 
 void psx_pad_attach_mcd(psx_pad_t* pad, int slot, const char* path) {
+    printf("Memory Card support is disabled\n");
+
+    return;
+
     if (pad->mcd_slot[slot])
         psx_pad_detach_mcd(pad, slot);
 
@@ -294,6 +314,11 @@
 
         if (pad->cycles_until_irq <= 0) {
             psx_ic_irq(pad->ic, IC_JOY);
+
+            if (pad->irq_bit) {
+                pad->stat |= STAT_IRQ7;
+                pad->irq_bit = 0;
+            }
 
             pad->cycles_until_irq = 0;
         }
--- a/psx/dev/pad.h
+++ b/psx/dev/pad.h
@@ -115,6 +115,7 @@
     int cycles_until_irq;
     int cycle_counter;
     int dest[2];
+    int irq_bit;
 
     uint16_t mode, ctrl, baud, stat;
 } psx_pad_t;
--- a/psx/input/sda.c
+++ b/psx/input/sda.c
@@ -23,7 +23,7 @@
     sda->model = model;
     sda->state = SDA_STATE_TX_HIZ;
     sda->sw = 0xffff;
-    sda->sa_mode = 0;
+    sda->sa_mode = SA_MODE_DIGITAL;
     sda->adc0 = 0x80;
     sda->adc1 = 0x80;
     sda->adc2 = 0x80;
@@ -81,11 +81,6 @@
     psxi_sda_t* sda = (psxi_sda_t*)udata;
 
     // To-do: Handle TAP and MOT bytes here
-    if (data == 0x01) {
-        sda->tx_data = 0xff;
-        sda->tx_data_ready = 1;
-        sda->state = SDA_STATE_TX_HIZ;
-    }
 
     if (data == 0x43) {
         if (sda->sa_mode == SA_MODE_ANALOG) {
@@ -97,8 +92,6 @@
             sda->state = SDA_STATE_TX_HIZ;
         }
     }
-
-    return;
 }
 
 void psxi_sda_on_button_press(void* udata, uint32_t data) {
--