mirror of https://github.com/PCSX2/pcsx2.git
Merge pull request #448 from PCSX2/lilypad-linux-port
Lilypad linux port Basic support of Keyboard and Joystick No gui to configure anything. Not well tested yet.
This commit is contained in:
commit
b68270ded1
|
@ -6,7 +6,7 @@ set(msg_dep_pcsx2 "check these libraries -> wxWidgets (>=2.8.10), gtk2 (>=
|
||||||
set(msg_dep_cdvdiso "check these libraries -> bzip2 (>=1.0.5), gtk2 (>=2.16)")
|
set(msg_dep_cdvdiso "check these libraries -> bzip2 (>=1.0.5), gtk2 (>=2.16)")
|
||||||
set(msg_dep_zerogs "check these libraries -> glew (>=1.6), opengl, X11, nvidia-cg-toolkit (>=2.1)")
|
set(msg_dep_zerogs "check these libraries -> glew (>=1.6), opengl, X11, nvidia-cg-toolkit (>=2.1)")
|
||||||
set(msg_dep_gsdx "check these libraries -> opengl, egl, X11")
|
set(msg_dep_gsdx "check these libraries -> opengl, egl, X11")
|
||||||
set(msg_dep_onepad "check these libraries -> sdl (>=1.2)")
|
set(msg_dep_onepad "check these libraries -> sdl (>=1.2), X11")
|
||||||
set(msg_dep_spu2x "check these libraries -> soundtouch (>=1.5), alsa, portaudio (>=1.9), sdl (>=1.2) pcsx2 common libs")
|
set(msg_dep_spu2x "check these libraries -> soundtouch (>=1.5), alsa, portaudio (>=1.9), sdl (>=1.2) pcsx2 common libs")
|
||||||
set(msg_dep_zerospu2 "check these libraries -> soundtouch (>=1.5), alsa")
|
set(msg_dep_zerospu2 "check these libraries -> soundtouch (>=1.5), alsa")
|
||||||
if(GLSL_API)
|
if(GLSL_API)
|
||||||
|
@ -205,12 +205,22 @@ if(GTKn_FOUND AND EXTRA_PLUGINS)
|
||||||
endif()
|
endif()
|
||||||
#---------------------------------------
|
#---------------------------------------
|
||||||
|
|
||||||
|
#---------------------------------------
|
||||||
|
# LilyPad
|
||||||
|
# requires: -X11
|
||||||
|
#---------------------------------------
|
||||||
|
if(GTKn_FOUND AND X11_FOUND)
|
||||||
|
set(LilyPad TRUE)
|
||||||
|
endif()
|
||||||
|
#---------------------------------------
|
||||||
|
|
||||||
#---------------------------------------
|
#---------------------------------------
|
||||||
# onepad
|
# onepad
|
||||||
#---------------------------------------
|
#---------------------------------------
|
||||||
# requires: -SDL
|
# requires: -SDL
|
||||||
|
# -X11
|
||||||
#---------------------------------------
|
#---------------------------------------
|
||||||
if(SDLn_FOUND)
|
if(SDLn_FOUND AND X11_FOUND)
|
||||||
set(onepad TRUE)
|
set(onepad TRUE)
|
||||||
elseif(NOT EXISTS "${CMAKE_SOURCE_DIR}/plugins/onepad")
|
elseif(NOT EXISTS "${CMAKE_SOURCE_DIR}/plugins/onepad")
|
||||||
set(onepad FALSE)
|
set(onepad FALSE)
|
||||||
|
@ -286,7 +296,6 @@ set(cdvdGigaherz FALSE)
|
||||||
set(CDVDisoEFP FALSE)
|
set(CDVDisoEFP FALSE)
|
||||||
set(CDVDolio FALSE)
|
set(CDVDolio FALSE)
|
||||||
set(CDVDpeops FALSE)
|
set(CDVDpeops FALSE)
|
||||||
set(LilyPad FALSE)
|
|
||||||
set(PeopsSPU2 FALSE)
|
set(PeopsSPU2 FALSE)
|
||||||
set(SSSPSXPAD FALSE)
|
set(SSSPSXPAD FALSE)
|
||||||
set(xpad FALSE)
|
set(xpad FALSE)
|
||||||
|
|
|
@ -6,123 +6,99 @@ if(NOT TOP_CMAKE_WAS_SOURCED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# make cdvdGigaherz
|
|
||||||
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/cdvdGigaherz" AND cdvdGigaherz)
|
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/cdvdGigaherz" AND cdvdGigaherz)
|
||||||
# add_subdirectory(cdvdGigaherz)
|
# add_subdirectory(cdvdGigaherz)
|
||||||
#endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/cdvdGigaherz" AND cdvdGigaherz)
|
#endif()
|
||||||
|
|
||||||
# make CDVDiso
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDiso" AND CDVDiso)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDiso" AND CDVDiso)
|
||||||
add_subdirectory(CDVDiso/src)
|
add_subdirectory(CDVDiso/src)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDiso" AND CDVDiso)
|
endif()
|
||||||
|
|
||||||
# make CDVDisoEFP
|
|
||||||
# if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDisoEFP" AND CDVDisoEFP)
|
# if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDisoEFP" AND CDVDisoEFP)
|
||||||
# add_subdirectory(CDVDisoEFP)
|
# add_subdirectory(CDVDisoEFP)
|
||||||
# endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDisoEFP" AND CDVDisoEFP)
|
# endif()
|
||||||
|
|
||||||
# make CDVDlinuz
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDlinuz" AND CDVDlinuz)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDlinuz" AND CDVDlinuz)
|
||||||
add_subdirectory(CDVDlinuz/Src)
|
add_subdirectory(CDVDlinuz/Src)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDlinuz" AND CDVDlinuz)
|
endif()
|
||||||
|
|
||||||
# make CDVDnull
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDnull" AND CDVDnull)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDnull" AND CDVDnull)
|
||||||
add_subdirectory(CDVDnull)
|
add_subdirectory(CDVDnull)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDnull" AND CDVDnull)
|
endif()
|
||||||
|
|
||||||
# make CDVDolio
|
|
||||||
# if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDolio" AND CDVDolio)
|
# if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDolio" AND CDVDolio)
|
||||||
# add_subdirectory(CDVDolio)
|
# add_subdirectory(CDVDolio)
|
||||||
# endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDolio" AND CDVDolio)
|
# endif()
|
||||||
|
|
||||||
# make CDVDpeops
|
|
||||||
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDpeops" AND CDVDpeops)
|
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDpeops" AND CDVDpeops)
|
||||||
# add_subdirectory(CDVDpeops)
|
# add_subdirectory(CDVDpeops)
|
||||||
#endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDpeops" AND CDVDpeops)
|
#endif()
|
||||||
|
|
||||||
# make dev9null
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/dev9null" AND dev9null)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/dev9null" AND dev9null)
|
||||||
add_subdirectory(dev9null)
|
add_subdirectory(dev9null)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/dev9null" AND dev9null)
|
endif()
|
||||||
|
|
||||||
# make FWnull
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/FWnull" AND FWnull)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/FWnull" AND FWnull)
|
||||||
add_subdirectory(FWnull)
|
add_subdirectory(FWnull)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/FWnull" AND FWnull)
|
endif()
|
||||||
|
|
||||||
# make GSdx
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/GSdx" AND GSdx)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/GSdx" AND GSdx)
|
||||||
add_subdirectory(GSdx)
|
add_subdirectory(GSdx)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/GSdx" AND GSdx)
|
endif()
|
||||||
|
|
||||||
# make GSnull
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/GSnull" AND GSnull)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/GSnull" AND GSnull)
|
||||||
add_subdirectory(GSnull)
|
add_subdirectory(GSnull)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/GSnull" AND GSnull)
|
endif()
|
||||||
|
|
||||||
# make LilyPad
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/LilyPad" AND LilyPad)
|
||||||
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/LilyPad" AND LilyPad)
|
add_subdirectory(LilyPad)
|
||||||
# add_subdirectory(LilyPad)
|
endif()
|
||||||
#endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/LilyPad" AND LilyPad)
|
|
||||||
|
|
||||||
# make onepad
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/onepad" AND onepad)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/onepad" AND onepad)
|
||||||
add_subdirectory(onepad)
|
add_subdirectory(onepad)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/onepad" AND onepad)
|
endif()
|
||||||
|
|
||||||
# make PadNull
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/PadNull" AND PadNull)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/PadNull" AND PadNull)
|
||||||
add_subdirectory(PadNull)
|
add_subdirectory(PadNull)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/PadNull" AND PadNull)
|
endif()
|
||||||
|
|
||||||
# make PeopsSPU2
|
|
||||||
# if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/PeopsSPU2" AND PeopsSPU2)
|
# if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/PeopsSPU2" AND PeopsSPU2)
|
||||||
# add_subdirectory(PeopsSPU2)
|
# add_subdirectory(PeopsSPU2)
|
||||||
# endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/PeopsSPU2" AND PeopsSPU2)
|
# endif()
|
||||||
|
|
||||||
# make SPU2null
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/SPU2null" AND SPU2null)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/SPU2null" AND SPU2null)
|
||||||
add_subdirectory(SPU2null)
|
add_subdirectory(SPU2null)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/SPU2null" AND SPU2null)
|
endif()
|
||||||
|
|
||||||
# make spu2-x
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/spu2-x" AND spu2-x)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/spu2-x" AND spu2-x)
|
||||||
add_subdirectory(spu2-x/src)
|
add_subdirectory(spu2-x/src)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/spu2-x" AND spu2-x)
|
endif()
|
||||||
|
|
||||||
# make SSSPSXPAD
|
|
||||||
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/SSSPSXPAD" AND SSSPSXPAD)
|
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/SSSPSXPAD" AND SSSPSXPAD)
|
||||||
# add_subdirectory(SSSPSXPAD)
|
# add_subdirectory(SSSPSXPAD)
|
||||||
#endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/SSSPSXPAD" AND SSSPSXPAD)
|
#endif()
|
||||||
|
|
||||||
# make USBnull
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/USBnull" AND USBnull)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/USBnull" AND USBnull)
|
||||||
add_subdirectory(USBnull)
|
add_subdirectory(USBnull)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/USBnull" AND USBnull)
|
endif()
|
||||||
|
|
||||||
# make xpad
|
|
||||||
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/xpad" AND xpad)
|
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/xpad" AND xpad)
|
||||||
# add_subdirectory(xpad)
|
# add_subdirectory(xpad)
|
||||||
#endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/xpad" AND xpad)
|
#endif()
|
||||||
|
|
||||||
# make zerogs
|
|
||||||
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zerogs" AND zerogs)
|
#if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zerogs" AND zerogs)
|
||||||
# add_subdirectory(zerogs)
|
# add_subdirectory(zerogs)
|
||||||
#endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zerogs" AND zerogs)
|
#endif()
|
||||||
|
|
||||||
# make zzogl-pg
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zzogl-pg" AND zzogl)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zzogl-pg" AND zzogl)
|
||||||
add_subdirectory(zzogl-pg/opengl)
|
add_subdirectory(zzogl-pg/opengl)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zzogl-pg" AND zzogl)
|
endif()
|
||||||
|
|
||||||
# make zeropad
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zeropad" AND zeropad)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zeropad" AND zeropad)
|
||||||
add_subdirectory(zeropad)
|
add_subdirectory(zeropad)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zeropad" AND zeropad)
|
endif()
|
||||||
|
|
||||||
# make zerospu2
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zerospu2" AND zerospu2)
|
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zerospu2" AND zerospu2)
|
||||||
add_subdirectory(zerospu2)
|
add_subdirectory(zerospu2)
|
||||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/plugins/zerospu2" AND zerospu2)
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Check that people use the good file
|
||||||
|
if(NOT TOP_CMAKE_WAS_SOURCED)
|
||||||
|
message(FATAL_ERROR "
|
||||||
|
You did not 'cmake' the good CMakeLists.txt file. Use the one in the top dir.
|
||||||
|
It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# plugin name
|
||||||
|
set(Output LilyPad-0.11.0)
|
||||||
|
|
||||||
|
set(OptimizationFlags
|
||||||
|
-O2
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||||
|
set(lilypadFinalFlags "-DPCSX2_DEBUG")
|
||||||
|
|
||||||
|
elseif(CMAKE_BUILD_TYPE STREQUAL Devel)
|
||||||
|
set(lilypadFinalFlags ${OptimizationFlags})
|
||||||
|
|
||||||
|
elseif(CMAKE_BUILD_TYPE STREQUAL Release)
|
||||||
|
set(lilypadFinalFlags ${OptimizationFlags})
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# lilypad sources
|
||||||
|
set(lilypadSources
|
||||||
|
DeviceEnumerator.cpp
|
||||||
|
InputManager.cpp
|
||||||
|
KeyboardQueue.cpp
|
||||||
|
LilyPad.cpp
|
||||||
|
Linux/Config.cpp
|
||||||
|
Linux/ConfigHelper.cpp
|
||||||
|
Linux/JoyEvdev.cpp
|
||||||
|
Linux/KeyboardMouse.cpp
|
||||||
|
Linux/KeyboardQueue.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# lilypad headers
|
||||||
|
set(lilypadHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
# lilypad Linux sources
|
||||||
|
set(lilypadLinuxSources
|
||||||
|
)
|
||||||
|
|
||||||
|
# lilypad Linux headers
|
||||||
|
set(lilypadLinuxHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
if (SDL2_API)
|
||||||
|
set(lilypadFinalLibs
|
||||||
|
${SDL2_LIBRARIES}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(lilypadFinalLibs
|
||||||
|
${SDL_LIBRARY}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(lilypadFinalLibs
|
||||||
|
#${lilypadFinalLibs}
|
||||||
|
#${GTK2_LIBRARIES}
|
||||||
|
#${X11_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(lilypadFinalSources
|
||||||
|
${lilypadSources}
|
||||||
|
${lilypadHeaders}
|
||||||
|
${lilypadLinuxSources}
|
||||||
|
${lilypadLinuxHeaders}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_pcsx2_plugin(${Output} "${lilypadFinalSources}" "${lilypadFinalLibs}" "${lilypadFinalFlags}")
|
|
@ -84,8 +84,6 @@ extern GeneralConfig config;
|
||||||
|
|
||||||
void UnloadConfigs();
|
void UnloadConfigs();
|
||||||
|
|
||||||
void AddIgnore(LPARAM k);
|
|
||||||
|
|
||||||
void SetVolume(int volume);
|
void SetVolume(int volume);
|
||||||
|
|
||||||
int LoadSettings(int force = 0, wchar_t *file = 0);
|
int LoadSettings(int force = 0, wchar_t *file = 0);
|
||||||
|
|
|
@ -27,18 +27,28 @@
|
||||||
#include "HidDevice.h"
|
#include "HidDevice.h"
|
||||||
#include "DualShock3.h"
|
#include "DualShock3.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include "Linux/KeyboardMouse.h"
|
||||||
|
#include "Linux/JoyEvdev.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void EnumDevices(int hideDXXinput) {
|
void EnumDevices(int hideDXXinput) {
|
||||||
// Needed for enumeration of some device types.
|
// Needed for enumeration of some device types.
|
||||||
dm->ReleaseInput();
|
dm->ReleaseInput();
|
||||||
InputDeviceManager *oldDm = dm;
|
InputDeviceManager *oldDm = dm;
|
||||||
dm = new InputDeviceManager();
|
dm = new InputDeviceManager();
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
EnumHookDevices();
|
EnumHookDevices();
|
||||||
EnumWindowsMessagingDevices();
|
EnumWindowsMessagingDevices();
|
||||||
EnumRawInputDevices();
|
EnumRawInputDevices();
|
||||||
EnumDualShock3s();
|
EnumDualShock3s();
|
||||||
EnumXInputDevices();
|
EnumXInputDevices();
|
||||||
EnumDirectInputDevices(hideDXXinput);
|
EnumDirectInputDevices(hideDXXinput);
|
||||||
|
#else
|
||||||
|
EnumLnx();
|
||||||
|
EnumJoystickEvdev();
|
||||||
|
#endif
|
||||||
|
|
||||||
dm->CopyBindings(oldDm->numDevices, oldDm->devices);
|
dm->CopyBindings(oldDm->numDevices, oldDm->devices);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,76 @@
|
||||||
// dll size by over 100k while avoiding any dependencies on updated CRT dlls.
|
// dll size by over 100k while avoiding any dependencies on updated CRT dlls.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
// Seriously why there is no standard
|
||||||
|
#include "stdint.h"
|
||||||
|
typedef uint32_t DWORD;
|
||||||
|
typedef uint16_t USHORT;
|
||||||
|
typedef int64_t __int64;
|
||||||
|
|
||||||
|
#define MAX_PATH (256) // random value
|
||||||
|
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
|
#define VK_SHIFT XK_Shift_L
|
||||||
|
#define VK_LSHIFT XK_Shift_L
|
||||||
|
#define VK_RSHIFT XK_Shift_R
|
||||||
|
#define VK_LMENU XK_Menu
|
||||||
|
#define VK_RMENU XK_Menu
|
||||||
|
#define VK_MENU XK_Menu
|
||||||
|
#define VK_CONTROL XK_Control_L
|
||||||
|
#define VK_TAB XK_Tab
|
||||||
|
#define VK_ESCAPE XK_Escape
|
||||||
|
#define VK_F4 XK_F4
|
||||||
|
|
||||||
|
#include <cwchar>
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
template <typename Array>
|
||||||
|
void wsprintfW(Array& buf, const wchar_t *format, ...) {
|
||||||
|
va_list a;
|
||||||
|
va_start(a, format);
|
||||||
|
|
||||||
|
vswprintf(buf, sizeof(buf)/sizeof(buf[0]), format, a);
|
||||||
|
|
||||||
|
va_end(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Array>
|
||||||
|
void wsprintf(Array& buf, const wchar_t *format, ...) {
|
||||||
|
va_list a;
|
||||||
|
va_start(a, format);
|
||||||
|
|
||||||
|
vswprintf(buf, sizeof(buf)/sizeof(buf[0]), format, a);
|
||||||
|
|
||||||
|
va_end(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wcsicmp(const wchar_t* w1, const wchar_t* w2) {
|
||||||
|
// I didn't find a way to put ignore case ...
|
||||||
|
return wcscmp(w1, w2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
static inline unsigned int timeGetTime() {
|
||||||
|
struct timeval now;
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
uint64_t ms = (now.tv_usec/1000) + (now.tv_sec * 1000);
|
||||||
|
return (ms & 0xFFFFFFFF); // MS code is u32 ...
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "Utilities/Dependencies.h"
|
||||||
|
#include "Utilities/StringHelpers.h"
|
||||||
|
#include "Utilities/Path.h"
|
||||||
|
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
|
extern Display *GSdsp;
|
||||||
|
extern Window GSwin;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define DIRECTINPUT_VERSION 0x0800
|
#define DIRECTINPUT_VERSION 0x0800
|
||||||
|
|
||||||
#ifdef NO_CRT
|
#ifdef NO_CRT
|
||||||
|
@ -40,9 +110,10 @@ inline void * realloc(void *mem, size_t size);
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define EXPORT_C_(type) extern "C" __declspec(dllexport) type CALLBACK
|
#define EXPORT_C_(type) extern "C" __declspec(dllexport) type CALLBACK
|
||||||
#else
|
#else
|
||||||
#define EXPORT_C_(type) extern "C" type
|
#define EXPORT_C_(type) extern "C" __attribute__((externally_visible,visibility("default"))) type CALLBACK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
// Actually works with 0x0400, but need 0x500 to get XBUTTON defines,
|
// Actually works with 0x0400, but need 0x500 to get XBUTTON defines,
|
||||||
// 0x501 to get raw input structures, and 0x0600 to get WM_MOUSEHWHEEL.
|
// 0x501 to get raw input structures, and 0x0600 to get WM_MOUSEHWHEEL.
|
||||||
#define WINVER 0x0600
|
#define WINVER 0x0600
|
||||||
|
@ -61,17 +132,28 @@ inline void * realloc(void *mem, size_t size);
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
// Only needed for DBT_DEVNODES_CHANGED
|
// Only needed for DBT_DEVNODES_CHANGED
|
||||||
#include <Dbt.h>
|
#include <Dbt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "PS2Edefs.h"
|
#include "PS2Edefs.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
extern HINSTANCE hInst;
|
extern HINSTANCE hInst;
|
||||||
|
#endif
|
||||||
// Needed for config screen
|
// Needed for config screen
|
||||||
void GetNameAndVersionString(wchar_t *out);
|
void GetNameAndVersionString(wchar_t *out);
|
||||||
|
|
||||||
|
@ -106,6 +188,7 @@ EXPORT_C_(void) PADconfigure();
|
||||||
EXPORT_C_(s32) PADfreeze(int mode, freezeData *data);
|
EXPORT_C_(s32) PADfreeze(int mode, freezeData *data);
|
||||||
EXPORT_C_(s32) PADsetSlot(u8 port, u8 slot);
|
EXPORT_C_(s32) PADsetSlot(u8 port, u8 slot);
|
||||||
EXPORT_C_(s32) PADqueryMtap(u8 port);
|
EXPORT_C_(s32) PADqueryMtap(u8 port);
|
||||||
|
EXPORT_C_(void) PADsetSettingsDir(const char *dir);
|
||||||
|
|
||||||
#ifdef NO_CRT
|
#ifdef NO_CRT
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,9 @@ Device::Device(DeviceAPI api, DeviceType d, const wchar_t *displayName, const wc
|
||||||
attached = 1;
|
attached = 1;
|
||||||
enabled = 0;
|
enabled = 0;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
hWndProc = 0;
|
hWndProc = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
virtualControls = 0;
|
virtualControls = 0;
|
||||||
numVirtualControls = 0;
|
numVirtualControls = 0;
|
||||||
|
@ -221,7 +223,11 @@ void Device::CalcVirtualState() {
|
||||||
double East = sin(angle);
|
double East = sin(angle);
|
||||||
double South = -cos(angle);
|
double South = -cos(angle);
|
||||||
// Normalize so greatest direction is 1.
|
// Normalize so greatest direction is 1.
|
||||||
|
#ifdef __linux__
|
||||||
|
double mul = FULLY_DOWN / std::max(fabs(South), fabs(East));
|
||||||
|
#else
|
||||||
double mul = FULLY_DOWN / max(fabs(South), fabs(East));
|
double mul = FULLY_DOWN / max(fabs(South), fabs(East));
|
||||||
|
#endif
|
||||||
iEast = (int) floor(East * mul + 0.5);
|
iEast = (int) floor(East * mul + 0.5);
|
||||||
iSouth = (int) floor(South * mul + 0.5);
|
iSouth = (int) floor(South * mul + 0.5);
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,9 @@ enum DeviceAPI {
|
||||||
// to ignore individual buttons. Wrapper itself takes care
|
// to ignore individual buttons. Wrapper itself takes care
|
||||||
// of ignoring bound keys. Otherwise, works normally.
|
// of ignoring bound keys. Otherwise, works normally.
|
||||||
IGNORE_KEYBOARD = 7,
|
IGNORE_KEYBOARD = 7,
|
||||||
|
// XXX
|
||||||
|
LNX_KEYBOARD = 16,
|
||||||
|
LNX_JOY = 17,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DeviceType {
|
enum DeviceType {
|
||||||
|
@ -196,12 +199,18 @@ struct InitInfo {
|
||||||
// 1 when binding.
|
// 1 when binding.
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
HWND hWndTop;
|
HWND hWndTop;
|
||||||
|
|
||||||
// For config screen, need to eat button's message handling.
|
// For config screen, need to eat button's message handling.
|
||||||
//HWND hWndButton;
|
//HWND hWndButton;
|
||||||
|
|
||||||
WndProcEater* hWndProc;
|
WndProcEater* hWndProc;
|
||||||
|
#else
|
||||||
|
// Linux equivalent to HWND
|
||||||
|
Display *GSdsp;
|
||||||
|
Window GSwin;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,9 +225,11 @@ public:
|
||||||
// Based on input modes.
|
// Based on input modes.
|
||||||
char enabled;
|
char enabled;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
// Not all devices need to subclass the windproc, but most do so might as well
|
// Not all devices need to subclass the windproc, but most do so might as well
|
||||||
// put it here... --air
|
// put it here... --air
|
||||||
WndProcEater* hWndProc;
|
WndProcEater* hWndProc;
|
||||||
|
#endif
|
||||||
|
|
||||||
union {
|
union {
|
||||||
// Allows for one loop to compare all 3 in order.
|
// Allows for one loop to compare all 3 in order.
|
||||||
|
|
|
@ -21,8 +21,12 @@
|
||||||
|
|
||||||
// What MS calls a single process Mutex. Faster, supposedly.
|
// What MS calls a single process Mutex. Faster, supposedly.
|
||||||
// More importantly, can be abbreviated, amusingly, as cSection.
|
// More importantly, can be abbreviated, amusingly, as cSection.
|
||||||
|
#ifdef _MSC_VER
|
||||||
static CRITICAL_SECTION cSection;
|
static CRITICAL_SECTION cSection;
|
||||||
static u8 csInitialized = 0;
|
static u8 csInitialized = 0;
|
||||||
|
#else
|
||||||
|
static std::mutex cSection;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define EVENT_QUEUE_LEN 16
|
#define EVENT_QUEUE_LEN 16
|
||||||
// Actually points one beyond the last queued event.
|
// Actually points one beyond the last queued event.
|
||||||
|
@ -31,11 +35,15 @@ static u8 nextQueuedEvent = 0;
|
||||||
static keyEvent queuedEvents[EVENT_QUEUE_LEN];
|
static keyEvent queuedEvents[EVENT_QUEUE_LEN];
|
||||||
|
|
||||||
void QueueKeyEvent(int key, int event) {
|
void QueueKeyEvent(int key, int event) {
|
||||||
|
#ifdef _MSC_VER
|
||||||
if (!csInitialized) {
|
if (!csInitialized) {
|
||||||
csInitialized = 1;
|
csInitialized = 1;
|
||||||
InitializeCriticalSection(&cSection);
|
InitializeCriticalSection(&cSection);
|
||||||
}
|
}
|
||||||
EnterCriticalSection(&cSection);
|
EnterCriticalSection(&cSection);
|
||||||
|
#else
|
||||||
|
std::lock_guard<std::mutex> lock(cSection);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Don't queue events if escape is on top of queue. This is just for safety
|
// Don't queue events if escape is on top of queue. This is just for safety
|
||||||
// purposes when a game is killing the emulator for whatever reason.
|
// purposes when a game is killing the emulator for whatever reason.
|
||||||
|
@ -57,23 +65,33 @@ void QueueKeyEvent(int key, int event) {
|
||||||
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
|
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef _MSC_VER
|
||||||
LeaveCriticalSection(&cSection);
|
LeaveCriticalSection(&cSection);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetQueuedKeyEvent(keyEvent *event) {
|
int GetQueuedKeyEvent(keyEvent *event) {
|
||||||
if (lastQueuedEvent == nextQueuedEvent) return 0;
|
if (lastQueuedEvent == nextQueuedEvent) return 0;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
EnterCriticalSection(&cSection);
|
EnterCriticalSection(&cSection);
|
||||||
|
#else
|
||||||
|
std::lock_guard<std::mutex> lock(cSection);
|
||||||
|
#endif
|
||||||
*event = queuedEvents[nextQueuedEvent];
|
*event = queuedEvents[nextQueuedEvent];
|
||||||
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
|
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
|
||||||
|
#ifdef _MSC_VER
|
||||||
LeaveCriticalSection(&cSection);
|
LeaveCriticalSection(&cSection);
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearKeyQueue() {
|
void ClearKeyQueue() {
|
||||||
lastQueuedEvent = nextQueuedEvent;
|
lastQueuedEvent = nextQueuedEvent;
|
||||||
|
#ifdef _MSC_VER
|
||||||
if (csInitialized) {
|
if (csInitialized) {
|
||||||
DeleteCriticalSection(&cSection);
|
DeleteCriticalSection(&cSection);
|
||||||
csInitialized = 0;
|
csInitialized = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,3 +24,9 @@ int GetQueuedKeyEvent(keyEvent *event);
|
||||||
|
|
||||||
// Cleans up as well as clears queue.
|
// Cleans up as well as clears queue.
|
||||||
void ClearKeyQueue();
|
void ClearKeyQueue();
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
void R_QueueKeyEvent(const keyEvent& event);
|
||||||
|
int R_GetQueuedKeyEvent(keyEvent *event);
|
||||||
|
void R_ClearKeyQueue();
|
||||||
|
#endif
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
#define PADdefs
|
#define PADdefs
|
||||||
|
|
||||||
#include "DeviceEnumerator.h"
|
#include "DeviceEnumerator.h"
|
||||||
|
#ifdef _MSC_VER
|
||||||
#include "WndProcEater.h"
|
#include "WndProcEater.h"
|
||||||
|
#endif
|
||||||
#include "KeyboardQueue.h"
|
#include "KeyboardQueue.h"
|
||||||
#include "svnrev.h"
|
#include "svnrev.h"
|
||||||
#include "DualShock3.h"
|
#include "DualShock3.h"
|
||||||
|
@ -39,6 +41,10 @@
|
||||||
// LilyPad version.
|
// LilyPad version.
|
||||||
#define VERSION ((0<<8) | 11 | (0<<24))
|
#define VERSION ((0<<8) | 11 | (0<<24))
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
Display *GSdsp;
|
||||||
|
Window GSwin;
|
||||||
|
#else
|
||||||
HINSTANCE hInst;
|
HINSTANCE hInst;
|
||||||
HWND hWnd;
|
HWND hWnd;
|
||||||
HWND hWndTop;
|
HWND hWndTop;
|
||||||
|
@ -49,10 +55,15 @@ WndProcEater hWndTopProc;
|
||||||
// ButtonProc is used mostly by the Config panel for eating the procedures of the
|
// ButtonProc is used mostly by the Config panel for eating the procedures of the
|
||||||
// button with keyboard focus.
|
// button with keyboard focus.
|
||||||
WndProcEater hWndButtonProc;
|
WndProcEater hWndButtonProc;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Keeps the various sources for Update polling (PADpoll, PADupdate, etc) from wreaking
|
// Keeps the various sources for Update polling (PADpoll, PADupdate, etc) from wreaking
|
||||||
// havoc on each other...
|
// havoc on each other...
|
||||||
|
#ifdef __linux__
|
||||||
|
static std::mutex updateLock;
|
||||||
|
#else
|
||||||
CRITICAL_SECTION updateLock;
|
CRITICAL_SECTION updateLock;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Used to toggle mouse listening.
|
// Used to toggle mouse listening.
|
||||||
u8 miceEnabled;
|
u8 miceEnabled;
|
||||||
|
@ -61,8 +72,10 @@ u8 miceEnabled;
|
||||||
int openCount = 0;
|
int openCount = 0;
|
||||||
|
|
||||||
int activeWindow = 0;
|
int activeWindow = 0;
|
||||||
|
#ifdef _MSC_VER
|
||||||
int windowThreadId = 0;
|
int windowThreadId = 0;
|
||||||
int updateQueued = 0;
|
int updateQueued = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
int bufSize = 0;
|
int bufSize = 0;
|
||||||
unsigned char outBuf[50];
|
unsigned char outBuf[50];
|
||||||
|
@ -74,6 +87,7 @@ unsigned char inBuf[50];
|
||||||
#define MODE_ANALOG 0x73
|
#define MODE_ANALOG 0x73
|
||||||
#define MODE_DS2_NATIVE 0x79
|
#define MODE_DS2_NATIVE 0x79
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
int IsWindowMaximized (HWND hWnd) {
|
int IsWindowMaximized (HWND hWnd) {
|
||||||
RECT rect;
|
RECT rect;
|
||||||
if (GetWindowRect(hWnd, &rect)) {
|
if (GetWindowRect(hWnd, &rect)) {
|
||||||
|
@ -92,8 +106,10 @@ int IsWindowMaximized (HWND hWnd) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void DEBUG_TEXT_OUT(const char *text) {
|
void DEBUG_TEXT_OUT(const char *text) {
|
||||||
|
#ifdef _MSC_VER
|
||||||
if (config.debug) {
|
if (config.debug) {
|
||||||
HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
|
HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
|
||||||
if (hFile != INVALID_HANDLE_VALUE) {
|
if (hFile != INVALID_HANDLE_VALUE) {
|
||||||
|
@ -102,9 +118,11 @@ void DEBUG_TEXT_OUT(const char *text) {
|
||||||
CloseHandle(hFile);;
|
CloseHandle(hFile);;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DEBUG_NEW_SET() {
|
void DEBUG_NEW_SET() {
|
||||||
|
#ifdef _MSC_VER
|
||||||
if (config.debug && bufSize>1) {
|
if (config.debug && bufSize>1) {
|
||||||
HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
|
HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
|
||||||
if (hFile != INVALID_HANDLE_VALUE) {
|
if (hFile != INVALID_HANDLE_VALUE) {
|
||||||
|
@ -132,6 +150,7 @@ void DEBUG_NEW_SET() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bufSize = 0;
|
bufSize = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DEBUG_IN(unsigned char c) {
|
inline void DEBUG_IN(unsigned char c) {
|
||||||
|
@ -289,6 +308,7 @@ void UpdateEnabledDevices(int updateList = 0) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, void* lpvReserved) {
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, void* lpvReserved) {
|
||||||
hInst = hInstance;
|
hInst = hInstance;
|
||||||
if (fdwReason == DLL_PROCESS_ATTACH) {
|
if (fdwReason == DLL_PROCESS_ATTACH) {
|
||||||
|
@ -306,6 +326,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, void* lpvReserved) {
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void AddForce(ButtonSum *sum, u8 cmd, int delta = 255) {
|
void AddForce(ButtonSum *sum, u8 cmd, int delta = 255) {
|
||||||
if (!delta) return;
|
if (!delta) return;
|
||||||
|
@ -400,7 +421,11 @@ void ProcessButtonBinding(Binding *b, ButtonSum *sum, int value) {
|
||||||
void CapSum(ButtonSum *sum) {
|
void CapSum(ButtonSum *sum) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<3; i++) {
|
for (i=0; i<3; i++) {
|
||||||
|
#ifdef __linux__
|
||||||
|
int div = std::max(abs(sum->sticks[i].horiz), abs(sum->sticks[i].vert));
|
||||||
|
#else
|
||||||
int div = max(abs(sum->sticks[i].horiz), abs(sum->sticks[i].vert));
|
int div = max(abs(sum->sticks[i].horiz), abs(sum->sticks[i].vert));
|
||||||
|
#endif
|
||||||
if (div > 255) {
|
if (div > 255) {
|
||||||
sum->sticks[i].horiz = sum->sticks[i].horiz * 255 / div;
|
sum->sticks[i].horiz = sum->sticks[i].horiz * 255 / div;
|
||||||
sum->sticks[i].vert = sum->sticks[i].vert * 255 / div;
|
sum->sticks[i].vert = sum->sticks[i].vert * 255 / div;
|
||||||
|
@ -423,6 +448,7 @@ char padReadKeyUpdated[4] = {0, 0, 0, 0};
|
||||||
#define LOCK_BUTTONS 4
|
#define LOCK_BUTTONS 4
|
||||||
#define LOCK_BOTH 1
|
#define LOCK_BOTH 1
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
struct EnterScopedSection
|
struct EnterScopedSection
|
||||||
{
|
{
|
||||||
CRITICAL_SECTION& m_cs;
|
CRITICAL_SECTION& m_cs;
|
||||||
|
@ -435,6 +461,7 @@ struct EnterScopedSection
|
||||||
LeaveCriticalSection( &m_cs );
|
LeaveCriticalSection( &m_cs );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
void Update(unsigned int port, unsigned int slot) {
|
void Update(unsigned int port, unsigned int slot) {
|
||||||
char *stateUpdated;
|
char *stateUpdated;
|
||||||
|
@ -452,12 +479,17 @@ void Update(unsigned int port, unsigned int slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock prior to timecheck code to avoid pesky race conditions.
|
// Lock prior to timecheck code to avoid pesky race conditions.
|
||||||
|
#ifdef __linux__
|
||||||
|
std::lock_guard<std::mutex> lock(updateLock);
|
||||||
|
#else
|
||||||
EnterScopedSection padlock( updateLock );
|
EnterScopedSection padlock( updateLock );
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned int LastCheck = 0;
|
static unsigned int LastCheck = 0;
|
||||||
unsigned int t = timeGetTime();
|
unsigned int t = timeGetTime();
|
||||||
if (t - LastCheck < 15 || !openCount) return;
|
if (t - LastCheck < 15 || !openCount) return;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
if (windowThreadId != GetCurrentThreadId()) {
|
if (windowThreadId != GetCurrentThreadId()) {
|
||||||
if (stateUpdated[0] < 0) {
|
if (stateUpdated[0] < 0) {
|
||||||
if (!updateQueued) {
|
if (!updateQueued) {
|
||||||
|
@ -470,6 +502,7 @@ void Update(unsigned int port, unsigned int slot) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LastCheck = t;
|
LastCheck = t;
|
||||||
|
|
||||||
|
@ -481,10 +514,15 @@ void Update(unsigned int port, unsigned int slot) {
|
||||||
for (i=0; i<8; i++) {
|
for (i=0; i<8; i++) {
|
||||||
s[i&1][i>>1] = pads[i&1][i>>1].lockedSum;
|
s[i&1][i>>1] = pads[i&1][i>>1].lockedSum;
|
||||||
}
|
}
|
||||||
|
#ifdef __linux__
|
||||||
|
InitInfo info = {
|
||||||
|
0, 0, GSdsp, GSwin
|
||||||
|
};
|
||||||
|
#else
|
||||||
InitInfo info = {
|
InitInfo info = {
|
||||||
0, 0, hWndTop, &hWndGSProc
|
0, 0, hWndTop, &hWndGSProc
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
dm->Update(&info);
|
dm->Update(&info);
|
||||||
static int turbo = 0;
|
static int turbo = 0;
|
||||||
turbo++;
|
turbo++;
|
||||||
|
@ -669,6 +707,7 @@ u32 CALLBACK PS2EgetLibVersion2(u32 type) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
// Used in about and config screens.
|
// Used in about and config screens.
|
||||||
void GetNameAndVersionString(wchar_t *out) {
|
void GetNameAndVersionString(wchar_t *out) {
|
||||||
#ifdef NO_CRT
|
#ifdef NO_CRT
|
||||||
|
@ -679,6 +718,7 @@ void GetNameAndVersionString(wchar_t *out) {
|
||||||
wsprintfW(out, L"LilyPad %i.%i.%i (%lld)", (VERSION>>8)&0xFF, VERSION&0xFF, (VERSION>>24)&0xFF, SVN_REV);
|
wsprintfW(out, L"LilyPad %i.%i.%i (%lld)", (VERSION>>8)&0xFF, VERSION&0xFF, (VERSION>>24)&0xFF, SVN_REV);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
char* CALLBACK PSEgetLibName() {
|
char* CALLBACK PSEgetLibName() {
|
||||||
#ifdef NO_CRT
|
#ifdef NO_CRT
|
||||||
|
@ -760,7 +800,9 @@ struct QueryInfo {
|
||||||
u8 response[42];
|
u8 response[42];
|
||||||
} query = {0,0,0,0, 0,0xFF, 0xF3};
|
} query = {0,0,0,0, 0,0xFF, 0xF3};
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
int saveStateIndex = 0;
|
int saveStateIndex = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
s32 CALLBACK PADinit(u32 flags) {
|
s32 CALLBACK PADinit(u32 flags) {
|
||||||
// Note: Won't load settings if already loaded.
|
// Note: Won't load settings if already loaded.
|
||||||
|
@ -773,7 +815,7 @@ s32 CALLBACK PADinit(u32 flags) {
|
||||||
return PADinit(2);
|
return PADinit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PCSX2_DEBUG
|
#if defined(PCSX2_DEBUG) && defined(_MSC_VER)
|
||||||
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
|
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
|
||||||
tmpFlag |= _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF;
|
tmpFlag |= _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF;
|
||||||
_CrtSetDbgFlag( tmpFlag );
|
_CrtSetDbgFlag( tmpFlag );
|
||||||
|
@ -790,6 +832,9 @@ s32 CALLBACK PADinit(u32 flags) {
|
||||||
query.lastByte = 1;
|
query.lastByte = 1;
|
||||||
query.numBytes = 0;
|
query.numBytes = 0;
|
||||||
ClearKeyQueue();
|
ClearKeyQueue();
|
||||||
|
#ifdef __linux__
|
||||||
|
R_ClearKeyQueue();
|
||||||
|
#endif
|
||||||
// Just in case, when resuming emulation.
|
// Just in case, when resuming emulation.
|
||||||
ReleaseModifierKeys();
|
ReleaseModifierKeys();
|
||||||
|
|
||||||
|
@ -836,6 +881,7 @@ static const u8 queryMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
static const u8 setNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A};
|
static const u8 setNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A};
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
// Implements a couple of the hacks that affect whatever top-level window
|
// Implements a couple of the hacks that affect whatever top-level window
|
||||||
// the GS viewport belongs to (title, screensaver)
|
// the GS viewport belongs to (title, screensaver)
|
||||||
ExtraWndProcResult TitleHackWndProc(HWND hWndTop, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
|
ExtraWndProcResult TitleHackWndProc(HWND hWndTop, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
|
||||||
|
@ -943,6 +989,7 @@ DWORD WINAPI MaximizeWindowThreadProc(void *lpParameter) {
|
||||||
keybd_event(VK_LMENU, MapVirtualKey(VK_LMENU, MAPVK_VK_TO_VSC), KEYEVENTF_KEYUP, 0);
|
keybd_event(VK_LMENU, MapVirtualKey(VK_LMENU, MAPVK_VK_TO_VSC), KEYEVENTF_KEYUP, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void CALLBACK PADconfigure() {
|
void CALLBACK PADconfigure() {
|
||||||
if (openCount) {
|
if (openCount) {
|
||||||
|
@ -951,7 +998,7 @@ void CALLBACK PADconfigure() {
|
||||||
Configure();
|
Configure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
DWORD WINAPI RenameWindowThreadProc(void *lpParameter) {
|
DWORD WINAPI RenameWindowThreadProc(void *lpParameter) {
|
||||||
wchar_t newTitle[200];
|
wchar_t newTitle[200];
|
||||||
if (hWndTop) {
|
if (hWndTop) {
|
||||||
|
@ -973,12 +1020,14 @@ void SaveStateChanged() {
|
||||||
if (hThread) CloseHandle(hThread);
|
if (hThread) CloseHandle(hThread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
s32 CALLBACK PADopen(void *pDsp) {
|
s32 CALLBACK PADopen(void *pDsp) {
|
||||||
if (openCount++) return 0;
|
if (openCount++) return 0;
|
||||||
DEBUG_TEXT_OUT("LilyPad opened\n\n");
|
DEBUG_TEXT_OUT("LilyPad opened\n\n");
|
||||||
|
|
||||||
miceEnabled = !config.mouseUnfocus;
|
miceEnabled = !config.mouseUnfocus;
|
||||||
|
#ifdef _MSC_VER
|
||||||
if (!hWnd) {
|
if (!hWnd) {
|
||||||
if (IsWindow((HWND)pDsp)) {
|
if (IsWindow((HWND)pDsp)) {
|
||||||
hWnd = (HWND) pDsp;
|
hWnd = (HWND) pDsp;
|
||||||
|
@ -1036,6 +1085,7 @@ s32 CALLBACK PADopen(void *pDsp) {
|
||||||
}
|
}
|
||||||
restoreFullScreen = 0;
|
restoreFullScreen = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
for (int port=0; port<2; port++) {
|
for (int port=0; port<2; port++) {
|
||||||
for (int slot=0; slot<4; slot++) {
|
for (int slot=0; slot<4; slot++) {
|
||||||
memset(&pads[port][slot].sum, 0, sizeof(pads[port][slot].sum));
|
memset(&pads[port][slot].sum, 0, sizeof(pads[port][slot].sum));
|
||||||
|
@ -1044,6 +1094,7 @@ s32 CALLBACK PADopen(void *pDsp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
// I'd really rather use this line, but GetActiveWindow() does not have complete specs.
|
// I'd really rather use this line, but GetActiveWindow() does not have complete specs.
|
||||||
// It *seems* to return null when no window from this thread has focus, but the
|
// It *seems* to return null when no window from this thread has focus, but the
|
||||||
// Microsoft specs seem to imply it returns the window from this thread that would have focus,
|
// Microsoft specs seem to imply it returns the window from this thread that would have focus,
|
||||||
|
@ -1052,6 +1103,11 @@ s32 CALLBACK PADopen(void *pDsp) {
|
||||||
// activeWindow = GetActiveWindow() == hWnd;
|
// activeWindow = GetActiveWindow() == hWnd;
|
||||||
|
|
||||||
// activeWindow = (GetAncestor(hWnd, GA_ROOT) == GetAncestor(GetForegroundWindow(), GA_ROOT));
|
// activeWindow = (GetAncestor(hWnd, GA_ROOT) == GetAncestor(GetForegroundWindow(), GA_ROOT));
|
||||||
|
#else
|
||||||
|
// Not used so far
|
||||||
|
GSdsp = *(Display**)pDsp;
|
||||||
|
GSwin = (Window)*(((uptr*)pDsp)+1);
|
||||||
|
#endif
|
||||||
activeWindow = 1;
|
activeWindow = 1;
|
||||||
UpdateEnabledDevices();
|
UpdateEnabledDevices();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1060,12 +1116,16 @@ s32 CALLBACK PADopen(void *pDsp) {
|
||||||
void CALLBACK PADclose() {
|
void CALLBACK PADclose() {
|
||||||
if (openCount && !--openCount) {
|
if (openCount && !--openCount) {
|
||||||
DEBUG_TEXT_OUT("LilyPad closed\n\n");
|
DEBUG_TEXT_OUT("LilyPad closed\n\n");
|
||||||
|
#ifdef _MSC_VER
|
||||||
updateQueued = 0;
|
updateQueued = 0;
|
||||||
hWndGSProc.Release();
|
hWndGSProc.Release();
|
||||||
hWndTopProc.Release();
|
hWndTopProc.Release();
|
||||||
dm->ReleaseInput();
|
dm->ReleaseInput();
|
||||||
hWnd = 0;
|
hWnd = 0;
|
||||||
hWndTop = 0;
|
hWndTop = 0;
|
||||||
|
#else
|
||||||
|
R_ClearKeyQueue();
|
||||||
|
#endif
|
||||||
ClearKeyQueue();
|
ClearKeyQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1363,6 +1423,7 @@ u32 CALLBACK PADquery() {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
INT_PTR CALLBACK AboutDialogProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
INT_PTR CALLBACK AboutDialogProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
if (uMsg == WM_INITDIALOG) {
|
if (uMsg == WM_INITDIALOG) {
|
||||||
wchar_t idString[100];
|
wchar_t idString[100];
|
||||||
|
@ -1375,10 +1436,13 @@ INT_PTR CALLBACK AboutDialogProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void CALLBACK PADabout() {
|
void CALLBACK PADabout() {
|
||||||
|
#ifdef _MSC_VER
|
||||||
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), 0, AboutDialogProc);
|
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), 0, AboutDialogProc);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 CALLBACK PADtest() {
|
s32 CALLBACK PADtest() {
|
||||||
|
@ -1395,11 +1459,12 @@ keyEvent* CALLBACK PADkeyEvent() {
|
||||||
eventCount = 0;
|
eventCount = 0;
|
||||||
|
|
||||||
Update(2, 0);
|
Update(2, 0);
|
||||||
static char shiftDown = 0;
|
|
||||||
static char altDown = 0;
|
|
||||||
static keyEvent ev;
|
static keyEvent ev;
|
||||||
if (!GetQueuedKeyEvent(&ev)) return 0;
|
if (!GetQueuedKeyEvent(&ev)) return 0;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
static char shiftDown = 0;
|
||||||
|
static char altDown = 0;
|
||||||
if (miceEnabled && (ev.key == VK_ESCAPE || (int)ev.key == -2) && ev.evt == KEYPRESS) {
|
if (miceEnabled && (ev.key == VK_ESCAPE || (int)ev.key == -2) && ev.evt == KEYPRESS) {
|
||||||
// Disable mouse/KB hooks on escape (before going into paused mode).
|
// Disable mouse/KB hooks on escape (before going into paused mode).
|
||||||
// This is a hack, since PADclose (which is called on pause) should enevtually also deactivate the
|
// This is a hack, since PADclose (which is called on pause) should enevtually also deactivate the
|
||||||
|
@ -1453,6 +1518,7 @@ keyEvent* CALLBACK PADkeyEvent() {
|
||||||
ev.key = VK_MENU;
|
ev.key = VK_MENU;
|
||||||
altDown = (ev.evt == KEYPRESS);
|
altDown = (ev.evt == KEYPRESS);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return &ev;
|
return &ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,514 @@
|
||||||
|
/* LilyPad - Pad plugin for PS2 Emulator
|
||||||
|
* Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Found- ation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
|
||||||
|
#include "InputManager.h"
|
||||||
|
#include "Config.h"
|
||||||
|
#include "DeviceEnumerator.h"
|
||||||
|
#include "Linux/ConfigHelper.h"
|
||||||
|
|
||||||
|
GeneralConfig config;
|
||||||
|
u8 ps2e = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
remove 0x10F0 to compute the cmd value
|
||||||
|
|
||||||
|
#define ID_SENSITIVITY 0x1007
|
||||||
|
#define ID_LOCK_BUTTONS 0x10FC
|
||||||
|
#define ID_LOCK 0x10FD
|
||||||
|
#define ID_LOCK_DIRECTION 0x10FE
|
||||||
|
#define ID_MOUSE 0x10FF
|
||||||
|
#define ID_SELECT 0x1100
|
||||||
|
#define ID_L3 0x1101
|
||||||
|
#define ID_R3 0x1102
|
||||||
|
#define ID_START 0x1103
|
||||||
|
#define ID_DPAD_UP 0x1104
|
||||||
|
#define ID_DPAD_RIGHT 0x1105
|
||||||
|
#define ID_DPAD_DOWN 0x1106
|
||||||
|
#define ID_DPAD_LEFT 0x1107
|
||||||
|
#define ID_L2 0x1108
|
||||||
|
#define ID_R2 0x1109
|
||||||
|
#define ID_L1 0x110A
|
||||||
|
#define ID_R1 0x110B
|
||||||
|
#define ID_TRIANGLE 0x110C
|
||||||
|
#define ID_CIRCLE 0x110D
|
||||||
|
#define ID_CROSS 0x110E
|
||||||
|
#define ID_SQUARE 0x110F
|
||||||
|
#define ID_LSTICK_UP 0x1110
|
||||||
|
#define ID_LSTICK_RIGHT 0x1111
|
||||||
|
#define ID_LSTICK_DOWN 0x1112
|
||||||
|
#define ID_LSTICK_LEFT 0x1113
|
||||||
|
#define ID_RSTICK_UP 0x1114
|
||||||
|
#define ID_RSTICK_RIGHT 0x1115
|
||||||
|
#define ID_RSTICK_DOWN 0x1116
|
||||||
|
#define ID_RSTICK_LEFT 0x1117
|
||||||
|
#define ID_ANALOG 0x1118
|
||||||
|
#define ID_DELETE 0x11FF
|
||||||
|
#define ID_DEBUG 0x1200
|
||||||
|
#define ID_IGNORE 0x1201
|
||||||
|
#define ID_CLEAR 0x1202
|
||||||
|
#define ID_REFRESH 0x1202
|
||||||
|
#define ID_SAVE 0x1204
|
||||||
|
#define ID_LOAD 0x1205
|
||||||
|
#define ID_BIG_MOTOR 0x120A
|
||||||
|
#define ID_SMALL_MOTOR 0x120B
|
||||||
|
#define ID_TEST 0x1300
|
||||||
|
#define ID_CONTROLS 0x1301
|
||||||
|
#define ID_FF 0x1304
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct GeneralSettingsBool {
|
||||||
|
const wchar_t *name;
|
||||||
|
unsigned int ControlId;
|
||||||
|
u8 defaultValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// XXX: I try to remove only gui stuff
|
||||||
|
void DeleteBinding(int port, int slot, Device *dev, Binding *b) {
|
||||||
|
fprintf(stderr, "delete binding %d:%d\n", port, slot);
|
||||||
|
Binding *bindings = dev->pads[port][slot].bindings;
|
||||||
|
int i = b - bindings;
|
||||||
|
memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[port][slot].numBindings - i - 1));
|
||||||
|
dev->pads[port][slot].numBindings--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteBinding(int port, int slot, Device *dev, ForceFeedbackBinding *b) {
|
||||||
|
ForceFeedbackBinding *bindings = dev->pads[port][slot].ffBindings;
|
||||||
|
int i = b - bindings;
|
||||||
|
memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[port][slot].numFFBindings - i - 1));
|
||||||
|
dev->pads[port][slot].numFFBindings--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo, int deadZone) {
|
||||||
|
// Checks needed because I use this directly when loading bindings.
|
||||||
|
if (port > 1 || slot>3) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!sensitivity) sensitivity = BASE_SENSITIVITY;
|
||||||
|
if ((uid>>16) & (PSHBTN|TGLBTN)) {
|
||||||
|
deadZone = 0;
|
||||||
|
}
|
||||||
|
else if (!deadZone) {
|
||||||
|
if ((uid>>16) & PRESSURE_BTN) {
|
||||||
|
deadZone = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
deadZone = DEFAULT_DEADZONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Relative axes can have negative sensitivity.
|
||||||
|
else if (((uid>>16) & 0xFF) == RELAXIS) {
|
||||||
|
sensitivity = abs(sensitivity);
|
||||||
|
}
|
||||||
|
VirtualControl *c = dev->GetVirtualControl(uid);
|
||||||
|
if (!c) return -1;
|
||||||
|
// Add before deleting. Means I won't scroll up one line when scrolled down to bottom.
|
||||||
|
int controlIndex = c - dev->virtualControls;
|
||||||
|
int index = 0;
|
||||||
|
PadBindings *p = dev->pads[port]+slot;
|
||||||
|
p->bindings = (Binding*) realloc(p->bindings, (p->numBindings+1) * sizeof(Binding));
|
||||||
|
for (index = p->numBindings; index > 0; index--) {
|
||||||
|
if (p->bindings[index-1].controlIndex < controlIndex) break;
|
||||||
|
p->bindings[index] = p->bindings[index-1];
|
||||||
|
}
|
||||||
|
Binding *b = p->bindings+index;
|
||||||
|
p->numBindings++;
|
||||||
|
b->command = command;
|
||||||
|
b->controlIndex = controlIndex;
|
||||||
|
b->turbo = turbo;
|
||||||
|
b->sensitivity = sensitivity;
|
||||||
|
b->deadZone = deadZone;
|
||||||
|
// Where it appears in listview.
|
||||||
|
//int count = ListBoundCommand(port, slot, dev, b);
|
||||||
|
|
||||||
|
int newBindingIndex = index;
|
||||||
|
index = 0;
|
||||||
|
while (index < p->numBindings) {
|
||||||
|
if (index == newBindingIndex) {
|
||||||
|
index ++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
b = p->bindings + index;
|
||||||
|
int nuke = 0;
|
||||||
|
if (config.multipleBinding) {
|
||||||
|
if (b->controlIndex == controlIndex && b->command == command)
|
||||||
|
nuke = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int uid2 = dev->virtualControls[b->controlIndex].uid;
|
||||||
|
if (b->controlIndex == controlIndex || (!((uid2^uid) & 0xFFFFFF) && ((uid|uid2) & (UID_POV | UID_AXIS))))
|
||||||
|
nuke = 1;
|
||||||
|
}
|
||||||
|
if (!nuke) {
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (index < newBindingIndex) {
|
||||||
|
newBindingIndex--;
|
||||||
|
//count --;
|
||||||
|
}
|
||||||
|
DeleteBinding(port, slot, dev, b);
|
||||||
|
}
|
||||||
|
if (!config.multipleBinding) {
|
||||||
|
for (int port2=0; port2<2; port2++) {
|
||||||
|
for (int slot2=0; slot2<4; slot2++) {
|
||||||
|
if (port2==port && slot2 == slot) continue;
|
||||||
|
PadBindings *p = dev->pads[port2]+slot2;
|
||||||
|
for (int i=0; i < p->numBindings; i++) {
|
||||||
|
Binding *b = p->bindings+i;
|
||||||
|
int uid2 = dev->virtualControls[b->controlIndex].uid;
|
||||||
|
if (b->controlIndex == controlIndex || (!((uid2^uid) & 0xFFFFFF) && ((uid|uid2) & (UID_POV | UID_AXIS)))) {
|
||||||
|
DeleteBinding(port2, slot2, dev, b);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//return count;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ties together config data structure, config files, and general config
|
||||||
|
// dialog.
|
||||||
|
const GeneralSettingsBool BoolOptionsInfo[] = {
|
||||||
|
{L"Force Cursor Hide", 0 /*IDC_FORCE_HIDE*/, 0},
|
||||||
|
{L"Mouse Unfocus", 0 /*IDC_MOUSE_UNFOCUS*/, 1},
|
||||||
|
{L"Background", 0 /*IDC_BACKGROUND*/, 1},
|
||||||
|
{L"Multiple Bindings", 0 /*IDC_MULTIPLE_BINDING*/, 0},
|
||||||
|
|
||||||
|
{L"DirectInput Game Devices", 0 /*IDC_G_DI*/, 1},
|
||||||
|
{L"XInput", 0 /*IDC_G_XI*/, 1},
|
||||||
|
{L"DualShock 3", 0 /*IDC_G_DS3*/, 0},
|
||||||
|
|
||||||
|
{L"Multitap 1", 0 /*IDC_MULTITAP1*/, 0},
|
||||||
|
{L"Multitap 2", 0 /*IDC_MULTITAP2*/, 0},
|
||||||
|
|
||||||
|
{L"Escape Fullscreen Hack", 0 /*IDC_ESCAPE_FULLSCREEN_HACK*/, 1},
|
||||||
|
{L"Disable Screen Saver", 0 /*IDC_DISABLE_SCREENSAVER*/, 1},
|
||||||
|
{L"Logging", 0 /*IDC_DEBUG_FILE*/, 0},
|
||||||
|
|
||||||
|
{L"Save State in Title", 0 /*IDC_SAVE_STATE_TITLE*/, 0}, //No longer required, PCSX2 now handles it - avih 2011-05-17
|
||||||
|
{L"GH2", 0 /*IDC_GH2_HACK*/, 0},
|
||||||
|
{L"Turbo Key Hack", 0 /*IDC_TURBO_KEY_HACK*/, 0},
|
||||||
|
|
||||||
|
{L"Vista Volume", 0 /*IDC_VISTA_VOLUME*/, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
void CALLBACK PADsetSettingsDir( const char *dir )
|
||||||
|
{
|
||||||
|
CfgHelper::SetSettingsDir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SaveSettings(wchar_t *file=0) {
|
||||||
|
CfgHelper cfg;
|
||||||
|
|
||||||
|
for (int i=0; i<sizeof(BoolOptionsInfo)/sizeof(BoolOptionsInfo[0]); i++) {
|
||||||
|
cfg.WriteBool(L"General Settings", BoolOptionsInfo[i].name, config.bools[i]);
|
||||||
|
}
|
||||||
|
cfg.WriteInt(L"General Settings", L"Close Hacks", config.closeHacks);
|
||||||
|
|
||||||
|
cfg.WriteInt(L"General Settings", L"Keyboard Mode", config.keyboardApi);
|
||||||
|
cfg.WriteInt(L"General Settings", L"Mouse Mode", config.mouseApi);
|
||||||
|
|
||||||
|
cfg.WriteInt(L"General Settings", L"Volume", config.volume);
|
||||||
|
|
||||||
|
for (int port=0; port<2; port++) {
|
||||||
|
for (int slot=0; slot<4; slot++) {
|
||||||
|
wchar_t temp[50];
|
||||||
|
wsprintf(temp, L"Pad %i %i", port, slot);
|
||||||
|
cfg.WriteInt(temp, L"Mode", config.padConfigs[port][slot].type);
|
||||||
|
cfg.WriteInt(temp, L"Auto Analog", config.padConfigs[port][slot].autoAnalog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dm)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (int i=0; i<dm->numDevices; i++) {
|
||||||
|
wchar_t id[50];
|
||||||
|
wchar_t temp[50], temp2[1000];
|
||||||
|
wsprintfW(id, L"Device %i", i);
|
||||||
|
Device *dev = dm->devices[i];
|
||||||
|
wchar_t *name = dev->displayName;
|
||||||
|
while (name[0] == '[') {
|
||||||
|
wchar_t *name2 = wcschr(name, ']');
|
||||||
|
if (!name2) break;
|
||||||
|
name = name2+1;
|
||||||
|
while (iswspace(name[0])) name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.WriteStr(id, L"Display Name", name);
|
||||||
|
cfg.WriteStr(id, L"Instance ID", dev->instanceID);
|
||||||
|
if (dev->productID) {
|
||||||
|
cfg.WriteStr(id, L"Product ID", dev->productID);
|
||||||
|
}
|
||||||
|
cfg.WriteInt(id, L"API", dev->api);
|
||||||
|
cfg.WriteInt(id, L"Type", dev->type);
|
||||||
|
int ffBindingCount = 0;
|
||||||
|
int bindingCount = 0;
|
||||||
|
for (int port=0; port<2; port++) {
|
||||||
|
for (int slot=0; slot<4; slot++) {
|
||||||
|
for (int j=0; j<dev->pads[port][slot].numBindings; j++) {
|
||||||
|
Binding *b = dev->pads[port][slot].bindings+j;
|
||||||
|
VirtualControl *c = &dev->virtualControls[b->controlIndex];
|
||||||
|
wsprintfW(temp, L"Binding %i", bindingCount++);
|
||||||
|
wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot, b->deadZone);
|
||||||
|
cfg.WriteStr(id, temp, temp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j=0; j<dev->pads[port][slot].numFFBindings; j++) {
|
||||||
|
ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings+j;
|
||||||
|
ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex];
|
||||||
|
wsprintfW(temp, L"FF Binding %i", ffBindingCount++);
|
||||||
|
wsprintfW(temp2, L"%s %i, %i, %i", eff->effectID, port, b->motor, slot);
|
||||||
|
for (int k=0; k<dev->numFFAxes; k++) {
|
||||||
|
ForceFeedbackAxis *axis = dev->ffAxes + k;
|
||||||
|
AxisEffectInfo *info = b->axes + k;
|
||||||
|
//wsprintfW(wcschr(temp2,0), L", %i, %i", axis->id, info->force);
|
||||||
|
// Not secure because I'm too lazy to compute the remaining size
|
||||||
|
wprintf(wcschr(temp2, 0), L", %i, %i", axis->id, info->force);
|
||||||
|
}
|
||||||
|
cfg.WriteStr(id, temp, temp2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LoadSettings(int force, wchar_t *file) {
|
||||||
|
if (dm && !force) return 0;
|
||||||
|
|
||||||
|
// Could just do ClearDevices() instead, but if I ever add any extra stuff,
|
||||||
|
// this will still work.
|
||||||
|
UnloadConfigs();
|
||||||
|
dm = new InputDeviceManager();
|
||||||
|
|
||||||
|
CfgHelper cfg;
|
||||||
|
|
||||||
|
for (int i=0; i<sizeof(BoolOptionsInfo)/sizeof(BoolOptionsInfo[0]); i++) {
|
||||||
|
config.bools[i] = cfg.ReadBool(L"General Settings", BoolOptionsInfo[i].name, BoolOptionsInfo[i].defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
config.closeHacks = (u8)cfg.ReadInt(L"General Settings", L"Close Hacks");
|
||||||
|
if (config.closeHacks&1) config.closeHacks &= ~2;
|
||||||
|
|
||||||
|
config.keyboardApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Keyboard Mode", LNX_KEYBOARD);
|
||||||
|
if (!config.keyboardApi) config.keyboardApi = LNX_KEYBOARD;
|
||||||
|
config.mouseApi = (DeviceAPI) cfg.ReadInt(L"General Settings", L"Mouse Mode");
|
||||||
|
|
||||||
|
config.volume = cfg.ReadInt(L"General Settings", L"Volume", 100);
|
||||||
|
|
||||||
|
for (int port=0; port<2; port++) {
|
||||||
|
for (int slot=0; slot<4; slot++) {
|
||||||
|
wchar_t temp[50];
|
||||||
|
wsprintf(temp, L"Pad %i %i", port, slot);
|
||||||
|
config.padConfigs[port][slot].type = (PadType) cfg.ReadInt(temp, L"Mode", Dualshock2Pad);
|
||||||
|
config.padConfigs[port][slot].autoAnalog = cfg.ReadBool(temp, L"Auto Analog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
int multipleBinding = config.multipleBinding;
|
||||||
|
// Disabling multiple binding only prevents new multiple bindings.
|
||||||
|
config.multipleBinding = 1;
|
||||||
|
while (1) {
|
||||||
|
wchar_t id[50];
|
||||||
|
wchar_t temp[50], temp2[1000], temp3[1000], temp4[1000];
|
||||||
|
wsprintfW(id, L"Device %i", i++);
|
||||||
|
if (!cfg.ReadStr(id, L"Display Name", temp2) || !temp2[0] ||
|
||||||
|
!cfg.ReadStr(id, L"Instance ID", temp3) || !temp3[0]) {
|
||||||
|
if (i >= 100) break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wchar_t *id2 = 0;
|
||||||
|
if (cfg.ReadStr(id, L"Product ID", temp4) && temp4[0])
|
||||||
|
id2 = temp4;
|
||||||
|
|
||||||
|
int api = cfg.ReadInt(id, L"API");
|
||||||
|
int type = cfg.ReadInt(id, L"Type");
|
||||||
|
if (!api || !type) continue;
|
||||||
|
|
||||||
|
Device *dev = new Device((DeviceAPI)api, (DeviceType)type, temp2, temp3, id2);
|
||||||
|
dev->attached = 0;
|
||||||
|
dm->AddDevice(dev);
|
||||||
|
int j = 0;
|
||||||
|
int last = 0;
|
||||||
|
while (1) {
|
||||||
|
wsprintfW(temp, L"Binding %i", j++);
|
||||||
|
if (!cfg.ReadStr(id, temp, temp2)) {
|
||||||
|
if (j >= 100) {
|
||||||
|
if (!last) break;
|
||||||
|
last = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
last = 1;
|
||||||
|
unsigned int uid;
|
||||||
|
int port, command, sensitivity, turbo, slot = 0, deadZone = 0;
|
||||||
|
int w = 0;
|
||||||
|
char string[1000];
|
||||||
|
while (temp2[w]) {
|
||||||
|
string[w] = (char)temp2[w];
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
string[w] = 0;
|
||||||
|
int len = sscanf(string, " %i , %i , %i , %i , %i , %i , %i", &uid, &port, &command, &sensitivity, &turbo, &slot, &deadZone);
|
||||||
|
if (len >= 5 && type) {
|
||||||
|
VirtualControl *c = dev->GetVirtualControl(uid);
|
||||||
|
if (!c) c = dev->AddVirtualControl(uid, -1);
|
||||||
|
if (c) {
|
||||||
|
BindCommand(dev, uid, port, slot, command, sensitivity, turbo, deadZone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
j = 0;
|
||||||
|
while (1) {
|
||||||
|
wsprintfW(temp, L"FF Binding %i", j++);
|
||||||
|
if (!cfg.ReadStr(id, temp, temp2)) {
|
||||||
|
if (j >= 10) {
|
||||||
|
if (!last) break;
|
||||||
|
last = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
last = 1;
|
||||||
|
int port, slot, motor;
|
||||||
|
int w = 0;
|
||||||
|
char string[1000];
|
||||||
|
char effect[1000];
|
||||||
|
while (temp2[w]) {
|
||||||
|
string[w] = (char)temp2[w];
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
string[w] = 0;
|
||||||
|
// wcstok not in ntdll. More effore than its worth to shave off
|
||||||
|
// whitespace without it.
|
||||||
|
if (sscanf(string, " %s %i , %i , %i", effect, &port, &motor, &slot) == 4) {
|
||||||
|
char *s = strchr(strchr(strchr(string, ',')+1, ',')+1, ',');
|
||||||
|
if (!s) continue;
|
||||||
|
s++;
|
||||||
|
w = 0;
|
||||||
|
while (effect[w]) {
|
||||||
|
temp2[w] = effect[w];
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
temp2[w] = 0;
|
||||||
|
ForceFeedbackEffectType *eff = dev->GetForcefeedbackEffect(temp2);
|
||||||
|
if (!eff) {
|
||||||
|
// At the moment, don't record effect types.
|
||||||
|
// Only used internally, anyways, so not an issue.
|
||||||
|
dev->AddFFEffectType(temp2, temp2, EFFECT_CONSTANT);
|
||||||
|
// eff = &dev->ffEffectTypes[dev->numFFEffectTypes-1];
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
ForceFeedbackBinding *b;
|
||||||
|
CreateEffectBinding(dev, temp2, port, slot, motor, &b);
|
||||||
|
if (b) {
|
||||||
|
while (1) {
|
||||||
|
int axisID = atoi(s);
|
||||||
|
if (!(s = strchr(s, ','))) break;
|
||||||
|
s++;
|
||||||
|
int force = atoi(s);
|
||||||
|
int i;
|
||||||
|
for (i=0; i<dev->numFFAxes; i++) {
|
||||||
|
if (axisID == dev->ffAxes[i].id) break;
|
||||||
|
}
|
||||||
|
if (i == dev->numFFAxes) {
|
||||||
|
dev->AddFFAxis(L"?", axisID);
|
||||||
|
}
|
||||||
|
b->axes[i].force = force;
|
||||||
|
if (!(s = strchr(s, ','))) break;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.multipleBinding = multipleBinding;
|
||||||
|
|
||||||
|
//TODO RefreshEnabledDevicesAndDisplay(1);
|
||||||
|
RefreshEnabledDevices(1); // XXX For the moment only a subfonction
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadConfigs() {
|
||||||
|
if (dm) {
|
||||||
|
delete dm;
|
||||||
|
dm = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshEnabledDevices(int updateDeviceList) {
|
||||||
|
// Clears all device state.
|
||||||
|
static int lastXInputState = -1;
|
||||||
|
if (updateDeviceList || lastXInputState != config.gameApis.xInput) {
|
||||||
|
EnumDevices(config.gameApis.xInput);
|
||||||
|
lastXInputState = config.gameApis.xInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<dm->numDevices; i++) {
|
||||||
|
Device *dev = dm->devices[i];
|
||||||
|
|
||||||
|
// XXX windows magic?
|
||||||
|
if (!dev->attached && dev->displayName[0] != '[') {
|
||||||
|
wchar_t *newName = (wchar_t*) malloc(sizeof(wchar_t) * (wcslen(dev->displayName) + 12));
|
||||||
|
wsprintfW(newName, L"[Detached] %s", dev->displayName);
|
||||||
|
free(dev->displayName);
|
||||||
|
dev->displayName = newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
dm->EnableDevice(i);
|
||||||
|
#if 0 // windows magic?
|
||||||
|
if ((dev->type == KEYBOARD && dev->api == IGNORE_KEYBOARD) ||
|
||||||
|
(dev->type == KEYBOARD && dev->api == config.keyboardApi) ||
|
||||||
|
(dev->type == MOUSE && dev->api == config.mouseApi) ||
|
||||||
|
(dev->type == OTHER &&
|
||||||
|
((dev->api == DI && config.gameApis.directInput) ||
|
||||||
|
(dev->api == DS3 && config.gameApis.dualShock3) ||
|
||||||
|
(dev->api == XINPUT && config.gameApis.xInput)))) {
|
||||||
|
dm->EnableDevice(i);
|
||||||
|
if (config.gameApis.dualShock3 && dev->api == DI && dev->displayName &&
|
||||||
|
!wcsicmp(dev->displayName, L"DX PLAYSTATION(R)3 Controller")) {
|
||||||
|
dm->DisableDevice(i);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dm->EnableDevice(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dm->DisableDevice(i);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Configure() {
|
||||||
|
// Can end up here without PADinit() being called first.
|
||||||
|
LoadSettings();
|
||||||
|
// Can also end up here after running emulator a bit, and possibly
|
||||||
|
// disabling some devices due to focus changes, or releasing mouse.
|
||||||
|
RefreshEnabledDevices(0);
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/* LilyPad - Pad plugin for PS2 Emulator
|
||||||
|
* Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* File imported from SPU2-X (and tranformed to object)
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Found- ation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Linux/ConfigHelper.h"
|
||||||
|
#include <wx/fileconf.h>
|
||||||
|
|
||||||
|
wxString CfgHelper::m_path = L"inis/LilyPad.ini";
|
||||||
|
|
||||||
|
void CfgHelper::SetSettingsDir(const char* dir)
|
||||||
|
{
|
||||||
|
m_path = wxString::FromAscii(dir) + L"/LilyPad.ini";
|
||||||
|
}
|
||||||
|
|
||||||
|
CfgHelper::CfgHelper()
|
||||||
|
{
|
||||||
|
m_config = new wxFileConfig(L"", L"", m_path, L"", wxCONFIG_USE_LOCAL_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CfgHelper::~CfgHelper()
|
||||||
|
{
|
||||||
|
delete m_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CfgHelper::setIni(const wchar_t* Section)
|
||||||
|
{
|
||||||
|
m_config->SetPath(wxsFormat(L"/%s", Section));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CfgHelper::WriteBool(const wchar_t* Section, const wchar_t* Name, bool Value)
|
||||||
|
{
|
||||||
|
setIni(Section);
|
||||||
|
m_config->Write(Name, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CfgHelper::WriteInt(const wchar_t* Section, const wchar_t* Name, int Value)
|
||||||
|
{
|
||||||
|
setIni(Section);
|
||||||
|
m_config->Write(Name, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CfgHelper::WriteFloat(const wchar_t* Section, const wchar_t* Name, float Value)
|
||||||
|
{
|
||||||
|
setIni(Section);
|
||||||
|
m_config->Write(Name, (double)Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CfgHelper::WriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data)
|
||||||
|
{
|
||||||
|
setIni(Section);
|
||||||
|
m_config->Write(Name, Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CfgHelper::ReadBool(const wchar_t *Section,const wchar_t* Name, bool Default)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
setIni(Section);
|
||||||
|
m_config->Read(Name, &ret, Default);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CfgHelper::ReadInt(const wchar_t* Section, const wchar_t* Name,int Default)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
setIni(Section);
|
||||||
|
m_config->Read(Name, &ret, Default);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CfgHelper::ReadFloat(const wchar_t* Section, const wchar_t* Name, float Default)
|
||||||
|
{
|
||||||
|
double ret;
|
||||||
|
|
||||||
|
setIni(Section);
|
||||||
|
m_config->Read(Name, &ret, (double)Default);
|
||||||
|
|
||||||
|
return (float)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CfgHelper::ReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, const wchar_t* Default)
|
||||||
|
{
|
||||||
|
setIni(Section);
|
||||||
|
wcscpy(Data, m_config->Read(Name, Default).wc_str());
|
||||||
|
return wcslen(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CfgHelper::ReadStr(const wchar_t* Section, const wchar_t* Name, wxString& Data, const wchar_t* Default)
|
||||||
|
{
|
||||||
|
setIni(Section);
|
||||||
|
Data = m_config->Read(Name, Default);
|
||||||
|
return Data.size();
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* LilyPad - Pad plugin for PS2 Emulator
|
||||||
|
* Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* File imported from SPU2-X (and tranformed to object)
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Found- ation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
#include <wx/fileconf.h>
|
||||||
|
|
||||||
|
extern void CfgSetSettingsDir(const char* dir);
|
||||||
|
|
||||||
|
class CfgHelper {
|
||||||
|
wxFileConfig* m_config;
|
||||||
|
static wxString m_path;
|
||||||
|
|
||||||
|
void setIni(const wchar_t* Section);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CfgHelper();
|
||||||
|
~CfgHelper();
|
||||||
|
|
||||||
|
void WriteBool(const wchar_t* Section, const wchar_t* Name, bool Value);
|
||||||
|
void WriteInt(const wchar_t* Section, const wchar_t* Name, int Value);
|
||||||
|
void WriteFloat(const wchar_t* Section, const wchar_t* Name, float Value);
|
||||||
|
void WriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data);
|
||||||
|
|
||||||
|
bool ReadBool(const wchar_t *Section,const wchar_t* Name, bool Default = false);
|
||||||
|
int ReadStr(const wchar_t* Section, const wchar_t* Name, wxString& Data, const wchar_t* Default = 0);
|
||||||
|
int ReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, const wchar_t* Default = 0);
|
||||||
|
int ReadInt(const wchar_t* Section, const wchar_t* Name,int Default = 0);
|
||||||
|
float ReadFloat(const wchar_t* Section, const wchar_t* Name, float Default = 0.0f);
|
||||||
|
|
||||||
|
static void SetSettingsDir(const char* dir);
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,208 @@
|
||||||
|
/* LilyPad - Pad plugin for PS2 Emulator
|
||||||
|
* Copyright (C) 2002-2015 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Found- ation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
#include "InputManager.h"
|
||||||
|
#include "Linux/JoyEvdev.h"
|
||||||
|
#include "Linux/bitmaskros.h"
|
||||||
|
|
||||||
|
JoyEvdev::JoyEvdev(int fd, bool ds3, const wchar_t *id) : Device(LNX_JOY, OTHER, id, id), m_fd(fd) {
|
||||||
|
// XXX LNX_JOY => DS3 or ???
|
||||||
|
|
||||||
|
m_abs.clear();
|
||||||
|
m_btn.clear();
|
||||||
|
m_rel.clear();
|
||||||
|
int last = 0;
|
||||||
|
|
||||||
|
uint8_t abs_bitmap[nUcharsForNBits(ABS_CNT)] = {0};
|
||||||
|
uint8_t btn_bitmap[nUcharsForNBits(KEY_CNT)] = {0};
|
||||||
|
uint8_t rel_bitmap[nUcharsForNBits(REL_CNT)] = {0};
|
||||||
|
|
||||||
|
// Add buttons
|
||||||
|
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(btn_bitmap)), btn_bitmap) >= 0) {
|
||||||
|
for (int bit = BTN_MISC; bit < KEY_CNT; bit++) {
|
||||||
|
if (testBit(bit, btn_bitmap)) {
|
||||||
|
AddPhysicalControl(PSHBTN, last, 0);
|
||||||
|
m_btn.push_back(bit);
|
||||||
|
last++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Absolute axis
|
||||||
|
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmap)), abs_bitmap) >= 0) {
|
||||||
|
for (int bit = 0; bit < ABS_CNT; bit++) {
|
||||||
|
ControlType type = ABSAXIS; // FIXME DS3
|
||||||
|
|
||||||
|
if (testBit(bit, abs_bitmap)) {
|
||||||
|
input_absinfo info;
|
||||||
|
if (ioctl(m_fd, EVIOCGABS(bit), &info) < 0) {
|
||||||
|
fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddPhysicalControl(ABSAXIS, last, 0);
|
||||||
|
last++;
|
||||||
|
if (std::abs(info.value - 127) < 2) {
|
||||||
|
fprintf(stderr, "HALF Axis info %d=>%d, current %d, flat %d, resolution %d\n", info.minimum, info.maximum, info.value, info.flat, info.resolution);
|
||||||
|
|
||||||
|
// Half axis must be split into 2 parts...
|
||||||
|
AddPhysicalControl(ABSAXIS, last, 0);
|
||||||
|
last++;
|
||||||
|
|
||||||
|
m_abs.push_back(abs_info(bit, info.minimum, info.value, type));
|
||||||
|
m_abs.push_back(abs_info(bit, info.value, info.maximum, type));
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "FULL Axis info %d=>%d, current %d, flat %d, resolution %d\n", info.minimum, info.maximum, info.value, info.flat, info.resolution);
|
||||||
|
|
||||||
|
m_abs.push_back(abs_info(bit, info.minimum, info.maximum, type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add relative axis
|
||||||
|
if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmap)), rel_bitmap) >= 0) {
|
||||||
|
for (int bit = 0; bit < REL_CNT; bit++) {
|
||||||
|
if (testBit(bit, rel_bitmap)) {
|
||||||
|
AddPhysicalControl(RELAXIS, last, last);
|
||||||
|
m_rel.push_back(bit);
|
||||||
|
last++;
|
||||||
|
|
||||||
|
fprintf(stderr, "Add relative nb %d\n", bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "New device created. Found axe:%d, buttons:%d, m_rel:%d\n\n", m_abs.size(), m_btn.size(), m_rel.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
JoyEvdev::~JoyEvdev() {
|
||||||
|
close(m_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int JoyEvdev::Activate(InitInfo* args) {
|
||||||
|
AllocState();
|
||||||
|
|
||||||
|
uint16_t size = m_abs.size()+m_rel.size()+m_btn.size();
|
||||||
|
memset(physicalControlState, 0, sizeof(int)*size);
|
||||||
|
|
||||||
|
active = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JoyEvdev::Update() {
|
||||||
|
struct input_event events[32];
|
||||||
|
int len;
|
||||||
|
int status = 0;
|
||||||
|
//fprintf(stderr, "Update was called\n");
|
||||||
|
|
||||||
|
// Do a big read to reduce kernel validation
|
||||||
|
while ((len = read(m_fd, events, (sizeof events))) > 0) {
|
||||||
|
int evt_nb = len / sizeof(input_event);
|
||||||
|
//fprintf(stderr, "Poll %d events available\n", evt_nb);
|
||||||
|
for (int i = 0; i < evt_nb; i++) {
|
||||||
|
switch(events[i].type) {
|
||||||
|
case EV_ABS:
|
||||||
|
{
|
||||||
|
for (size_t idx = 0; idx < m_abs.size(); idx++) {
|
||||||
|
if (m_abs[idx].code == events[i].code) {
|
||||||
|
// XXX strict or not ?
|
||||||
|
if ((events[i].value >= m_abs[idx].min) && (events[i].value <= m_abs[idx].max)) {
|
||||||
|
// XXX FIX shitty api
|
||||||
|
int scale = m_abs[idx].scale(events[i].value);
|
||||||
|
fprintf(stderr, "axis value %d scaled to %d\n", events[i].value, scale);
|
||||||
|
physicalControlState[idx + m_btn.size()] = scale;
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EV_KEY:
|
||||||
|
{
|
||||||
|
for (size_t idx = 0; idx < m_btn.size(); idx++) {
|
||||||
|
if (m_btn[idx] == events[i].code) {
|
||||||
|
fprintf(stderr, "Event KEY:%d detected with value %d\n", events[i].code, events[i].value);
|
||||||
|
physicalControlState[idx] = FULLY_DOWN * events[i].value;
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EV_REL:
|
||||||
|
// XXX
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static std::wstring CorrectJoySupport(int fd) {
|
||||||
|
struct input_id id;
|
||||||
|
if (ioctl(fd, EVIOCGID, &id) < 0) {
|
||||||
|
fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
char dev_name[128];
|
||||||
|
if (ioctl(fd, EVIOCGNAME(128), dev_name) < 0) {
|
||||||
|
fprintf(stderr, "Invalid IOCTL EVIOCGNAME\n");
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Found input device => bustype:%x, vendor:%x, product:%x, version:%x\n", id.bustype, id.vendor, id.product, id.version);
|
||||||
|
fprintf(stderr, "\tName:%s\n", dev_name);
|
||||||
|
|
||||||
|
std::string s(dev_name);
|
||||||
|
return std::wstring(s.begin(), s.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumJoystickEvdev() {
|
||||||
|
// Technically it must be done with udev but another lib for
|
||||||
|
// avoid a loop is too much for me (even if udev is mandatory
|
||||||
|
// so maybe later)
|
||||||
|
int found_devices = 0;
|
||||||
|
std::string input_root("/dev/input/event");
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
std::string dev = input_root + std::to_string(i);
|
||||||
|
|
||||||
|
int fd = open(dev.c_str(), O_RDWR | O_NONBLOCK);
|
||||||
|
if (fd < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring id = CorrectJoySupport(fd);
|
||||||
|
if (id.size() != 0) {
|
||||||
|
bool ds3 = id.find(L"PLAYSTATION(R)3") != std::string::npos;
|
||||||
|
if (ds3) {
|
||||||
|
fprintf(stderr, "DS3 device detected !!!\n");
|
||||||
|
}
|
||||||
|
dm->AddDevice(new JoyEvdev(fd, ds3, id.c_str()));
|
||||||
|
} else if (fd >= 0)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* LilyPad - Pad plugin for PS2 Emulator
|
||||||
|
* Copyright (C) 2002-2015 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Found- ation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
#include "InputManager.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
struct abs_info {
|
||||||
|
uint16_t code;
|
||||||
|
int32_t min;
|
||||||
|
int32_t max;
|
||||||
|
|
||||||
|
int32_t factor;
|
||||||
|
int32_t translation;
|
||||||
|
|
||||||
|
abs_info(int32_t _code, int32_t _min, int32_t _max, ControlType type) : code(_code), min(_min), max(_max) {
|
||||||
|
translation = 0;
|
||||||
|
// Note: ABSAXIS ranges from -64K to 64K
|
||||||
|
// Note: PSHBTN ranges from 0 to 64K
|
||||||
|
if ((min == 0) && (max == 255)) {
|
||||||
|
if (type == ABSAXIS) {
|
||||||
|
translation = 128;
|
||||||
|
factor = FULLY_DOWN/128;
|
||||||
|
} else {
|
||||||
|
factor = FULLY_DOWN/256;
|
||||||
|
}
|
||||||
|
} else if ((min == -1) && (max == 1)) {
|
||||||
|
factor = FULLY_DOWN;
|
||||||
|
} else if ((min == 0) && (std::abs(max - 127) < 2)) {
|
||||||
|
translation = 64;
|
||||||
|
factor = -FULLY_DOWN/64;
|
||||||
|
} else if ((max == 255) && (std::abs(min - 127) < 2)) {
|
||||||
|
translation = 64+128;
|
||||||
|
factor = FULLY_DOWN/64;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Scale not supported\n");
|
||||||
|
factor = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int scale(int32_t value) {
|
||||||
|
return (value - translation) * factor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JoyEvdev : public Device {
|
||||||
|
int m_fd;
|
||||||
|
std::vector<abs_info> m_abs;
|
||||||
|
std::vector<uint16_t> m_btn;
|
||||||
|
std::vector<uint16_t> m_rel;
|
||||||
|
|
||||||
|
public:
|
||||||
|
JoyEvdev(int fd, bool ds3, const wchar_t *id);
|
||||||
|
~JoyEvdev();
|
||||||
|
int Activate(InitInfo* args);
|
||||||
|
int Update();
|
||||||
|
};
|
||||||
|
|
||||||
|
void EnumJoystickEvdev();
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* LilyPad - Pad plugin for PS2 Emulator
|
||||||
|
* Copyright (C) 2002-2015 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Found- ation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Linux/KeyboardMouse.h"
|
||||||
|
|
||||||
|
// actually it is even more but it is enough to distinguish different key
|
||||||
|
#define MAX_KEYCODE (0xFF)
|
||||||
|
|
||||||
|
LinuxKeyboard::LinuxKeyboard() :
|
||||||
|
Device(LNX_KEYBOARD, KEYBOARD, L"displayName", L"instanceID", L"deviceID")
|
||||||
|
{
|
||||||
|
for (int i=0; i<MAX_KEYCODE; i++) {
|
||||||
|
AddPhysicalControl(PSHBTN, i, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinuxKeyboard::Activate(InitInfo* args) {
|
||||||
|
// Always active
|
||||||
|
active = 1;
|
||||||
|
|
||||||
|
AllocState();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (int vkey=5; vkey<256; vkey++) {
|
||||||
|
int value = (unsigned short)(((short)GetAsyncKeyState(vkey))>>15);
|
||||||
|
value += value&1;
|
||||||
|
if (vkey == VK_CONTROL || vkey == VK_MENU || vkey == VK_SHIFT) {
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
physicalControlState[vkey] = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Every button released
|
||||||
|
memset(physicalControlState, 0, sizeof(int)*MAX_KEYCODE);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinuxKeyboard::Update() {
|
||||||
|
keyEvent event;
|
||||||
|
int status = 0;
|
||||||
|
while (R_GetQueuedKeyEvent(&event)) {
|
||||||
|
switch (event.evt) {
|
||||||
|
case KeyPress:
|
||||||
|
physicalControlState[MAX_KEYCODE & event.key] = FULLY_DOWN;
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
case KeyRelease:
|
||||||
|
physicalControlState[MAX_KEYCODE & event.key] = 0;
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//fprintf(stderr, "Unsupported event %x\n", event.evt);
|
||||||
|
//assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status; // XXX ????
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumLnx() {
|
||||||
|
dm->AddDevice(new LinuxKeyboard());
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* LilyPad - Pad plugin for PS2 Emulator
|
||||||
|
* Copyright (C) 2002-2015 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Found- ation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
#include "InputManager.h"
|
||||||
|
#include "KeyboardQueue.h"
|
||||||
|
|
||||||
|
class LinuxKeyboard : public Device {
|
||||||
|
public:
|
||||||
|
LinuxKeyboard();
|
||||||
|
int Activate(InitInfo* args);
|
||||||
|
int Update();
|
||||||
|
};
|
||||||
|
|
||||||
|
void EnumLnx();
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* LilyPad - Pad plugin for PS2 Emulator
|
||||||
|
* Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Found- ation, either version 3 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
// This is undoubtedly completely unnecessary.
|
||||||
|
#include "KeyboardQueue.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
// Above code is for events that go from the plugin to core
|
||||||
|
// Here we need the contrary, event that come from core to the plugin
|
||||||
|
// Yes it is a crazy ping-pong hell ! I mostly copy past with
|
||||||
|
// a R_ (which stand for reverse)
|
||||||
|
|
||||||
|
#define R_EVENT_QUEUE_LEN 256
|
||||||
|
static std::mutex core_event;
|
||||||
|
|
||||||
|
static u8 R_lastQueuedEvent = 0;
|
||||||
|
static u8 R_nextQueuedEvent = 0;
|
||||||
|
static keyEvent R_queuedEvents[R_EVENT_QUEUE_LEN];
|
||||||
|
|
||||||
|
void R_QueueKeyEvent(const keyEvent &evt) {
|
||||||
|
std::lock_guard<std::mutex> lock(core_event);
|
||||||
|
|
||||||
|
R_queuedEvents[R_lastQueuedEvent] = evt;
|
||||||
|
R_lastQueuedEvent = (R_lastQueuedEvent + 1) % R_EVENT_QUEUE_LEN;
|
||||||
|
// In case someone has a severe Parkingson's disease
|
||||||
|
assert(R_nextQueuedEvent != R_lastQueuedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
int R_GetQueuedKeyEvent(keyEvent *event) {
|
||||||
|
if (R_lastQueuedEvent == R_nextQueuedEvent) return 0;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(core_event);
|
||||||
|
*event = R_queuedEvents[R_nextQueuedEvent];
|
||||||
|
R_nextQueuedEvent = (R_nextQueuedEvent + 1) % R_EVENT_QUEUE_LEN;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_ClearKeyQueue() {
|
||||||
|
R_lastQueuedEvent = R_nextQueuedEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_C_(void) PADWriteEvent(keyEvent &evt)
|
||||||
|
{
|
||||||
|
R_QueueKeyEvent(evt);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* bitmaskros.h
|
||||||
|
*
|
||||||
|
* Helper macros for large bit masks management
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Jean-Philippe Meuret
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Number of bits for 1 unsigned char */
|
||||||
|
#define nBitsPerUchar (sizeof(unsigned char) * 8)
|
||||||
|
|
||||||
|
/* Number of unsigned chars to contain a given number of bits */
|
||||||
|
#define nUcharsForNBits(nBits) ((((nBits)-1)/nBitsPerUchar)+1)
|
||||||
|
|
||||||
|
/* Index=Offset of given bit in 1 unsigned char */
|
||||||
|
#define bitOffsetInUchar(bit) ((bit)%nBitsPerUchar)
|
||||||
|
|
||||||
|
/* Index=Offset of the unsigned char associated to the bit
|
||||||
|
at the given index=offset */
|
||||||
|
#define ucharIndexForBit(bit) ((bit)/nBitsPerUchar)
|
||||||
|
|
||||||
|
/* Value of an unsigned char with bit set at given index=offset */
|
||||||
|
#define ucharValueForBit(bit) (((unsigned char)(1))<<bitOffsetInUchar(bit))
|
||||||
|
|
||||||
|
/* Test the bit with given index=offset in an unsigned char array */
|
||||||
|
#define testBit(bit, array) ((array[ucharIndexForBit(bit)] >> bitOffsetInUchar(bit)) & 1)
|
|
@ -219,9 +219,9 @@ bool JoystickInfo::Init(int id)
|
||||||
// work sometime on half axis neg others time in fulll axis. So better keep them as button for the moment
|
// work sometime on half axis neg others time in fulll axis. So better keep them as button for the moment
|
||||||
u32 found_hack = devname.find(string("PLAYSTATION(R)3"));
|
u32 found_hack = devname.find(string("PLAYSTATION(R)3"));
|
||||||
if (found_hack != string::npos) {
|
if (found_hack != string::npos) {
|
||||||
numbuttons = 4;
|
numbuttons = 4; // (select, start, l3, r3)
|
||||||
// Enable this hack is bluetooth too. It avoid to restart the onepad gui
|
// Enable this hack in bluetooth too. It avoid to restart the onepad gui
|
||||||
numbuttons += 4;
|
numbuttons += 4; // the 4 hat buttons
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SDL_MAJOR_VERSION >= 2
|
#if SDL_MAJOR_VERSION >= 2
|
||||||
|
|
Loading…
Reference in New Issue