diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-10-25 14:21:02 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-10-25 14:21:02 +0000 |
| commit | 7d0f136239c4dcee9f27adf9f7a8c262fcbfe95f (patch) | |
| tree | 18b5c5292a39fcda65327e2dd32e44e70ef8e5ff /plugins/dfinput | |
| parent | 5408345d8b1cde19a19ddf324d3439ead6e80709 (diff) | |
| download | pcsxr-7d0f136239c4dcee9f27adf9f7a8c262fcbfe95f.tar.gz | |
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@32889 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'plugins/dfinput')
| -rw-r--r-- | plugins/dfinput/Makefile.am | 9 | ||||
| -rw-r--r-- | plugins/dfinput/Makefile.in | 27 | ||||
| -rw-r--r-- | plugins/dfinput/analog.c | 62 | ||||
| -rw-r--r-- | plugins/dfinput/cfg-gtk2.c | 666 | ||||
| -rw-r--r-- | plugins/dfinput/cfg.c | 1558 | ||||
| -rw-r--r-- | plugins/dfinput/dfinput.glade2 | 508 | ||||
| -rw-r--r-- | plugins/dfinput/pad.c | 1323 | ||||
| -rw-r--r-- | plugins/dfinput/pad.h | 182 | ||||
| -rw-r--r-- | plugins/dfinput/padjoy.h | 82 | ||||
| -rw-r--r-- | plugins/dfinput/sdljoy.c | 112 | ||||
| -rw-r--r-- | plugins/dfinput/xkb.c | 97 |
11 files changed, 2192 insertions, 2434 deletions
diff --git a/plugins/dfinput/Makefile.am b/plugins/dfinput/Makefile.am index fa20fb13..b600352f 100644 --- a/plugins/dfinput/Makefile.am +++ b/plugins/dfinput/Makefile.am @@ -3,19 +3,20 @@ libdir = @libdir@/games/psemu/ lib_LTLIBRARIES = libDFInput.la -libDFInput_la_SOURCES = pad.c padjoy.h +libDFInput_la_SOURCES = cfg.c pad.c pad.h sdljoy.c xkb.c analog.c libDFInput_la_LDFLAGS = -module -avoid-version -lpthread -lX11 \ - -L/usr/X11R6/lib64 -L/usr/X11R6/lib + `sdl-config --libs` -L/usr/X11R6/lib64 -L/usr/X11R6/lib INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ -DLOCALE_DIR=\"${datadir}/locale/\" \ -DDATADIR=\"${datadir}/psemu/\" \ $(GTK2_CFLAGS) $(GLADE2_CFLAGS) -I/usr/X11R6/include \ - -I../../include + -I../../include -I../../libpcsxcore `sdl-config --cflags` bin_PROGRAMS = cfgDFInput -cfgDFInput_SOURCES = cfg.c padjoy.h +cfgDFInput_SOURCES = cfg-gtk2.c pad.h cfgDFInput_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) +cfgDFInput_LDFLAGS = `sdl-config --libs` glade_DATA = dfinput.glade2 gladedir = $(datadir)/psemu/ diff --git a/plugins/dfinput/Makefile.in b/plugins/dfinput/Makefile.in index b221dcfe..4a2982ba 100644 --- a/plugins/dfinput/Makefile.in +++ b/plugins/dfinput/Makefile.in @@ -56,17 +56,20 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) libDFInput_la_LIBADD = -am_libDFInput_la_OBJECTS = pad.lo +am_libDFInput_la_OBJECTS = cfg.lo pad.lo sdljoy.lo xkb.lo analog.lo libDFInput_la_OBJECTS = $(am_libDFInput_la_OBJECTS) libDFInput_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libDFInput_la_LDFLAGS) $(LDFLAGS) -o $@ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) -am_cfgDFInput_OBJECTS = cfg.$(OBJEXT) +am_cfgDFInput_OBJECTS = cfg-gtk2.$(OBJEXT) cfgDFInput_OBJECTS = $(am_cfgDFInput_OBJECTS) am__DEPENDENCIES_1 = cfgDFInput_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +cfgDFInput_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(cfgDFInput_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -167,6 +170,9 @@ PEOPSXGL = @PEOPSXGL@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -233,18 +239,19 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ lib_LTLIBRARIES = libDFInput.la -libDFInput_la_SOURCES = pad.c padjoy.h +libDFInput_la_SOURCES = cfg.c pad.c pad.h sdljoy.c xkb.c analog.c libDFInput_la_LDFLAGS = -module -avoid-version -lpthread -lX11 \ - -L/usr/X11R6/lib64 -L/usr/X11R6/lib + `sdl-config --libs` -L/usr/X11R6/lib64 -L/usr/X11R6/lib INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ -DLOCALE_DIR=\"${datadir}/locale/\" \ -DDATADIR=\"${datadir}/psemu/\" \ $(GTK2_CFLAGS) $(GLADE2_CFLAGS) -I/usr/X11R6/include \ - -I../../include + -I../../include -I../../libpcsxcore `sdl-config --cflags` -cfgDFInput_SOURCES = cfg.c padjoy.h +cfgDFInput_SOURCES = cfg-gtk2.c pad.h cfgDFInput_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) +cfgDFInput_LDFLAGS = `sdl-config --libs` glade_DATA = dfinput.glade2 gladedir = $(datadir)/psemu/ EXTRA_DIST = $(glade_DATA) @@ -340,7 +347,7 @@ clean-binPROGRAMS: done cfgDFInput$(EXEEXT): $(cfgDFInput_OBJECTS) $(cfgDFInput_DEPENDENCIES) @rm -f cfgDFInput$(EXEEXT) - $(LINK) $(cfgDFInput_OBJECTS) $(cfgDFInput_LDADD) $(LIBS) + $(cfgDFInput_LINK) $(cfgDFInput_OBJECTS) $(cfgDFInput_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -348,8 +355,12 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/analog.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg-gtk2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pad.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdljoy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkb.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/plugins/dfinput/analog.c b/plugins/dfinput/analog.c new file mode 100644 index 00000000..34d3dcbe --- /dev/null +++ b/plugins/dfinput/analog.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#include "pad.h" + +void InitAnalog() { + g.PadState[0].AnalogStatus[ANALOG_LEFT][ANALOG_X] = 128; + g.PadState[0].AnalogStatus[ANALOG_LEFT][ANALOG_Y] = 128; + g.PadState[0].AnalogStatus[ANALOG_RIGHT][ANALOG_X] = 128; + g.PadState[0].AnalogStatus[ANALOG_RIGHT][ANALOG_Y] = 128; + g.PadState[1].AnalogStatus[ANALOG_LEFT][ANALOG_X] = 128; + g.PadState[1].AnalogStatus[ANALOG_LEFT][ANALOG_Y] = 128; + g.PadState[1].AnalogStatus[ANALOG_RIGHT][ANALOG_X] = 128; + g.PadState[1].AnalogStatus[ANALOG_RIGHT][ANALOG_Y] = 128; +} + +void CheckAnalog() { + int i, j, k, val; + uint8_t n; + + for (i = 0; i < 2; i++) { + if (g.cfg.PadDef[i].Type != PSE_PAD_TYPE_ANALOGPAD) { + continue; + } + + for (j = 0; j < ANALOG_TOTAL; j++) { + for (k = 0; k < 2; k++) { + if (g.cfg.PadDef[i].AnalogDef[j][k] == 0) { + continue; + } + + n = abs(g.cfg.PadDef[i].AnalogDef[j][k]) - 1; + + val = SDL_JoystickGetAxis(g.PadState[i].JoyDev, n); + + val += 32768; + val /= 256; + + if (g.cfg.PadDef[i].AnalogDef[j][k] < 0) { + g.PadState[i].AnalogStatus[j][k] = 255 - val; + } else { + g.PadState[i].AnalogStatus[j][k] = val; + } + } + } + } +} diff --git a/plugins/dfinput/cfg-gtk2.c b/plugins/dfinput/cfg-gtk2.c new file mode 100644 index 00000000..ae36dcd6 --- /dev/null +++ b/plugins/dfinput/cfg-gtk2.c @@ -0,0 +1,666 @@ +/* + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#include "cfg.c" + +#include <time.h> +#include <gdk/gdk.h> +#include <gtk/gtk.h> +#include <glade/glade.h> + +GtkWidget *MainWindow; + +const int DPad[DKEY_TOTAL] = { + DKEY_UP, + DKEY_DOWN, + DKEY_LEFT, + DKEY_RIGHT, + DKEY_CROSS, + DKEY_CIRCLE, + DKEY_SQUARE, + DKEY_TRIANGLE, + DKEY_L1, + DKEY_R1, + DKEY_L2, + DKEY_R2, + DKEY_L3, + DKEY_R3, + DKEY_SELECT, + DKEY_START +}; + +const char *DPadText[DKEY_TOTAL] = { + N_("D-Pad Up"), + N_("D-Pad Down"), + N_("D-Pad Left"), + N_("D-Pad Right"), + N_("Cross"), + N_("Circle"), + N_("Square"), + N_("Triangle"), + N_("L1"), + N_("R1"), + N_("L2"), + N_("R2"), + N_("L3"), + N_("R3"), + N_("Select"), + N_("Start") +}; + +const char *AnalogText[] = { + N_("L-Stick X"), + N_("L-Stick Y"), + N_("R-Stick X"), + N_("R-Stick Y") +}; + +static int GetSelectedKeyIndex(int padnum) { + GladeXML *xml; + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + gboolean selected; + int i; + + xml = glade_get_widget_tree(MainWindow); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(glade_xml_get_widget(xml, padnum == 0 ? "treeview1" : "treeview2"))); + selected = gtk_tree_selection_get_selected(selection, &model, &iter); + + if (!selected) { + return -1; + } + + path = gtk_tree_model_get_path(model, &iter); + i = *gtk_tree_path_get_indices(path); + + return i; +} + +static void GetKeyDescription(char *buf, int joynum, int key) { + const char *hatname[16] = {_("Centered"), _("Up"), _("Right"), _("Rightup"), + _("Down"), "", _("Rightdown"), "", _("Left"), _("Leftup"), "", "", + _("Leftdown"), "", "", ""}; + + switch (g.cfg.PadDef[joynum].KeyDef[key].JoyEvType) { + case BUTTON: + sprintf(buf, _("Joystick: Button %d"), g.cfg.PadDef[joynum].KeyDef[key].J.Button); + break; + + case AXIS: + sprintf(buf, _("Joystick: Axis %d%c"), abs(g.cfg.PadDef[joynum].KeyDef[key].J.Axis) - 1, + g.cfg.PadDef[joynum].KeyDef[key].J.Axis > 0 ? '+' : '-'); + break; + + case HAT: + sprintf(buf, _("Joystick: Hat %d %s"), (g.cfg.PadDef[joynum].KeyDef[key].J.Hat >> 8), + hatname[g.cfg.PadDef[joynum].KeyDef[key].J.Hat & 0x0F]); + break; + + case NONE: + default: + buf[0] = '\0'; + break; + } + + if (g.cfg.PadDef[joynum].KeyDef[key].Key != 0) { + if (buf[0] != '\0') { + strcat(buf, " / "); + } + + strcat(buf, _("Keyboard:")); + strcat(buf, " "); + strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].KeyDef[key].Key)); + } else if (buf[0] == '\0') { + strcpy(buf, _("(Not Set)")); + } +} + +static void GetAnalogDescription(char *buf, int joynum, int analognum, int analogaxis) { + int16_t v = g.cfg.PadDef[joynum].AnalogDef[analognum][analogaxis]; + + if (v == 0) { + sprintf(buf, _("(Not Set)")); + } else { + sprintf(buf, _("Joystick: Axis %d%s"), abs(v) - 1, (v < 0) ? _(" (Reversed)") : ""); + } +} + +static void UpdateKeyList() { + const char *widgetname[2] = {"treeview1", "treeview2"}; + + GladeXML *xml; + GtkWidget *widget; + GtkListStore *store; + GtkTreeIter iter; + int i, j; + char buf[256]; + + xml = glade_get_widget_tree(MainWindow); + + for (i = 0; i < 2; i++) { + widget = glade_xml_get_widget(xml, widgetname[i]); + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + + for (j = 0; j < DKEY_TOTAL; j++) { + gtk_list_store_append(store, &iter); + GetKeyDescription(buf, i, DPad[j]); + gtk_list_store_set(store, &iter, 0, _(DPadText[j]), 1, buf, -1); + } + + if (g.cfg.PadDef[i].Type == PSE_PAD_TYPE_ANALOGPAD) { + for (j = 0; j < 4; j++) { + gtk_list_store_append(store, &iter); + GetAnalogDescription(buf, i, j / 2, j % 2); + gtk_list_store_set(store, &iter, 0, _(AnalogText[j]), 1, buf, -1); + } + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widget), TRUE); + gtk_widget_show(widget); + } +} + +static void UpdateKey() { + const char *widgetname[2] = {"treeview1", "treeview2"}; + int i, index; + GladeXML *xml; + GtkWidget *widget; + GtkTreeModel *model; + GtkTreeIter iter; + GValue value = {0, }; + char buf[256]; + + xml = glade_get_widget_tree(MainWindow); + + for (i = 0; i < 2; i++) { + index = GetSelectedKeyIndex(i); + if (index == -1) continue; + + widget = glade_xml_get_widget(xml, widgetname[i]); + gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)), &model, &iter); + + if (index < DKEY_TOTAL) { + GetKeyDescription(buf, i, DPad[index]); + } else { + GetAnalogDescription(buf, i, (index - DKEY_TOTAL) / 2, (index - DKEY_TOTAL) % 2); + } + + g_value_init(&value, G_TYPE_STRING); + g_value_set_string(&value, buf); + gtk_list_store_set_value(GTK_LIST_STORE(model), &iter, 1, &value); + } +} + +static void OnConfigExit(GtkWidget *widget, gpointer user_data) { + SaveConfig(); + + gtk_widget_destroy(widget); + SDL_Quit(); + + gtk_exit(0); +} + +static void TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) { + GladeXML *xml; + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + + gboolean selected; + int i; + + selected = gtk_tree_selection_get_selected(selection, &model, &iter); + + if (selected) { + path = gtk_tree_model_get_path(model, &iter); + i = *gtk_tree_path_get_indices(path); + + // If a row was selected, and the row is not blank, we can now enable + // some of the disabled widgets + xml = glade_get_widget_tree(MainWindow); + + if ((int)user_data == 0) { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnchange1")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnreset1")), TRUE); + } else { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnchange2")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnreset2")), TRUE); + } + } else { + xml = glade_get_widget_tree(MainWindow); + + if ((int)user_data == 0) { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnchange1")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnreset1")), FALSE); + } else { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnchange2")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btnreset2")), FALSE); + } + } +} + +static void OnDeviceChanged(GtkWidget *widget, gpointer user_data) { + int n = (int)user_data, current = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + current--; + g.cfg.PadDef[n].DevNum = current; +} + +static void OnTypeChanged(GtkWidget *widget, gpointer user_data) { + int n = (int)user_data, current = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + g.cfg.PadDef[n].Type = (current == 0 ? PSE_PAD_TYPE_STANDARD : PSE_PAD_TYPE_ANALOGPAD); + + UpdateKeyList(); +} + +static void OnThreadedToggled(GtkWidget *widget, gpointer user_data) { + g.cfg.Threaded = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} + +static void SysErrorMessage(gchar *primary, gchar *secondary) { + GtkWidget *message_dialog; + + message_dialog = gtk_message_dialog_new(NULL, + GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, primary, NULL); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG (message_dialog), secondary); + + gtk_dialog_run(GTK_DIALOG(message_dialog)); + gtk_widget_destroy(message_dialog); +} + +static void ReadDKeyEvent(int padnum, int key) { + SDL_Joystick *js; + time_t t; + GdkEvent *ge; + int i; + Sint16 axis; + + if (g.cfg.PadDef[padnum].DevNum >= 0) { + js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum); + SDL_JoystickEventState(SDL_IGNORE); + } else { + js = NULL; + } + + t = time(NULL); + + while (time(NULL) < t + 10) { + // check joystick events + if (js != NULL) { + SDL_JoystickUpdate(); + + for (i = 0; i < SDL_JoystickNumButtons(js); i++) { + if (SDL_JoystickGetButton(js, i)) { + g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = BUTTON; + g.cfg.PadDef[padnum].KeyDef[key].J.Button = i; + goto end; + } + } + + for (i = 0; i < SDL_JoystickNumAxes(js); i++) { + axis = SDL_JoystickGetAxis(js, i); + if (abs(axis) > 16383) { + g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = AXIS; + g.cfg.PadDef[padnum].KeyDef[key].J.Axis = (i + 1) * (axis > 0 ? 1 : -1); + goto end; + } + } + + for (i = 0; i < SDL_JoystickNumHats(js); i++) { + axis = SDL_JoystickGetHat(js, i); + if (axis != SDL_HAT_CENTERED) { + g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = HAT; + + if (axis & SDL_HAT_UP) { + g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_UP); + } else if (axis & SDL_HAT_DOWN) { + g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_DOWN); + } else if (axis & SDL_HAT_LEFT) { + g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_LEFT); + } else if (axis & SDL_HAT_RIGHT) { + g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_RIGHT); + } + + goto end; + } + } + } + + // check keyboard events + while ((ge = gdk_event_get()) != NULL) { + if (ge->type == GDK_KEY_PRESS) { + if (ge->key.keyval != XK_Escape) { + g.cfg.PadDef[padnum].KeyDef[key].Key = ge->key.keyval; + } + gdk_event_free(ge); + goto end; + } + gdk_event_free(ge); + } + + usleep(5000); + } + +end: + if (js != NULL) { + SDL_JoystickClose(js); + } +} + +static void ReadAnalogEvent(int padnum, int analognum, int analogaxis) { + SDL_Joystick *js; + time_t t; + GdkEvent *ge; + int i; + Sint16 axis; + + if (g.cfg.PadDef[padnum].DevNum < 0) { + SysErrorMessage(_("Device not set"), _("Please select a valid Joystick Device")); + return; + } + + js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum); + if (js == NULL) { + SysErrorMessage(_("Device open error"), _("Unable to open Joystick Device")); + return; + } + + t = time(NULL); + + while (time(NULL) < t + 10) { + // check joystick events + SDL_JoystickUpdate(); + for (i = 0; i < SDL_JoystickNumAxes(js); i++) { + axis = SDL_JoystickGetAxis(js, i); + if (abs(axis) > 16383) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogaxis] = (i + 1) * (axis > 0 ? 1 : -1); + goto end1; + } + } + + // check keyboard events + while ((ge = gdk_event_get()) != NULL) { + if (ge->type == GDK_KEY_PRESS) { + if (ge->key.keyval == XK_Escape) { + gdk_event_free(ge); + goto end1; + } + } + gdk_event_free(ge); + } + + usleep(5000); + } + +end1: + SDL_JoystickClose(js); +} + +static void OnChangeClicked(GtkWidget *widget, gpointer user_data) { + int pad = (int)user_data; + int index = GetSelectedKeyIndex(pad); + + if (index == -1) return; + + if (index < DKEY_TOTAL) { + ReadDKeyEvent(pad, DPad[index]); + } else { + index -= DKEY_TOTAL; + ReadAnalogEvent(pad, index / 2, index % 2); + } + + UpdateKey(); +} + +static void OnResetClicked(GtkWidget *widget, gpointer user_data) { + int pad = (int)user_data; + int index = GetSelectedKeyIndex(pad); + + if (index == -1) return; + + if (index < DKEY_TOTAL) { + g.cfg.PadDef[pad].KeyDef[DPad[index]].Key = 0; + g.cfg.PadDef[pad].KeyDef[DPad[index]].JoyEvType = NONE; + g.cfg.PadDef[pad].KeyDef[DPad[index]].J.Button = 0; + } else { + index -= DKEY_TOTAL; + g.cfg.PadDef[pad].AnalogDef[index / 2][index % 2] = 0; + } + + UpdateKey(); +} + +static void PopulateDevList() { + const char *widgetname[2] = {"combodev1", "combodev2"}; + int i, j, n; + GtkWidget *widget; + GladeXML *xml; + GtkTreeIter iter; + GtkListStore *store; + GtkCellRenderer *renderer; + char buf[256]; + + xml = glade_get_widget_tree(MainWindow); + + for (i = 0; i < 2; i++) { + widget = glade_xml_get_widget(xml, widgetname[i]); + + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, FALSE); + gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0); + + store = gtk_list_store_new(1, G_TYPE_STRING); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, _("None"), -1); + + n = SDL_NumJoysticks(); + for (j = 0; j < n; j++) { + sprintf(buf, "%d: %s", j + 1, SDL_JoystickName(j)); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, buf, -1); + } + + gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store)); + + n = g.cfg.PadDef[i].DevNum + 1; + if (n > SDL_NumJoysticks()) { + n = 0; + g.cfg.PadDef[i].DevNum = -1; + } + + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), n); + } +} + +long PADconfigure() { + GladeXML *xml; + GtkWidget *widget; + GtkTreeSelection *treesel; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + if (SDL_Init(SDL_INIT_JOYSTICK) == -1) { + fprintf(stderr, "Failed to initialize SDL!\n"); + return -1; + } + + LoadConfig(); + + xml = glade_xml_new(DATADIR "dfinput.glade2", "CfgWnd", NULL); + if (xml == NULL) { + g_warning("We could not load the interface!"); + return -1; + } + + MainWindow = glade_xml_get_widget(xml, "CfgWnd"); + gtk_window_set_title(GTK_WINDOW(MainWindow), _("Gamepad/Keyboard Input Configuration")); + + widget = glade_xml_get_widget(xml, "treeview1"); + + // column for key + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Key"), + renderer, "text", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + // column for button + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Button"), + renderer, "text", 1, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); + + g_signal_connect_data(G_OBJECT(treesel), "changed", + G_CALLBACK(TreeSelectionChanged), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "treeview2"); + + // column for key + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Key"), + renderer, "text", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + // column for button + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Button"), + renderer, "text", 1, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); + + g_signal_connect_data(G_OBJECT(treesel), "changed", + G_CALLBACK(TreeSelectionChanged), (gpointer)1, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "delete_event", + GTK_SIGNAL_FUNC(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btnclose"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnConfigExit), xml, NULL, G_CONNECT_AFTER); + + PopulateDevList(); + UpdateKeyList(); + + widget = glade_xml_get_widget(xml, "checkmt"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), g.cfg.Threaded); + g_signal_connect_data(GTK_OBJECT(widget), "toggled", + GTK_SIGNAL_FUNC(OnThreadedToggled), NULL, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "combodev1"); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + GTK_SIGNAL_FUNC(OnDeviceChanged), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "combodev2"); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + GTK_SIGNAL_FUNC(OnDeviceChanged), (gpointer)1, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "combotype1"); + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), + g.cfg.PadDef[0].Type == PSE_PAD_TYPE_ANALOGPAD ? 1 : 0); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + GTK_SIGNAL_FUNC(OnTypeChanged), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "combotype2"); + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), + g.cfg.PadDef[1].Type == PSE_PAD_TYPE_ANALOGPAD ? 1 : 0); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + GTK_SIGNAL_FUNC(OnTypeChanged), (gpointer)1, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btnchange1"); + gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnChangeClicked), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btnreset1"); + gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnResetClicked), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btnchange2"); + gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnChangeClicked), (gpointer)1, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btnreset2"); + gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnResetClicked), (gpointer)1, NULL, G_CONNECT_AFTER); + + gtk_widget_show(MainWindow); + gtk_main(); + + return 0; +} + +static void OnAboutExit(GtkWidget *widget, gpointer user_data) { + gtk_widget_destroy(widget); + gtk_exit(0); +} + +void PADabout() { + const char *authors[]= {"Wei Mingzhi <weimingzhi@gmail.com>", NULL}; + GtkWidget *widget; + + widget = gtk_about_dialog_new(); +#ifdef EPSXE + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "Gamepad/Keyboard Input (ePSXe)"); +#else + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "Gamepad/Keyboard Input"); +#endif + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "1.1"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://www.codeplex.com/pcsxr/"); + + g_signal_connect_data(GTK_OBJECT(widget), "response", + GTK_SIGNAL_FUNC(OnAboutExit), NULL, NULL, G_CONNECT_AFTER); + + gtk_widget_show(widget); + gtk_main(); +} + +int main(int argc, char *argv[]) { +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); +#endif + + gtk_set_locale(); + gtk_init(&argc, &argv); + + if (argc > 1 && !strcmp(argv[1], "-about")) { + PADabout(); + } else { + PADconfigure(); + } + + gtk_exit(0); + return 0; +} diff --git a/plugins/dfinput/cfg.c b/plugins/dfinput/cfg.c index d5f54a63..d8f7a78c 100644 --- a/plugins/dfinput/cfg.c +++ b/plugins/dfinput/cfg.c @@ -1,1299 +1,295 @@ /* - * Pad for Psemu Pro like Emulators - * This is the config program, taken out from the pad - * It's also responsible for the about-dialog box + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. * - * Written by Erich Kitzmuller <ammoq@ammoq.com> - * Based on padXwin by linuzappz <linuzappz@hotmail.com> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. * - * Copyright 2002,2003 by Erich Kitzmuller - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. */ -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#ifdef __linux__ -#include <linux/joystick.h> -#endif -#include <sys/stat.h> -#include <sys/time.h> -#include <unistd.h> -#include <gdk/gdk.h> -#include <gtk/gtk.h> -#include <glade/glade.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <errno.h> -#include "padjoy.h" - -#ifdef ENABLE_NLS -#include <libintl.h> -#include <locale.h> -#endif - -#ifdef __linux__ -char *LibName = "Gamepad/Keyboard Input"; -#else -char *LibName = "Keyboard Input"; -#endif - -#define CONFIG_FILENAME "dfinput.cfg" - -// Prototypes -static void loadConfig(); -static void saveConfig(); -static char *eventDescription(EventCode); -static void initPadtime(); - -// Filenames for device files, e.g. "/dev/input/js0" -static char devicefilename[MAXDEVICES][FILENAME_MAX+1] = {"/dev/input/js0", "/dev/input/js1"}; - -// File desciptors for device files -static int devicefile[MAXDEVICES] = { -1, -1 }; - -// Use Threading for joy device input? -static int use_threads = 1; - -// Emulate Dualshock(TM) analog pad? -static int use_analog = 0; - -// calibration data -int minzero[MAXAXES]; -int maxzero[MAXAXES]; - -// axes status - so only changing status are reported -int axestatus[MAXDEVICES][MAXAXES]; - -// Assignment of PSX buttons to Events -static EventCode PadButtons[MAXDEVICES][MAXPSXBUTTONS] = -{ - { - KEY_EVENT(XK_e), // L2 - KEY_EVENT(XK_t), // R2 - KEY_EVENT(XK_w), // L1 - KEY_EVENT(XK_r), // R1 - KEY_EVENT(XK_d), // Triangle - KEY_EVENT(XK_x), // Circle - KEY_EVENT(XK_z), // Cross - KEY_EVENT(XK_s), // Square - KEY_EVENT(XK_c), // Select - NO_EVENT, // Left Analog - NO_EVENT, // Right Analog - KEY_EVENT(XK_v), // Start - KEY_EVENT(XK_Up), // Up - KEY_EVENT(XK_Right), // Right - KEY_EVENT(XK_Down), // Down - KEY_EVENT(XK_Left), // Left - NO_EVENT, // Left Anlaog X - NO_EVENT, // Left Analog Y - NO_EVENT, // Right Analog X - NO_EVENT // Right Analog Y - }, - { - NO_EVENT, // L2 - NO_EVENT, // R2 - NO_EVENT, // L1 - NO_EVENT, // R1 - NO_EVENT, // Triangle - NO_EVENT, // Circle - NO_EVENT, // Cross - NO_EVENT, // Square - NO_EVENT, // Select - NO_EVENT, // Left Analog - NO_EVENT, // Right Analog - NO_EVENT, // Start - NO_EVENT, // Up - NO_EVENT, // Right - NO_EVENT, // Down - NO_EVENT, // Left - NO_EVENT, // Left Anlaog X - NO_EVENT, // Left Analog Y - NO_EVENT, // Right Analog X - NO_EVENT // Right Analog Y - } -}; - -static Display *Dsp; - -static EventCode macroLaunch[MAXDEVICES][MAXMACROS]; -static EventCode macroEvents[MAXDEVICES][MAXMACROS][MAXMACROLENGTH]; -static long macroInterval[MAXDEVICES][MAXMACROS][MAXMACROLENGTH]; -static int macroActive[MAXDEVICES]; -static int macroIndex[MAXDEVICES]; -static long macroNext[MAXDEVICES]; - -void init_macros() { - int i,j; - - for (i=0; i<MAXDEVICES; i++) { - for (j=0; j<MAXMACROS; j++) { - macroLaunch[i][j]=NO_EVENT; - macroEvents[i][j][0]=NO_EVENT; - macroInterval[i][j][0]=0; - } - macroActive[i]=-1; - macroIndex[i]=0; - macroNext[i]=0; - } -} - -long PADinit(long flags) { - int i,j; - - init_macros(); - initPadtime(); - for (i=0; i<MAXDEVICES; i++) { - maxzero[i] = 250; - minzero[i] = -250; - - for (j=0; j<MAXAXES; j++) { - axestatus[i][j] = AXESTS_UNKNOWN; - } - } - loadConfig(); - - return 0; -} - -static long firstsecond = 0; - -static void initPadtime() { - struct timeval tv; - gettimeofday(&tv, NULL); - firstsecond = tv.tv_sec; -} - -// construct a time on our own -long getPadtime() { - struct timeval tv; - gettimeofday(&tv, NULL); - return (tv.tv_sec-firstsecond)*10000+tv.tv_usec/100; -} - -unsigned short PadStat[2] = {0xffff, 0xffff}; - -// get pending events -static int getPendingEvents(int millisecondstowait, EventCode *events, int maxevents, int useGDK, int checkJoydevice, int checkXKeyboard, long *timing) { - fd_set rfds; - int retval; - int i; - int md; - int eventsread=0; - XEvent xe; - GdkEvent *ge; - int cntopen; - struct timeval tv; - int oldstatus; - -#ifdef __linux__ - struct js_event je; - - if (checkJoydevice) { - FD_ZERO(&rfds); - md = -1; - cntopen=0; - for (i=0; i<MAXDEVICES; i++) { - if (devicefile[i] > -1) { - FD_SET(devicefile[i], &rfds); - cntopen++; - } - if (devicefile[i] > md) md = devicefile[i]; - } - tv.tv_sec = millisecondstowait / 1000; - tv.tv_usec = 1000 * (millisecondstowait % 1000); - - retval = select(md+1, &rfds, NULL, NULL, &tv); - - while (retval && eventsread<maxevents-2*checkXKeyboard) { - for (i=0; i<MAXDEVICES; i++) { - if (devicefile[i]>-1 && FD_ISSET(devicefile[i], &rfds)) { - read (devicefile[i], &je, 8); - - if (je.type == JS_EVENT_AXIS && je.number<MAXAXES) { - if (axestatus[i][je.number] == AXESTS_ANALOG) { - /* this axe should be reported analog */ - events[eventsread++] = ANALOGAXIS_EVENT(i,je.number, (je.value+32768)>>8); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - } - else if (je.value > maxzero[i]) { - if (axestatus[i][je.number] != AXESTS_PLUS && - axestatus[i][je.number] != AXESTS_UNUSED) { - - oldstatus = axestatus[i][je.number]; - - axestatus[i][je.number] = AXESTS_PLUS; - - events[eventsread++] = AXISPLUS_EVENT(i,je.number); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - - if (oldstatus == AXESTS_MINUS) { - events[eventsread++] = RELEASE_EVENT+AXISMINUS_EVENT(i,je.number); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - } - - } - } - else if (je.value < minzero[i]) { - if (axestatus[i][je.number] != AXESTS_MINUS && - axestatus[i][je.number] != AXESTS_UNUSED) { - - oldstatus = axestatus[i][je.number]; - - axestatus[i][je.number] = AXESTS_MINUS; - - events[eventsread++] = AXISMINUS_EVENT(i,je.number); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - - if (oldstatus == AXESTS_PLUS) { - events[eventsread++] = RELEASE_EVENT+AXISPLUS_EVENT(i,je.number); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - } - } - } - else { - if (axestatus[i][je.number] != AXESTS_CENTER && - axestatus[i][je.number] != AXESTS_UNUSED) { - - oldstatus = axestatus[i][je.number]; - - axestatus[i][je.number] = AXESTS_CENTER; - - if (oldstatus == AXESTS_PLUS) { - events[eventsread++] = RELEASE_EVENT+AXISPLUS_EVENT(i,je.number); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - } - else if (oldstatus == AXESTS_MINUS) { - events[eventsread++] = RELEASE_EVENT+AXISMINUS_EVENT(i,je.number); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - } - } - } - } - else if (je.type == JS_EVENT_BUTTON && je.number<MAXBUTTONS) { - events[eventsread++] = (je.value?0:RELEASE_EVENT) + BUTTON_EVENT(i,je.number); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - } - } - } - tv.tv_sec = 0; - tv.tv_usec = 0; - - retval = select(md+1, &rfds, NULL, NULL, &tv); - } - - } -#endif - - if (checkXKeyboard) { - if (useGDK) { - while ((ge = gdk_event_get() ) != NULL ) { - if (ge->type == GDK_KEY_PRESS) { - events[eventsread++] = KEY_EVENT(ge->key.keyval); - if (timing) { - (*timing)=((GdkEventKey *)ge)->time*10; - timing++; - } - if (eventsread==maxevents) return eventsread; - } - else if (ge->type == GDK_KEY_RELEASE) { - events[eventsread++] = RELEASE_EVENT+KEY_EVENT(ge->key.keyval); - if (timing) { - (*timing)=((GdkEventKey *)ge)->time*10; - timing++; - } - if (eventsread==maxevents) return eventsread; - } - gdk_event_free(ge); - } - } - else { - while ((i=XPending(Dsp))) { - while (i--) { - XNextEvent(Dsp, &xe); - switch (xe.type) { - case KeyPress: - events[eventsread++] = KEY_EVENT(XLookupKeysym((XKeyEvent *)&xe, 0)); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - break; - case KeyRelease: - events[eventsread++] = RELEASE_EVENT+KEY_EVENT(XLookupKeysym((XKeyEvent *)&xe, 0)); - if (timing) { - (*timing)=getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - break; -/* - case FocusIn: - XAutoRepeatOff(Dsp); - break; - case FocusOut: - XAutoRepeatOn(Dsp); - break; -*/ - } - } - } - } - } - - return eventsread; -} - - -/*---------------------------------------------------------------------*/ -/* Config Dialogue stuff */ -/*---------------------------------------------------------------------*/ - -// analyse Eventcode -static PadJoyEvent *EventCode2PadJoyEvent(EventCode p_e) { - static PadJoyEvent event; - EventCode e; - int i,p; - - event.event_type = EVENTTYPE_NONE; - event.pad = 0; - event.no = 0; - event.value = 0; - - if (!p_e) { - return &event; - } - - e = p_e; - - if (e>RELEASE_EVENT) { - event.value = 0; - e -= RELEASE_EVENT; - } - else { - event.value = 1; - } - - if (e && e<FIRST_JOY_EVENT) { - event.event_type = EVENTTYPE_KEY; - event.no = e; - return &event; - } - - if (e >= FIRST_ANALOG_EVENT) { - event.event_type = EVENTTYPE_ANALOG; - event.pad = (e-FIRST_ANALOG_EVENT)/(256*MAXAXES); - event.no = (e-ANALOGAXIS_EVENT(event.pad,0,0))/256; - event.value = e & 0xff; - return &event; - } - - - for (p=0; p<MAXDEVICES; p++) { - for (i=0; i<MAXAXES; i++) { - if (e == AXISPLUS_EVENT(p,i)) { - event.event_type = EVENTTYPE_AXISPLUS; - event.pad = p; - event.no = i; - return &event; - } - if (e == AXISMINUS_EVENT(p,i)) { - event.event_type = EVENTTYPE_AXISMINUS; - event.pad = p; - event.no = i; - return &event; - } - } - - for (i=0; i<MAXBUTTONS; i++) { - if (e == BUTTON_EVENT(p,i)) { - event.event_type = EVENTTYPE_BUTTON; - event.pad = p; - event.no = i; - return &event; - } - } - } - - return &event; -} - - - -// get the description of an Eventcode -// this implementation is not optimized, -// but I only need it for the configuration part so speed doesn't matter -// should be changed to use EventCode2PadJoyEvent -static char *eventDescription(EventCode e) { - static char buffer[256]; - int i,p; - - if (e && e<FIRST_JOY_EVENT) { - sprintf(buffer, "\"%s\"", XKeysymToString(e-FIRST_KEY_EVENT)); - return buffer; - } - - if (e >= FIRST_ANALOG_EVENT) { - p = (e-FIRST_ANALOG_EVENT)/(256*MAXAXES); - i = (e-ANALOGAXIS_EVENT(p,0,0))/256; - sprintf(buffer, "X%d", i); - return buffer; - } - - for (p=0; p<MAXDEVICES; p++) { - for (i=0; i<MAXAXES; i++) { - if (e == AXISPLUS_EVENT(p,i)) { - sprintf(buffer, "A%d+", i); - return buffer; - } - if (e == AXISMINUS_EVENT(p,i)) { - sprintf(buffer, "A%d-", i); - return buffer; - } - } - - for (i=0; i<MAXBUTTONS; i++) { - if (e == BUTTON_EVENT(p,i)) { - sprintf(buffer, "B%d", i); - return buffer; - } - } - } - - sprintf(buffer, "???"); - return buffer; -} - - -// get a String for each EventCode -// more accurate than eventDescription() -// should be changed to use EventCode2PadJoyEvent -static char *EventCode2String(EventCode p_e) { - static char buffer[256]; - int i,p,v; - char push_release; - EventCode e; - - if (!p_e) { - sprintf(buffer, "???"); - return buffer; - } - - e = p_e; - - if (e>RELEASE_EVENT) { - push_release = 'R'; - e -= RELEASE_EVENT; - } - else { - push_release = 'P'; - } - - if (e && e<FIRST_JOY_EVENT) { - sprintf(buffer, "K%c\"%s\"", push_release, XKeysymToString(e-FIRST_KEY_EVENT)); - return buffer; - } - - if (e >= FIRST_ANALOG_EVENT) { - p = (e-FIRST_ANALOG_EVENT)/(256*MAXAXES); - i = (e-ANALOGAXIS_EVENT(p,0,0))/256; - v = e & 0xff;; - sprintf(buffer, "X%dP%dv%d",p, i, v); - return buffer; - } - - - for (p=0; p<MAXDEVICES; p++) { - for (i=0; i<MAXAXES; i++) { - if (e == AXISPLUS_EVENT(p,i)) { - sprintf(buffer, "A%d%c%d+", p, push_release, i); - return buffer; - } - if (e == AXISMINUS_EVENT(p,i)) { - sprintf(buffer, "A%d%c%d-", p, push_release, i); - return buffer; - } - } - - for (i=0; i<MAXBUTTONS; i++) { - if (e == BUTTON_EVENT(p,i)) { - sprintf(buffer, "B%d%c%d", p, push_release, i); - return buffer; - } - } - } - - sprintf(buffer, "???"); - return buffer; -} - -// reversal of EventCode2String -static EventCode String2EventCode(char *s) { - static char buffer[256]; - int i,p; - char *q; - char push_release; - EventCode e; - - if (s[0]>='0' && s[0]<='9') return atoi(s); // allow numeric input - - e=0; - push_release = 'P'; - - switch(s[0]) { - case 'K': - push_release = s[1]; - strncpy(buffer, s+3, 255); - q=buffer; - i=1; - while (*q) { - if (*q=='"') i=!i; - if (*q==' ' && !i) - *q='\0'; - else - q++; - } - if (s[2]=='"' && buffer[0] && buffer[strlen(buffer)-1]=='"') { - buffer[strlen(buffer)-1] = '\0'; - e = KEY_EVENT(XStringToKeysym(buffer)); - } - break; - case 'A': - if (s[1]>='0' && s[1]<='1' && strlen(s)>=5) { - p = s[1]-'0'; - push_release = s[2]; - i = atoi(s+3); - q=s+3; - while (*q && *q!='+' && *q!='-') q++; - if (*q=='+') - e = AXISPLUS_EVENT(p,i); - else if (*q=='-') - e = AXISMINUS_EVENT(p,i); - } - break; - case 'B': - if (s[1]>='0' && s[1]<='1' && strlen(s)>=4) { - p = s[1]-'0'; - push_release = s[2]; - i = atoi(s+3); - e = BUTTON_EVENT(p,i); - } - break; - case 'X': - if (s[1]>='0' && s[1]<='1' && strlen(s)>=5) { - p = s[1]-'0'; - i = atoi(s+3); - q=s+3; - while (*q && *q!='v') q++; - if (*q=='v') - e = ANALOGAXIS_EVENT(p,i,atoi(q+1)); - } - break; - } - - if (push_release=='R') - return e+RELEASE_EVENT; - else - return e; -} - -static void saveConfig() { - FILE *f; - int i,j,k; - - f = fopen(CONFIG_FILENAME, "w"); - if (!f) { - fprintf(stderr, "DFInput error: couldn't write config file!\n"); - return; - } - - fprintf(f,"[general]\n"); - fprintf(f,"use_threads = %d\n", use_threads); - fprintf(f,"use_analog = %d\n", use_analog); - for (i=0;i<MAXDEVICES;i++) { - fprintf(f,"[pad %d]\n", i+1); - fprintf(f,"devicefilename = %s\n", devicefilename[i]); - fprintf(f,"minzero = %d\n", minzero[i]); - fprintf(f,"maxzero = %d\n", maxzero[i]); - fprintf(f,"event_l2 = %s\n", EventCode2String(PadButtons[i][0])); - fprintf(f,"event_r2 = %s\n", EventCode2String(PadButtons[i][1])); - fprintf(f,"event_l1 = %s\n", EventCode2String(PadButtons[i][2])); - fprintf(f,"event_r1 = %s\n", EventCode2String(PadButtons[i][3])); - fprintf(f,"event_triangle = %s\n", EventCode2String(PadButtons[i][4])); - fprintf(f,"event_circle = %s\n", EventCode2String(PadButtons[i][5])); - fprintf(f,"event_cross = %s\n", EventCode2String(PadButtons[i][6])); - fprintf(f,"event_square = %s\n", EventCode2String(PadButtons[i][7])); - fprintf(f,"event_select = %s\n", EventCode2String(PadButtons[i][8])); - fprintf(f,"event_lanalog = %s\n", EventCode2String(PadButtons[i][9])); - fprintf(f,"event_ranalog = %s\n", EventCode2String(PadButtons[i][10])); - fprintf(f,"event_start = %s\n", EventCode2String(PadButtons[i][11])); - fprintf(f,"event_up = %s\n", EventCode2String(PadButtons[i][12])); - fprintf(f,"event_right = %s\n", EventCode2String(PadButtons[i][13])); - fprintf(f,"event_down = %s\n", EventCode2String(PadButtons[i][14])); - fprintf(f,"event_left = %s\n", EventCode2String(PadButtons[i][15])); - fprintf(f,"event_lanax = %s\n", EventCode2String(PadButtons[i][16])); - fprintf(f,"event_lanay = %s\n", EventCode2String(PadButtons[i][17])); - fprintf(f,"event_ranax = %s\n", EventCode2String(PadButtons[i][18])); - fprintf(f,"event_ranay = %s\n", EventCode2String(PadButtons[i][19])); - for (j=0; j<MAXMACROS; j++) { - fprintf(f, "[macro %d]\n", j+1); - fprintf(f, "event_launch = %s\n", EventCode2String(macroLaunch[i][j])); - fprintf(f, "events ="); - for (k=0; k<MAXMACROLENGTH && macroEvents[i][j][k]; k++) { - fprintf(f, " %s", EventCode2String(macroEvents[i][j][k])); - } - fprintf(f,"\n"); - fprintf(f, "interval ="); - for (k=0; k<MAXMACROLENGTH && macroEvents[i][j][k]; k++) { - fprintf(f, " %ld", macroInterval[i][j][k]); - } - fprintf(f,"\n"); - } - } - - fclose(f); -} - -static void loadConfig() { - FILE *f; - int i; - char line[FILENAME_MAX+30]; - int pad=0; - int macronr=0; - char *val; - - f = fopen(CONFIG_FILENAME, "r"); - if (!f) { -// fprintf(stderr, "DFInput warning: config file not found."); - return; - } - - while(!feof(f)) { - fgets(line, FILENAME_MAX+29, f); - i=strlen(line)-1; - while (i>0 && line[i]<32) line[i--]='\0'; - - val=NULL; - while(i>0) { - if (line[i]=='=') val = line+(i+1); - i--; - } - if (val) { - while (*val==' ') val++; - } - - if (!strcmp(line, "[general]")) { - // nothing to do - } - else if (!strncmp(line, "use_threads", 11)) { - use_threads = atoi(val); - } - else if (!strncmp(line, "use_analog", 10)) { - use_analog = atoi(val); - } - else if (!strcmp(line, "[pad 1]")) { - pad = 0; - } - else if (!strcmp(line, "[pad 2]")) { - pad = 1; - } - else if (!strncmp(line, "[macro ", 7)) { - macronr = atoi(line+7)-1; - if (macronr<0 || macronr>=MAXMACROS) macronr=0; - } - else if (!strncmp(line, "devicefilename", 14)) { - strcpy(devicefilename[pad], val); - } - else if (!strncmp(line, "minzero", 7)) { - minzero[pad] = atoi(val); - } - else if (!strncmp(line, "maxzero", 7)) { - maxzero[pad] = atoi(val); - } - else if (!strncmp(line, "event_l2", 8)) PadButtons[pad][0] = String2EventCode(val); - else if (!strncmp(line, "event_r2", 8)) PadButtons[pad][1] = String2EventCode(val); - else if (!strncmp(line, "event_l1", 8)) PadButtons[pad][2] = String2EventCode(val); - else if (!strncmp(line, "event_r1", 8)) PadButtons[pad][3] = String2EventCode(val); - else if (!strncmp(line, "event_triangle", 14)) PadButtons[pad][4] = String2EventCode(val); - else if (!strncmp(line, "event_circle", 12)) PadButtons[pad][5] = String2EventCode(val); - else if (!strncmp(line, "event_cross", 11)) PadButtons[pad][6] = String2EventCode(val); - else if (!strncmp(line, "event_square", 12)) PadButtons[pad][7] = String2EventCode(val); - else if (!strncmp(line, "event_select", 12)) PadButtons[pad][8] = String2EventCode(val); - else if (!strncmp(line, "event_lanalog", 13)) PadButtons[pad][9] = String2EventCode(val); - else if (!strncmp(line, "event_ranalog", 13)) PadButtons[pad][10] = String2EventCode(val); - else if (!strncmp(line, "event_start", 11)) PadButtons[pad][11] = String2EventCode(val); - else if (!strncmp(line, "event_up", 8)) PadButtons[pad][12] = String2EventCode(val); - else if (!strncmp(line, "event_right", 11)) PadButtons[pad][13] = String2EventCode(val); - else if (!strncmp(line, "event_down", 10)) PadButtons[pad][14] = String2EventCode(val); - else if (!strncmp(line, "event_left", 10)) PadButtons[pad][15] = String2EventCode(val); - else if (!strncmp(line, "event_lanax", 11)) PadButtons[pad][16] = String2EventCode(val); - else if (!strncmp(line, "event_lanay", 11)) PadButtons[pad][17] = String2EventCode(val); - else if (!strncmp(line, "event_ranax", 11)) PadButtons[pad][18] = String2EventCode(val); - else if (!strncmp(line, "event_ranay", 11)) PadButtons[pad][19] = String2EventCode(val); - else if (!strncmp(line, "event_launch", 12)) macroLaunch[pad][macronr] = String2EventCode(val); - else if (!strncmp(line, "events", 6)) { - i=0; - while (*val) { - macroEvents[pad][macronr][i++]=String2EventCode(val); - while (*val && *val!=' ') val++; - if (*val==' ') val++; - } - macroEvents[pad][macronr][i]=NO_EVENT; - } - else if (!strncmp(line, "interval", 8)) { - i=0; - while (*val) { - macroInterval[pad][macronr][i++]=atol(val); - while (*val && *val!=' ') val++; - if (*val==' ') val++; - } - } -// else fprintf(stderr, "DFInput error: can't interpret %s\n", line); - } -} - -static int currentPad=0; - -static struct { - GtkWidget *config_window; - -/* ADB - GSList *padnogroup; - GtkWidget *padno_radio[2];*/ - GtkWidget *filename_entry; // TODO - GtkWidget *button[CONFIGBUTTONCOUNT]; - GtkWidget *label[CONFIGBUTTONCOUNT]; -/* ADB - GSList *pcsxgroup; - GtkWidget *epsxe_radio; - GtkWidget *pcsx_radio; - GtkWidget *thread_check; - GtkWidget *analog_check;*/ - GtkWidget *macro_button[MAXMACROS]; - GtkWidget *macro_label[MAXMACROS]; - GtkWidget *macro_def_button[MAXMACROS]; - - GtkWidget *ok_button; - GtkWidget *cancel_button; -} ConfWidgets; - -static struct { int nr; - char *label; - int x; - int y; } - buttonInfo[CONFIGBUTTONCOUNT] = -{ -{0, " L2 ", 20, 30}, -{2, " L1 ", 20, 70}, -{1, " R2 ", 350, 30}, -{3, " R1 ", 350, 70}, -{12, " ^ ", 70, 110}, -{15, " < ", 20, 140}, -{13, " > ", 120, 140}, -{14, " v ", 70, 170}, -{4, " /\\ ", 300, 110}, -{7, " [_] ", 250, 140}, -{5, " (_) ", 350, 140}, -{6, " >< ", 300, 170}, -{8, " Select ", 100, 200}, -{11, " Start ", 250, 200}, -{9, " + ", 90, 280}, -{10," + ", 320, 280}, -{16," -- ", 20, 280}, -{17," | ", 70, 250}, -{18," -- ",250, 280}, -{19," | ",300, 250} -}; - -static void showPadConfiguration() { - int i; - - // gtk_toggle_button_set_active(ConfWidgets.padno_radio[currentPad], TRUE); - // gtk_toggle_button_set_active(ConfWidgets.padno_radio[1-currentPad], FALSE); - - gtk_entry_set_text ( GTK_ENTRY(ConfWidgets.filename_entry), devicefilename[currentPad] ); - - for (i=0; i<CONFIGBUTTONCOUNT; i++) { - gtk_label_set(GTK_LABEL(ConfWidgets.label[i]), eventDescription(PadButtons[currentPad][buttonInfo[i].nr])); - } - - for (i=0; i<MAXMACROS; i++) { - gtk_label_set(GTK_LABEL(ConfWidgets.macro_label[i]), eventDescription(macroLaunch[currentPad][i])); - } -} - -static void OnConfCancel(GtkWidget *widget, gpointer user_data) { - loadConfig(); - gtk_widget_hide(ConfWidgets.config_window); - gtk_widget_destroy(ConfWidgets.config_window); - gtk_main_quit(); -} - -static void OnConfOk(GtkWidget *widget, gpointer user_data) { - saveConfig(); - gtk_widget_hide(ConfWidgets.config_window); - gtk_widget_destroy(ConfWidgets.config_window); - gtk_main_quit(); -} - -static void OnConfBtn(GtkWidget *But, gpointer data) { - EventCode events[MAXCNT]; - EventCode e=NO_EVENT; - int i,j,cnt; - KeySym ksym; - PadJoyEvent *pje; - int ok=0; - int labelnr = (int) gtk_object_get_user_data(GTK_OBJECT(But)); - int btnnr = buttonInfo[labelnr].nr; - int e_rem1 =NO_EVENT; - int e_rem2 =NO_EVENT; - - devicefile[currentPad] = open(devicefilename[currentPad], O_RDONLY); - - if (devicefilename[currentPad][0] && devicefile[currentPad] == -1) { - fprintf(stderr, "DFInput: could not open device %s, errno=%d\n", devicefilename[currentPad], errno); - } - - for (i=0; i<MAXDEVICES; i++) { - for (j=0; j<MAXAXES; j++) { - axestatus[i][j] = AXESTS_UNKNOWN; - } - } - - for (i=0; i<100 && !ok; i++) { - cnt = getPendingEvents(30, events, MAXCNT, 1, 1, 1, NULL); - - for (j=0; j<cnt && !ok; j++) { - e = events[j]; - if (e<RELEASE_EVENT) { - pje = EventCode2PadJoyEvent(e); - if (btnnr>15) { - if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { - e = ANALOGAXIS_EVENT(pje->pad, pje->no, 0); - PadButtons[currentPad][btnnr] = e; - ok = 1; - e_rem1 = AXISPLUS_EVENT(pje->pad, pje->no); - e_rem2 = AXISMINUS_EVENT(pje->pad, pje->no); - } - } - else if (e<FIRST_JOY_EVENT) { - ksym = e-FIRST_KEY_EVENT; - if (ksym != XK_Escape) { - PadButtons[currentPad][btnnr] = e; - ok=1; - } - } - else { - PadButtons[currentPad][btnnr] = e; - if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { - e_rem1 = ANALOGAXIS_EVENT(pje->pad, pje->no, 0); - } - ok=1; - } - } - - if (!ok) { - fprintf(stderr, "DFInput: event %ld (%s) is not usable.\n", (long) e, EventCode2String(e)); - } - } - } - - if (!ok) { - fprintf(stderr, "DFInput: no usable input received.\n"); - } - - while (getPendingEvents(0, events, MAXCNT, 1, 1, 1, NULL)){} // read pending events to clear buffers - - close(devicefile[currentPad]); - devicefile[currentPad] = -1; - - if (ok) { - // If this event is assigned to another button, remove this assignment - for (i=0; i<MAXDEVICES; i++) { - for (j=0; j<MAXPSXBUTTONS; j++) { - if ((PadButtons[i][j] == e || PadButtons[i][j] == e_rem1 || PadButtons[i][j] == e_rem2) && - (i!=currentPad || j!=btnnr)) { - PadButtons[i][j] = NO_EVENT; - } - } - for (j=0; j<MAXMACROS; j++) { - if (macroLaunch[i][j] == e || macroLaunch[i][j] == e_rem1 || macroLaunch[i][j] == e_rem2) { - macroLaunch[i][j] = NO_EVENT; - } - } - } - - showPadConfiguration(); - } -} - -static void OnMacroBtn(GtkWidget *But, gpointer data) { - EventCode events[MAXCNT]; - EventCode e=NO_EVENT; - PadJoyEvent *pje; - int i,j,cnt; - KeySym ksym; - int ok=0; - int e_rem1 =NO_EVENT; - - int macronr = (int) gtk_object_get_user_data(GTK_OBJECT(But)); - - devicefile[currentPad] = open(devicefilename[currentPad], O_RDONLY); - - for (i=0; i<MAXDEVICES; i++) { - for (j=0; j<MAXAXES; j++) { - axestatus[i][j] = AXESTS_UNKNOWN; - } - } - - for (i=0; i<100 && !ok; i++) { - cnt = getPendingEvents(30, events, MAXCNT, 1, 1, 1, NULL); - - for (j=0; j<cnt && !ok; j++) { - e = events[j]; - if (e<RELEASE_EVENT) { - pje = EventCode2PadJoyEvent(e); - if (e<FIRST_JOY_EVENT) { - ksym = e-FIRST_KEY_EVENT; - if (ksym != XK_Escape) { - macroLaunch[currentPad][macronr] = e; - ok=1; - } - } - else { - macroLaunch[currentPad][macronr] = e; - ok=1; - if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { - e_rem1 = ANALOGAXIS_EVENT(pje->pad, pje->no, 0); - } - } - } - } - } - while (getPendingEvents(0, events, MAXCNT, 1, 1, 1, NULL)){} // read pending events to clear buffers - - close(devicefile[currentPad]); - devicefile[currentPad] = -1; - - if (ok) { - // If this event is assigned to another button, remove this assignment - for (i=0; i<MAXDEVICES; i++) { - for (j=0; j<MAXPSXBUTTONS; j++) { - if (PadButtons[i][j] == e || PadButtons[i][j] == e_rem1) { - PadButtons[i][j] = NO_EVENT; - } - } - for (j=0; j<MAXMACROS; j++) { - if (macroLaunch[i][j] == e && (i!=currentPad || j!=macronr)) { - macroLaunch[i][j] = NO_EVENT; - } - } - } - - showPadConfiguration(); - } -} - -static void OnMacroDefineBtn(GtkWidget *But, gpointer data) { - EventCode events[MAXCNT]; - EventCode e=NO_EVENT; - PadJoyEvent *pje; - int i,j,cnt; - int ok=0; - long now; - long timing[MAXCNT]; - - int macronr = (int) gtk_object_get_user_data(GTK_OBJECT(But)); - - devicefile[currentPad] = open(devicefilename[currentPad], O_RDONLY); - - now = -1; - - for (i=0; i<MAXDEVICES; i++) { - for (j=0; j<MAXAXES; j++) { - axestatus[i][j] = AXESTS_UNUSED; - } - } - - for (i=0; i<MAXDEVICES; i++) { - for (j=0; j<MAXPSXBUTTONS; j++) { - pje = EventCode2PadJoyEvent(PadButtons[i][j]); - - if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { - axestatus[pje->pad][pje->no] = AXESTS_UNKNOWN; - } - else if (pje->event_type == EVENTTYPE_ANALOG && use_analog) { - axestatus[pje->pad][pje->no] = AXESTS_ANALOG; - } - } - } - - i=0; - - gtk_widget_add_events(ConfWidgets.config_window,GDK_KEY_RELEASE_MASK); - - /* Listen for input events until finished (Escape is pressed) or timeout */ - while (!ok && i<MAXMACROLENGTH-1) { - cnt = getPendingEvents(2000, events, MAXCNT, 1, 1, 1, timing); - - if (cnt && now<0) { - now=timing[0]; - } - else if (!cnt && i) { - // inactivity for 2 seconds, finish definition - ok=1; - } - - for (j=0; j<cnt && !ok && i<MAXMACROLENGTH-1; j++) { - e = events[j]; - if ((e-FIRST_KEY_EVENT) != XK_Escape && (e-FIRST_KEY_EVENT) != (XK_Escape+RELEASE_EVENT)) { - macroEvents[currentPad][macronr][i] = e; - macroInterval[currentPad][macronr][i] = timing[j]-now; - now = timing[j]; - i++; - } - else { - ok=1; - } - } - } - - if (i>0) { - macroEvents[currentPad][macronr][i] = NO_EVENT; - } - - close(devicefile[currentPad]); - devicefile[currentPad] = -1; - -} - -static void OnThreadCheck(GtkWidget *But, gpointer data) { - use_threads = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(But)); -} - -static void OnAnalogCheck(GtkWidget *But, gpointer data) { - use_analog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(But)); -} - -static void OnPadnoRadio(GtkWidget *But, gpointer data) { - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (But))) - currentPad = (int) data; - showPadConfiguration(); -} - -static void OnFilenameEntry(GtkWidget *Ent, gpointer data) { - strcpy(devicefilename[currentPad], gtk_entry_get_text(GTK_ENTRY(Ent))); -} - -/* Closed by clicking on the top-right hand corner */ -void on_config_win_clicked (GtkWidget *widget, gpointer user_data) { - gtk_widget_destroy (widget); - gtk_main_quit(); - exit (0); -} - -static void CreateConfigWindow(void) { - char buffer[100]; - int i; - GtkWidget *hbox; - - GladeXML *xml; - xml = glade_xml_new (DATADIR "dfinput.glade2", "CfgWin", NULL); - /* ADB TODO Error checking */ - - GtkWidget *widget = glade_xml_get_widget (xml, "CfgWin"); - ConfWidgets.config_window = widget; - GtkWidget *fixedbox = glade_xml_get_widget (xml, "fixed1"); - - g_signal_connect_data(GTK_OBJECT(widget), "delete_event", - GTK_SIGNAL_FUNC(on_config_win_clicked), NULL, NULL, G_CONNECT_AFTER); - -/* DELETE hbox = gtk_hbox_new(FALSE, 0); - gtk_fixed_put(GTK_FIXED(fixedbox), hbox, 10, 10); - gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("Pad number:"), FALSE, TRUE, 2);*/ - -// ConfWidgets.padnogroup = NULL; - - widget = glade_xml_get_widget (xml, "radiobutton1"); - g_signal_connect_data (GTK_OBJECT (widget), "toggled", - GTK_SIGNAL_FUNC (OnPadnoRadio), (gpointer) 0, NULL, G_CONNECT_AFTER); - widget = glade_xml_get_widget (xml, "radiobutton2"); - g_signal_connect_data (GTK_OBJECT (widget), "toggled", - GTK_SIGNAL_FUNC (OnPadnoRadio), (gpointer) 1, NULL, G_CONNECT_AFTER); - -// hbox = gtk_hbox_new(FALSE, 0); -// gtk_fixed_put (GTK_FIXED (fixedbox), hbox, 10, 40); - -// gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("Device file:"), FALSE, TRUE, 2); - /*ConfWidgets.filename_entry = gtk_entry_new();*/ - - widget = glade_xml_get_widget (xml, "filename_entry"); - gtk_entry_set_text ( GTK_ENTRY(widget), (gchar *) devicefilename[0] ); - gtk_entry_set_max_length ( GTK_ENTRY(widget), FILENAME_MAX); - //gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.filename_entry, FALSE, TRUE, 2); - gtk_signal_connect(GTK_OBJECT(widget), "changed", GTK_SIGNAL_FUNC(OnFilenameEntry), NULL); - ConfWidgets.filename_entry = widget; - -/* TODO - ConfWidgets.thread_check = gtk_check_button_new_with_label("multithreaded");*/ - widget = glade_xml_get_widget (xml, "chkMultithreaded"); - g_signal_connect_data (GTK_OBJECT (widget), "toggled", - GTK_SIGNAL_FUNC (OnThreadCheck), NULL, NULL, G_CONNECT_AFTER); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), use_threads); - - /* TODO - ConfWidgets.analog_check = gtk_check_button_new_with_label("analog");*/ - widget = glade_xml_get_widget (xml, "chkAnalog"); - g_signal_connect_data (GTK_OBJECT (widget), "toggled", - GTK_SIGNAL_FUNC (OnAnalogCheck), NULL, NULL, G_CONNECT_AFTER); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), use_analog); - - // Pad Buttons - for (i=0; i<CONFIGBUTTONCOUNT; i++) { - hbox = gtk_hbox_new(FALSE, 0); - ConfWidgets.button[i] = gtk_button_new_with_label(buttonInfo[i].label); - gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.button[i], FALSE, TRUE, 2); - gtk_fixed_put(GTK_FIXED(fixedbox), hbox, buttonInfo[i].x, buttonInfo[i].y); - gtk_object_set_user_data(GTK_OBJECT(ConfWidgets.button[i]), (char *)i); - gtk_signal_connect(GTK_OBJECT(ConfWidgets.button[i]), "clicked", GTK_SIGNAL_FUNC(OnConfBtn), NULL); - ConfWidgets.label[i] = gtk_label_new(eventDescription(PadButtons[0][buttonInfo[i].nr])); - gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.label[i], FALSE, TRUE, 2); - } - - hbox = gtk_hbox_new(FALSE, 0); - gtk_fixed_put(GTK_FIXED(fixedbox), hbox, 20, 390); - // Macro Buttons - for (i=0; i<MAXMACROS; i++) { - sprintf(buffer, "M%d", i+1); - ConfWidgets.macro_button[i] = gtk_button_new_with_label(buffer); - gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.macro_button[i], FALSE, TRUE, 2); - gtk_object_set_user_data(GTK_OBJECT(ConfWidgets.macro_button[i]), (char *)i); - gtk_signal_connect(GTK_OBJECT(ConfWidgets.macro_button[i]), "clicked", GTK_SIGNAL_FUNC(OnMacroBtn), NULL); - ConfWidgets.macro_label[i] = gtk_label_new(eventDescription(macroLaunch[0][i])); - gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.macro_label[i], FALSE, TRUE, 2); - ConfWidgets.macro_def_button[i] = gtk_button_new_with_label("Def"); - gtk_box_pack_start(GTK_BOX(hbox), ConfWidgets.macro_def_button[i], FALSE, TRUE, 2); - gtk_object_set_user_data(GTK_OBJECT(ConfWidgets.macro_def_button[i]), (char *)i); - gtk_signal_connect(GTK_OBJECT(ConfWidgets.macro_def_button[i]), "clicked", GTK_SIGNAL_FUNC(OnMacroDefineBtn), NULL); - if (i<MAXMACROS-1) { - gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(" "), FALSE, TRUE, 2); - } - } - - gtk_widget_show_all (GTK_WIDGET (fixedbox)); - - widget = glade_xml_get_widget (xml, "btnOK"); - g_signal_connect_data (GTK_OBJECT (widget), "clicked", GTK_SIGNAL_FUNC (OnConfOk), NULL, NULL, G_CONNECT_AFTER); - - widget = glade_xml_get_widget (xml, "btnCancel"); - g_signal_connect_data (GTK_OBJECT (widget), "clicked", GTK_SIGNAL_FUNC (OnConfCancel), NULL, NULL, G_CONNECT_AFTER); -} - -long PADconfigure(void) { - currentPad = 0; - initPadtime(); - PADinit(0); - CreateConfigWindow(); - gtk_widget_show_all(ConfWidgets.config_window); - - gtk_main(); - - return 0; +#include "pad.h" + +#define CONFIG_FILE "dfinput.cfg" + +GLOBALDATA g; + +static void SetDefaultConfig() { + memset(&g.cfg, 0, sizeof(g.cfg)); + + g.cfg.Threaded = 1; + + g.cfg.PadDef[0].DevNum = 0; + g.cfg.PadDef[1].DevNum = 1; + + g.cfg.PadDef[0].Type = PSE_PAD_TYPE_STANDARD; + g.cfg.PadDef[1].Type = PSE_PAD_TYPE_STANDARD; + + // Pad1 keyboard + g.cfg.PadDef[0].KeyDef[DKEY_SELECT].Key = XK_c; + g.cfg.PadDef[0].KeyDef[DKEY_START].Key = XK_v; + g.cfg.PadDef[0].KeyDef[DKEY_UP].Key = XK_Up; + g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].Key = XK_Right; + g.cfg.PadDef[0].KeyDef[DKEY_DOWN].Key = XK_Down; + g.cfg.PadDef[0].KeyDef[DKEY_LEFT].Key = XK_Left; + g.cfg.PadDef[0].KeyDef[DKEY_L2].Key = XK_e; + g.cfg.PadDef[0].KeyDef[DKEY_R2].Key = XK_t; + g.cfg.PadDef[0].KeyDef[DKEY_L1].Key = XK_w; + g.cfg.PadDef[0].KeyDef[DKEY_R1].Key = XK_r; + g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].Key = XK_d; + g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].Key = XK_x; + g.cfg.PadDef[0].KeyDef[DKEY_CROSS].Key = XK_z; + g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].Key = XK_s; + + // Pad1 joystick + g.cfg.PadDef[0].KeyDef[DKEY_SELECT].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_SELECT].J.Button = 8; + g.cfg.PadDef[0].KeyDef[DKEY_START].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_START].J.Button = 9; + g.cfg.PadDef[0].KeyDef[DKEY_UP].JoyEvType = AXIS; + g.cfg.PadDef[0].KeyDef[DKEY_UP].J.Axis = -2; + g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].JoyEvType = AXIS; + g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].J.Axis = 1; + g.cfg.PadDef[0].KeyDef[DKEY_DOWN].JoyEvType = AXIS; + g.cfg.PadDef[0].KeyDef[DKEY_DOWN].J.Axis = 2; + g.cfg.PadDef[0].KeyDef[DKEY_LEFT].JoyEvType = AXIS; + g.cfg.PadDef[0].KeyDef[DKEY_LEFT].J.Axis = -1; + g.cfg.PadDef[0].KeyDef[DKEY_L2].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_L2].J.Button = 4; + g.cfg.PadDef[0].KeyDef[DKEY_L1].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_L1].J.Button = 6; + g.cfg.PadDef[0].KeyDef[DKEY_R2].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_R2].J.Button = 5; + g.cfg.PadDef[0].KeyDef[DKEY_R1].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_R1].J.Button = 7; + g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].J.Button = 0; + g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].J.Button = 1; + g.cfg.PadDef[0].KeyDef[DKEY_CROSS].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_CROSS].J.Button = 2; + g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].JoyEvType = BUTTON; + g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].J.Button = 3; + + // Pad2 joystick + g.cfg.PadDef[1].KeyDef[DKEY_SELECT].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_SELECT].J.Button = 8; + g.cfg.PadDef[1].KeyDef[DKEY_START].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_START].J.Button = 9; + g.cfg.PadDef[1].KeyDef[DKEY_UP].JoyEvType = AXIS; + g.cfg.PadDef[1].KeyDef[DKEY_UP].J.Axis = -2; + g.cfg.PadDef[1].KeyDef[DKEY_RIGHT].JoyEvType = AXIS; + g.cfg.PadDef[1].KeyDef[DKEY_RIGHT].J.Axis = 1; + g.cfg.PadDef[1].KeyDef[DKEY_DOWN].JoyEvType = AXIS; + g.cfg.PadDef[1].KeyDef[DKEY_DOWN].J.Axis = 2; + g.cfg.PadDef[1].KeyDef[DKEY_LEFT].JoyEvType = AXIS; + g.cfg.PadDef[1].KeyDef[DKEY_LEFT].J.Axis = -1; + g.cfg.PadDef[1].KeyDef[DKEY_L2].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_L2].J.Button = 4; + g.cfg.PadDef[1].KeyDef[DKEY_L1].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_L1].J.Button = 6; + g.cfg.PadDef[1].KeyDef[DKEY_R2].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_R2].J.Button = 5; + g.cfg.PadDef[1].KeyDef[DKEY_R1].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_R1].J.Button = 7; + g.cfg.PadDef[1].KeyDef[DKEY_TRIANGLE].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_TRIANGLE].J.Button = 0; + g.cfg.PadDef[1].KeyDef[DKEY_CIRCLE].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_CIRCLE].J.Button = 1; + g.cfg.PadDef[1].KeyDef[DKEY_CROSS].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_CROSS].J.Button = 2; + g.cfg.PadDef[1].KeyDef[DKEY_SQUARE].JoyEvType = BUTTON; + g.cfg.PadDef[1].KeyDef[DKEY_SQUARE].J.Button = 3; } +void LoadConfig() { + FILE *fp; + char buf[256]; + int current, a, b, c; -/*---------------------------------------------------------------------*/ -/* About dialogue stuff */ -/*---------------------------------------------------------------------*/ - -void PADabout(void) { - GladeXML *xml; - xml = glade_xml_new (DATADIR "dfinput.glade2", "AboutWin", NULL); + SetDefaultConfig(); - GtkWidget *widget = glade_xml_get_widget (xml, "AboutWin"); + fp = fopen(CONFIG_FILE, "r"); + if (fp == NULL) { + return; + } - /* TODO Authors, about, version */ + current = 0; + + while (fgets(buf, 256, fp) != NULL) { + if (strncmp(buf, "Threaded=", 9) == 0) { + g.cfg.Threaded = atoi(&buf[9]); + } else if (strncmp(buf, "[PAD", 4) == 0) { + current = atoi(&buf[4]) - 1; + if (current < 0) { + current = 0; + } else if (current > 1) { + current = 1; + } + } else if (strncmp(buf, "DevNum=", 7) == 0) { + g.cfg.PadDef[current].DevNum = atoi(&buf[7]); + } else if (strncmp(buf, "Type=", 5) == 0) { + g.cfg.PadDef[current].Type = atoi(&buf[5]); + } else if (strncmp(buf, "Select=", 7) == 0) { + sscanf(buf, "Select=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_SELECT].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_SELECT].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_SELECT].J.d = c; + } else if (strncmp(buf, "L3=", 3) == 0) { + sscanf(buf, "L3=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_L3].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_L3].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_L3].J.d = c; + } else if (strncmp(buf, "R3=", 3) == 0) { + sscanf(buf, "R3=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_R3].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_R3].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_R3].J.d = c; + } else if (strncmp(buf, "Start=", 6) == 0) { + sscanf(buf, "Start=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_START].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_START].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_START].J.d = c; + } else if (strncmp(buf, "Up=", 3) == 0) { + sscanf(buf, "Up=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_UP].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_UP].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_UP].J.d = c; + } else if (strncmp(buf, "Right=", 6) == 0) { + sscanf(buf, "Right=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].J.d = c; + } else if (strncmp(buf, "Down=", 5) == 0) { + sscanf(buf, "Down=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_DOWN].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_DOWN].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_DOWN].J.d = c; + } else if (strncmp(buf, "Left=", 5) == 0) { + sscanf(buf, "Left=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_LEFT].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_LEFT].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_LEFT].J.d = c; + } else if (strncmp(buf, "L2=", 3) == 0) { + sscanf(buf, "L2=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_L2].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_L2].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_L2].J.d = c; + } else if (strncmp(buf, "R2=", 3) == 0) { + sscanf(buf, "R2=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_R2].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_R2].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_R2].J.d = c; + } else if (strncmp(buf, "L1=", 3) == 0) { + sscanf(buf, "L1=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_L1].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_L1].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_L1].J.d = c; + } else if (strncmp(buf, "R1=", 3) == 0) { + sscanf(buf, "R1=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_R1].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_R1].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_R1].J.d = c; + } else if (strncmp(buf, "Triangle=", 9) == 0) { + sscanf(buf, "Triangle=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].J.d = c; + } else if (strncmp(buf, "Circle=", 7) == 0) { + sscanf(buf, "Circle=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].J.d = c; + } else if (strncmp(buf, "Cross=", 6) == 0) { + sscanf(buf, "Cross=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_CROSS].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_CROSS].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_CROSS].J.d = c; + } else if (strncmp(buf, "Square=", 7) == 0) { + sscanf(buf, "Square=%d,%d,%d", &a, &b, &c); + g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].Key = a; + g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].JoyEvType = b; + g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].J.d = c; + } else if (strncmp(buf, "LeftAnalogX=", 11) == 0) { + g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_X] = atoi(&buf[11]); + } else if (strncmp(buf, "LeftAnalogY=", 11) == 0) { + g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_Y] = atoi(&buf[11]); + } else if (strncmp(buf, "RightAnalogX=", 12) == 0) { + g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_X] = atoi(&buf[12]); + } else if (strncmp(buf, "RightAnalogY=", 12) == 0) { + g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_Y] = atoi(&buf[12]); + } + } - gtk_dialog_run (GTK_DIALOG (widget)); - gtk_widget_destroy (widget); -// gtk_main_quit(); + fclose(fp); } -/*---------------------------------------------------------------------*/ -/* Main program */ -/*---------------------------------------------------------------------*/ - -int main(int argc, char **argv) { -#ifdef ENABLE_NLS - setlocale (LC_ALL, ""); - bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); -#endif +void SaveConfig() { + FILE *fp; + int i; - gtk_set_locale(); - gtk_init (&argc, &argv); - - if (argc>1 && !strcmp(argv[1], "-about")) { - PADabout(); - } - else { - PADconfigure(); - } + fp = fopen(CONFIG_FILE, "w"); + if (fp == NULL) { + return; + } - gtk_exit (0); + fprintf(fp, "[CONFIG]\n"); + fprintf(fp, "Threaded=%d\n", g.cfg.Threaded); + fprintf(fp, "\n"); + + for (i = 0; i < 2; i++) { + fprintf(fp, "[PAD%d]\n", i + 1); + fprintf(fp, "DevNum=%d\n", g.cfg.PadDef[i].DevNum); + fprintf(fp, "Type=%d\n", g.cfg.PadDef[i].Type); + + fprintf(fp, "Select=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_SELECT].Key, + g.cfg.PadDef[i].KeyDef[DKEY_SELECT].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_SELECT].J.d); + fprintf(fp, "L3=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_L3].Key, + g.cfg.PadDef[i].KeyDef[DKEY_L3].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_L3].J.d); + fprintf(fp, "R3=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_R3].Key, + g.cfg.PadDef[i].KeyDef[DKEY_R3].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_R3].J.d); + fprintf(fp, "Start=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_START].Key, + g.cfg.PadDef[i].KeyDef[DKEY_START].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_START].J.d); + fprintf(fp, "Up=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_UP].Key, + g.cfg.PadDef[i].KeyDef[DKEY_UP].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_UP].J.d); + fprintf(fp, "Right=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_RIGHT].Key, + g.cfg.PadDef[i].KeyDef[DKEY_RIGHT].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_RIGHT].J.d); + fprintf(fp, "Down=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_DOWN].Key, + g.cfg.PadDef[i].KeyDef[DKEY_DOWN].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_DOWN].J.d); + fprintf(fp, "Left=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_LEFT].Key, + g.cfg.PadDef[i].KeyDef[DKEY_LEFT].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_LEFT].J.d); + fprintf(fp, "L2=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_L2].Key, + g.cfg.PadDef[i].KeyDef[DKEY_L2].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_L2].J.d); + fprintf(fp, "R2=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_R2].Key, + g.cfg.PadDef[i].KeyDef[DKEY_R2].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_R2].J.d); + fprintf(fp, "L1=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_L1].Key, + g.cfg.PadDef[i].KeyDef[DKEY_L1].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_L1].J.d); + fprintf(fp, "R1=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_R1].Key, + g.cfg.PadDef[i].KeyDef[DKEY_R1].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_R1].J.d); + fprintf(fp, "Triangle=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_TRIANGLE].Key, + g.cfg.PadDef[i].KeyDef[DKEY_TRIANGLE].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_TRIANGLE].J.d); + fprintf(fp, "Circle=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_CIRCLE].Key, + g.cfg.PadDef[i].KeyDef[DKEY_CIRCLE].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_CIRCLE].J.d); + fprintf(fp, "Cross=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_CROSS].Key, + g.cfg.PadDef[i].KeyDef[DKEY_CROSS].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_CROSS].J.d); + fprintf(fp, "Square=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_SQUARE].Key, + g.cfg.PadDef[i].KeyDef[DKEY_SQUARE].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_SQUARE].J.d); + + fprintf(fp, "LeftAnalogX=%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_X]); + fprintf(fp, "LeftAnalogY=%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_Y]); + fprintf(fp, "RightAnalogX=%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_X]); + fprintf(fp, "RightAnalogY=%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_Y]); + + fprintf(fp, "\n"); + } - return 0; + fclose(fp); } diff --git a/plugins/dfinput/dfinput.glade2 b/plugins/dfinput/dfinput.glade2 index d98fcbd7..e4a9ba81 100644 --- a/plugins/dfinput/dfinput.glade2 +++ b/plugins/dfinput/dfinput.glade2 @@ -1,31 +1,95 @@ <?xml version="1.0"?> <glade-interface> - <!-- interface-requires gtk+ 2.6 --> - <!-- interface-naming-policy toplevel-contextual --> - <widget class="GtkWindow" id="CfgWin"> - <property name="visible">True</property> - <property name="title" translatable="yes">Configure Gamepad/Keyboard</property> - <property name="modal">True</property> - <property name="type_hint">dialog</property> - <child> - <widget class="GtkVBox" id="vbox1"> + <!-- interface-requires gtk+ 2.12 --> + <!-- interface-naming-policy project-wide --> + <widget class="GtkDialog" id="CfgWnd"> + <property name="border_width">5</property> + <property name="resizable">False</property> + <property name="type_hint">normal</property> + <property name="has_separator">False</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> <property name="visible">True</property> - <property name="border_width">6</property> <property name="orientation">vertical</property> - <property name="spacing">6</property> + <property name="spacing">2</property> <child> - <widget class="GtkVBox" id="vbox2"> + <widget class="GtkNotebook" id="notebook1"> <property name="visible">True</property> - <property name="orientation">vertical</property> + <property name="can_focus">True</property> <child> - <widget class="GtkHBox" id="hbox1"> + <widget class="GtkVBox" id="vbox1"> <property name="visible">True</property> - <property name="border_width">6</property> - <property name="spacing">50</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> <child> - <widget class="GtkLabel" id="label1"> + <widget class="GtkHButtonBox" id="hbuttonbox1"> <property name="visible">True</property> - <property name="label" translatable="yes">Pad number:</property> + <child> + <widget class="GtkHBox" id="hbox6"> + <property name="visible">True</property> + <property name="spacing">10</property> + <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes">Device:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="combodev1"> + <property name="width_request">150</property> + <property name="visible">True</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox5"> + <property name="visible">True</property> + <property name="spacing">10</property> + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes">Type:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="combotype1"> + <property name="width_request">200</property> + <property name="visible">True</property> + <property name="items" translatable="yes">Digital Pad +Analog Pad</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> </widget> <packing> <property name="expand">False</property> @@ -34,50 +98,195 @@ </packing> </child> <child> - <widget class="GtkRadioButton" id="radiobutton1"> - <property name="label" translatable="yes">1</property> + <widget class="GtkScrolledWindow" id="scrolledwindow1"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="border_width">5</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <property name="window_placement_set">True</property> + <property name="shadow_type">etched-in</property> + <child> + <widget class="GtkTreeView" id="treeview1"> + <property name="width_request">500</property> + <property name="height_request">275</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + </widget> + </child> </widget> <packing> - <property name="expand">False</property> - <property name="fill">False</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkRadioButton" id="radiobutton2"> - <property name="label" translatable="yes">2</property> + <widget class="GtkHButtonBox" id="hbuttonbox2"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - <property name="group">radiobutton1</property> + <property name="spacing">20</property> + <property name="layout_style">center</property> + <child> + <widget class="GtkButton" id="btnchange1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-edit</property> + <property name="icon-size">1</property> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">Change</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="btnreset1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="stock">gtk-undo</property> + <property name="icon-size">1</property> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Reset</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> </widget> <packing> - <property name="expand">False</property> - <property name="fill">False</property> <property name="position">2</property> </packing> </child> </widget> + </child> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Controller 1</property> + </widget> <packing> - <property name="position">0</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkHBox" id="hbox2"> + <widget class="GtkVBox" id="vbox2"> <property name="visible">True</property> - <property name="border_width">6</property> - <property name="spacing">6</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> <child> - <widget class="GtkLabel" id="label3"> + <widget class="GtkHButtonBox" id="hbuttonbox4"> <property name="visible">True</property> - <property name="label" translatable="yes">Device file:</property> + <child> + <widget class="GtkHBox" id="hbox8"> + <property name="visible">True</property> + <property name="spacing">10</property> + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="label" translatable="yes">Device:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="combodev2"> + <property name="width_request">150</property> + <property name="visible">True</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox7"> + <property name="visible">True</property> + <property name="spacing">10</property> + <child> + <widget class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="label" translatable="yes">Type:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="combotype2"> + <property name="width_request">200</property> + <property name="visible">True</property> + <property name="items" translatable="yes">Digital Pad +Analog Pad</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> </widget> <packing> <property name="expand">False</property> @@ -86,52 +295,145 @@ </packing> </child> <child> - <widget class="GtkEntry" id="filename_entry"> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="border_width">5</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <property name="window_placement_set">True</property> + <property name="shadow_type">etched-in</property> + <child> + <widget class="GtkTreeView" id="treeview2"> + <property name="width_request">500</property> + <property name="height_request">275</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + </widget> + </child> </widget> <packing> <property name="position">1</property> </packing> </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - <child> - <widget class="GtkHBox" id="hbox3"> - <property name="visible">True</property> - <property name="border_width">6</property> - <property name="spacing">6</property> <child> - <widget class="GtkCheckButton" id="chkMultithreaded"> - <property name="label" translatable="yes">Multi-threaded</property> + <widget class="GtkHButtonBox" id="hbuttonbox3"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="spacing">20</property> + <property name="layout_style">center</property> + <child> + <widget class="GtkButton" id="btnchange2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="stock">gtk-edit</property> + <property name="icon-size">1</property> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="label" translatable="yes">Change</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="btnreset2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-undo</property> + <property name="icon-size">1</property> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes">Reset</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> </widget> <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">0</property> + <property name="position">2</property> </packing> </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Controller 2</property> + </widget> + <packing> + <property name="position">1</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">20</property> <child> - <widget class="GtkCheckButton" id="chkAnalog"> - <property name="label" translatable="yes">Analog</property> + <widget class="GtkCheckButton" id="checkmt"> + <property name="label" translatable="yes">Multi-Threaded (Recommended)</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> - <property name="use_underline">True</property> <property name="draw_indicator">True</property> </widget> <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">1</property> + <property name="padding">16</property> + <property name="position">0</property> </packing> </child> </widget> @@ -140,55 +442,31 @@ </packing> </child> <child> - <widget class="GtkFrame" id="frame1"> + <widget class="GtkLabel" id="label3"> <property name="visible">True</property> - <property name="label_xalign">0</property> - <property name="shadow_type">out</property> - <child> - <widget class="GtkAlignment" id="alignment1"> - <property name="visible">True</property> - <property name="bottom_padding">5</property> - <property name="left_padding">12</property> - <property name="right_padding">12</property> - <child> - <widget class="GtkFixed" id="fixed1"> - <property name="visible">True</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label4"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Button Configuration</b></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="type">label_item</property> - </packing> - </child> + <property name="label" translatable="yes">Options</property> </widget> <packing> - <property name="position">3</property> + <property name="position">2</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> </packing> </child> </widget> <packing> - <property name="position">0</property> + <property name="position">1</property> </packing> </child> - <child> - <widget class="GtkHButtonBox" id="hbuttonbox1"> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> <property name="visible">True</property> - <property name="spacing">6</property> <property name="layout_style">end</property> <child> - <widget class="GtkButton" id="btnCancel"> - <property name="label">gtk-cancel</property> + <widget class="GtkButton" id="btnclose"> + <property name="label">gtk-close</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="receives_default">False</property> + <property name="receives_default">True</property> <property name="use_stock">True</property> </widget> <packing> @@ -197,45 +475,9 @@ <property name="position">0</property> </packing> </child> - <child> - <widget class="GtkButton" id="btnOK"> - <property name="label">gtk-ok</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="receives_default">False</property> - <property name="use_stock">True</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> </widget> <packing> <property name="expand">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> - <widget class="GtkAboutDialog" id="AboutWin"> - <property name="visible">True</property> - <property name="window_position">center</property> - <property name="type_hint">normal</property> - <property name="comments" translatable="yes">Based on PadJoy by Erich Kitzmüller (ammoq@ammoq.com)</property> - <property name="authors">Erich Kitzmüller (ammoq@ammoq.com) -Andrew Burton (adb@iinet.net.au)</property> - <property name="translator_credits" translatable="yes" comments="TRANSLATORS: Replace this string with your names, one name per line.">translator-credits</property> - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox1"> - <property name="orientation">vertical</property> - <child internal-child="action_area"> - <widget class="GtkHButtonBox" id="dialog-action_area1"/> - <packing> - <property name="expand">False</property> <property name="pack_type">end</property> <property name="position">0</property> </packing> diff --git a/plugins/dfinput/pad.c b/plugins/dfinput/pad.c index d67a3a7b..564aa324 100644 --- a/plugins/dfinput/pad.c +++ b/plugins/dfinput/pad.c @@ -1,1001 +1,472 @@ /* - * Pad for Psemu Pro like Emulators - * This is the plugin + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. * - * Modified for PCSX-df by Ryan Schultz + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. * - * Written by Erich Kitzmuller <ammoq@ammoq.com> - * Based on padXwin by linuzappz <linuzappz@hotmail.com> + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Copyright 2002,2003 by Erich Kitzmuller - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. */ -#include "config.h" +#include "pad.h" -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#ifdef __linux__ -#include <linux/joystick.h> -#endif -#include <sys/stat.h> -#include <sys/time.h> -#include <unistd.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <X11/XKBlib.h> -#include <pthread.h> -#include <errno.h> -#include "padjoy.h" -#ifdef ENABLE_NLS -#include <libintl.h> -#include <locale.h> -#define _(x) gettext(x) -#define N_(x) (x) -#else -#define _(x) (x) -#define N_(x) (x) -#endif - -#ifdef __linux__ -char *LibName = N_("Gamepad/Keyboard Input"); +char *PSEgetLibName(void) { +#ifdef EPSXE + return _("Gamepad/Keyboard Input (ePSXe)"); #else -char *LibName = N_("Keyboard Input"); + return _("Gamepad/Keyboard Input"); #endif - -// Prototypes -static void loadConfig(); -static void *thread_check_joydevice(void *arg); -static void initPadtime(); -static PadJoyEvent *EventCode2PadJoyEvent(EventCode p_e); - -// Filenames for device files, e.g. "/dev/input/js0" -static char devicefilename[MAXDEVICES][FILENAME_MAX+1] = {"/dev/input/js0", "/dev/input/js1"}; - -// File desciptors for device files -static int devicefile[MAXDEVICES] = { -1, -1 }; - -// Use Threading for joy device input? -static int use_threads = 1; -static pthread_t joy_thread; -static int die_thread_die = 0; - -// Emulate Dualshock(TM) analog pad? -static int use_analog = 0; - -// any joydevice open? -static int joydevice_open = 0; - -// initialisation already done? -static int init_done = 0; - -// calibration data -int minzero[MAXAXES]; -int maxzero[MAXAXES]; - -// axes status - so only changing status are reported -int axestatus[MAXDEVICES][MAXAXES]; - -// Assignment of PSX buttons to Events -static EventCode PadButtons[MAXDEVICES][MAXPSXBUTTONS] = -{ - { - KEY_EVENT(XK_e), // L2 - KEY_EVENT(XK_t), // R2 - KEY_EVENT(XK_w), // L1 - KEY_EVENT(XK_r), // R1 - KEY_EVENT(XK_d), // Triangle - KEY_EVENT(XK_x), // Circle - KEY_EVENT(XK_z), // Cross - KEY_EVENT(XK_s), // Square - KEY_EVENT(XK_c), // Select - NO_EVENT, // Left Analog - NO_EVENT, // Right Analog - KEY_EVENT(XK_v), // Start - KEY_EVENT(XK_Up), // Up - KEY_EVENT(XK_Right), // Right - KEY_EVENT(XK_Down), // Down - KEY_EVENT(XK_Left), // Left - NO_EVENT, // Left Analog X - NO_EVENT, // Left Analog Y - NO_EVENT, // Right Analog X - NO_EVENT // Right Analog Y - }, - { - NO_EVENT, // L2 - NO_EVENT, // R2 - NO_EVENT, // L1 - NO_EVENT, // R1 - NO_EVENT, // Triangle - NO_EVENT, // Circle - NO_EVENT, // Cross - NO_EVENT, // Square - NO_EVENT, // Select - NO_EVENT, // Left Analog - NO_EVENT, // Right Analog - NO_EVENT, // Start - NO_EVENT, // Up - NO_EVENT, // Right - NO_EVENT, // Down - NO_EVENT, // Left - NO_EVENT, // Left Analog X - NO_EVENT, // Left Analog Y - NO_EVENT, // Right Analog X - NO_EVENT // Right Analog Y - } -}; - -static Display *Dsp; -static Atom wmprotocols, wmdelwindow; - -static EventCode macroLaunch[MAXDEVICES][MAXMACROS]; -static EventCode macroEvents[MAXDEVICES][MAXMACROS][MAXMACROLENGTH]; -static long macroInterval[MAXDEVICES][MAXMACROS][MAXMACROLENGTH]; -static int macroActive[MAXDEVICES]; -static int macroIndex[MAXDEVICES]; -static long macroNext[MAXDEVICES]; - -unsigned short PadStat[MAXDEVICES] = {0xffff, 0xffff}; - -int AnalogValue[MAXDEVICES][MAXPSXBUTTONS-4] = {{127,127,127,127}, {127,127,127,127}}; - -char *PSEgetLibName(void) { - return _(LibName); } uint32_t PSEgetLibType(void) { - return 8; // PSE_LT_PAD + return PSE_LT_PAD; } uint32_t PSEgetLibVersion(void) { - return 1 << 16; -} - -void init_macros() { - int i,j; - - for (i=0; i<MAXDEVICES; i++) { - for (j=0; j<MAXMACROS; j++) { - macroLaunch[i][j] = NO_EVENT; - macroEvents[i][j][0] = NO_EVENT; - macroInterval[i][j][0] = 0; - } - macroActive[i] = -1; - macroIndex[i] = 0; - macroNext[i] = 0; - } + return (1 << 16) | (1 << 8); } long PADinit(long flags) { - int i,j; + LoadConfig(); - init_macros(); - initPadtime(); - for (i = 0; i < MAXDEVICES; i++) { - maxzero[i] = 250; - minzero[i] = -250; + g.PadState[0].PadMode = 0; + g.PadState[0].PadID = 0x41; + g.PadState[1].PadMode = 0; + g.PadState[1].PadID = 0x41; - for (j = 0; j < MAXAXES; j++) { - axestatus[i][j] = AXESTS_UNKNOWN; - } - } - loadConfig(); - - return 0; + return PSE_PAD_ERR_SUCCESS; } long PADshutdown(void) { - return 0; + PADclose(); + return PSE_PAD_ERR_SUCCESS; } -long PADopen(unsigned long *Disp) { - int i,j; - int res; - PadJoyEvent *pje; - - if (init_done) { -// fprintf(stderr, "DFInput warning: device already initialized.\n"); - return 0; - } - - Dsp = (Display *)*Disp; - XkbSetDetectableAutoRepeat(Dsp, 1, NULL); - - // TODO: find a way to grab the window, and set protocol WM_DELETE_WINDOW if not already set by the video plugin - wmprotocols = XInternAtom(Dsp,"WM_PROTOCOLS",0); - wmdelwindow = XInternAtom(Dsp,"WM_DELETE_WINDOW",0); - //XSetWMProtocols(Dsp, window, &wmdelwindow, 1); //need window! - - joydevice_open = 0; - -#ifdef __linux__ - for (i = 0; i < MAXDEVICES; i++) { - if (devicefilename[i][0]) { - devicefile[i] = open(devicefilename[i], O_RDONLY); - if (devicefile[i] == -1) { - fprintf(stderr, "DFInput error: could not open device %s!\n", devicefilename[i]); - } - else { - joydevice_open = 1; - } - } - else { - devicefile [i] = -1; - } - } -#endif +static pthread_t ThreadID; +static uint8_t TerminateThread = 0; - for (i = 0; i < MAXDEVICES; i++) { - for (j = 0; j < MAXAXES; j++) { - axestatus[i][j] = AXESTS_UNUSED; - } - } - - for (i=0; i<MAXDEVICES; i++) { - for (j = 0; j < MAXPSXBUTTONS; j++) { - pje = EventCode2PadJoyEvent(PadButtons[i][j]); - - if (pje->event_type == EVENTTYPE_AXISPLUS || pje->event_type == EVENTTYPE_AXISMINUS) { - axestatus[pje->pad][pje->no] = AXESTS_UNKNOWN; - } -#ifdef __linux__ - else if (pje->event_type == EVENTTYPE_ANALOG && use_analog) { - axestatus[pje->pad][pje->no] = AXESTS_ANALOG; - } -#endif - } - } - -#ifdef __linux__ - if (use_threads) { - die_thread_die = 0; - if (joydevice_open) { - fprintf(stderr, "DFInput: starting thread...\n"); - sleep(1); - res = pthread_create(&joy_thread, NULL, thread_check_joydevice, (void *) NULL); - - if (res!=0) { - fprintf(stderr, "DFInput warning: thread failure, switching to polling!\n"); - use_threads = 0; - } - } - } -#endif +static void *JoyThread(void *param) { + while (!TerminateThread) { + CheckJoy(); + usleep(1000); + } + pthread_exit(0); + return NULL; +} - init_done = 1; +long PADopen(unsigned long *Disp) { + g.Disp = (Display *)*Disp; + + if (!g.Opened) { + if (SDL_WasInit(SDL_INIT_EVERYTHING)) { + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { + return PSE_PAD_ERR_FAILURE; + } + } else if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == -1) { + return PSE_PAD_ERR_FAILURE; + } + + InitSDLJoy(); + InitKeyboard(); + + g.KeyLeftOver = 0; + + if (g.cfg.Threaded) { + TerminateThread = 0; + + if (pthread_create(&ThreadID, NULL, JoyThread, NULL) != 0) { + // thread creation failed, fallback to polling + g.cfg.Threaded = 0; + } + } + } + + g.Opened = 1; - return 0; + return PSE_PAD_ERR_SUCCESS; } long PADclose(void) { - int i; - -#ifdef __linux__ - for (i=0; i<2; i++) { - if (devicefile[i] > -1) { - close (devicefile[i]); - } - } - - if (use_threads) { - die_thread_die = 1; - if (joydevice_open) { - pthread_join(joy_thread, (void **) NULL); - } - } -#endif - - init_done = 0; + if (g.Opened) { + if (g.cfg.Threaded) { + TerminateThread = 1; + pthread_join(ThreadID, NULL); + } + + DestroySDLJoy(); + DestroyKeyboard(); + + if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_JOYSTICK)) { + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + } else { + SDL_Quit(); + } + } - XAutoRepeatOn(Dsp); + g.Opened = 0; - return 0; + return PSE_PAD_ERR_SUCCESS; } long PADquery(void) { - return 3; // both pads + return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2; } -static long firstsecond = 0; - -static void initPadtime() { - struct timeval tv; - gettimeofday(&tv, NULL); - firstsecond = tv.tv_sec; +static void UpdateInput(void) { + if (!g.cfg.Threaded) CheckJoy(); + CheckKeyboard(); } -// construct a time on our own -long getPadtime() { - struct timeval tv; - gettimeofday(&tv, NULL); - return (tv.tv_sec-firstsecond)*10000+tv.tv_usec/100; -} +#ifndef EPSXE -// get pending events -static int getPendingEvents(int millisecondstowait, EventCode *events, int maxevents, int checkJoydevice, int checkXKeyboard, long *timing) { - fd_set rfds; - int retval; - int i; - int md; - int eventsread=0; - XEvent xe; - XClientMessageEvent *xce; - int cntopen; - struct timeval tv; - int oldstatus; - -#ifdef __linux__ - struct js_event je; - - if (checkJoydevice) { - FD_ZERO(&rfds); - md = -1; - cntopen=0; - for (i=0; i<MAXDEVICES; i++) { - if (devicefile[i] > -1) { - FD_SET(devicefile[i], &rfds); - cntopen++; - } - if (devicefile[i] > md) md = devicefile[i]; - } - tv.tv_sec = millisecondstowait / 1000; - tv.tv_usec = 1000 * (millisecondstowait % 1000); - - retval = select(md + 1, &rfds, NULL, NULL, &tv); - - while (retval && eventsread < maxevents - 2 * checkXKeyboard) { - for (i = 0; i < MAXDEVICES; i++) { - if (devicefile[i] > -1 && FD_ISSET(devicefile[i], &rfds)) { - read (devicefile[i], &je, 8); - - if (je.type == JS_EVENT_AXIS && je.number < MAXAXES) { - if (axestatus[i][je.number] == AXESTS_ANALOG) { - /* this axe should be reported analog */ - events[eventsread++] = ANALOGAXIS_EVENT(i,je.number, (je.value + 32768) >> 8); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - - } - else if (je.value > maxzero[i]) { - if (axestatus[i][je.number] != AXESTS_PLUS && - axestatus[i][je.number] != AXESTS_UNUSED) { - - oldstatus = axestatus[i][je.number]; - - axestatus[i][je.number] = AXESTS_PLUS; - - events[eventsread++] = AXISPLUS_EVENT(i, je.number); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread==maxevents) return eventsread; - - if (oldstatus == AXESTS_MINUS) { - events[eventsread++] = RELEASE_EVENT + AXISMINUS_EVENT(i, je.number); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - } - - } - } - else if (je.value < minzero[i]) { - if (axestatus[i][je.number] != AXESTS_MINUS && - axestatus[i][je.number] != AXESTS_UNUSED) { - - oldstatus = axestatus[i][je.number]; - - axestatus[i][je.number] = AXESTS_MINUS; - - events[eventsread++] = AXISMINUS_EVENT(i, je.number); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - - if (oldstatus == AXESTS_PLUS) { - events[eventsread++] = RELEASE_EVENT+AXISPLUS_EVENT(i, je.number); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - } - } - } - else { - if (axestatus[i][je.number] != AXESTS_CENTER && - axestatus[i][je.number] != AXESTS_UNUSED) { - - oldstatus = axestatus[i][je.number]; - - axestatus[i][je.number] = AXESTS_CENTER; - - if (oldstatus == AXESTS_PLUS) { - events[eventsread++] = RELEASE_EVENT+AXISPLUS_EVENT(i,je.number); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - } - else if (oldstatus == AXESTS_MINUS) { - events[eventsread++] = RELEASE_EVENT+AXISMINUS_EVENT(i,je.number); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - } - } - } - } - else if (je.type == JS_EVENT_BUTTON && je.number<MAXBUTTONS) { - events[eventsread++] = (je.value ? 0 : RELEASE_EVENT) + BUTTON_EVENT(i, je.number); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - } - } - } - tv.tv_sec = 0; - tv.tv_usec = 0; - - retval = select(md + 1, &rfds, NULL, NULL, &tv); - } - - } -#endif +static uint8_t stdpar[2][20] = { + {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} +}; - if (checkXKeyboard) { - while ((i = XPending(Dsp))) { - while (i--) { - XNextEvent(Dsp, &xe); - switch (xe.type) { - case KeyPress: - events[eventsread++] = KEY_EVENT(XLookupKeysym((XKeyEvent *)&xe, 0)); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - break; - case KeyRelease: - events[eventsread++] = RELEASE_EVENT + KEY_EVENT(XLookupKeysym((XKeyEvent *)&xe, 0)); - if (timing) { - (*timing) = getPadtime(); - timing++; - } - if (eventsread == maxevents) return eventsread; - break; - case ClientMessage: - xce = (XClientMessageEvent *)&xe; - if (xce->message_type == wmprotocols && (Atom)xce->data.l[0] == wmdelwindow) { - events[eventsread++] = KEY_EVENT(XK_Escape); - if (eventsread == maxevents) return eventsread; - } - break; -/* - case FocusIn: - XAutoRepeatOff(Dsp); - break; - case FocusOut: - XAutoRepeatOn(Dsp); - break; -*/ - } - } - } - } - - return eventsread; -} +static uint8_t unk46[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, + {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A} +}; -// Key Event not used... -static EventCode keyLeftOver = NO_EVENT; - -static void CheckPads(int checkJoydevice, int checkXKeyboard, int blocking) { - EventCode events[MAXCNT]; - int cnt; - int release; - EventCode e; - int i,j,k,l; - int notfound; - long now; - int v; - - if (checkJoydevice || checkXKeyboard) { - cnt = getPendingEvents(blocking<<8, events, MAXCNT, checkJoydevice, checkXKeyboard, NULL); - } - else { - cnt = 0; - } - - // more events come from the macros - // only process makros when blocking is not set, since - // this cannot be done by the joy device thread - - if (!blocking) { - now= -1; - for (j = 0; j < MAXDEVICES; j++) { - if (macroActive[j] > -1) { - if (now < 0) { - now = getPadtime(); - } - - while (now >= macroNext[j] && cnt < MAXCNT && macroActive[j] > -1) { - events[cnt++]=macroEvents[j][macroActive[j]][macroIndex[j]]; - macroIndex[j]++; - if (macroIndex[j] == MAXMACROLENGTH || macroEvents[j][macroActive[j]][macroIndex[j]] == NO_EVENT) { - macroActive[j] = -1; - } - else { - macroNext[j] += macroInterval[j][macroActive[j]][macroIndex[j]]; - } - } - } - } - } - - for (i = 0; i < cnt; i++) { - e = events[i]; - if (e >= RELEASE_EVENT) { - release = 1; - e -= RELEASE_EVENT; - } - else { - release = 0; - } - - notfound = 1; - if (e >= FIRST_ANALOG_EVENT) { - v = e & 0xff; - e -= v; - for (j = 0; j < MAXDEVICES && notfound; j++) { - for (k = 16; k < MAXPSXBUTTONS && notfound; k++) { - if (PadButtons[j][k] == e) { - AnalogValue[j][k - 16] = v; - notfound = 0; - } - } - } - } - else - { - for (j=0; j<MAXDEVICES && notfound; j++) { - for (k=0; k<MAXPSXBUTTONS && notfound; k++) { - if (PadButtons[j][k] == e) { - notfound = 0; - if (release) { - PadStat[j]|=(1<<k); - } - else { - PadStat[j]&=~(1<<k); - } - } - } - for (k=0; k<MAXMACROS && notfound; k++) { - if (macroLaunch[j][k] == e) { - notfound=0; - if (release) { - // release all buttons pressed by the macro - for (l=macroIndex[j]; l<MAXMACROLENGTH && macroEvents[j][macroActive[j]][l] != NO_EVENT; l++) { - if (macroEvents[j][macroActive[j]][l] >= RELEASE_EVENT) { - if (cnt<MAXCNT) { - events[cnt++]=macroEvents[j][macroActive[j]][l]; - } - } - - } - - macroActive[j]= -1; // stop Makro from running - } - else { - macroActive[j]=k; - macroIndex[j]=0; - macroNext[j]=getPadtime(); - } - } - } - } - } - if (notfound && e < FIRST_JOY_EVENT) { - keyLeftOver = e + (release << 30); - } - } -} +static uint8_t unk47[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}, + {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00} +}; +static uint8_t unk4c[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; -long PADreadPort1(PadDataS *pad) { - if (!use_threads) { - CheckPads(joydevice_open, 1, 0); - } - else { - CheckPads(0, 1, 0); - } - - pad->buttonStatus = PadStat[0]; -#ifdef __linux__ - if (use_analog) { - pad->controllerType = 7; // analog Pad - pad->leftJoyX = AnalogValue[0][0]; - pad->leftJoyY = AnalogValue[0][1]; - pad->rightJoyX = AnalogValue[0][2]; - pad->rightJoyY = AnalogValue[0][3]; - } - else { -#endif - pad->controllerType = 4; // standard -#ifdef __linux__ - } -#endif - // ePSXe different from pcsx, swap bytes - pad->buttonStatus = (pad->buttonStatus>>8)|(pad->buttonStatus<<8); +static uint8_t unk4d[2][8] = { + {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} +}; - return 0; -} +static uint8_t stdcfg[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; -long PADreadPort2(PadDataS *pad) { - if (!use_threads) { - CheckPads(joydevice_open, 1, 0); - } - else { - CheckPads(0, 1, 0); - } - - pad->buttonStatus = PadStat[1]; -#ifdef __linux__ - if (use_analog) { - pad->controllerType = 7; // analog Pad - pad->leftJoyX = AnalogValue[1][0]; - pad->leftJoyY = AnalogValue[1][1]; - pad->rightJoyX = AnalogValue[1][2]; - pad->rightJoyY = AnalogValue[1][3]; - } - else { -#endif - pad->controllerType = 4; // standard -#ifdef __linux__ - } -#endif +static uint8_t stdmode[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; - // ePSXe different from pcsx, swap bytes - pad->buttonStatus = (pad->buttonStatus>>8)|(pad->buttonStatus<<8); +static uint8_t stdmodel[2][8] = { + {0xFF, + 0x5A, + 0x01, // 03 - dualshock2, 01 - dualshock + 0x02, // number of modes + 0x01, // current mode: 01 - analog, 00 - digital + 0x02, + 0x01, + 0x00}, + {0xFF, + 0x5A, + 0x01, // 03 - dualshock2, 01 - dualshock + 0x02, // number of modes + 0x01, // current mode: 01 - analog, 00 - digital + 0x02, + 0x01, + 0x00} +}; - return 0; -} +static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0; -long PADkeypressed(void) { - int ksym; +unsigned char PADstartPoll(int pad) { + CurPad = pad - 1; + CurByte = 0; - CheckPads(0, 1, 1); + return 0xFF; +} +
+unsigned char PADpoll(unsigned char value) { + static uint8_t *buf = NULL; + uint16_t n; + + if (CurByte == 0) { + CurByte++; + + // Don't enable Analog/Vibration for a standard pad + if (g.cfg.PadDef[CurPad].Type != PSE_PAD_TYPE_ANALOGPAD) { + CurCmd = CMD_READ_DATA_AND_VIBRATE; + } else { + CurCmd = value; + } + + switch (CurCmd) { + case CMD_CONFIG_MODE: + CmdLen = 8; + buf = stdcfg[CurPad]; + if (stdcfg[CurPad][3] == 0xFF) return 0xF3; + else return g.PadState[CurPad].PadID; + + case CMD_SET_MODE_AND_LOCK: + CmdLen = 8; + buf = stdmode[CurPad]; + return 0xF3; + + case CMD_QUERY_MODEL_AND_MODE: + CmdLen = 8; + buf = stdmodel[CurPad]; + buf[4] = g.PadState[CurPad].PadMode; + return 0xF3; + + case CMD_QUERY_ACT: + CmdLen = 8; + buf = unk46[CurPad]; + return 0xF3; + + case CMD_QUERY_COMB: + CmdLen = 8; + buf = unk47[CurPad]; + return 0xF3; + + case CMD_QUERY_MODE: + CmdLen = 8; + buf = unk4c[CurPad]; + return 0xF3; + + case CMD_VIBRATION_TOGGLE: + CmdLen = 8; + buf = unk4d[CurPad]; + return 0xF3; + + case CMD_READ_DATA_AND_VIBRATE: + default: + UpdateInput(); + + n = g.PadState[CurPad].KeyStatus; + n &= g.PadState[CurPad].JoyKeyStatus; + + stdpar[CurPad][2] = n & 0xFF; + stdpar[CurPad][3] = n >> 8; + + if (g.PadState[CurPad].PadMode == 1) { + CmdLen = 20; + + stdpar[CurPad][4] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][ANALOG_X]; + stdpar[CurPad][5] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][ANALOG_Y]; + stdpar[CurPad][6] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][ANALOG_X]; + stdpar[CurPad][7] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][ANALOG_Y]; + + switch (stdpar[CurPad][3]) { + case 0xBF: // X + stdpar[CurPad][14] = 0xFF; + break; + + case 0xDF: // Circle + stdpar[CurPad][13] = 0xFF; + break; + + case 0xEF: // Triangle + stdpar[CurPad][12] = 0xFF; + break; + + case 0x7F: // Square + stdpar[CurPad][15] = 0xFF; + break; + + case 0xFB: // L1 + stdpar[CurPad][16] = 0xFF; + break; + + case 0xF7: // R1 + stdpar[CurPad][17] = 0xFF; + break; + + case 0xFE: // L2 + stdpar[CurPad][18] = 0xFF; + break; + + case 0xFD: // R2 + stdpar[CurPad][19] = 0xFF; + break; + + default: + stdpar[CurPad][14] = 0x00; // Not pressed + stdpar[CurPad][13] = 0x00; // Not pressed + stdpar[CurPad][12] = 0x00; // Not pressed + stdpar[CurPad][15] = 0x00; // Not pressed + stdpar[CurPad][16] = 0x00; // Not pressed + stdpar[CurPad][17] = 0x00; // Not pressed + stdpar[CurPad][18] = 0x00; // Not pressed + stdpar[CurPad][19] = 0x00; // Not pressed + break; + } + + switch (stdpar[CurPad][2] >> 4) { + case 0x0E: // UP + stdpar[CurPad][10] = 0xFF; + break; + + case 0x0B: // DOWN + stdpar[CurPad][11] = 0xFF; + break; + + case 0x07: // LEFT + stdpar[CurPad][9] = 0xFF; + break; + + case 0x0D: // RIGHT + stdpar[CurPad][8] = 0xFF; + break; + + default: + stdpar[CurPad][8] = 0x00; // Not pressed + stdpar[CurPad][9] = 0x00; // Not pressed + stdpar[CurPad][10] = 0x00; // Not pressed + stdpar[CurPad][11] = 0x00; // Not pressed + break; + } + } else { + CmdLen = 4; + } - if (keyLeftOver == NO_EVENT) return 0; + buf = stdpar[CurPad]; + return g.PadState[CurPad].PadID; + } + } - ksym = keyLeftOver-FIRST_KEY_EVENT; - keyLeftOver = NO_EVENT; + switch (CurCmd) { + case CMD_CONFIG_MODE: + if (CurByte == 2) { + switch (value) { + case 0: + buf[2] = 0; + buf[3] = 0; + break; + + case 1: + buf[2] = 0xFF; + buf[3] = 0xFF; + break; + } + } + break; + + case CMD_SET_MODE_AND_LOCK: + if (CurByte == 2) { + g.PadState[CurPad].PadMode = value; + g.PadState[CurPad].PadID = value ? 0x73 : 0x41; + } + break; + + case CMD_QUERY_ACT: + if (CurByte == 2) { + switch (value) { + case 0: // default + buf[5] = 0x02; + buf[6] = 0x00; + buf[7] = 0x0A; + break; + + case 1: // Param std conf change + buf[5] = 0x01; + buf[6] = 0x01; + buf[7] = 0x14; + break; + } + } + break; + + case CMD_QUERY_MODE: + if (CurByte == 2) { + switch (value) { + case 0: // mode 0 - digital mode + buf[5] = PSE_PAD_TYPE_STANDARD; + break; + + case 1: // mode 1 - analog mode + buf[5] = PSE_PAD_TYPE_ANALOGPAD; + break; + } + } + break; + } - return ksym; + if (CurByte >= CmdLen) return 0; + return buf[CurByte++]; } -#ifdef __linux__ +#endif -static void *thread_check_joydevice(void *arg) { - while (!die_thread_die) { - CheckPads(1, 0, 1); - } - return NULL; -} +static long PADreadPort(int num, PadDataS *pad) { + UpdateInput(); -#endif + pad->buttonStatus = (g.PadState[num].KeyStatus & g.PadState[num].JoyKeyStatus); -// analyse Eventcode -static PadJoyEvent *EventCode2PadJoyEvent(EventCode p_e) { - static PadJoyEvent event; - EventCode e; - int i,p; - - event.event_type = EVENTTYPE_NONE; - event.pad = 0; - event.no = 0; - event.value = 0; - - if (!p_e) { - return &event; - } - - e = p_e; - - if (e > RELEASE_EVENT) { - event.value = 0; - e -= RELEASE_EVENT; - } - else { - event.value = 1; - } - - if (e && e<FIRST_JOY_EVENT) { - event.event_type = EVENTTYPE_KEY; - event.no = e; - return &event; - } - - if (e >= FIRST_ANALOG_EVENT) { - event.event_type = EVENTTYPE_ANALOG; - event.pad = (e-FIRST_ANALOG_EVENT)/(256*MAXAXES); - event.no = (e-ANALOGAXIS_EVENT(event.pad,0,0))/256; - event.value = e & 0xff; - return &event; - } - - - for (p=0; p<MAXDEVICES; p++) { - for (i=0; i<MAXAXES; i++) { - if (e == AXISPLUS_EVENT(p,i)) { - event.event_type = EVENTTYPE_AXISPLUS; - event.pad = p; - event.no = i; - return &event; - } - if (e == AXISMINUS_EVENT(p,i)) { - event.event_type = EVENTTYPE_AXISMINUS; - event.pad = p; - event.no = i; - return &event; - } - } - - for (i=0; i<MAXBUTTONS; i++) { - if (e == BUTTON_EVENT(p,i)) { - event.event_type = EVENTTYPE_BUTTON; - event.pad = p; - event.no = i; - return &event; - } - } - } - - return &event; -} +#ifdef EPSXE + // ePSXe different from pcsx, swap bytes + pad->buttonStatus = (pad->buttonStatus >> 8) | (pad->buttonStatus << 8); +#endif + switch (g.cfg.PadDef[num].Type) { + case PSE_PAD_TYPE_ANALOGPAD: // Analog Controller SCPH-1150 + pad->controllerType = PSE_PAD_TYPE_ANALOGPAD; + pad->rightJoyX = g.PadState[num].AnalogStatus[ANALOG_RIGHT][ANALOG_X]; + pad->rightJoyY = g.PadState[num].AnalogStatus[ANALOG_RIGHT][ANALOG_Y]; + pad->leftJoyX = g.PadState[num].AnalogStatus[ANALOG_LEFT][ANALOG_X]; + pad->leftJoyY = g.PadState[num].AnalogStatus[ANALOG_LEFT][ANALOG_Y]; + break; + + case PSE_PAD_TYPE_STANDARD: // Standard Pad SCPH-1080, SCPH-1150 + default: + pad->controllerType = PSE_PAD_TYPE_STANDARD; + break; + } -// reversal of EventCode2String -static EventCode String2EventCode(char *s) { - static char buffer[256]; - int i,p; - char *q; - char push_release; - EventCode e; - - if (s[0] >= '0' && s[0] <= '9') return atoi(s); // allow numeric input - - e=0; - push_release = 'P'; - - switch(s[0]) { - case 'K': - push_release = s[1]; - strncpy(buffer, s + 3, 255); - q=buffer; - i=1; - while (*q) { - if (*q=='"') i = !i; - if (*q==' ' && !i) - *q='\0'; - else - q++; - } - if (s[2]=='"' && buffer[0] && buffer[strlen(buffer)-1]=='"') { - buffer[strlen(buffer)-1] = '\0'; - e = KEY_EVENT(XStringToKeysym(buffer)); - } - break; - case 'A': - if (s[1] >= '0' && s[1] <= '1' && strlen(s) >= 5) { - p = s[1] - '0'; - push_release = s[2]; - i = atoi(s+3); - q=s+3; - while (*q && *q != '+' && *q != '-') q++; - if (*q == '+') - e = AXISPLUS_EVENT(p,i); - else if (*q == '-') - e = AXISMINUS_EVENT(p,i); - } - break; - case 'B': - if (s[1] >= '0' && s[1] <= '1' && strlen(s) >= 4) { - p = s[1] - '0'; - push_release = s[2]; - i = atoi(s + 3); - e = BUTTON_EVENT(p, i); - } - break; - case 'X': - if (s[1] >= '0' && s[1] <= '1' && strlen(s) >= 5) { - p = s[1] - '0'; - i = atoi(s + 3); - q = s + 3; - while (*q && *q != 'v') q++; - if (*q == 'v') - e = ANALOGAXIS_EVENT(p,i,atoi(q + 1)); - } - break; - } - - if (push_release == 'R') - return e + RELEASE_EVENT; - else - return e; + return PSE_PAD_ERR_SUCCESS; } -static void loadConfig() { - FILE *f; - int i; - char line[FILENAME_MAX+30]; - int pad=0; - int macronr=0; - char *val; - - f = fopen("dfinput.cfg", "r"); - if (f == NULL) { -// fprintf(stderr, "DFInput warning: config file not found.\n"); - return; - } - - while(!feof(f)) { - fgets(line, FILENAME_MAX+29, f); - i=strlen(line)-1; - while (i>0 && line[i]<32) line[i--]='\0'; - - val=NULL; - while(i>0) { - if (line[i]=='=') val = line+(i+1); - i--; - } - if (val) { - while (*val==' ') val++; - } - - if (!strcmp(line, "[general]")) { - // nothing to do - } - else if (!strncmp(line, "use_threads", 11)) { - use_threads = atoi(val); - } - else if (!strncmp(line, "use_analog", 10)) { - use_analog = atoi(val); - } - - else if (!strcmp(line, "[pad 1]")) { - pad = 0; - } - else if (!strcmp(line, "[pad 2]")) { - pad = 1; - } - else if (!strncmp(line, "[macro ", 7)) { - macronr = atoi(line+7)-1; - if (macronr<0 || macronr>=MAXMACROS) macronr=0; - } - else if (!strncmp(line, "devicefilename", 14)) { - strcpy(devicefilename[pad], val); - } - else if (!strncmp(line, "minzero", 7)) { - minzero[pad] = atoi(val); - } - else if (!strncmp(line, "maxzero", 7)) { - maxzero[pad] = atoi(val); - } - else if (!strncmp(line, "event_l2", 8)) PadButtons[pad][0] = String2EventCode(val); - else if (!strncmp(line, "event_r2", 8)) PadButtons[pad][1] = String2EventCode(val); - else if (!strncmp(line, "event_l1", 8)) PadButtons[pad][2] = String2EventCode(val); - else if (!strncmp(line, "event_r1", 8)) PadButtons[pad][3] = String2EventCode(val); - else if (!strncmp(line, "event_triangle", 14)) PadButtons[pad][4] = String2EventCode(val); - else if (!strncmp(line, "event_circle", 12)) PadButtons[pad][5] = String2EventCode(val); - else if (!strncmp(line, "event_cross", 11)) PadButtons[pad][6] = String2EventCode(val); - else if (!strncmp(line, "event_square", 12)) PadButtons[pad][7] = String2EventCode(val); - else if (!strncmp(line, "event_select", 12)) PadButtons[pad][8] = String2EventCode(val); - else if (!strncmp(line, "event_lanalog", 13)) PadButtons[pad][9] = String2EventCode(val); - else if (!strncmp(line, "event_ranalog", 13)) PadButtons[pad][10] = String2EventCode(val); - else if (!strncmp(line, "event_start", 11)) PadButtons[pad][11] = String2EventCode(val); - else if (!strncmp(line, "event_up", 8)) PadButtons[pad][12] = String2EventCode(val); - else if (!strncmp(line, "event_right", 11)) PadButtons[pad][13] = String2EventCode(val); - else if (!strncmp(line, "event_down", 10)) PadButtons[pad][14] = String2EventCode(val); - else if (!strncmp(line, "event_left", 10)) PadButtons[pad][15] = String2EventCode(val); - else if (!strncmp(line, "event_lanax", 11)) PadButtons[pad][16] = String2EventCode(val); - else if (!strncmp(line, "event_lanay", 11)) PadButtons[pad][17] = String2EventCode(val); - else if (!strncmp(line, "event_ranax", 11)) PadButtons[pad][18] = String2EventCode(val); - else if (!strncmp(line, "event_ranay", 11)) PadButtons[pad][19] = String2EventCode(val); - else if (!strncmp(line, "event_launch", 12)) macroLaunch[pad][macronr] = String2EventCode(val); - else if (!strncmp(line, "events", 6)) { - i=0; - while (*val) { - macroEvents[pad][macronr][i++]=String2EventCode(val); - while (*val && *val!=' ') val++; - if (*val==' ') val++; - } - macroEvents[pad][macronr][i]=NO_EVENT; - } - else if (!strncmp(line, "interval", 8)) { - i=0; - while (*val) { - macroInterval[pad][macronr][i++]=atol(val); - while (*val && *val!=' ') val++; - if (*val==' ') val++; - } - } -// else fprintf(stderr, "DFInput error: can't interpret %s\n", line); - } +long PADreadPort1(PadDataS *pad) { + return PADreadPort(0, pad); } -long PADconfigure(void) { - if (fork() == 0) { - execl("cfg/cfgDFInput", "cfgDFInput", NULL); - exit(0); - } - return 0; +long PADreadPort2(PadDataS *pad) { + return PADreadPort(1, pad); } +long PADkeypressed(void) { + long s; + + CheckKeyboard(); -/*---------------------------------------------------------------------*/ -/* About dialogue stuff */ -/*---------------------------------------------------------------------*/ + s = g.KeyLeftOver; + g.KeyLeftOver = 0; + return s; +} -void PADabout(void) { - if (fork() == 0) { - execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL); - } +long PADconfigure(void) { + if (fork() == 0) { + execl("cfg/cfgDFInput", "cfgDFInput", NULL); + exit(0); + } + return PSE_PAD_ERR_SUCCESS; } -#ifdef __linux__ +void PADabout(void) { + if (fork() == 0) { + execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL); + exit(0); + } +} long PADtest(void) { - int i; - int f; - - int r=1; - - loadConfig(); - for (i=0; i<2; i++) { - if (devicefilename[i][0]) { - r = 0; - f = open(devicefilename[i], O_RDONLY); - if (f == -1) { - return -1; - } - close (f); - } - } - - return r; + return PSE_PAD_ERR_SUCCESS; } - -#endif diff --git a/plugins/dfinput/pad.h b/plugins/dfinput/pad.h new file mode 100644 index 00000000..da4fc727 --- /dev/null +++ b/plugins/dfinput/pad.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#ifndef PAD_H_ +#define PAD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//#define EPSXE 1 + +#include "config.h" + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <pthread.h> + +#include <SDL.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/XKBlib.h> + +#include "psemu_plugin_defs.h" + +#ifdef ENABLE_NLS +#include <libintl.h> +#include <locale.h> +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +enum { + DKEY_SELECT = 0, + DKEY_L3, + DKEY_R3, + DKEY_START, + DKEY_UP, + DKEY_RIGHT, + DKEY_DOWN, + DKEY_LEFT, + DKEY_L2, + DKEY_R2, + DKEY_L1, + DKEY_R1, + DKEY_TRIANGLE, + DKEY_CIRCLE, + DKEY_CROSS, + DKEY_SQUARE, + + DKEY_TOTAL +}; + +enum { + ANALOG_LEFT = 0, + ANALOG_RIGHT, + + ANALOG_TOTAL +}; + +enum { NONE = 0, AXIS, HAT, BUTTON }; + +typedef struct tagKeyDef { + uint8_t JoyEvType; + union { + int16_t d; + int16_t Axis; // positive=axis+, negative=axis-, abs(Axis)-1=axis index + uint16_t Hat; // 8-bit for hat number, 8-bit for direction + uint16_t Button; // button number + } J; + uint16_t Key; +} KEYDEF; + +enum { ANALOG_X = 0, ANALOG_Y }; + +typedef struct tagPadDef { + int8_t DevNum; + uint16_t Type; + KEYDEF KeyDef[DKEY_TOTAL]; + int16_t AnalogDef[ANALOG_TOTAL][2]; // positive=axis+, negative=axis-, abs(Axis)-1=axis index +} PADDEF; + +typedef struct tagConfig { + uint8_t Threaded; + PADDEF PadDef[2]; +} CONFIG; + +typedef struct tagPadState { + SDL_Joystick *JoyDev; + uint8_t PadMode; + uint8_t PadID; + uint16_t KeyStatus; + uint16_t JoyKeyStatus; + uint8_t AnalogStatus[ANALOG_TOTAL][2]; // 0-255 where 128 is center position +} PADSTATE; + +typedef struct tagGlobalData { + CONFIG cfg; + + uint8_t Opened; + Display *Disp; + + PADSTATE PadState[2]; + long KeyLeftOver; +} GLOBALDATA; + +extern GLOBALDATA g; + +enum { + CMD_READ_DATA_AND_VIBRATE = 0x42, + CMD_CONFIG_MODE = 0x43, + CMD_SET_MODE_AND_LOCK = 0x44, + CMD_QUERY_MODEL_AND_MODE = 0x45, + CMD_QUERY_ACT = 0x46, // ?? + CMD_QUERY_COMB = 0x47, // ?? + CMD_QUERY_MODE = 0x4C, // QUERY_MODE ?? + CMD_VIBRATION_TOGGLE = 0x4D, +}; + +// cfg.c functions... +void LoadConfig(); +void SaveConfig(); + +// sdljoy.c functions... +void InitSDLJoy(); +void DestroySDLJoy(); +void CheckJoy(); + +// xkb.c functions... +void InitKeyboard(); +void DestroyKeyboard(); +void CheckKeyboard(); + +// analog.c functions... +void InitAnalog(); +void CheckAnalog(); + +// pad.c functions... +char *PSEgetLibName(void); +uint32_t PSEgetLibType(void); +uint32_t PSEgetLibVersion(void); +long PADinit(long flags); +long PADshutdown(void); +long PADopen(unsigned long *Disp); +long PADclose(void); +long PADquery(void); +unsigned char PADstartPoll(int pad); +unsigned char PADpoll(unsigned char value); +long PADreadPort1(PadDataS *pad); +long PADreadPort2(PadDataS *pad); +long PADkeypressed(void); +long PADconfigure(void); +void PADabout(void); +long PADtest(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/dfinput/padjoy.h b/plugins/dfinput/padjoy.h deleted file mode 100644 index e51f2db4..00000000 --- a/plugins/dfinput/padjoy.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _PADJOY_H_ - -#define _PADJOY_H_ - -#define DEBUG(x) fprintf(stderr, "DFInput: %s\n", x); - -// Maximum number of joy devices -#define MAXDEVICES 2 -// Maximum number of supported axis (per device, a normal joystick has 2) -#define MAXAXES 20 -// Maximum number of supported buttons (per device) -#define MAXBUTTONS 32 -// Number of PSX-Buttons (including analog axis) -#define MAXPSXBUTTONS 20 - -// Status of digital Axes (avoids repeated events of the same type on an analog pad) -#define AXESTS_UNUSED -1 -#define AXESTS_UNKNOWN 0 -#define AXESTS_CENTER 1 -#define AXESTS_PLUS 2 -#define AXESTS_MINUS 3 -#define AXESTS_ANALOG 4 - -// every kind of supported event is coded into a long int -typedef int32_t EventCode; - -// Position of directional buttons in PadButtons -#define PSXBTN_UP 12 -#define PSXBTN_RIGHT 13 -#define PSXBTN_DOWN 14 -#define PSXBTN_LEFT 15 - -// macros to define Eventcodes -// this may look like I make it too complicated, but it keeps things open for future improvements -#define NO_EVENT 0 -#define FIRST_KEY_EVENT 0 -#define FIRST_JOY_EVENT (1<<16) -#define RELEASE_EVENT (1<<30) -#define FIRST_ANALOG_EVENT (1<<20) - -#define KEY_EVENT(n) (FIRST_KEY_EVENT+(n)) -#define AXISPLUS_EVENT(p,n) (FIRST_JOY_EVENT+2*(n)+(p)*(2*MAXAXES+MAXBUTTONS)) -#define AXISMINUS_EVENT(p,n) (FIRST_JOY_EVENT+2*(n)+1+(p)*(2*MAXAXES+MAXBUTTONS)) -#define BUTTON_EVENT(p,n) (FIRST_JOY_EVENT+2*MAXAXES+(n)+(p)*(2*MAXAXES+MAXBUTTONS)) -#define ANALOGAXIS_EVENT(p,n,v) (FIRST_ANALOG_EVENT+256*(n)+(v)+(p)*(256*MAXAXES)) - -// Makro Definitions etc. -#define MAXMACROS 3 -#define MAXMACROLENGTH 100 - -typedef struct -{ - unsigned char controllerType; - unsigned short buttonStatus; - unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY; - unsigned char moveX, moveY; - unsigned char reserved[91]; -} PadDataS; - -// Number of events to fetch at once... -#define MAXCNT 100 - -/* number of buttons required for configuration */ -#define CONFIGBUTTONCOUNT 20 - -#define EVENTTYPE_NONE -1 -#define EVENTTYPE_KEY 0 -#define EVENTTYPE_BUTTON 1 -#define EVENTTYPE_AXISPLUS 2 -#define EVENTTYPE_AXISMINUS 3 -#define EVENTTYPE_ANALOG 4 - -// The following struct is used in the config part only -typedef struct -{ - unsigned int event_type; // Button, Axe, AnalogAxe - unsigned int pad; - unsigned int no; // Keycode in case of key event - int value; // 0=release, 1=press, or analog value in case of EVENTTYPE_ANALOG -} PadJoyEvent; - -#endif diff --git a/plugins/dfinput/sdljoy.c b/plugins/dfinput/sdljoy.c new file mode 100644 index 00000000..2a80cfa8 --- /dev/null +++ b/plugins/dfinput/sdljoy.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#include "pad.h" + +void InitSDLJoy() { + uint8_t i; + + g.PadState[0].JoyKeyStatus = 0xFFFF; + g.PadState[1].JoyKeyStatus = 0xFFFF; + + for (i = 0; i < 2; i++) { + if (g.cfg.PadDef[i].DevNum >= 0) { + g.PadState[i].JoyDev = SDL_JoystickOpen(g.cfg.PadDef[i].DevNum); + } else { + g.PadState[i].JoyDev = NULL; + } + } + + SDL_JoystickEventState(SDL_IGNORE); + + InitAnalog(); +} + +void DestroySDLJoy() { + uint8_t i; + + if (SDL_WasInit(SDL_INIT_JOYSTICK)) { + for (i = 0; i < 2; i++) { + if (g.PadState[i].JoyDev != NULL) { + SDL_JoystickClose(g.PadState[i].JoyDev); + } + } + } + + for (i = 0; i < 2; i++) { + g.PadState[i].JoyDev = NULL; + } +} + +void CheckJoy() { + uint8_t i, j, n; + int dx, dy; + + SDL_JoystickUpdate(); + + for (i = 0; i < 2; i++) { + if (g.PadState[i].JoyDev == NULL) { + continue; + } + + for (j = 0; j < DKEY_TOTAL; j++) { + switch (g.cfg.PadDef[i].KeyDef[j].JoyEvType) { + case AXIS: + n = abs(g.cfg.PadDef[i].KeyDef[j].J.Axis) - 1; + + if (g.cfg.PadDef[i].KeyDef[j].J.Axis > 0) { + if (SDL_JoystickGetAxis(g.PadState[i].JoyDev, n) > 16383) { + g.PadState[i].JoyKeyStatus &= ~(1 << j); + } else { + g.PadState[i].JoyKeyStatus |= (1 << j); + } + } else if (g.cfg.PadDef[i].KeyDef[j].J.Axis < 0) { + if (SDL_JoystickGetAxis(g.PadState[i].JoyDev, n) < -16383) { + g.PadState[i].JoyKeyStatus &= ~(1 << j); + } else { + g.PadState[i].JoyKeyStatus |= (1 << j); + } + } + break; + + case HAT: + n = (g.cfg.PadDef[i].KeyDef[j].J.Hat >> 8); + + if (SDL_JoystickGetHat(g.PadState[i].JoyDev, n) & (g.cfg.PadDef[i].KeyDef[j].J.Hat & 0xFF)) { + g.PadState[i].JoyKeyStatus &= ~(1 << j); + } else { + g.PadState[i].JoyKeyStatus |= (1 << j); + } + break; + + case BUTTON: + if (SDL_JoystickGetButton(g.PadState[i].JoyDev, g.cfg.PadDef[i].KeyDef[j].J.Button)) { + g.PadState[i].JoyKeyStatus &= ~(1 << j); + } else { + g.PadState[i].JoyKeyStatus |= (1 << j); + } + break; + + default: + break; + } + } + } + + CheckAnalog(); +} diff --git a/plugins/dfinput/xkb.c b/plugins/dfinput/xkb.c new file mode 100644 index 00000000..5706d230 --- /dev/null +++ b/plugins/dfinput/xkb.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#include "pad.h" + +static Atom wmprotocols, wmdelwindow; + +void InitKeyboard() { + wmprotocols = XInternAtom(g.Disp, "WM_PROTOCOLS", 0); + wmdelwindow = XInternAtom(g.Disp, "WM_DELETE_WINDOW", 0); + + XAutoRepeatOff(g.Disp); + + g.PadState[0].KeyStatus = 0xFFFF; + g.PadState[1].KeyStatus = 0xFFFF; +} + +void DestroyKeyboard() { + XAutoRepeatOn(g.Disp); +} + +void CheckKeyboard() { + uint8_t i, j, found; + XEvent evt; + XClientMessageEvent *xce; + uint16_t Key; + + while (XPending(g.Disp)) { + XNextEvent(g.Disp, &evt); + switch (evt.type) { + case KeyPress: + Key = XLookupKeysym((XKeyEvent *)&evt, 0); + found = 0; + for (i = 0; i < 2; i++) { + for (j = 0; j < DKEY_TOTAL; j++) { + if (g.cfg.PadDef[i].KeyDef[j].Key == Key) { + found = 1; + g.PadState[i].KeyStatus &= ~(1 << j); + } + } + } + if (!found) { + g.KeyLeftOver = Key; + } + return; + + case KeyRelease: + Key = XLookupKeysym((XKeyEvent *)&evt, 0); + found = 0; + for (i = 0; i < 2; i++) { + for (j = 0; j < DKEY_TOTAL; j++) { + if (g.cfg.PadDef[i].KeyDef[j].Key == Key) { + found = 1; + g.PadState[i].KeyStatus |= (1 << j); + } + } + } + if (!found) { + g.KeyLeftOver = ((long)Key | 0x40000000); + } + break; + + case ClientMessage: + xce = (XClientMessageEvent *)&evt; + if (xce->message_type == wmprotocols && (Atom)xce->data.l[0] == wmdelwindow) { + // Fake an ESC key if user clicked the close button on window + g.KeyLeftOver = XK_Escape; + return; + } + break; + + case FocusOut: + XAutoRepeatOn(g.Disp); + break; + + case FocusIn: + XAutoRepeatOff(g.Disp); + break; + } + } +} + |
