[mednaffe] 54/99: Controller (joysticks and gamepads) setup on Windows Support for XInput devices is experimental
Stephen Kitt
skitt at moszumanska.debian.org
Tue Aug 2 21:00:06 UTC 2016
This is an automated email from the git hooks/post-receive script.
skitt pushed a commit to branch master
in repository mednaffe.
commit 472b1789a1f6e4a4f01b92b2547e82ac47633766
Author: AmatCoder <amatcoder at gmail.com>
Date: Fri May 1 17:15:36 2015 +0200
Controller (joysticks and gamepads) setup on Windows
Support for XInput devices is experimental
---
src/common.h | 13 +++
src/input.c | 315 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/joystick_win.c | 78 +++++++++++++
src/joystick_win.h | 29 +++++
src/mednaffe.c | 2 +
5 files changed, 436 insertions(+), 1 deletion(-)
diff --git a/src/common.h b/src/common.h
index 7b40da4..cde1812 100644
--- a/src/common.h
+++ b/src/common.h
@@ -22,13 +22,25 @@
#include <gtk/gtk.h>
+#ifdef G_OS_WIN32
+ #include <windows.h>
+ #include "SDL2/SDL.h"
+#endif
+
typedef struct
{
+#ifdef G_OS_UNIX
gint js_fd;
gint ev_fd;
long long unsigned int id;
gchar name[128];
GIOChannel *channel;
+#else
+ SDL_Joystick *sdljoy;
+ SDL_JoystickID sdl_id;
+ long long unsigned int id;
+ gchar *name;
+#endif
}joydata;
typedef struct
@@ -52,6 +64,7 @@ typedef struct
GtkBuilder *settings;
GtkTreeViewColumn *column;
GtkListStore *store;
+ GtkCellEditable *editable;
gint listmode;
gint filter;
gint pagesys;
diff --git a/src/input.c b/src/input.c
index f7e76d3..0b0c481 100644
--- a/src/input.c
+++ b/src/input.c
@@ -28,6 +28,15 @@
#include "joystick_linux.h"
#include <linux/joystick.h>
#include <fcntl.h>
+#else
+ #include <windows.h>
+ #include "joystick_win.h"
+
+ static int bool;
+ static guint which;
+ static gchar *on;
+ static gchar *joyc;
+ static GMutex mutex;
#endif
void close_channels(guidata *gui)
@@ -43,6 +52,16 @@ void close_channels(guidata *gui)
}
#endif
+#ifdef G_OS_WIN32
+int i;
+for(i=0;i<9;i++)
+{
+ if(SDL_JoystickGetAttached(gui->joy[i].sdljoy))
+ SDL_JoystickClose(gui->joy[i].sdljoy);
+}
+ SDL_Quit();
+#endif
+
gtk_window_set_resizable(GTK_WINDOW(gui->inputwindow), TRUE);
}
@@ -285,6 +304,45 @@ void read_input(guidata *gui)
g_free(hash);
}
#endif
+
+ #ifdef G_OS_WIN32
+ else if (hashkey[0]=='j')
+ {
+ gchar *value = hash2joy(hashkey, 2);
+ gchar *hash = hash2joy(hashkey, 1);
+ long long unsigned int ll = g_ascii_strtoull(value, NULL, 16);
+
+ g_free(value);
+
+ int a;
+ for (a=0;a<9;a++)
+ {
+ if (gui->joy[a].id == g_ascii_strtoull(hash, NULL, 16))
+ {
+ if (ll>0x7FFF)
+ {
+ if (ll % 2)
+ {
+ if (ll<0xc000) value = g_strdup_printf("Axis %01I64x Down", ll & 0xFFF);
+ else value = g_strdup_printf("Axis %01I64x Up", ll & 0xFFF);
+ }
+ else
+ {
+ if (ll<0xc000) value = g_strdup_printf("Axis %01I64x Right", ll & 0xFFF);
+ else value = g_strdup_printf("Axis %01I64x Left", ll & 0xFFF);
+ }
+ }
+ else value = g_strdup_printf("Button %02I64i", ll & 0xFF);
+ if ((value) && (gui->joy[a].name))
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter, 2, value, 3, gui->joy[a].name, -1);
+ g_free(value);
+ }
+ // else gtk_list_store_set(GTK_LIST_STORE(model), &iter, 2, "", 3 , hash, -1);
+ }
+ g_free(hash);
+ }
+ #endif
+
else gtk_list_store_set(GTK_LIST_STORE(model), &iter, 2, "", 3 , "", -1);
}
} while (gtk_tree_model_iter_next(model, &iter));
@@ -328,6 +386,121 @@ void set_builtin(GtkNotebook *notebook, guidata *gui)
gtk_notebook_set_show_tabs(notebook, FALSE);
}
+ #ifdef G_OS_WIN32
+ int GetControllerIndex(SDL_JoystickID instance, guidata *gui)
+ {
+ int i;
+ for(i=0;i<9;i++){
+ if (gui->joy[i].sdl_id == instance)
+ return i;
+ }
+ return -1;
+ }
+
+DWORD WINAPI joy_thread(LPVOID lpParam)
+{
+ guidata *gui = lpParam;
+ SDL_Event event;
+
+ SDL_JoystickEventState(SDL_ENABLE);
+
+ while (SDL_PollEvent(&event)){} //Drops pending events
+
+ while(SDL_WaitEvent(&event)) {
+
+ if (bool==1) break;
+
+ //printf("Unhandled Event: %i\n", event.type);
+
+ if ((event.type == SDL_JOYBUTTONDOWN) ||
+ (event.type == SDL_JOYAXISMOTION) ||
+ (event.type == SDL_JOYHATMOTION))
+ {
+
+ unsigned int b;
+ int a;
+
+ g_mutex_lock (&mutex);
+ bool=1;
+ g_mutex_unlock (&mutex);
+
+ if (event.type == SDL_JOYBUTTONDOWN) {
+
+ b = event.jbutton.button;
+ on = g_strdup_printf("Button %02i", b);
+ a = GetControllerIndex(event.jbutton.which, gui);
+ if (a>-1)
+ {
+ joyc = g_strdup_printf("joystick %016I64x %08x", gui->joy[a].id, b);
+ //printf("Button Event: %s\n", joyc);
+ which = a;
+ }
+ }
+ else
+ if (event.type == SDL_JOYHATMOTION) {
+ a = GetControllerIndex(event.jhat.which, gui);
+ if (a>-1)
+ {
+ //printf("Value: %i\n", event.jhat.value);
+ int h=(((event.jhat.hat*2)-1) + SDL_JoystickNumAxes(gui->joy[a].sdljoy));
+ b = (0x8000 | h);
+ if (event.jhat.value == SDL_HAT_UP)
+ {
+ on = g_strdup_printf("Axis %i Up", h+2);
+ b = (0x4000 | b)+2;
+ }
+ else if(event.jhat.value == SDL_HAT_DOWN)
+ {
+ on = g_strdup_printf("Axis %i Down", h+2);
+ b=b+2;
+ }
+ else if(event.jhat.value == SDL_HAT_RIGHT)
+ {
+ on = g_strdup_printf("Axis %i Right", h+1);
+ b=b+1;
+ }
+ else if(event.jhat.value == SDL_HAT_LEFT)
+ {
+ on = g_strdup_printf("Axis %i Left", h+1);
+ b = (0x4000 | b)+1;
+ }
+
+ which = a;
+ joyc = g_strdup_printf("joystick %016I64x %08x", gui->joy[a].id, b);
+ //printf("Hat Event: %s\n", joyc);
+ }
+}
+ else
+ if (event.type == SDL_JOYAXISMOTION) {
+ a = GetControllerIndex(event.jaxis.which, gui);
+ if (a>-1)
+ {
+ //printf("Value: %i\n", event.jaxis.value);
+
+ if (event.jaxis.axis % 2)
+ {
+ if (event.jaxis.value<0) on = g_strdup_printf("Axis %i Up", event.jaxis.axis);
+ else on = g_strdup_printf("Axis %i Down", event.jaxis.axis);
+ }
+ else
+ {
+ if (event.jaxis.value<0) on = g_strdup_printf("Axis %i Left", event.jaxis.axis);
+ else on = g_strdup_printf("Axis %i Right", event.jaxis.axis);
+ }
+ which = a;
+ b = (0x8000 | event.jaxis.axis);
+ if (event.jaxis.value<0) b = (0x4000 | b);
+ joyc = g_strdup_printf("joystick %016I64x %08x", gui->joy[a].id, b);
+ //printf("Axis Event: %s\n", joyc);
+ }
+ }
+ }
+}
+ SDL_JoystickEventState(SDL_IGNORE);
+ return 0;
+}
+#endif
+
#ifdef G_OS_WIN32
G_MODULE_EXPORT
#endif
@@ -396,6 +569,77 @@ void on_input_clicked (GtkButton *button, guidata *gui)
gui->joy[a].channel = NULL;
}
}
+ #endif
+
+ #ifdef G_OS_WIN32
+
+ SDL_SetHint("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", "1");
+ SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
+
+ int i;
+ for(i=0;i<9;i++)
+ {
+ gui->joy[i].sdljoy = SDL_JoystickOpen(i);
+
+ if(!gui->joy[i].sdljoy)
+ {
+ printf("Couldn't open Joystick %i\n", i);
+ }
+ else
+ {
+ gui->joy[i].sdl_id = SDL_JoystickInstanceID(gui->joy[i].sdljoy);
+ gui->joy[i].name = g_strdup(SDL_JoystickName(gui->joy[i].sdljoy));
+
+ SDL_JoystickGUID guid = SDL_JoystickGetGUID(gui->joy[i].sdljoy);
+ if ((guid.data[0]=='x') &&
+ (guid.data[1]=='i') &&
+ (guid.data[2]=='n') &&
+ (guid.data[3]=='p') &&
+ (guid.data[4]=='u') &&
+ (guid.data[5]=='t'))
+ {
+ gui->joy[i].id = (0x01 << 24) | (guid.data[6] << 16);
+ }
+ else GetJoy(i, gui);
+
+ CheckDuplicates(i, gui);
+ printf("Index: %i - Instance: %i - Name: %s - ID: %016I64x\n", i,
+ SDL_JoystickInstanceID(gui->joy[i].sdljoy),
+ SDL_JoystickName(gui->joy[i].sdljoy),
+ gui->joy[i].id);
+ }
+ }
+
+ /* gchar *string;
+
+ gchar *dir = g_win32_get_package_installation_directory_of_module(NULL);
+ gchar *path =g_strconcat(dir, "\\stdout.txt", NULL);
+
+ if (g_file_get_contents(path, &string, NULL, NULL))
+ {
+ gchar **aline = g_strsplit(string, "\n", 0);
+ gint num = g_strv_length(aline);
+ gint l;
+ for(l=0;l<num-1;l++)
+ {
+ if (aline[l][2]=='J')
+ {
+ gint ii = g_ascii_digit_value(aline[l][11]);
+ printf ("\n%i\n",ii);
+ gchar *id = g_strrstr(aline[l],"ID:");
+ gui->joy[ii].id = g_strndup(id+=4,16);
+ //id = g_strrstr(aline[l],"Joystick ");
+ //gui->joy[ii].name = g_strndup(id+=13,(strlen(aline[l])-45));
+ printf (gui->joy[ii].id);
+ //printf (gui->joy[ii].name);
+ }
+ }
+ g_free(string);
+ g_strfreev(aline);
+ }
+ g_free(dir);
+ g_free(path); */
+
#endif
read_input(gui);
@@ -427,11 +671,17 @@ guint gdk_to_sdl_keyval(guint gdk_key)
return sdl_key;
}
+#ifdef G_OS_WIN32
+G_MODULE_EXPORT
+#endif
gboolean editable_mouse_cb(GtkWidget *ed, GdkEvent *event, guidata *gui)
{
return TRUE;
}
+#ifdef G_OS_WIN32
+G_MODULE_EXPORT
+#endif
gboolean editable_key_cb(GtkWidget *ed, GdkEventKey *event, guidata *gui)
{
GtkTreeModel *model;
@@ -440,7 +690,16 @@ gboolean editable_key_cb(GtkWidget *ed, GdkEventKey *event, guidata *gui)
gchar *fullcommand;
gchar *key = NULL;
guint nkey;
-
+
+ #ifdef G_OS_WIN32
+ g_mutex_lock (&mutex);
+ if (bool==1) {
+ g_mutex_unlock (&mutex);
+ return TRUE;
+ }
+ bool=1;
+ #endif
+
nkey = gdk_to_sdl_keyval(event->keyval);
if (sdl_to_gdk[nkey] != NULL)
key = g_strdup(sdl_to_gdk[nkey]);//g_ascii_strup(gdk_keyval_name(event->keyval), -1);
@@ -466,6 +725,12 @@ gboolean editable_key_cb(GtkWidget *ed, GdkEventKey *event, guidata *gui)
gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(ed));
gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(ed));
+ gui->inputedited = TRUE;
+
+ #ifdef G_OS_WIN32
+ g_mutex_unlock (&mutex);
+ #endif
+
return TRUE;
}
@@ -483,6 +748,42 @@ else
}
#ifdef G_OS_WIN32
+void thread_watch(GPid pid, gint status, guidata *gui)
+{
+ //printf("Exiting from thread\n");
+ g_mutex_lock (&mutex);
+
+ if ((joyc != NULL) && (on != NULL) && (!gui->inputedited))
+ {
+ GtkTreeIter iter;
+ gchar *command;
+
+ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtk_builder_get_object(gui->specific, "treeview_input")));
+ gtk_tree_model_get_iter_from_string(model, &iter, gui->treepath);
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter, 2, on, 3, gui->joy[which].name, -1);
+ gtk_tree_model_get(model, &iter, 1, &command, -1);
+
+ gchar *fullcommand = g_strconcat(gui->system,".input.",gui->port, command, NULL);
+ g_free(command);
+ g_hash_table_replace(gui->clist, fullcommand, fullcommand);
+ fullcommand++;
+ g_hash_table_insert(gui->hash, g_strdup(fullcommand), joyc);
+ fullcommand--;
+
+ gtk_cell_editable_editing_done(gui->editable);
+ gtk_cell_editable_remove_widget(gui->editable);
+ }
+
+ gui->inputedited = TRUE;
+
+ g_free(on);
+
+ g_mutex_unlock (&mutex);
+ g_spawn_close_pid(pid);
+}
+#endif
+
+#ifdef G_OS_WIN32
G_MODULE_EXPORT
#endif
void key_setting (GtkCellRendererText *renderer,
@@ -496,6 +797,8 @@ void key_setting (GtkCellRendererText *renderer,
g_free(gui->treepath);
gui->treepath = g_strdup(path);
+
+ gui->editable = editable;
gui->inputedited = FALSE;
g_signal_connect(GTK_WIDGET(editable), "button-press-event",
@@ -503,6 +806,16 @@ void key_setting (GtkCellRendererText *renderer,
g_signal_connect(GTK_WIDGET(editable), "key-press-event",
G_CALLBACK(editable_key_cb), gui);
+
+#ifdef G_OS_WIN32
+ bool = 0;
+ on = NULL;
+ joyc = NULL;
+ which = 0;
+
+ HANDLE hThread = CreateThread(NULL, 0, joy_thread, gui, 0, NULL);
+ g_child_watch_add(hThread, (GChildWatchFunc)thread_watch, gui);
+#endif
}
}
diff --git a/src/joystick_win.c b/src/joystick_win.c
new file mode 100644
index 0000000..19b395c
--- /dev/null
+++ b/src/joystick_win.c
@@ -0,0 +1,78 @@
+/*
+ * joystick_win.c
+ *
+ * Copyright 2013-2015 AmatCoder
+ *
+ * This file is part of Mednaffe.
+ *
+ * Mednaffe 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.
+ *
+ * Mednaffe 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 Mednaffe; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common.h"
+#include "md5.h"
+#include "stdint.h"
+#include "string.h"
+
+uint64_t CalcOldStyleID(unsigned arg_num_axes, unsigned arg_num_balls,
+ unsigned arg_num_hats, unsigned arg_num_buttons)
+{
+ uint8 digest[16];
+ int tohash[4];
+ md5_context hashie;
+ uint64_t ret = 0;
+
+ tohash[0] = arg_num_axes;
+ tohash[1] = arg_num_balls;
+ tohash[2] = arg_num_hats;
+ tohash[3] = arg_num_buttons;
+
+ md5_starts(&hashie);
+ md5_update(&hashie, (uint8 *)tohash, sizeof(tohash));
+ md5_finish(&hashie, digest);
+
+ int x;
+ for(x = 0; x < 16; x++)
+ {
+ ret ^= (uint64_t)digest[x] << ((x & 7) * 8);
+ }
+ return ret;
+}
+
+void CheckDuplicates(guint js, guidata *gui)
+{
+ int a;
+ for (a=0;a<9;a++)
+ {
+ if (a==js) break;
+ if (gui->joy[js].id == gui->joy[a].id)
+ gui->joy[a].id++;
+ }
+}
+
+gint GetJoy(guint js, guidata *gui)
+{
+ //printf("Number of Axes: %d\n", SDL_JoystickNumAxes(gui->joy[js].sdljoy));
+ //printf("Number of Hats: %d\n", SDL_JoystickNumHats(gui->joy[js].sdljoy));
+ //printf("Number of Buttons: %d\n", SDL_JoystickNumButtons(gui->joy[js].sdljoy));
+ //printf("Number of Balls: %d\n", SDL_JoystickNumBalls(gui->joy[js].sdljoy));
+
+ gui->joy[js].id = CalcOldStyleID(SDL_JoystickNumAxes(gui->joy[js].sdljoy),
+ 0,
+ SDL_JoystickNumHats(gui->joy[js].sdljoy),
+ SDL_JoystickNumButtons(gui->joy[js].sdljoy));
+
+ return 1;
+
+}
diff --git a/src/joystick_win.h b/src/joystick_win.h
new file mode 100644
index 0000000..1422fc6
--- /dev/null
+++ b/src/joystick_win.h
@@ -0,0 +1,29 @@
+/*
+ * joystick_win.h
+ *
+ * Copyright 2013-2015 AmatCoder
+ *
+ * This file is part of Mednaffe.
+ *
+ * Mednaffe 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.
+ *
+ * Mednaffe 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 Mednaffe; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef JOYSTICK_WIN_H
+#define JOYSTICK_WIN_H
+
+ void CheckDuplicates(guint js, guidata *gui);
+ gint GetJoy(guint js, guidata *gui);
+
+#endif /* JOYSTICK_WIN_H */
diff --git a/src/mednaffe.c b/src/mednaffe.c
index 0c47733..2ac1139 100644
--- a/src/mednaffe.c
+++ b/src/mednaffe.c
@@ -465,8 +465,10 @@ int main(int argc, char **argv)
gui.system = NULL;
gui.port = NULL;
gui.treepath = NULL;
+ gui.editable = NULL;
gui.inputedited = TRUE;
gui.m_error = FALSE;
+
gui.clist = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
gui.hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/mednaffe.git
More information about the Pkg-games-commits
mailing list