diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-04-16 06:22:51 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-04-16 06:22:51 +0000 |
| commit | 8139fbf8204882663446bcb06f68789353597820 (patch) | |
| tree | 6ea1f39932b33faee84d603e956470e37f135804 /plugins/dfinput | |
| download | pcsxr-8139fbf8204882663446bcb06f68789353597820.tar.gz | |
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@23061 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'plugins/dfinput')
| -rw-r--r-- | plugins/dfinput/Makefile.am | 22 | ||||
| -rw-r--r-- | plugins/dfinput/Makefile.in | 583 | ||||
| -rw-r--r-- | plugins/dfinput/cfg.c | 1289 | ||||
| -rw-r--r-- | plugins/dfinput/dfinput.glade2 | 226 | ||||
| -rw-r--r-- | plugins/dfinput/pad.c | 989 | ||||
| -rw-r--r-- | plugins/dfinput/padjoy.h | 82 |
6 files changed, 3191 insertions, 0 deletions
diff --git a/plugins/dfinput/Makefile.am b/plugins/dfinput/Makefile.am new file mode 100644 index 00000000..cb6d2648 --- /dev/null +++ b/plugins/dfinput/Makefile.am @@ -0,0 +1,22 @@ +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +lib_LTLIBRARIES = libDFInput.la + +libDFInput_la_SOURCES = pad.c padjoy.h +libDFInput_la_LDFLAGS = -module -avoid-version -lpthread -lX11 \ + -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 \ + -DVERSION=0 -DREVISION=1 -DBUILD=0 + +bin_PROGRAMS = cfgDFInput +cfgDFInput_SOURCES = cfg.c padjoy.h +cfgDFInput_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) + +glade_DATA = dfinput.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) diff --git a/plugins/dfinput/Makefile.in b/plugins/dfinput/Makefile.in new file mode 100644 index 00000000..6210f4cb --- /dev/null +++ b/plugins/dfinput/Makefile.in @@ -0,0 +1,583 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = cfgDFInput$(EXEEXT) +subdir = plugins/dfinput +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(gladedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libDFInput_la_LIBADD = +am_libDFInput_la_OBJECTS = pad.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) +cfgDFInput_OBJECTS = $(am_cfgDFInput_OBJECTS) +am__DEPENDENCIES_1 = +cfgDFInput_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libDFInput_la_SOURCES) $(cfgDFInput_SOURCES) +DIST_SOURCES = $(libDFInput_la_SOURCES) $(cfgDFInput_SOURCES) +gladeDATA_INSTALL = $(INSTALL_DATA) +DATA = $(glade_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFOPENGL = @DFOPENGL@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE2_CFLAGS = @GLADE2_CFLAGS@ +GLADE2_LIBS = @GLADE2_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @libdir@/games/psemu/ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@/games/psemu/ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +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_LDFLAGS = -module -avoid-version -lpthread -lX11 \ + -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 \ + -DVERSION=0 -DREVISION=1 -DBUILD=0 + +cfgDFInput_SOURCES = cfg.c padjoy.h +cfgDFInput_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) +glade_DATA = dfinput.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/dfinput/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/dfinput/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libDFInput.la: $(libDFInput_la_OBJECTS) $(libDFInput_la_DEPENDENCIES) + $(libDFInput_la_LINK) -rpath $(libdir) $(libDFInput_la_OBJECTS) $(libDFInput_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +cfgDFInput$(EXEEXT): $(cfgDFInput_OBJECTS) $(cfgDFInput_DEPENDENCIES) + @rm -f cfgDFInput$(EXEEXT) + $(LINK) $(cfgDFInput_OBJECTS) $(cfgDFInput_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pad.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-gladeDATA: $(glade_DATA) + @$(NORMAL_INSTALL) + test -z "$(gladedir)" || $(MKDIR_P) "$(DESTDIR)$(gladedir)" + @list='$(glade_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(gladeDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(gladedir)/$$f'"; \ + $(gladeDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(gladedir)/$$f"; \ + done + +uninstall-gladeDATA: + @$(NORMAL_UNINSTALL) + @list='$(glade_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(gladedir)/$$f'"; \ + rm -f "$(DESTDIR)$(gladedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(gladedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-gladeDATA + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-gladeDATA \ + uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-gladeDATA install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-gladeDATA uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/dfinput/cfg.c b/plugins/dfinput/cfg.c new file mode 100644 index 00000000..3f6d0184 --- /dev/null +++ b/plugins/dfinput/cfg.c @@ -0,0 +1,1289 @@ +/* + * 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 + * + * Written by Erich Kitzmuller <ammoq@ammoq.com> + * Based on padXwin by linuzappz <linuzappz@hotmail.com> + * + * 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 + * + */ + +#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 __linux__ +char *LibName = "Gamepad/Keyboard Input"; +#else +char *LibName = "Keyboard Input"; +#endif + +#define CONFIG_FILENAME "dfinput.cfg" + +const unsigned char version = VERSION; +const unsigned char revision = REVISION; +const unsigned char build = BUILD; + +// 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; +} + + +/*---------------------------------------------------------------------*/ +/* About dialogue stuff */ +/*---------------------------------------------------------------------*/ + +void PADabout(void) { + GladeXML *xml; + xml = glade_xml_new (DATADIR "dfinput.glade2", "AboutWin", NULL); + + GtkWidget *widget = glade_xml_get_widget (xml, "AboutWin"); + + /* TODO Authors, about, version */ + + gtk_dialog_run (GTK_DIALOG (widget)); + gtk_widget_destroy (widget); +// gtk_main_quit(); +} + +/*---------------------------------------------------------------------*/ +/* Main program */ +/*---------------------------------------------------------------------*/ + +int main(int argc, char **argv) { + 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/dfinput.glade2 b/plugins/dfinput/dfinput.glade2 new file mode 100644 index 00000000..b6905f2e --- /dev/null +++ b/plugins/dfinput/dfinput.glade2 @@ -0,0 +1,226 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkWindow" id="CfgWin"> + <property name="visible">True</property> + <property name="title" translatable="yes">Configure Gamepad/Keyboard</property> + <property name="modal">True</property> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="border_width">6</property> + <property name="spacing">6</property> + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="border_width">6</property> + <property name="spacing">50</property> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Pad number:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="radiobutton1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">1</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </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="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">2</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + <property name="group">radiobutton1</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="border_width">6</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Device file:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="filename_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </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="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Multi-threaded</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkAnalog"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Analog</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">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="position">2</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">GTK_SHADOW_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> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="spacing">6</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="btnCancel"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + </child> + <child> + <widget class="GtkButton" id="btnOK"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <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="type_hint">GDK_WINDOW_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"> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/plugins/dfinput/pad.c b/plugins/dfinput/pad.c new file mode 100644 index 00000000..dd564479 --- /dev/null +++ b/plugins/dfinput/pad.c @@ -0,0 +1,989 @@ +/* + * Pad for Psemu Pro like Emulators + * This is the plugin + * + * Modified for PCSX-df by Ryan Schultz + * + * Written by Erich Kitzmuller <ammoq@ammoq.com> + * Based on padXwin by linuzappz <linuzappz@hotmail.com> + * + * 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 + */ + +#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 __linux__ +char *LibName = "Gamepad/Keyboard Input"; +#else +char *LibName = "Keyboard Input"; +#endif + +const unsigned char version = VERSION; +const unsigned char revision = REVISION; +const unsigned char build = BUILD; + +// 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 +} + +uint32_t PSEgetLibVersion(void) { + return version<<16|revision<<8|build; +} + +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; +} + +long PADshutdown(void) { + return 0; +} + +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 + + 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 + + init_done = 1; + + return 0; +} + +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; + + XAutoRepeatOn(Dsp); + + return 0; +} + +long PADquery(void) { + return 3; // both pads +} + +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; +} + +// 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 + + 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; +} + +// 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); + } + } +} + + +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); + + return 0; +} + +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 + + // ePSXe different from pcsx, swap bytes + pad->buttonStatus = (pad->buttonStatus>>8)|(pad->buttonStatus<<8); + + return 0; +} + +long PADkeypressed(void) { + int ksym; + + CheckPads(0, 1, 1); + + if (keyLeftOver == NO_EVENT) return 0; + + ksym = keyLeftOver-FIRST_KEY_EVENT; + keyLeftOver = NO_EVENT; + + return ksym; +} + +#ifdef __linux__ + +static void *thread_check_joydevice(void *arg) { + while (!die_thread_die) { + CheckPads(1, 0, 1); + } + return NULL; +} + +#endif + +// 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; +} + + +// 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 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 PADconfigure(void) { + system("cfg/cfgDFInput"); + return 0; +} + + +/*---------------------------------------------------------------------*/ +/* About dialogue stuff */ +/*---------------------------------------------------------------------*/ + + +void PADabout(void) { + system("cfg/cfgDFInput -about"); +} + +#ifdef __linux__ + +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; +} + +#endif diff --git a/plugins/dfinput/padjoy.h b/plugins/dfinput/padjoy.h new file mode 100644 index 00000000..e51f2db4 --- /dev/null +++ b/plugins/dfinput/padjoy.h @@ -0,0 +1,82 @@ +#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 |
