shithub: psxe

Download patch

ref: 92c0706c0003ee1684ed83472e2ef1377fe6ea4c
parent: c84d48a6abd8f595a1d3b9780bd73c5983502c02
author: allkern <lisandroaalarcon@gmail.com>
date: Sun Jul 2 13:40:51 EDT 2023

Implement very basic input support

--- a/frontend/screen.c
+++ b/frontend/screen.c
@@ -1,5 +1,20 @@
 #include "screen.h"
 
+uint16_t screen_get_button(SDL_Keycode k) {
+    if (k == SDLK_x     ) return PSXI_SW_SDA_CROSS;
+    if (k == SDLK_a     ) return PSXI_SW_SDA_SQUARE;
+    if (k == SDLK_w     ) return PSXI_SW_SDA_TRIANGLE;
+    if (k == SDLK_d     ) return PSXI_SW_SDA_CIRCLE;
+    if (k == SDLK_RETURN) return PSXI_SW_SDA_START;
+    if (k == SDLK_q     ) return PSXI_SW_SDA_SELECT;
+    if (k == SDLK_UP    ) return PSXI_SW_SDA_PAD_UP;
+    if (k == SDLK_DOWN  ) return PSXI_SW_SDA_PAD_DOWN;
+    if (k == SDLK_LEFT  ) return PSXI_SW_SDA_PAD_LEFT;
+    if (k == SDLK_RIGHT ) return PSXI_SW_SDA_PAD_RIGHT;
+
+    return 0;
+}
+
 psxe_screen_t* psxe_screen_create() {
     return (psxe_screen_t*)malloc(sizeof(psxe_screen_t));
 }
@@ -19,6 +34,7 @@
     screen->open = 1;
     screen->format = SDL_PIXELFORMAT_BGR555;
     screen->psx = psx;
+    screen->pad = psx_get_pad(psx);
 
     SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
 
@@ -97,8 +113,20 @@
                 switch (event.key.keysym.sym) {
                     case SDLK_F1: {
                         psxe_screen_toggle_debug_mode(screen);
+
+                        return;
                     } break;
                 }
+
+                uint16_t mask = screen_get_button(event.key.keysym.sym);
+
+                psx_pad_button_press(screen->pad, mask);
+            } break;
+
+            case SDL_KEYUP: {
+                uint16_t mask = screen_get_button(event.key.keysym.sym);
+
+                psx_pad_button_release(screen->pad, mask);
             } break;
         }
     }
--- a/frontend/screen.h
+++ b/frontend/screen.h
@@ -14,6 +14,7 @@
     SDL_Texture* texture;
 
     psx_t* psx;
+    psx_pad_t* pad;
 
     unsigned int saved_scale;
     unsigned int width, height, scale;
--- a/psx/dev/ic.c
+++ b/psx/dev/ic.c
@@ -53,7 +53,7 @@
 void psx_ic_write32(psx_ic_t* ic, uint32_t offset, uint32_t value) {
     switch (offset) {
         case 0x00: ic->stat &= value; break;
-        case 0x04: ic->mask = value; break;
+        case 0x04: log_fatal("32 IMASK write %08x", value); ic->mask = value; break;
 
         default: {
             log_warn("Unhandled 32-bit IC write at offset %08x (%08x)", offset, value);
@@ -69,7 +69,7 @@
 void psx_ic_write16(psx_ic_t* ic, uint32_t offset, uint16_t value) {
     switch (offset) {
         case 0x00: ic->stat &= value; break;
-        case 0x04: ic->mask = value; break;
+        case 0x04: log_fatal("16 IMASK write %04x", value); ic->mask = value; break;
 
         default: {
             log_warn("Unhandled 16-bit IC write at offset %08x (%08x)", offset, value);
--- a/psx/dev/pad.c
+++ b/psx/dev/pad.c
@@ -9,23 +9,32 @@
     return (psx_pad_t*)malloc(sizeof(psx_pad_t));
 }
 
-void psx_pad_init(psx_pad_t* pad) {
+void psx_pad_init(psx_pad_t* pad, psx_ic_t* ic) {
     memset(pad, 0, sizeof(psx_pad_t));
 
+    pad->ic = ic;
+
     pad->io_base = PSX_PAD_BEGIN;
     pad->io_size = PSX_PAD_SIZE;
+
+    pad->rx_buf[0] = 0xff;
+    pad->rx_buf[1] = 0xff;
+    pad->rx_buf[2] = 0x41;
+    pad->rx_buf[3] = 0x5a;
+    pad->rx_buf[4] = 0xff;
+    pad->rx_buf[5] = 0xff;
 }
 
 uint32_t psx_pad_read32(psx_pad_t* pad, uint32_t offset) {
-    switch (offset) {
-        case 0: return 0x00;
-        case 4: return 0x03;
-        case 8: return pad->mode;
-        case 10: return pad->ctrl;
-        case 14: return pad->baud;
-    }
+    // switch (offset) {
+    //     case 0: return 0x00;
+    //     case 4: return 0x01;
+    //     case 8: return pad->mode;
+    //     case 10: return pad->ctrl;
+    //     case 14: return pad->baud;
+    // }
 
-    log_warn("Unhandled 32-bit PAD read at offset %08x", offset);
+    log_fatal("Unhandled 32-bit PAD read at offset %08x", offset);
 
     return 0x0;
 }
@@ -32,14 +41,14 @@
 
 uint16_t psx_pad_read16(psx_pad_t* pad, uint32_t offset) {
     switch (offset) {
-        case 0: return 0x00;
-        case 4: return 0x03;
-        case 8: return pad->mode;
+        // case 0: return 0x00;
+        // case 4: return 0x03;
+        // case 8: return pad->mode;
         case 10: return pad->ctrl;
-        case 14: return pad->baud;
+        // case 14: return pad->baud;
     }
 
-    log_warn("Unhandled 16-bit PAD read at offset %08x", offset);
+    log_fatal("Unhandled 16-bit PAD read at offset %08x", offset);
 
     return 0x0;
 }
@@ -46,7 +55,7 @@
 
 uint8_t psx_pad_read8(psx_pad_t* pad, uint32_t offset) {
     switch (offset) {
-        case 0: return 0x00;
+        case 0: return pad->rx_buf[(pad->rx_index++) % 6];
         case 4: return 0x03;
         case 8: return pad->mode;
         case 10: return pad->ctrl;
@@ -53,38 +62,38 @@
         case 14: return pad->baud;
     }
 
-    log_warn("Unhandled 8-bit PAD read at offset %08x", offset);
+    log_fatal("Unhandled 8-bit PAD read at offset %08x", offset);
 
     return 0x0;
 }
 
 void psx_pad_write32(psx_pad_t* pad, uint32_t offset, uint32_t value) {
-    switch (offset) {
-        case 0: break;
-        case 4: break;
-        case 8: pad->mode = value & 0xffff; return;
-        case 10: pad->ctrl = value & 0xffff; return;
-        case 14: pad->baud = value & 0xffff; return;
-    }
+    // switch (offset) {
+    //     case 0: log_fatal("PAD write %08x", value); break;
+    //     case 4: break;
+    //     case 8: pad->mode = value & 0xffff; return;
+    //     case 10: pad->ctrl = value & 0xffff; return;
+    //     case 14: pad->baud = value & 0xffff; return;
+    // }
 
-    log_warn("Unhandled 32-bit PAD write at offset %08x (%08x)", offset, value);
+    log_fatal("Unhandled 32-bit PAD write at offset %08x (%08x)", offset, value);
 }
 
 void psx_pad_write16(psx_pad_t* pad, uint32_t offset, uint16_t value) {
     switch (offset) {
-        case 0: break;
-        case 4: break;
-        case 8: pad->mode = value; return;
+        // case 0: break;
+        // case 4: break;
+        // case 8: pad->mode = value; return;
         case 10: pad->ctrl = value; return;
-        case 14: pad->baud = value; return;
+        // case 14: pad->baud = value; return;
     }
 
-    log_warn("Unhandled 16-bit PAD write at offset %08x (%04x)", offset, value);
+    log_fatal("Unhandled 16-bit PAD write at offset %08x (%04x)", offset, value);
 }
 
 void psx_pad_write8(psx_pad_t* pad, uint32_t offset, uint8_t value) {
     switch (offset) {
-        case 0: break;
+        case 0: return; break;
         case 4: break;
         case 8: pad->mode = value; return;
         case 10: pad->ctrl = value; return;
@@ -91,7 +100,15 @@
         case 14: pad->baud = value; return;
     }
 
-    log_warn("Unhandled 8-bit PAD write at offset %08x (%02x)", offset, value);
+    log_fatal("Unhandled 8-bit PAD write at offset %08x (%02x)", offset, value);
+}
+
+void psx_pad_button_press(psx_pad_t* pad, uint16_t data) {
+    *((uint16_t*)(&pad->rx_buf[4])) &= ~data;
+}
+
+void psx_pad_button_release(psx_pad_t* pad, uint16_t data) {
+    *((uint16_t*)(&pad->rx_buf[4])) |= data;
 }
 
 void psx_pad_destroy(psx_pad_t* pad) {
--- a/psx/dev/pad.h
+++ b/psx/dev/pad.h
@@ -3,18 +3,65 @@
 
 #include <stdint.h>
 
+#include "ic.h"
+
 #define PSX_PAD_BEGIN 0x1f801040
 #define PSX_PAD_SIZE  0x10
 #define PSX_PAD_END   0x1f80104f
 
+// Controller/Input IDs
+#define PSXI_ID_SD          0x5a41
+#define PSXI_ID_SA_PAD      0x5a73
+#define PSXI_ID_SA_STICK    0x5a53
+
+#define PSXI_SW_SDA_SELECT      0x0001
+#define PSXI_SW_SDA_L3          0x0002
+#define PSXI_SW_SDA_R3          0x0004
+#define PSXI_SW_SDA_START       0x0008
+#define PSXI_SW_SDA_PAD_UP      0x0010
+#define PSXI_SW_SDA_PAD_RIGHT   0x0020
+#define PSXI_SW_SDA_PAD_DOWN    0x0040
+#define PSXI_SW_SDA_PAD_LEFT    0x0080
+#define PSXI_SW_SDA_L2          0x0100
+#define PSXI_SW_SDA_R2          0x0200
+#define PSXI_SW_SDA_L1          0x0400
+#define PSXI_SW_SDA_R1          0x0800
+#define PSXI_SW_SDA_TRIANGLE    0x1000
+#define PSXI_SW_SDA_CIRCLE      0x2000
+#define PSXI_SW_SDA_CROSS       0x4000
+#define PSXI_SW_SDA_SQUARE      0x8000
+
+/*
+    To-do: Design API to interface any type of controller.
+
+    Possible names:
+    - psx_im (Input Method)
+    - psx_controller
+    - psx_input
+
+    Private API should contain a way to get the ID of
+    this controller, public API should contain the following
+    functions: (WIP)
+    - _write(data)
+    - _read()
+    _ _on_button_press(id)
+    - _on_button_release(id)
+    - _on_analog_change(id)
+*/
+
 typedef struct {
     uint32_t io_base, io_size;
 
+    psx_ic_t* ic;
+
+    uint8_t rx_buf[6];
+    int rx_index;
+
     uint16_t mode, ctrl, baud;
 } psx_pad_t;
 
 psx_pad_t* psx_pad_create();
-void psx_pad_init(psx_pad_t*);
+void psx_pad_init(psx_pad_t*, psx_ic_t*);
 uint32_t psx_pad_read32(psx_pad_t*, uint32_t);
 uint16_t psx_pad_read16(psx_pad_t*, uint32_t);
 uint8_t psx_pad_read8(psx_pad_t*, uint32_t);
@@ -22,5 +69,7 @@
 void psx_pad_write16(psx_pad_t*, uint32_t, uint16_t);
 void psx_pad_write8(psx_pad_t*, uint32_t, uint8_t);
 void psx_pad_destroy(psx_pad_t*);
+void psx_pad_button_press(psx_pad_t*, uint16_t);
+void psx_pad_button_release(psx_pad_t*, uint16_t);
 
 #endif
\ No newline at end of file
--- a/psx/psx.c
+++ b/psx/psx.c
@@ -113,7 +113,7 @@
     psx_spu_init(psx->spu);
     psx_timer_init(psx->timer);
     psx_cdrom_init(psx->cdrom, psx->ic);
-    psx_pad_init(psx->pad);
+    psx_pad_init(psx->pad, psx->ic);
     psx_bios_load(psx->bios, bios_path);
     psx_cpu_init(psx->cpu, psx->bus);
 }
--