First dummy input implementation
authorFrancisco Javier Trujillo Mata <fjtrujy@gmail.com>
Sun, 31 Dec 2023 16:00:46 +0000 (17:00 +0100)
committerkub <derkub@gmail.com>
Sun, 18 Feb 2024 22:30:09 +0000 (23:30 +0100)
Makefile
platform/ps2/emu.c [new file with mode: 0644]
platform/ps2/in_ps2.c [new file with mode: 0644]
platform/ps2/in_ps2.h [new file with mode: 0644]
platform/ps2/plat.c

index 4174c29..cbed790 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -239,6 +239,8 @@ ifeq "$(PLATFORM)" "ps2"
 CFLAGS += -DUSE_BGR555 # -DLOG_TO_FILE
 LDLIBS += -lpatches -lgskit -ldmakit -lps2_drivers
 OBJS += platform/ps2/plat.o
+OBJS += platform/ps2/emu.o
+OBJS += platform/ps2/in_ps2.o
 USE_FRONTEND = 1
 endif
 ifeq "$(PLATFORM)" "libretro"
diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c
new file mode 100644 (file)
index 0000000..4ff7f16
--- /dev/null
@@ -0,0 +1,41 @@
+#include <stddef.h>
+
+#include <ps2_joystick_driver.h>
+#include <ps2_audio_driver.h>
+#include <libpad.h>
+
+#include "in_ps2.h"
+#include "../libpicofe/input.h"
+#include "../common/input_pico.h"
+#include "../common/emu.h"
+
+static struct in_default_bind in_ps2_defbinds[] =
+{
+       { PAD_UP,          IN_BINDTYPE_PLAYER12, GBTN_UP },
+       { PAD_DOWN,        IN_BINDTYPE_PLAYER12, GBTN_DOWN },
+       { PAD_LEFT,        IN_BINDTYPE_PLAYER12, GBTN_LEFT },
+       { PAD_RIGHT,       IN_BINDTYPE_PLAYER12, GBTN_RIGHT },
+       { PAD_SQUARE,      IN_BINDTYPE_PLAYER12, GBTN_A },
+       { PAD_CROSS,       IN_BINDTYPE_PLAYER12, GBTN_B },
+       { PAD_CIRCLE,      IN_BINDTYPE_PLAYER12, GBTN_C },
+       { PAD_START,       IN_BINDTYPE_PLAYER12, GBTN_START },
+       { PAD_TRIANGLE,    IN_BINDTYPE_EMU, PEVB_SWITCH_RND },
+       { PAD_L1,          IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
+       { PAD_R1,          IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
+       { PAD_SELECT,      IN_BINDTYPE_EMU, PEVB_MENU },
+       { 0, 0, 0 }
+};
+
+void plat_init(void) 
+{
+    init_joystick_driver(false);
+    in_ps2_init(in_ps2_defbinds);
+    in_probe();
+    init_audio_driver();
+    // plat_get_data_dir(rom_fname_loaded, sizeof(rom_fname_loaded));
+}
+
+void plat_finish(void) {
+    deinit_audio_driver();
+    deinit_joystick_driver(false);
+}
\ No newline at end of file
diff --git a/platform/ps2/in_ps2.c b/platform/ps2/in_ps2.c
new file mode 100644 (file)
index 0000000..d58d514
--- /dev/null
@@ -0,0 +1,268 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "libpad.h"
+#include "libmtap.h"
+
+#include "../libpicofe/input.h"
+#include "in_ps2.h"
+
+#define IN_PS2_PREFIX "ps2:"
+#define IN_PS2_NBUTTONS 32
+#define ANALOG_DEADZONE 80
+
+/* note: in_ps2 handles combos (if 2 btns have the same bind,
+ * both must be pressed for action to happen) */
+static int in_ps2_combo_keys = 0;
+static int in_ps2_combo_acts = 0;
+
+static uintptr_t padBuf[2][4];
+static uint32_t padConnected[2][4]; // 2 ports, 4 slots
+static uint32_t padOpen[2][4];
+static uint32_t maxslot[2];
+
+
+static const char *in_ps2_keys[IN_PS2_NBUTTONS] = {
+       [0 ... IN_PS2_NBUTTONS-1] = NULL,
+};
+
+
+/* calculate bit number from bit mask (logarithm to the basis 2) */
+static int lg2(unsigned v)
+{
+       /* credits to https://graphics.stanford.edu/~seander/bithacks.html */
+       int r, s;
+
+       r = (v > 0xFFFF) << 4; v >>= r;
+       s = (v > 0xFF  ) << 3; v >>= s; r |= s;
+       s = (v > 0xF   ) << 2; v >>= s; r |= s;
+       s = (v > 0x3   ) << 1; v >>= s; r |= s;
+                                       r |= (v >> 1);
+       return r;
+}
+
+static unsigned int ps2_pad_read()
+{
+       unsigned int paddata;
+       struct padButtonStatus buttons;
+       int32_t ret, port, slot;
+
+       
+       // Using for now port 0, slot 0
+       port = 0;
+       slot = 0;
+
+       ret = padRead(port, slot, &buttons);
+
+       if (ret != 0) {
+               paddata = 0xffff ^ buttons.btns;
+       }
+
+       // analog..
+       // buttons &= ~(PS2_NUB_UP|PS2_NUB_DOWN|PS2_NUB_LEFT|PS2_NUB_RIGHT);
+       // if (pad.Lx < 128 - ANALOG_DEADZONE) buttons |= PS2_NUB_LEFT;
+       // if (pad.Lx > 128 + ANALOG_DEADZONE) buttons |= PS2_NUB_RIGHT;
+       // if (pad.Ly < 128 - ANALOG_DEADZONE) buttons |= PS2_NUB_UP;
+       // if (pad.Ly > 128 + ANALOG_DEADZONE) buttons |= PS2_NUB_DOWN;
+
+       return paddata;
+}
+
+static unsigned in_ps2_get_bits(void)
+{
+       unsigned mask =
+           PAD_UP|PAD_DOWN|PAD_LEFT|PAD_RIGHT |
+           PAD_CIRCLE|PAD_CROSS|PAD_TRIANGLE|PAD_SQUARE |
+           PAD_L1|PAD_R1|PAD_SELECT|PAD_START;
+               // PS2_NUB_UP|PS2_NUB_DOWN|PS2_NUB_LEFT|PS2_NUB_RIGHT |
+
+       return ps2_pad_read() & mask;
+}
+
+static void in_ps2_probe(const in_drv_t *drv)
+{
+       in_register(IN_PS2_PREFIX "PS2 pad", -1, NULL,
+               IN_PS2_NBUTTONS, in_ps2_keys, 1);
+}
+
+static void in_ps2_free(void *drv_data)
+{
+
+}
+
+static const char * const *
+in_ps2_get_key_names(const in_drv_t *drv, int *count)
+{
+       *count = IN_PS2_NBUTTONS;
+       return in_ps2_keys;
+}
+
+/* ORs result with pressed buttons */
+static int in_ps2_update(void *drv_data, const int *binds, int *result)
+{
+       int type_start = 0;
+       int i, t;
+       unsigned keys;
+
+       keys = in_ps2_get_bits();
+
+       if (keys & in_ps2_combo_keys) {
+               result[IN_BINDTYPE_EMU] = in_combos_do(keys, binds, IN_PS2_NBUTTONS,
+                                               in_ps2_combo_keys, in_ps2_combo_acts);
+               type_start = IN_BINDTYPE_PLAYER12;
+       }
+
+       for (i = 0; keys; i++, keys >>= 1) {
+               if (!(keys & 1))
+                       continue;
+
+               for (t = type_start; t < IN_BINDTYPE_COUNT; t++)
+                       result[t] |= binds[IN_BIND_OFFS(i, t)];
+       }
+
+       return 0;
+}
+
+int in_ps2_update_keycode(void *data, int *is_down)
+{
+       static unsigned old_val = 0;
+       unsigned val, diff, i;
+
+       val = in_ps2_get_bits();
+       diff = val ^ old_val;
+       if (diff == 0)
+               return -1;
+
+       /* take one bit only */
+       for (i = 0; i < sizeof(diff)*8; i++)
+               if (diff & (1<<i))
+                       break;
+
+       old_val ^= 1 << i;
+
+       if (is_down)
+               *is_down = !!(val & (1<<i));
+       return i;
+}
+
+static struct {
+       unsigned key;
+       int pbtn;
+} key_pbtn_map[] =
+{
+       { PAD_UP,               PBTN_UP },
+       { PAD_DOWN,     PBTN_DOWN },
+       { PAD_LEFT,     PBTN_LEFT },
+       { PAD_RIGHT,    PBTN_RIGHT },
+       { PAD_CIRCLE,   PBTN_MOK },
+       { PAD_CROSS,    PBTN_MBACK },
+       { PAD_TRIANGLE, PBTN_MA2 },
+       { PAD_SQUARE,   PBTN_MA3 },
+       { PAD_L1,       PBTN_L },
+       { PAD_R1,       PBTN_R },
+};
+
+#define KEY_PBTN_MAP_SIZE (sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]))
+
+static int in_ps2_menu_translate(void *drv_data, int keycode, char *charcode)
+{
+       int i;
+       if (keycode < 0)
+       {
+               /* menu -> kc */
+               keycode = -keycode;
+               for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
+                       if (key_pbtn_map[i].pbtn == keycode)
+                               return key_pbtn_map[i].key;
+       }
+       else
+       {
+               for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
+                       if (key_pbtn_map[i].key == keycode)
+                               return key_pbtn_map[i].pbtn;
+       }
+
+       return 0;
+}
+
+/* remove binds of missing keys, count remaining ones */
+static int in_ps2_clean_binds(void *drv_data, int *binds, int *def_binds)
+{
+       int i, count = 0;
+
+       for (i = 0; i < IN_PS2_NBUTTONS; i++) {
+               int t, offs;
+               for (t = 0; t < IN_BINDTYPE_COUNT; t++) {
+                       offs = IN_BIND_OFFS(i, t);
+                       if (in_ps2_keys[i] == NULL)
+                               binds[offs] = def_binds[offs] = 0;
+                       if (binds[offs])
+                               count++;
+               }
+       }
+
+       in_combos_find(binds, IN_PS2_NBUTTONS, &in_ps2_combo_keys, &in_ps2_combo_acts);
+
+       return count;
+}
+
+static const in_drv_t in_ps2_drv = {
+       .prefix         = IN_PS2_PREFIX,
+       .probe          = in_ps2_probe,
+       .free           = in_ps2_free,
+       .get_key_names  = in_ps2_get_key_names,
+       .clean_binds    = in_ps2_clean_binds,
+       .update         = in_ps2_update,
+       .update_keycode = in_ps2_update_keycode,
+       .menu_translate = in_ps2_menu_translate,
+};
+
+void in_ps2_init(struct in_default_bind *defbinds)
+{
+       int i, j;
+
+       for (j = 0; j < 2; j++) {
+       mtapPortOpen(j);
+
+               for (i = 0; i < 4; i++) {
+                       padConnected[j][i] = 0;
+                       padOpen[j][i] = 0;
+                       padBuf[j][i] = memalign(64, 256);
+                       padPortOpen(j, i, padBuf[j][i]);
+               }
+       }
+
+       /* PS2 keys have bit masks, Picodrive wants bit numbers */
+       for (i = 0; defbinds[i].code; i++)
+               defbinds[i].code = lg2(defbinds[i].code);
+       for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
+               key_pbtn_map[i].key = lg2(key_pbtn_map[i].key);
+
+       in_ps2_combo_keys = in_ps2_combo_acts = 0;
+
+       /* fill keys array, converting key bitmasks to bit numbers */
+       in_ps2_keys[lg2(PAD_UP)] = "Up";
+       in_ps2_keys[lg2(PAD_LEFT)] = "Left";
+       in_ps2_keys[lg2(PAD_DOWN)] = "Down";
+       in_ps2_keys[lg2(PAD_RIGHT)] = "Right";
+       in_ps2_keys[lg2(PAD_START)] = "Start";
+       in_ps2_keys[lg2(PAD_SELECT)] = "Select";
+       in_ps2_keys[lg2(PAD_L1)] = "L1";
+       in_ps2_keys[lg2(PAD_R1)] = "R1";
+       in_ps2_keys[lg2(PAD_TRIANGLE)] = "Triangle";
+       in_ps2_keys[lg2(PAD_CIRCLE)] = "Circle";
+       in_ps2_keys[lg2(PAD_CROSS)] = "Cross";
+       in_ps2_keys[lg2(PAD_SQUARE)] = "Square";
+       // in_ps2_keys[lg2(PS2_NUB_UP)] = "Analog up";
+       // in_ps2_keys[lg2(PS2_NUB_LEFT)] = "Analog left";
+       // in_ps2_keys[lg2(PS2_NUB_DOWN)] = "Analog down";
+       // in_ps2_keys[lg2(PS2_NUB_RIGHT)] = "Analog right";
+
+       in_register_driver(&in_ps2_drv, defbinds, NULL);
+}
+
diff --git a/platform/ps2/in_ps2.h b/platform/ps2/in_ps2.h
new file mode 100644 (file)
index 0000000..0f9bc8d
--- /dev/null
@@ -0,0 +1,6 @@
+
+struct in_default_bind;
+
+void in_ps2_init(struct in_default_bind *defbinds);
+
+void in_ps2_deinit();
index c3585df..02b3d73 100644 (file)
@@ -45,18 +45,6 @@ static void deinit_drivers() {
     deinit_ps2_filesystem_driver();
 }
 
-void plat_init(void) 
-{
-    init_joystick_driver(false);
-    init_audio_driver();
-}
-
-
-void plat_finish(void) {
-    deinit_audio_driver();
-    deinit_joystick_driver(false);
-}
-
 int  plat_target_init(void)
 { 
     return 0;