frontend: support analog controller using nubs; some refactoring
authornotaz <notasas@gmail.com>
Sat, 5 Feb 2011 23:27:48 +0000 (01:27 +0200)
committernotaz <notasas@gmail.com>
Thu, 10 Feb 2011 00:06:49 +0000 (02:06 +0200)
also enable frameskip by default, it makes the experience a bit
better on most games.

12 files changed:
Makefile
frontend/main.c
frontend/menu.c
frontend/pandora.c [new file with mode: 0644]
frontend/pandora.h [new file with mode: 0644]
frontend/plat_dummy.c
frontend/plat_omap.c
frontend/plugin.c
frontend/plugin_lib.c
frontend/plugin_lib.h
pandora/pcsx.sh
pandora/readme.txt

index 2ccd0e2..db8e1f6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -77,6 +77,7 @@ OBJS += frontend/main.o frontend/plugin.o
 ifeq "$(USE_GTK)" "1"
 OBJS += maemo/hildon.o maemo/main.o
 maemo/%.o: maemo/%.c
+maemo/%.o: CFLAGS += -Wall
 else
 OBJS += frontend/plugin_lib.o frontend/menu.o
 OBJS += frontend/linux/fbdev.o frontend/linux/in_evdev.o
@@ -84,6 +85,7 @@ OBJS += frontend/linux/plat.o frontend/linux/oshide.o
 OBJS += frontend/common/fonts.o frontend/common/input.o frontend/common/readpng.o
 ifeq "$(ARCH)" "arm"
 OBJS += frontend/plat_omap.o
+OBJS += frontend/pandora.o
 else
 OBJS += frontend/plat_dummy.o
 endif
index 550242a..3344819 100644 (file)
@@ -20,6 +20,7 @@
 #include "pcnt.h"
 #include "menu.h"
 #include "../libpcsxcore/misc.h"
+#include "../libpcsxcore/new_dynarec/new_dynarec.h"
 #include "../plugins/cdrcimg/cdrcimg.h"
 #include "common/plat.h"
 #include "common/input.h"
@@ -253,6 +254,7 @@ int main(int argc, char *argv[])
 
        while (1)
        {
+               stop = 0;
                psxCpu->Execute();
                menu_loop();
        }
index 754b6d2..0a4c271 100644 (file)
@@ -22,7 +22,7 @@
 #include "omap.h"
 #include "common/plat.h"
 #include "../libpcsxcore/misc.h"
-#include "../libpcsxcore/new_dynarec/new_dynarec.h"
+#include "../libpcsxcore/psemu_plugin_defs.h"
 #include "revision.h"
 
 #define MENU_X2 1
@@ -63,7 +63,7 @@ static int last_psx_w, last_psx_h, last_psx_bpp;
 static int scaling, filter, state_slot, cpu_clock, cpu_clock_st;
 static char rom_fname_reload[MAXPATHLEN];
 static char last_selected_fname[MAXPATHLEN];
-static int region;
+static int region, in_type_sel;
 int g_opts;
 
 // from softgpu plugin
@@ -147,8 +147,9 @@ static void menu_sync_config(void)
                Config.PsxAuto = 0;
                Config.PsxType = region - 1;
        }
-       pl_frame_interval = Config.PsxType ? 20000 : 16667;
+       in_type = in_type_sel ? PSE_PAD_TYPE_ANALOGPAD : PSE_PAD_TYPE_STANDARD;
 
+       pl_frame_interval = Config.PsxType ? 20000 : 16667;
        // used by P.E.Op.S. frameskip code
        fFrameRateHz = Config.PsxType ? 50.0f : 59.94f;
        dwFrameRateTicks = (100000*100 / (unsigned long)(fFrameRateHz*100));
@@ -160,10 +161,12 @@ static void menu_set_defconfig(void)
        scaling = SCALE_4_3;
 
        region = 0;
+       in_type_sel = 0;
        Config.Xa = Config.Cdda = Config.Sio =
        Config.SpuIrq = Config.RCntFix = Config.VSyncWA = 0;
 
-       iUseDither = UseFrameSkip = 0;
+       iUseDither = 0;
+       UseFrameSkip = 1;
        dwActFixes = 1<<7;
 
        iUseReverb = 2;
@@ -215,6 +218,7 @@ static const struct {
        CE_INTVAL(state_slot),
        CE_INTVAL(cpu_clock),
        CE_INTVAL(g_opts),
+       CE_INTVAL(in_type_sel),
        CE_INTVAL(iUseDither),
        CE_INTVAL(UseFrameSkip),
        CE_INTVAL(dwActFixes),
@@ -711,13 +715,17 @@ static int mh_savecfg(int id, int keys)
        return 1;
 }
 
+static const char *men_in_type_sel[] = { "Standard (SCPH-1080)", "Analog (SCPH-1150)", NULL };
+
 static menu_entry e_menu_keyconfig[] =
 {
        mee_handler_id("Player 1",          MA_CTRL_PLAYER1,    key_config_loop_wrap),
        mee_handler_id("Player 2",          MA_CTRL_PLAYER2,    key_config_loop_wrap),
        mee_handler_id("Emulator controls", MA_CTRL_EMU,        key_config_loop_wrap),
-//     mee_cust_nosave("Save global config",       MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg),
-//     mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
+       mee_label     (""),
+       mee_enum      ("Controller",        0, in_type_sel,     men_in_type_sel),
+       mee_cust_nosave("Save global config",       MA_OPT_SAVECFG,      mh_savecfg, mgn_saveloadcfg),
+       mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
        mee_label     (""),
        mee_label     ("Input devices:"),
        mee_label_mk  (MA_CTRL_DEV_FIRST, mgn_dev_name),
@@ -1434,7 +1442,6 @@ void menu_prepare_emu(void)
        }
        apply_filter(filter);
        apply_cpu_clock();
-       stop = 0;
 
        psxCpu = (Config.Cpu == CPU_INTERPRETER) ? &psxInt : &psxRec;
        if (psxCpu != prev_cpu)
diff --git a/frontend/pandora.c b/frontend/pandora.c
new file mode 100644 (file)
index 0000000..8eacabb
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * (C) notaz, 2011
+ *
+ * This work is licensed under the terms of the GNU GPLv2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <errno.h>
+
+#include "common/input.h"
+#include "plugin_lib.h"
+
+static int fdnub[2];
+static int analog_init_done;
+
+static const char * const pandora_gpio_keys[KEY_MAX + 1] = {
+       [0 ... KEY_MAX] = NULL,
+       [KEY_UP]        = "Up",
+       [KEY_LEFT]      = "Left",
+       [KEY_RIGHT]     = "Right",
+       [KEY_DOWN]      = "Down",
+       [KEY_HOME]      = "A",
+       [KEY_PAGEDOWN]  = "X",
+       [KEY_END]       = "B",
+       [KEY_PAGEUP]    = "Y",
+       [KEY_RIGHTSHIFT]= "L",
+       [KEY_RIGHTCTRL] = "R",
+       [KEY_LEFTALT]   = "Start",
+       [KEY_LEFTCTRL]  = "Select",
+       [KEY_MENU]      = "Pandora",
+};
+
+struct in_default_bind in_evdev_defbinds[] = {
+       { KEY_UP,       IN_BINDTYPE_PLAYER12, DKEY_UP },
+       { KEY_DOWN,     IN_BINDTYPE_PLAYER12, DKEY_DOWN },
+       { KEY_LEFT,     IN_BINDTYPE_PLAYER12, DKEY_LEFT },
+       { KEY_RIGHT,    IN_BINDTYPE_PLAYER12, DKEY_RIGHT },
+       { KEY_SPACE,    IN_BINDTYPE_EMU, PEVB_MENU },
+       { KEY_PAGEUP,   IN_BINDTYPE_PLAYER12, DKEY_TRIANGLE },
+       { KEY_PAGEDOWN, IN_BINDTYPE_PLAYER12, DKEY_CROSS },
+       { KEY_END,      IN_BINDTYPE_PLAYER12, DKEY_CIRCLE },
+       { KEY_HOME,     IN_BINDTYPE_PLAYER12, DKEY_SQUARE },
+       { KEY_LEFTALT,  IN_BINDTYPE_PLAYER12, DKEY_START },
+       { KEY_LEFTCTRL, IN_BINDTYPE_PLAYER12, DKEY_SELECT },
+       { KEY_RIGHTSHIFT,IN_BINDTYPE_PLAYER12, DKEY_L1 },
+       { KEY_RIGHTCTRL, IN_BINDTYPE_PLAYER12, DKEY_R1 },
+       { KEY_Q,        IN_BINDTYPE_PLAYER12, DKEY_L2 },
+       { KEY_P,        IN_BINDTYPE_PLAYER12, DKEY_R2 },
+       { 0, 0, 0 }
+};
+
+static void analog_init(void)
+{
+       int i, nub;
+
+       fdnub[0] = fdnub[1] = -1;
+
+       for (i = nub = 0; nub < 2; i++)
+       {
+               long absbits[(ABS_MAX+1) / sizeof(long) / 8];
+               int ret, fd, support = 0;
+               char name[64];
+
+               snprintf(name, sizeof(name), "/dev/input/event%d", i);
+               fd = open(name, O_RDONLY|O_NONBLOCK);
+               if (fd == -1) {
+                       if (errno == EACCES)
+                               continue;       /* maybe we can access next one */
+                       break;
+               }
+
+               /* check supported events */
+               ret = ioctl(fd, EVIOCGBIT(0, sizeof(support)), &support);
+               if (ret == -1) {
+                       printf("pandora: ioctl failed on %s\n", name);
+                       goto skip;
+               }
+
+               if (!(support & (1 << EV_ABS)))
+                       goto skip;
+
+               ret = ioctl(fd, EVIOCGNAME(sizeof(name)), name);
+               if (ret == -1 || strncmp(name, "nub", 3) != 0)
+                       goto skip;
+
+               ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits);
+               if (ret == -1)
+                       goto skip;
+               if ((absbits[0] & ((1 << ABS_X)|(1 << ABS_Y))) != ((1 << ABS_X)|(1 << ABS_Y)))
+                       goto skip;
+
+               printf("pandora: found analog #%d \"%s\"\n", nub, name);
+               fdnub[nub++] = fd;
+               continue;
+
+skip:
+               close(fd);
+       }
+
+       if (nub != 2)
+               printf("pandora: warning: not all nubs found: %d\n", nub);
+
+       analog_init_done = 1;
+}
+
+void in_update_analogs(void)
+{
+       int *nubp[2] = { in_a1, in_a2 };
+       struct input_absinfo ainfo;
+       int i, fd, v, ret;
+
+       if (!analog_init_done)
+               analog_init();
+
+       for (i = 0; i < 2; i++) {
+               fd = fdnub[i];
+               if (fd < 0)
+                       continue;
+
+               ret = ioctl(fd, EVIOCGABS(ABS_X), &ainfo);
+               if (ret == -1) {
+                       perror("ioctl");
+                       continue;
+               }
+               v = ainfo.value / 2 + 127;
+               nubp[i][0] = v < 0 ? 0 : v;
+
+               ret = ioctl(fd, EVIOCGABS(ABS_Y), &ainfo);
+               if (ret == -1) {
+                       perror("ioctl");
+                       continue;
+               }
+               v = ainfo.value / 2 + 127;
+               nubp[i][1] = v < 0 ? 0 : v;
+       }
+       //printf("%4d %4d %4d %4d\n", in_a1[0], in_a1[1], in_a2[0], in_a2[1]);
+}
+
+int pandora_init(void)
+{
+       in_set_config(in_name_to_id("evdev:gpio-keys"), IN_CFG_KEY_NAMES,
+                     pandora_gpio_keys, sizeof(pandora_gpio_keys));
+
+       return 0;
+}
diff --git a/frontend/pandora.h b/frontend/pandora.h
new file mode 100644 (file)
index 0000000..9bab84f
--- /dev/null
@@ -0,0 +1 @@
+int pandora_init(void);
index 44d9068..6cbe7f8 100644 (file)
@@ -50,3 +50,7 @@ void bgr555_to_rgb565(void *d, void *s, int len)
 void bgr888_to_rgb888(void *d, void *s, int len)
 {
 }
+
+void in_update_analogs(void)
+{
+}
index e6a1105..b479a66 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <sys/ioctl.h>
 #include <unistd.h>
-#include <linux/input.h>
 #include <linux/omapfb.h>
 
-#include "common/input.h"
 #include "common/menu.h"
 #include "linux/fbdev.h"
 #include "linux/oshide.h"
 #include "plugin_lib.h"
 #include "omap.h"
+#include "pandora.h"
 
 
 static struct vout_fbdev *main_fb;
@@ -28,42 +28,6 @@ int g_layer_w = 640, g_layer_h = 480;
 
 struct vout_fbdev *layer_fb;
 
-static const char * const pandora_gpio_keys[KEY_MAX + 1] = {
-       [0 ... KEY_MAX] = NULL,
-       [KEY_UP]        = "Up",
-       [KEY_LEFT]      = "Left",
-       [KEY_RIGHT]     = "Right",
-       [KEY_DOWN]      = "Down",
-       [KEY_HOME]      = "A",
-       [KEY_PAGEDOWN]  = "X",
-       [KEY_END]       = "B",
-       [KEY_PAGEUP]    = "Y",
-       [KEY_RIGHTSHIFT]= "L",
-       [KEY_RIGHTCTRL] = "R",
-       [KEY_LEFTALT]   = "Start",
-       [KEY_LEFTCTRL]  = "Select",
-       [KEY_MENU]      = "Pandora",
-};
-
-struct in_default_bind in_evdev_defbinds[] = {
-       { KEY_UP,       IN_BINDTYPE_PLAYER12, DKEY_UP },
-       { KEY_DOWN,     IN_BINDTYPE_PLAYER12, DKEY_DOWN },
-       { KEY_LEFT,     IN_BINDTYPE_PLAYER12, DKEY_LEFT },
-       { KEY_RIGHT,    IN_BINDTYPE_PLAYER12, DKEY_RIGHT },
-       { KEY_SPACE,    IN_BINDTYPE_EMU, PEVB_MENU },
-       { KEY_PAGEUP,   IN_BINDTYPE_PLAYER12, DKEY_TRIANGLE },
-       { KEY_PAGEDOWN, IN_BINDTYPE_PLAYER12, DKEY_CROSS },
-       { KEY_END,      IN_BINDTYPE_PLAYER12, DKEY_CIRCLE },
-       { KEY_HOME,     IN_BINDTYPE_PLAYER12, DKEY_SQUARE },
-       { KEY_LEFTALT,  IN_BINDTYPE_PLAYER12, DKEY_START },
-       { KEY_LEFTCTRL, IN_BINDTYPE_PLAYER12, DKEY_SELECT },
-       { KEY_RIGHTSHIFT,IN_BINDTYPE_PLAYER12, DKEY_L1 },
-       { KEY_RIGHTCTRL, IN_BINDTYPE_PLAYER12, DKEY_R1 },
-       { KEY_Q,        IN_BINDTYPE_PLAYER12, DKEY_L2 },
-       { KEY_P,        IN_BINDTYPE_PLAYER12, DKEY_R2 },
-       { 0, 0, 0 }
-};
-
 static int omap_setup_layer_(int fd, int enabled, int x, int y, int w, int h, int first_call)
 {
        struct omapfb_plane_info pi;
@@ -205,8 +169,7 @@ void plat_init(void)
        }
        g_menubg_ptr = temp_frame;
 
-       in_set_config(in_name_to_id("evdev:gpio-keys"), IN_CFG_KEY_NAMES,
-                     pandora_gpio_keys, sizeof(pandora_gpio_keys));
+       pandora_init();
        return;
 
 fail1:
index c11a1f0..33efbf0 100644 (file)
@@ -43,15 +43,21 @@ extern void SPUplayCDDAchannel(short *, int);
 /* PAD */
 static long PADreadPort1(PadDataS *pad)
 {
-       pad->controllerType = PSE_PAD_TYPE_STANDARD;
-       pad->buttonStatus = ~keystate;
+       pad->controllerType = in_type;
+       pad->buttonStatus = ~in_keystate;
+       if (in_type == PSE_PAD_TYPE_ANALOGPAD) {
+               pad->leftJoyX = in_a1[0];
+               pad->leftJoyY = in_a1[1];
+               pad->rightJoyX = in_a2[0];
+               pad->rightJoyY = in_a2[1];
+       }
        return 0;
 }
 
 static long PADreadPort2(PadDataS *pad)
 {
        pad->controllerType = PSE_PAD_TYPE_STANDARD;
-       pad->buttonStatus = ~keystate >> 16;
+       pad->buttonStatus = ~in_keystate >> 16;
        return 0;
 }
 
index 17ed79a..a2fb495 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <stdint.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "menu.h"
 #include "pcnt.h"
 #include "../libpcsxcore/new_dynarec/new_dynarec.h"
+#include "../libpcsxcore/psemu_plugin_defs.h"
 
 void *pl_fbdev_buf;
 int pl_frame_interval;
-int keystate;
+int in_type, in_keystate, in_a1[2], in_a2[2];
 static int pl_fbdev_w, pl_fbdev_h, pl_fbdev_bpp;
 static int flip_cnt, vsync_cnt, flips_per_sec, tick_per_sec;
 static float vsps_cur;
@@ -124,13 +126,15 @@ static void update_input(void)
        int actions[IN_BINDTYPE_COUNT] = { 0, };
 
        in_update(actions);
+       if (in_type == PSE_PAD_TYPE_ANALOGPAD)
+               in_update_analogs();
        if (actions[IN_BINDTYPE_EMU] & PEV_MENU)
                stop = 1;
-       keystate = actions[IN_BINDTYPE_PLAYER12];
+       in_keystate = actions[IN_BINDTYPE_PLAYER12];
 
 #ifdef X11
        extern int x11_update_keys(void);
-       keystate |= x11_update_keys();
+       in_keystate |= x11_update_keys();
 #endif
 }
 
@@ -268,6 +272,10 @@ static void *watchdog_thread(void *unused)
        int seen_dead = 0;
        int sleep_time = 5;
 
+#ifndef NDEBUG
+       // don't interfere with debug
+       return NULL;
+#endif
        while (1)
        {
                sleep(sleep_time);
index 6b01cea..53a597f 100644 (file)
@@ -1,5 +1,4 @@
 
-extern int keystate;
 enum {
        DKEY_SELECT = 0,
        DKEY_L3,
@@ -18,6 +17,8 @@ enum {
        DKEY_CROSS,
        DKEY_SQUARE,
 };
+extern int in_type, in_keystate, in_a1[2], in_a2[2];
+void in_update_analogs(void);
 
 extern void *pl_fbdev_buf;
 
index a401714..2062e78 100755 (executable)
@@ -1,6 +1,15 @@
 #!/bin/sh
 
+# stupid nub mode thing
+nub0mode=`cat /proc/pandora/nub0/mode`
+nub1mode=`cat /proc/pandora/nub1/mode`
+echo absolute > /proc/pandora/nub0/mode
+echo absolute > /proc/pandora/nub1/mode
+
 ./pcsx "$@"
 
 # restore stuff if pcsx crashes
 ./picorestore
+
+echo "$nub0mode" > /proc/pandora/nub0/mode
+echo "$nub1mode" > /proc/pandora/nub1/mode
index 8939ece..c0a59d2 100644 (file)
@@ -40,6 +40,9 @@ to work. To use real BIOS, copy uncompressed BIOS files to
 [sd card]/pandora/appdata/pcsx_rearmed/bios/
 then select the BIOS you want to use in Options->BIOS/Plugins menu.
 
+Analog controllers are supported using nubs, but this is disabled by
+default and needs to be enabled in 'Controls' menu.
+
 
 Plugins
 -------