diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d5fd38cb0..fb16a24d06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,7 +464,10 @@ elseif(SDL_FOUND) set(TargetBin PPSSPPSDL) # Require SDL include_directories(${SDL_INCLUDE_DIR}) - set(nativeExtra ${nativeExtra} native/base/PCMain.cpp) + set(nativeExtra ${nativeExtra} + SDL/SDLJoystick.h + SDL/SDLJoystick.cpp + native/base/PCMain.cpp) set(nativeExtraLibs ${nativeExtraLibs} ${SDL_LIBRARY}) if(APPLE) set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm) diff --git a/Core/Core.cpp b/Core/Core.cpp index 53db613311..f4064c4f75 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -145,7 +145,7 @@ void Core_RunLoop() { while (globalUIState != UISTATE_INGAME && globalUIState != UISTATE_EXIT) { time_update(); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) double startTime = time_now_d(); UpdateRunLoop(); @@ -164,7 +164,7 @@ void Core_RunLoop() { while (!coreState && globalUIState == UISTATE_INGAME) { time_update(); UpdateRunLoop(); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) if (!Core_IsStepping()) { GL_SwapBuffers(); } diff --git a/Qt/PPSSPP.pro b/Qt/PPSSPP.pro index 040922f8c8..9d4a908eeb 100755 --- a/Qt/PPSSPP.pro +++ b/Qt/PPSSPP.pro @@ -51,6 +51,8 @@ linux { PRE_TARGETDEPS += ./libCommon.a ./libCore.a ./libNative.a packagesExist(sdl) { DEFINES += QT_HAS_SDL + HEADERS += ../SDL/SDLJoystick.h + SOURCES += ../SDL/SDLJoystick.cpp PKGCONFIG += sdl } } diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp new file mode 100644 index 0000000000..abbe73b10e --- /dev/null +++ b/SDL/SDLJoystick.cpp @@ -0,0 +1,131 @@ +#include "SDL/SDLJoystick.h" + +#include + +extern "C" { + int SDLJoystickThreadWrapper(void *SDLJoy){ + SDLJoystick *stick = static_cast(SDLJoy); + stick->runLoop(); + return 0; + } +} + +SDLJoystick::SDLJoystick(bool init_SDL ){ + if (init_SDL) + { + SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO +#ifndef _WIN32 + | SDL_INIT_EVENTTHREAD +#endif + ); + } + fillMapping(); + + int numjoys = SDL_NumJoysticks(); + SDL_JoystickEventState(SDL_ENABLE); + if (numjoys > 0) { + joy = SDL_JoystickOpen(0); + } +} + +SDLJoystick::~SDLJoystick(){ + if (thread) + { + running = false; + SDL_Event evt; + evt.type = SDL_USEREVENT; + SDL_PushEvent(&evt); + SDL_WaitThread(thread,0); + } + SDL_JoystickClose(joy); +} + +void SDLJoystick::startEventLoop(){ + thread = SDL_CreateThread(SDLJoystickThreadWrapper, static_cast(this)); +} + +void SDLJoystick::ProcessInput(SDL_Event &event){ + switch (event.type) { + case SDL_JOYAXISMOTION: + { + AxisInput axis; + axis.axisId = SDLJoyAxisMap[event.jaxis.axis]; + // 1.2 to try to approximate the PSP's clamped rectangular range. + axis.value = 1.2 * event.jaxis.value / 32767.0f; + if (axis.value > 1.0f) axis.value = 1.0f; + if (axis.value < -1.0f) axis.value = -1.0f; + axis.deviceId = DEVICE_ID_PAD_0; + axis.flags = 0; + NativeAxis(axis); + break; + } + + case SDL_JOYBUTTONDOWN: + { + KeyInput key; + key.flags = KEY_DOWN; + key.keyCode = SDLJoyButtonMap[event.jbutton.button]; + key.deviceId = DEVICE_ID_PAD_0; + NativeKey(key); + break; + } + + case SDL_JOYBUTTONUP: + { + KeyInput key; + key.flags = KEY_UP; + key.keyCode = SDLJoyButtonMap[event.jbutton.button]; + key.deviceId = DEVICE_ID_PAD_0; + NativeKey(key); + break; + } + + case SDL_JOYHATMOTION: + { +#ifdef _WIN32 + KeyInput key; + key.deviceId = DEVICE_ID_PAD_0; + + key.flags = (event.jhat.value & SDL_HAT_UP)?KEY_DOWN:KEY_UP; + key.keyCode = NKCODE_DPAD_UP; + NativeKey(key); + key.flags = (event.jhat.value & SDL_HAT_LEFT)?KEY_DOWN:KEY_UP; + key.keyCode = NKCODE_DPAD_LEFT; + NativeKey(key); + key.flags = (event.jhat.value & SDL_HAT_DOWN)?KEY_DOWN:KEY_UP; + key.keyCode = NKCODE_DPAD_DOWN; + NativeKey(key); + key.flags = (event.jhat.value & SDL_HAT_RIGHT)?KEY_DOWN:KEY_UP; + key.keyCode = NKCODE_DPAD_RIGHT; + NativeKey(key); +#else + AxisInput axisX; + AxisInput axisY; + axisX.axisId = JOYSTICK_AXIS_HAT_X; + axisY.axisId = JOYSTICK_AXIS_HAT_Y; + axisX.deviceId = DEVICE_ID_PAD_0; + axisY.deviceId = DEVICE_ID_PAD_0; + axisX.value = 0.0f; + axisY.value = 0.0f; + if (event.jhat.value & SDL_HAT_LEFT) axisX.value = -1.0f; + if (event.jhat.value & SDL_HAT_RIGHT) axisX.value = 1.0f; + if (event.jhat.value & SDL_HAT_DOWN) axisY.value = 1.0f; + if (event.jhat.value & SDL_HAT_UP) axisY.value = -1.0f; + NativeAxis(axisX); + NativeAxis(axisY); +#endif + break; + } + } +} + + +void SDLJoystick::runLoop(){ + while (running){ + SDL_Event evt; + int res = SDL_WaitEvent(&evt); + if (res){ + ProcessInput(evt); + } + } +} \ No newline at end of file diff --git a/SDL/SDLJoystick.h b/SDL/SDLJoystick.h new file mode 100644 index 0000000000..e8fef3df97 --- /dev/null +++ b/SDL/SDLJoystick.h @@ -0,0 +1,97 @@ +//#ifdef _WIN32 +//#include "SDL/SDL.h" +//#include "SDL/SDL_joystick.h" +//#include "SDL/SDL_thread.h" +//#else +#pragma once + +#include "SDL.h" +#include "SDL_joystick.h" +#include "SDL_thread.h" +//#endif + +#include "input/input_state.h" +#include "input/keycodes.h" +#include "net/resolve.h" +#include "base/NKCodeFromSDL.h" +#include "base/NativeApp.h" + +extern "C" { + int SDLJoystickThreadWrapper(void *SDLJoy); +} + +class SDLJoystick{ + friend int ::SDLJoystickThreadWrapper(void *); +public: + SDLJoystick(bool init_SDL = false); + ~SDLJoystick(); + + void startEventLoop(); + void ProcessInput(SDL_Event &event); + +private: + + void runLoop(); + void fillMapping() + { + // This is just a standard mapping that matches the X360 controller on MacOSX. Names will probably be all wrong + // on other controllers. + + //TODO: C++11 aggregate initialization + //would remove runtime overhead completely +#ifdef _WIN32 + SDLJoyButtonMap[0] = NKCODE_BUTTON_2; + SDLJoyButtonMap[1] = NKCODE_BUTTON_3; + SDLJoyButtonMap[2] = NKCODE_BUTTON_4; + SDLJoyButtonMap[3] = NKCODE_BUTTON_1; + SDLJoyButtonMap[4] = NKCODE_BUTTON_7; + SDLJoyButtonMap[5] = NKCODE_BUTTON_8; + SDLJoyButtonMap[6] = NKCODE_BUTTON_9; + SDLJoyButtonMap[7] = NKCODE_BUTTON_10; + SDLJoyButtonMap[8] = NKCODE_BUTTON_11; + SDLJoyButtonMap[9] = NKCODE_BUTTON_12; + SDLJoyButtonMap[10] = NKCODE_BUTTON_5; + SDLJoyButtonMap[11] = NKCODE_BUTTON_6; + SDLJoyButtonMap[12] = NKCODE_BUTTON_7; + SDLJoyButtonMap[13] = NKCODE_BUTTON_8; + SDLJoyButtonMap[14] = NKCODE_BUTTON_9; + + SDLJoyAxisMap[0] = JOYSTICK_AXIS_X; + SDLJoyAxisMap[1] = JOYSTICK_AXIS_Y; + SDLJoyAxisMap[2] = JOYSTICK_AXIS_Z; + SDLJoyAxisMap[3] = JOYSTICK_AXIS_RZ; + SDLJoyAxisMap[4] = JOYSTICK_AXIS_LTRIGGER; + SDLJoyAxisMap[5] = JOYSTICK_AXIS_RTRIGGER; +#else + SDLJoyButtonMap[0] = NKCODE_DPAD_UP; + SDLJoyButtonMap[1] = NKCODE_DPAD_DOWN; + SDLJoyButtonMap[2] = NKCODE_DPAD_LEFT; + SDLJoyButtonMap[3] = NKCODE_DPAD_RIGHT; + SDLJoyButtonMap[4] = NKCODE_BUTTON_10; + SDLJoyButtonMap[5] = NKCODE_BUTTON_9; + SDLJoyButtonMap[6] = NKCODE_BUTTON_5; + SDLJoyButtonMap[7] = NKCODE_BUTTON_6; + SDLJoyButtonMap[8] = NKCODE_BUTTON_7; + SDLJoyButtonMap[9] = NKCODE_BUTTON_8; + SDLJoyButtonMap[10] = NKCODE_BUTTON_SELECT; + SDLJoyButtonMap[11] = NKCODE_BUTTON_2; + SDLJoyButtonMap[12] = NKCODE_BUTTON_3; + SDLJoyButtonMap[13] = NKCODE_BUTTON_4; + SDLJoyButtonMap[14] = NKCODE_BUTTON_1; + + SDLJoyAxisMap[0] = JOYSTICK_AXIS_X; + SDLJoyAxisMap[1] = JOYSTICK_AXIS_Y; + SDLJoyAxisMap[2] = JOYSTICK_AXIS_Z; + SDLJoyAxisMap[3] = JOYSTICK_AXIS_RZ; + SDLJoyAxisMap[4] = JOYSTICK_AXIS_LTRIGGER; + SDLJoyAxisMap[5] = JOYSTICK_AXIS_RTRIGGER; +#endif + } + std::map SDLJoyButtonMap; + std::map SDLJoyAxisMap; + + SDL_Joystick *joy = NULL; + SDL_Thread *thread = NULL; + bool running = true; + +}; diff --git a/native b/native index 58035235da..127d4b2d20 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 58035235dacdf50715ea23d25886475c635671bd +Subproject commit 127d4b2d200dae3174dc4739e7375292ad85c4ea