From 799b0b8773d6add1de99efd582c93701b82e970d Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 6 Feb 2011 01:27:48 +0200 Subject: [PATCH] frontend: support analog controller using nubs; some refactoring also enable frameskip by default, it makes the experience a bit better on most games. --- Makefile | 2 + frontend/main.c | 2 + frontend/menu.c | 21 ++++-- frontend/pandora.c | 153 ++++++++++++++++++++++++++++++++++++++++++ frontend/pandora.h | 1 + frontend/plat_dummy.c | 4 ++ frontend/plat_omap.c | 43 +----------- frontend/plugin.c | 12 +++- frontend/plugin_lib.c | 14 +++- frontend/plugin_lib.h | 3 +- pandora/pcsx.sh | 9 +++ pandora/readme.txt | 3 + 12 files changed, 213 insertions(+), 54 deletions(-) create mode 100644 frontend/pandora.c create mode 100644 frontend/pandora.h diff --git a/Makefile b/Makefile index 2ccd0e2a..db8e1f60 100644 --- 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 diff --git a/frontend/main.c b/frontend/main.c index 550242a9..3344819c 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -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(); } diff --git a/frontend/menu.c b/frontend/menu.c index 754b6d23..0a4c271e 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -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 index 00000000..8eacabb6 --- /dev/null +++ b/frontend/pandora.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 00000000..9bab84fc --- /dev/null +++ b/frontend/pandora.h @@ -0,0 +1 @@ +int pandora_init(void); diff --git a/frontend/plat_dummy.c b/frontend/plat_dummy.c index 44d9068a..6cbe7f8e 100644 --- a/frontend/plat_dummy.c +++ b/frontend/plat_dummy.c @@ -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) +{ +} diff --git a/frontend/plat_omap.c b/frontend/plat_omap.c index e6a1105d..b479a66b 100644 --- a/frontend/plat_omap.c +++ b/frontend/plat_omap.c @@ -10,16 +10,16 @@ #include #include #include +#include #include -#include #include -#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: diff --git a/frontend/plugin.c b/frontend/plugin.c index c11a1f05..33efbf0b 100644 --- a/frontend/plugin.c +++ b/frontend/plugin.c @@ -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; } diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c index 17ed79a9..a2fb4951 100644 --- a/frontend/plugin_lib.c +++ b/frontend/plugin_lib.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -24,10 +25,11 @@ #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); diff --git a/frontend/plugin_lib.h b/frontend/plugin_lib.h index 6b01cea3..53a597f2 100644 --- a/frontend/plugin_lib.h +++ b/frontend/plugin_lib.h @@ -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; diff --git a/pandora/pcsx.sh b/pandora/pcsx.sh index a4017141..2062e782 100755 --- a/pandora/pcsx.sh +++ b/pandora/pcsx.sh @@ -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 diff --git a/pandora/readme.txt b/pandora/readme.txt index 8939ece1..c0a59d2e 100644 --- a/pandora/readme.txt +++ b/pandora/readme.txt @@ -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 ------- -- 2.39.2